大学生智能车电磁三轮组pid算法控制

在此之前,首先先说一下我所理解的智能车电磁循迹的基本原理

首先是 

1——电磁传感器(也就是电感)采集数据

2——通过某种算法处理数据(滤波)计算误差,【左右电感差值】

3——将误差传入转向环pid——传出一个左右电机速度误差

4——左右电机速度环收到误差分别做加减运算完成差速转向

5——在这个转向过程中,电感采集到的数据在不断变化,同时误差也在不断变化,构成一个闭环循环体

ps:其中速度环控制的速度是由正交编码器采集到的。

在这个学习过程中最佳学习顺序如下

第一步,学习电感采集数据并在oled中显示

第二步,学习电感数据的滤波算法以及误差的计算方法(算法有很多种)

第三步,学习并写出编码器采集到的电机转速数据

第四步,学习并写出电机的速度环pid,左右电机分别写一个(因为要差速控制转向)

第五步,学习并写出转向环pid,传入差值传入速度环,进行速度控制

我在这个学习过程中遇到的问题有

1.在速度环中检测速度的是编码器,而控制电机转速的是pwm占空比,这两个数值大小,比例是不同的,要用那种算法来解决此问题?

        解决办法:我是直接将此差值写入到PID算法中比例系数Kp当中,编码器采集到的数据比较小而所需写入的占空比较大这两者的差值用这个系数来抵消。并且在此系数的基础上来进行PID系数的微调,

2.在转向环中仍然存在这种问题,电感值与电机差速比例不同,同样利用PID系数来修正。

代码如下 

//全部采用位置式PID(增量式还没学)
//代码更新时间2023.05.25
void PID_Init(void)//pid初始化
{

    pid_motorL.Kp=150;//Kp与Kd很大是因为误差与实际要用的值相差很大
    pid_motorL.Ki=0;
    pid_motorL.Kd=50;

    pid_motorR.Kp=150;
    pid_motorR.Ki=0;
    pid_motorR.Kd=50;

    pid_ADC.target_val=0;
    pid_ADC.Kp=0.7;
    pid_ADC.Ki=0;
    pid_ADC.Kd=0.5;
}
//左电机速度环
int16 PID_runL(float target_val,float now_val)
{


    pid_motorL.err=target_val-now_val;//计算误差值(期望转速-当前转速)
    pid_motorL.integral=pid_motorL.err-pid_motorL.err_last;//积分(误差的累加)
    pid_motorL.actual_val=  pid_motorL.Kp*pid_motorL.err+
                            pid_motorL.Ki*pid_motorL.actual_val+
                            pid_motorL.Kd*(pid_motorL.err-pid_motorL.err_last);
    pid_motorL.err_last=pid_motorL.err;
        return pid_motorL.actual_val;//返回电机转速
}
//右电机速度环
int16 PID_runR(float target_val,float now_val)
{


    pid_motorR.err=target_val-now_val;//计算误差值(期望转速-当前转速)
    pid_motorR.integral=pid_motorR.err-pid_motorR.err_last;//积分(误差的累加)
    pid_motorR.actual_val=  pid_motorR.Kp*pid_motorR.err+
                            pid_motorR.Ki*pid_motorR.actual_val+
                            pid_motorR.Kd*(pid_motorR.err-pid_motorR.err_last);
    pid_motorR.err_last=pid_motorR.err;
        return pid_motorR.actual_val;//返回电机转速
}
//电感值转向环
int16 PID_ADC(void)
{
    pid_ADC.err=Parameter_EM.ADC_E;//此误差位电感采集后的误差
    pid_ADC.integral=pid_ADC.err-pid_ADC.err_last;//积分(误差的累加)
    pid_ADC.actual_val=     pid_ADC.Kp*pid_ADC.err+
                            pid_ADC.Ki*pid_ADC.actual_val+
                            pid_ADC.Kd*(pid_ADC.err-pid_ADC.err_last);
    pid_ADC.err_last=pid_ADC.err;
    return pid_ADC.actual_val;//返回电机应该达到的转速差
}

如有更好解决办法欢迎在评论区指出,以上学习过程如有不足欢迎指出。

                        作者:一个学习单片机的小菜。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐