本文所讲闭环控制是通过编码器获取电机转速,再利用PI控制电机转速维持在设定值的一种控制方法。速度闭环不使用D微分项。
提示:本篇文章参考平衡小车之家、https://blog.csdn.net/chrnhao/article/details/112639533的部分内容
PWM(Pulse Width Modulation)脉冲宽度调制,PWM波形是一个数字输出信号,也是由高低电平组成。在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域。
使用PWM波形是为了等效地实现一个模拟信号地输出。PWM的秘诀就是天下武功唯快不破,只要闪的快,就发现不了是闪着187亮的,还是一个正常、平稳的亮度。PWM应用需要在惯性的系统,LED熄灭的时候,由于余晖和人眼视觉暂留现象,LED不会立马熄灭,而是有一定的惯性,过一小段时间才会熄灭;电机断电时,电机不会立马停止,而是有一定的惯性,过一会才停。
从下图可看出高低电平跳变的数字信号,可以等效为中间虚线所表示的模拟量。当上电平时间长,下电平时间短时,等效的模拟量就偏上,反之亦然。
PWM重要参数:
频率 = 1 / TS
占空比 = TON / TS
分辨率 = 占空比变化步距 (占空比变化1%2%3%,以1%的步距跳变,分辨率1%,分辨率就是占空比变化的精细程度)
控制直流减速电机的PID一般分为两种,一种叫位置式PID,一种叫增量式(速度)PID。
位置式PID一般用于倒立摆,平衡小车等,使一个参数准确的到达某一个指定的静止状态,比如让一个电机准确的转90度。
增量式PID用于让一个动态变量,尽可能稳定的维持在某一个设定目标值,若想让小车准确的匀速行驶,就是让每一个轮子的转速稳定在一个所设定目标值。
对于直流减速电机,想要启动电机并且对电机调速,就需要让单片机产生PWM脉冲,将脉冲输入到电机驱动器(L298N、DRV8848、TB6612、A4950等)。而PWM有一个极为重要的参数就是占空比,不同占空比对应电机的不同转速,占空比为100%,电机全速转动,占空比为0%,电机停止。比如我们的电机满转速为333 RPM(转每分),我们希望电机以半速运动即166.5 RPM,我们的PWM占空比就要设置为50%,但实际操做,转速很难达到并保持166.5 RPM,有可能为150、170 RPM,反正就不会保持166.5 RPM,此时就需要用到一个闭环的算法(增量式PID)。
带编码器的直流减速电机,电机转速不同,编码器就会输出不同的脉冲,单片机通过读取编码器输出的脉冲的边沿(上升沿、下降沿、上升沿和下降沿)来获取转速。
循环过程:
(1)单片机通过直流减速电机的编码器获得电机的实际转速,计算实际转速与设定的目标转速之间的误差;
(2)根据误差,PI控制器会算出一个用于将直流减速电机调整到目标转速的PWM值;
(3)将算出的PWM值输出给直流电机,对直流电机转速进行调整;
(4)再次读取直流电机转速传给单片机。
所讲的PI控制器是一个函数,输入的是当前转速与目标转速的误差,输出的是调整转速需要用到的PWM值。
PID公式如下:
PWM+=Kp×[e(k)-e(k-1)]+Ki×e(k)+Kd×[e(k)-2e(k-1)+e(k-2)]
PWM: 输出增量,即输出值;
Kp、Ki、Kd: 这三个参数是我们要来调节的,根据不断的测试调整得出一组最佳值;
e(k) :本次误差
e(k-1):上次误差
e(k-2):上上次误差
前文讲过在增量式(速度)PID中,我们仅需要Kp、Ki两个参数,所以公式可简化为:
PWM +=Kp×[e(k)-e(k-1)]+Ki×e(k)
Arduino中PI控制器代码实现:
//定义一个返回值为整形的函Incremental_PI,输入的是两个整形变量 Encoder,Target (Encoder代表编码器所测的当前速度,Target代表目标速度)
int Incremental_PI (int Encoder, int Target)
{ float Bias; //浮点型变量Bias (本次偏差)
static float PWM, Last_bias; // 两个全局浮点型静态变量:PWM(输出增量)、Last_bias(上次误差)
Bias = Encoder - Target; //计算偏差,当前值-目标值
PWM += Velocity_KP * (Bias - Last_bias) + Velocity_KI * Bias; //增量式PI控制器
if (PWM > 155)PWM = 155; //限幅,给小车限速
if (PWM < -155)PWM = -155; //限幅,给小车限速
Last_bias = Bias; //保存上一次偏差
return PWM; //增量输出
}
(1)Arduino mega 2560
(2)12V航模电源
(3)直流电机驱动A4950T
(4)带编码器的直流减速电机
如下图所示,编码器直接附在电机后面,这种是霍尔传感器形式的编码器,中间是一个圆形磁铁,边上有两个位置错开的霍尔传感器,当磁铁旋转时,通过霍尔传感器,就可以输出正交的方波信号。
编码器的A相和B相输出给单片机的是有相位差的两个脉冲(正交的方波信号)。如果设置计数器是通过A相输出方波的上升沿计数,当检测到A相输出方波的上升沿时,B相输出的是高电平则判断电机正转,B相输出的是低电平则判断电机反转。
通过计算确定时间内的脉冲个数得到转速的为M测速法。针对A、B相上升沿和下降沿都进行检测,检测精度可达四倍精度(四倍频测速)。本文只对A相的上升沿和下降沿进行检测并计数。
我们做四轮驱动车,需使用四个中断IO口,每一个中断IO口对应一个电机的编码器,一般来说我们都是采用Mega2560 ,下面是arduino系列单片机对应引脚号和中断号:
Arduino mega 2560 只有6个中断IO口,其中还有和I2C通信口和Serial1串口共用的IO口,所以可用的只有2、3、18、19四个引脚。
为了对设定时间内的脉冲的上升沿和下降沿计数,MEGA2560我们使用FlexiTimer2.h库进入定时内部中断,其他型号的arduino的板使用的是MsTimer2.h库。
使用时,在setup()函数里加上:
FlexiTimer2::set(20, control); //20毫秒定时中断函数,每20毫秒执行一次control函数
FlexiTimer2::start (); //中断使能
具体控制程序可以通过这里下载,也可以联系我
https://download.csdn.net/download/weixin_43002939/85438995