赞
踩
本文章主要介绍如何用PID算法和电感使你的小车完成最简单的循迹。
需要准备的硬件:芯片ch32v103R8T6,电机驱动板,核心板,两个电机,一个舵机,四个轮子,电磁传感器,干簧管(本文罗列的硬件对型号不做要求)。
我们使用的编译软件是MounRiver Studio,使用的库是由逐飞提供的库。
我们使用干黄管来使其可以完美的停车。
下图为我们对硬件结构的一个整体思路
下图为我们智能车
下图为我们程序设计的基本思路
程序源代码如下
- #include "headfile.h"
-
-
-
- int16 Left_Adc1=0,Right_Adc1=0; //转换后的左右电感值
- int16 Left_Adc2=0,Mid_Adc=0,Right_Adc2=0;
- int stop=0;
- uint16 duty3=8000;//停车电机反转
-
-
- int16 duty1=0; //舵机占空比
-
- float kp,kd; //舵机pid的p d参数
-
- //误差值
- float error;
- float error_last;
- float error_angle; //舵机转角pd算法偏值
-
- int16 ad_value1;
- int16 ad_value2;
-
- //获取电感值
- float get_adc(void){
- int i,j;
- float ad_value[10],sum_value=0;
- float temp;
- for(i=0;i<10;i++)
- {
- ad_value1=adc_convert(ADC_IN6_A6, ADC_12BIT);
- ad_value2=adc_convert(ADC_IN8_B0, ADC_12BIT);
- //差比和算法
- ad_value[i]=100*(ad_value2-ad_value1)/(ad_value2+ad_value1);
- }
-
- //冒泡算法
-
- for(j=0;j<9;j++)
- {
- for(i=0;i<9-j;i++)
- {
- if(ad_value[i]>ad_value[i+1])
- {
- temp=ad_value[i];
- ad_value[i]=ad_value[i+1];
- ad_value[i+1]=temp;
- }
- }
- }
- for(i=1;i<9;i++){
- sum_value+=ad_value[i];
- }
- temp=sum_value/8;
- return temp;
- }
-
-
-
-
-
- int main(void)
- {
- //关闭总中断
- DisableGlobalIRQ();
- //务必保留,本函数用于初始化MPU 时钟 调试串口
- board_init();
- //此处编写用户代码(例如:外设初始化代码等)
- //lcd初始化
- lcd_init();
- //lcd_clear(WHITE);
-
- //adc初始化
-
- adc_init(ADC_IN6_A6);//中
- adc_init(ADC_IN8_B0);//右二
-
-
- //电机初始化
-
- timer_pwm_init(PWM4_CH4_B9, 12500, 0);
- timer_pwm_init(PWM4_CH3_B8, 12500, 0);
- timer_pwm_init(PWM4_CH2_B7, 12500, 0);
- timer_pwm_init(PWM4_CH1_B6, 12500, 0);
- //舵机初始化
- timer_pwm_init(PWM3_CH1_C6,50,740);//舵机的pwm
- //D2口初始化
- gpio_init(D2,GPI,0,IN_PULLUP);
-
-
-
-
-
-
- //变量初始化
-
- error=0;
- error_last=0;
- //舵机pd算法的pd值
- kp=1.39;//5.2 4.57
- kd=0.02551; //1 1.15 1.55
-
-
- //总中断最后开启
- EnableGlobalIRQ(0);
- while(1)
- {
-
-
-
-
- error_last=error;
- error=get_adc();
-
- error_angle=kp*error+kd*(error-error_last);//舵机pd算法确定转角偏值
-
- duty1=740-(int16)error_angle;
- //舵机限幅
- if(duty1>=796)
- duty1=796;
- else if(duty1<=662)
- duty1=662;
- timer_pwm_duty(PWM3_CH1_C6,duty1);
-
- if(stop<=2)
- {
- //电机
- timer_pwm_duty(PWM4_CH3_B8,1500);//开关这边电机正转
- //timer_pwm_duty(PWM4_CH4_B9, 1800);//开关这边电机反转
-
- timer_pwm_duty(PWM4_CH2_B7,1850);//非正转
- //timer_pwm_duty(PWM4_CH1_B6,1800);//非反转
- }
- //干簧管停车
-
- if(gpio_get(D2)==0)
- {
- stop++;
- systick_delay_ms(100);
- }
-
-
-
- if(stop>2)
- {
- timer_pwm_duty(PWM3_CH1_C6,740);//992
- timer_pwm_duty(PWM4_CH4_B9,duty3);//开关这边电机
- timer_pwm_duty(PWM4_CH2_B7,0);
- timer_pwm_duty(PWM4_CH3_B8,0);//非开关这边电机
- timer_pwm_duty(PWM4_CH1_B6,duty3);
- systick_delay_ms(100);
- while(1){
-
- //电机反转实现停车
- timer_pwm_duty(PWM4_CH4_B9,0);//开关这边电机
- timer_pwm_duty(PWM4_CH2_B7,0);
- timer_pwm_duty(PWM4_CH3_B8,0);//非开关这边电机
- timer_pwm_duty(PWM4_CH1_B6,0);
-
- }
-
-
- }
-
-
-
-
-
- //lcd显示
-
-
-
- lcd_showstr(1, 0, "Left_Adc1");
- lcd_showint16(80,0, Left_Adc1);
- lcd_showstr(2, 1, "Left_Adc2");
- lcd_showint16(80, 1, Left_Adc2);
- lcd_showstr(3, 2, "L1");//左电感 A6
- lcd_showint16(80,2, ad_value1);
- lcd_showstr(4, 3, "Right_Adc1");
- lcd_showint16(90,3, Right_Adc1);
- lcd_showstr(5, 4, "R2");//右电感 B0
- lcd_showint16(90, 4, ad_value2);
- lcd_showint32(1, 5, duty1,4);
-
-
- }
- }
-
-
-
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
由于电感的接口不同,可能电感的初始化不同。
本人建议自己画电路板和驱动板,避免出现一些小问题。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。