PID调速
背景:
偶然购买了智能小车配件,使用现在大热的arduino控制板,实现了wifi的小车运动。但是遇到了走不直,控不住的问题。上网google后,发现里面还有很大的学问,直到发现了一个名为PID的控制方法,可以控制电机转速。只有实现了PID调速,才有基础让小车走直线。
硬件准备:
N20直流电机,配有1:145的金属变速箱。电机必须带测速。 Aduino nano控制板,主控芯片atmel328p。 实现电机控制的H桥电路板,带pwm输入。 供电电池。
软件准备:
Arduino IDE开发环境。
串口猎人,收集数据,绘制可视化图像。
目的就是控制电机转速,但是如何入手是个门槛。
通过疯狂google,网上的偏重理论研究的很多,也有很多的学生毕业设计论文,但是都是说的不仔细不透彻。我本身工作多年,数学基础,自动控制理论也比较薄弱,看了也是云里雾里。正在发愁之际,点入丁老师的“嵌入之梦”网站。里面的一篇PID调速文章使用通俗易懂的语言介绍让我非常兴奋,给我一个不错的起点,总算是找到门了!
还是要先有个大概的理论。PID指的是(比例-积分-微分)控制器。要控制就要涉及到三个量:设定值(控制目的)、被调量(控制什么)、输出量(控制结果)。对应到直流电机上就是:
设定值:希望(给定)电机输出的转速 被调量:PWM占空比
输出量:实际电机输出的转速
实现自动控制保持速度恒定,有一个必不可少的东西,反馈。只有有了反馈才能知道如何调整被调量。假设我是控制小车的程序,我只有看到当前时刻的速度才能采取动作,是调快点还是调慢点。
电机上体现速度的数字量是单位时间内的电平改变的次数(ticks)。我设置的是引脚变化触发计数,有改变就计数。因此,速度 = ticks。对应的量就变为:
设定值:希望的单位时间内ticks 被调量:PWM占空比
输出量:实际单位时间内ticks
下面问题来了,如何测定ticks。程序可以通过定时器来计数,问题是这个采样
参考丁老师的文章“因为 PID 控制的基础是以周期 T 测量,计算
出偏差后修正输出。而测量周期不能太长,那样响应将滞后;但过短也没有意义,因为对象的惯性特征,导致极小的时间间隔中不会有变化。根据小车电机的驱动特性,100ms 左右的周期比较合适。”这里我觉得我这个电机测速是放在转轴上未减速前,每圈有12个ticks应该可以再设短些,就设为15ms测速一次,30ms取上2次的平均值,作为测量输入,执行一次PID计算调整输出。
有了采样周期,就可以得到了2个量:设定值,输出量。下面就是建立被调量PWM与这2个量的关系了。
实现P控制器
再回到PID算法上来吧。我们现在知道了什么?有了设定值,有了输出值,那么就得到了偏差值。在时刻t ,e(t) = setpoint – inputMeter。Kp*e(t),就可以用来控制了PWM了。e(t)有可能为正,也有可能为负,快了就变成负值,慢了就变成正值,这正是我们想要的结果啊。赶快动手试一试:
结合我的情况我的给定值是40,测得的实际速度是25。最终稳定在25。Kp参数经过调整,直到不震荡的状态。
可以看到实际的输出值与想要的速度有一个恒定的误差,也就是专业术语的稳态误差了。
double error = mySetpoint - inputMeter; outputPWM = kp*error;
//arduino 的调节范围就是0 - 255 if(outputPWM > 255) outputPWM = 255; if(outputPWM < 0) outputPWM = 0;
实现PI控制器
实现了p控制器后,我们来看看有什么能改进的。通过改变参数kp,直到系统不震荡就达到目的了。“系统不振荡”就是一个“参数整定”的过程。P控制器可以快速响应我们的给定,比如我改变速度为50。实际速度也跟着上去了。可是我给定了一个速度,实际却不能达到,我需要电机速度是40ticks,真实输出是25ticks。为了消除这个稳态误差,就需要积分控制器帮忙。下面涉及到的理论偏多。但是耐心思考下,还是比较容易理解的。所谓积分作用是指调节器的输出与输入偏差的积分成比例的作用。积分方程为:
式中:
TI是积分时间常数,它表示积分速度的大小,TI越大,积分速度越慢,积分作用越弱。
这里说明下我们程序是在中断处理函数中进行。理论公式给出的是连续量,模拟式的表示方法。所以就要进行所谓的“离散化”。
离散化 t?kT(k?0,1,2,?)kke(t)dt???e(jT)Tj?0?T?e(jT)j?0
u(t)对应的就是我们的pwm输出。Kp就是P控制器整定后的值。T就是设定的采样周期。Ti就是需要通过实际测试,需要整定的值。理论公式要求的积分,对应到我们实际程序编写就是把所有的误差加起来。积分 约等于 做加法。更直观一些积分就是求面积。j就是执行了多少个采样周期了。面积可以用梯形求和法。
伪代码:
增加全局变量 errSUM
double error = mySetpoint - inputMeter; errSUM += error;
outputPWM = kp*error + ki * errSUM ; //arduino 的调节范围就是0 - 255 if(outputPWM > 255) outputPWM = 255; if(outputPWM < 0) outputPWM = 0;
这里需要说明的是,程序中的ki对应到理论公式其实是kp*T/Ti,实际中直接用ki替换。整定时只要改变ki,减少了程序的运算。马上动手实现,看效果吧
相关推荐: