基于平衡车多环pid控制算法
最近为了丰富项目经历,复刻了一些开源的平衡车项目。这里先简单说一些外设上的东西,方便大家有一个大概的印象。
我做的这个平衡车项目主要包括:
主控芯片STM32(这个不用多说了)
电机驱动模块(将单片机输出的PWM波形输出给电机驱动、电机驱动再控制电机转速)
MPU6050(负责检测平衡车姿态,可以测角度、角加速度,前后左右上下都能检测到)
0.96寸OLED(这个不用多说,就是显示东西的)
蓝牙模块(其实就是用来串口USART通讯和手机进行联系,方便控制小车运行)
超声波模块(用于测量距离,可以加到平衡车里面实现避障功能)
电机(带编码器,方便单片机测量转速)
然后其他的硬件电源、电源转换啥的我都不说了,大家找开源项目的时候会有准确说明,我这里用到的都是比较普通的,作为一个初学者也不会上手就找很难的没有接触到的东西,凡是都需要技术不断进阶,项目不断进阶才能一步一步接触到上层的东西,不然一下子很难接受。
以上说的都是要用到的模块,大家有个大概印象,认识平衡车是怎么个运行原理就行了。
那么平衡车怎么样才能保持平衡呢?
第一我们得知道车的倾斜角度吧,就像人走路总不可能不带眼睛吧,获取倾斜角度这里就要用到上面提到的MPU6050了。
第二我们得知道电机的转速,所以需要用到自带编码器电机,方便测速。所谓编码器,就是电机每转一下,编码器会输出高低电平(脉冲)给单片机,单片机可以用定时器进行计算转速。
现在抛开上面的东西不谈,设想一下假如你现在端着一叠盘子,盘子要往前倾,你的手也要迅速反应往前移动,往后也是一样。这里放在平衡车来说也是一样的,车子往前倾就要往前加速,车子往后倾就要往后移动,这样子就可以实现平衡效果。
有了预想期望,现在需要解决的问题是如何将MPU6050上的角度值传给小车?其实很简单,当角度为负(小车向前倾),那么让电机正转加速,反之如果角度为正(小车向后倾),就让电机反转(反向加速)。具体要转多快呢?就需要用到我们今天讲的pid控制算法了。
所谓pid就是比例p、积分i、微分d三个对应的项,OUT=Kp*error(t)+1/Terror(t)dt + Tderror(t)/dt,然后将积分项系数1/T和微分项系数T换成Ki,Kd,就成了
OUT=Kp*error(t)+Ki*error(t)dt + Kd* derror(t)/dt,这个式子方面我们观察三个环节的系数,由于我们单片机处理的是离散信号,接收到的信号不可能是连续的,总是各一段时间采样一次,这里再将pid的式子写出离散形式OUT=Kp*error+Ki*error_int+Kd*(error-error_last),error_int表示error的累加项,error_last表示上一次的误差值(从上面的式子变下来本来要对微分项除去时间t的,但是这里将T和t都归到了Kd系数里)。
这个式子为什么能控制电机转速呢?我们可以假设给一个error值代入式子看看输出变化,我们需要的预想值是0°,假设这时候车子向前倾斜,测得角度值为负,这时 error=0°-测得值,error值为正,代入上面的式子发现比例项“P”为正,积分项“I”也为正,微分项“D”为负,最后输出值OUT也为正。这里说一下三个环节的作用,比例项直接起到一个调节作用,对当前的误差值进行处理反馈给电机,积分项则是对之前的累加误差进行反馈处理,微分项则是阻碍error发生变化(如果误差变化越快,微分项输出的值也大,对系统变化的阻碍作用越强,这里可以把error增大的情况带进去,error变大越快,那么输出的OUT越大为了阻碍小车倾斜;反之如果error变小,这个时候比例和积分环节在起调节作用,让电机正转使小车平衡,那微分项D这个时候输出量为负,阻碍比例P和积分I的调节),所以总结“P”对当前误差反馈,“I”对累计误差反馈,“D”阻碍系统发生变化。这里就不深入讨论PID各个环节对系统的作用了,这里我只能告诉你KD越大,系统的快速性越大(调节越快),KI越大,消除稳态误差越快(所谓稳态误差就是系统达到稳定状态时与目标值还存在偏差,比如电机转动要克服摩擦力,光靠比例项是达不到规定的转速要求的,当比例项的输出与阻力大小一致时,电机不再加速,但这个时候系统还存在误差值error,转速还未达到指定值,这个时候微分项就起到补充作用,使转速不断靠近目标值),KD越大,阻尼效果越大(阻碍作用)。
控制系统保持目标值就用OUT=Kp*error+Ki*error_int+Kd*(error-error_last)公式,没错就是这么粗暴且不讲道理,他就是可以做的把误差值经过各个环节处理反馈给系统输出保持error为零。我们要控制平衡车保持平衡要涉及到两个变量
1、目标值target 2、测得角度值Angle error=target- Angle error_int+= error OUT=Kp*error+Ki*error_int+Kd*(error-error_last) ,逻辑上各个已经解释过,公式成立,至于Kp,Ki,Kd是多大,这个需要自己不断调节大小。这里还有一个环节选择问题,对于小车保持平衡的问题,他是不存在稳态误差的,他不像电机旋转存在阻力影响需要Ki去补充误差,所以可以直接用Kp和Kd环节解决,也就是OUT=Kp*error+Kd*(error-error_last)。这里说的都是理想情况下,不考虑添加偏移角的问题,假设小车水平时测得的角度为0°,这个时候就不需要加偏移角度了。如果水平时角度不为0°的情况下,就需要加上偏移角了,也就是target=target+偏移角。以上就是小车直立环的pid编写逻辑。
但是光靠直立环调节是远远不够的,有做过平衡车的朋友可以发现,光靠直立环小车只能勉强保持平衡,给小车施加外力会使小车前进或后退失去平衡。也就是说光靠直立环的调节是远远不够的,这个时候我们想要强化直立环的作用,那么就得多加一个pid进行串联,也就是双环pid控制。既然要加强直立环,这里的pid就必须是正反馈而不是负反馈了!!!什么是正负反馈呢? 拿我们的直立环来说OUT=Kp*error+Ki*error_int+Kd*(error-error_last),只要存在误差,直立环就会努力控制电机让误差角度减小,如果将直立环的pid各个系数加上负号,效果就截然相反了,这个时候是在努力往放大误差的方向进行,但是我们这里可不上放大误差,而是放大直立环的调节作用。 OUT1=-Kp*error-Ki*error_int-Kd*(error-error_last), error=target_speed-speed,error_int+= error
同样的涉及到两个变量 1、目标值target_speed 2、测得速度speed 只不过这里是正反馈,之前要把输出值OUT1给直立环的target值,形成一个串联pid控制,把速度环的输出值给直立环的输入,这样子一但直立环有误差存在,输出的转速反馈给速度环,速度环正反馈加大直立环的调节,直到角度输出为0°,电机才停下来。

以上就是双环控制平衡车直立的pid控制了,至于为什么速度环正反馈可以控制转速呢?我编程的时候也在思考,个人认为速度环输入的指定速度会输出给直立环对应的一个角度,小车倾斜直立环就会产生一个速度保持平衡,这个速度对应速度环输入的目标速度。这里在编程时也做了一个总结归纳:
这里需要提个醒,在调pid参数的时候不要上来就调很大,从小开始慢慢调,如果pid某个环节的极性反了就有可能烧坏电机驱动,本人由于直立环的微分项极性弄反,kd参数也没有从小开始调,已经烧坏了一个电机驱动了。
以上就是本次要分享的双环pid控制了,感谢观看。
更多推荐
所有评论(0)