智能车中的PID算法

本文章主要介绍如何用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);
         
          
    }
}



由于电感的接口不同,可能电感的初始化不同。

本人建议自己画电路板和驱动板,避免出现一些小问题。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值