四轮电磁------速度环增量式PID

这是我的第一次书写博客,仅代表我个人看法,若有问题希望各位大佬不吝赐教!!!

我们最近正在准备智能车四轮电磁的校内赛,我采用的是英飞凌的TC264单片机,使用的软件是AURIXTM Development Studio。以下是我在近日对速度环的一些学习。

例程学习+硬件测试

正式开始做一个项目,首先,我们学会使用这个软件和例程。例程是商家提供给我们学习测试硬件的一个代码,我们需要的是学会看,并且可以举一反三;与此同时,我们需要使用例程测试我们的硬件是否完好。在完全掌握和硬件测试之后,我们才能正式开始写代码。

速度环增量式PID

在博客里,介绍增量式的已经很多了,作为一只小菜熊,我就浅浅的把我的代码放出来请各位大佬指正指正。

PID结构体

typedef struct
{
    float actualValue;//真实值
    float set_point;//期望值
    float K_p;
    float K_i;
    float K_d;
    float sum_error;//本次error
    float last_error;//上一次error
    float last_2_error;//上两次error
}Pid;

设置PID参数

void setPIDParam(Pid* pid,float set_point,float p,float i,float d)//设置PID参数,
{
   pid->set_point=set_point;
   pid->K_p = p;
   pid->K_i = i;
   pid->K_d = d;
}

速度环PID

/****************************
 * 增量式pid
 * 控制电机
 * {
 * 本次误差 = 目标值-实际值
 * P输出 =Kp (本次误差-上次误差)
 * I输出 = Ki本次误差
 * D输出 =Kd (本次误差-2*上次误差+上上次误差)
 * ID输出 += P输出+I输出+D输出
 * 上上次误差=上次误差
 * 上次误差 = 本次误差
 * }
 ***************************/
int32 speed_pid_ctrl(Pid *PID,int value)
{
    if(value<0)
        {
        value=-value;
        i=0;
        }
    else i=1;
    PID->sum_error=PID->set_point-value; /*本次误差*/

    PID->actualValue += (PID->K_p * (PID->sum_error - PID->last_error))                          /* 比例*/
                         + (PID->K_i * PID->sum_error)                                             /* 积分 */
                         + (PID->K_d * (PID->sum_error - 2 * PID->last_error + PID->last_2_error));  /* 微分 */

    PID->last_2_error = PID->last_error;                                        /*储存偏差 */
    PID->last_error = PID->sum_error;
    if(PID->actualValue<2000)
       PID->actualValue=2000;
    if(PID->actualValue>6000)
       PID->actualValue=6000;
    if(i==1)
    return ((int32)(PID->actualValue));                                   /* 返回数值 */
    else
        return ((int32)(-PID->actualValue));
}

PID在主函数的设置

    setPIDParam(&speed_left_pid,230,13,1.4,0);//左轮pid
    setPIDParam(&speed_right_pid,230,13,1.4,0);//右轮pid

以上,便是我在写pid的一个简单过程,希望能够对初学者有一点帮助。
当然,如果有遗漏的地方,欢迎各位大佬指正。

过程中的简单问题

1.AURIXTM Development Studio这个软件对代码的要求很高:变量定义类型不同,会产生warning;全局若出现两个相同的变量名词,会产生error等等,遇到了很多不同的代码问题(这里想说一下,并不是所以的软件都需要之这样的要求,还是因软件而异)。
2.在这个过程中,我还遇到了一个硬件问题:我们对电机的控制是通过两个引脚(DIR和PWM)加上GND控制。

其中:

21.2 21.4 控制PWM
21.3 21.5 控制DIR

但是,控制方向的21.5引脚口,不能使用我在长达4个小时的寻找问题和思考如何解决问题后,我使用了如下代码来控制电机转动。

#define MOTOR1_A   ATOM0_CH0_P21_2   //定义1电机正转PWM引脚
#define MOTOR1_B   ATOM0_CH1_P21_3   //控制电机方向DIR引脚
#define MOTOR2_A   ATOM0_CH2_P21_4   //定义2电机正转PWM引脚
/************************
 * Motor_Ctrl(pwm1,pwm2)
 * pwm1:控制左电机(pwm1>0,向前;pwm1<0,向后)
 * pwm2:控制右电机(pwm2>0,向前;pwm2<0,向后)
 * *********************/
 * 
void Motor_Ctrl(sint32 pwm1,sint32 pwm2)
{
    if (pwm1 > 0)
        {
            pwm_duty(MOTOR1_A,pwm1);
            gpio_init(MOTOR1_B, GPO, 0, PUSHPULL);
        }
    else
        {
            pwm_duty(MOTOR1_A,0-pwm1);
            gpio_init(MOTOR1_B, GPO, 1, PUSHPULL);

        }
    if (pwm2 > 0)
        {
            pwm_duty(MOTOR2_A,pwm2);
            gpio_init(MOTOR1_B, GPO, 0, PUSHPULL);
        }
    else
        {
            pwm_duty(MOTOR2_A,0-pwm2);
            gpio_init(MOTOR1_B, GPO, 1, PUSHPULL);
        }
}

在这几个小时中,我排除掉了一下几个问题:

  • 驱动模块出现故障。排除方法:测试了那三根导线,发现了导出后并不是正确的电流,因此不能判断为电机驱动的问题。
  • 母板电路故障。排除方法:测试核心板上的引脚电流,依旧不是正确的电流,因此不能判断为母板发生故障。
  • 核心板出现故障。排除方法:我换了三块核心板,都是同样的电流,因此不能判断为核心板出现故障。

最后我也没能确定是那个部分的问题,但是我考虑到我是做的电磁四轮,后面的两个轮子也不会一个正转一个反转,于是,我使用了21.3这个引脚同时控制两个电机的正反转。最后,暴力解决了这个问题。

我寻找问题的方法可能不是那么的专业,而且最后也没能找出问题出在哪里。我的第一篇博客到这里就要结束了,可能会有许多问题,希望各位大佬多多指教!!