23| 0
|
[进阶] 使用DFR1188实现简单的pid控制实例 |
本帖最后由 uQ1GA4qGEMEQ 于 2025-5-25 21:04 编辑 经历了上一次的简单入门体验(Firework!BOOM!(基于DFR1188简单的烟花生成)) 接下来我们可以try一下进阶的项目了,比如接下来我将会展示一个简单的PID控制实例。 本次依然使用DFR1188开发板,得益于RP2350的强大性能,比普通用途更精密、更复杂、更高速的控制算法也可以完成。 环境配置方面可以看看我上面↑之前的帖子或参考社区其它相关内容,这里就不过多赘述了。 一、项目介绍 本次项目的灵感源自于曾经电脑装机多剩出来一个机箱风扇(12V,0.19A),突然想到现在的机箱风扇都是PWM调速,既然可以调速,那么操作空间就大了。 ![]() 最开始我想制作一个基于温度自动调速的风扇,但是感觉太没创意了,而且我也没有一个能让我便捷测试效果的热源。后来看到之前买的角度传感器(MPU6050)有了一个新点子...... 如图这是一块普通的硬纸板,现在先固定上角度传感器。 ![]() 再把它和风扇一起固定到架子上(其实这个小龙门架是我做激光雕刻的残次品,没想到有一天还能派上用场)就构成了完整结构 ![]() 接下来的目标是:通过风扇吹起纸板使之角度固定在一个设定值,风扇的转速控制使用pid算法,控制逻辑闭环 ![]() 二、控制原理 PID控制如雷贯耳,从我刚上大学时就有所耳闻,没接触之前一直认为它是一个非常高端的专业名词,但是实际使用上之后才发现原理原来真的不是很难,难的只是调参过程(何止是难,简直是太痛苦了) 简而言之,PID分为三个部分:比例(Proportional)、积分(Integral)、微分(Derivative),PID这个名字正是取其首字母。 1. 比例控制(P) 如果你去搜索什么是比例控制,百度会回复你“依据输出与当前误差(设定值与实际值之差)的比例进行控制”,这句话看起来还是很抽象的,不妨来看一个例子。小学时大家一定做过一个经典题目,泳池一边放水一边注水,多久能把水池填满?通常注水和放水的速度是固定的,但是在现实世界中很多的控制是,我们需要依据泳池里的剩余水量来改变注水的速度,举例一个量化的情况:有一个泳池,控制目标是要保证泳池的水位保持在1米的高度。t=0时,水池里的水位是0.2米,那么当前时刻的水位和目标水位之间是存在一个误差的e,且e为0.8.这时,管理员通过加水的方式来控制水位。如果单纯的用比例控制算法,就是指加入的水量u和误差e是成正比的。即 u=kp*error 假设kp取0.5,那么t=1时(表示第1次加水,也就是第一次对系统施加控制),那么u=0.5*0.8=0.4,所以这一次加入的水量会使水位在0.2的基础上上升0.4,达到0.6. 接着,t=2时刻(第2次施加控制),当前水位是0.6,所以error是0.4。u=0.5*0.4=0.2,会使水位再次上升0.2,达到0.8. 如此这么循环下去,就是比例控制算法的运行方法。 可以看到,最终水位会达到我们需要的1米。 但是,考虑另外一种情况,在加水的过程中,存在漏水的情况,假设每次在加水的时间中,都会漏掉0.1米高度的水。仍然假设kp取0.5,那么会存在着某种情况,假设经过几次加水,水位到0.8时,将不会再变换!因为,水位为0.8,则误差e=0.2. 所以每次加水的量为u=0.5*0.2=0.1.同时,每次加水,又会流出去0.1米的水,加入的水和流出的水相抵消,水位将不再变化! 也就是说,我的目标是1米,但是最后系统达到0.8米的水位就不再变化了,且系统已经达到稳定。由此产生的误差就是稳态误差了。 如何处理稳态误差?就要用到接下来的部分了。 2. 积分控制(I) 在上面的例子中,如果仅使用比例控制,会存在稳态误差,最后的水位就卡在0.8了。于是,在控制中,再引入一个分量,对注水量u进行一个修正,该分量和误差的积分是正比关系。所以,比例+积分控制算法为: u=kp*e+ ki∗∫ e 还是用上面的例子,第一次的误差e是0.8,第二次的误差是0.4,至此,误差的积分(此时是离散情况,积分其实就是做累加),∫e=0.8+0.4=1.2. 这个时候的控制量,除了比例的那一部分,还有一部分就是一个系数ki乘以这个积分项。由于这个积分项会将前面若干次的误差进行累计,所以可以很好的消除稳态误差(假设在仅有比例项的情况下,系统卡在稳态误差了,即上例中的0.8,由于加入了积分项的存在,会让输入增大,从而使得水缸的水位可以大于0.8,渐渐到达目标的1.0.)这就是积分项的作用。 但是我们又发现了一个新的问题:由于积分项的存在,注水量增大后可能将会超出我们的设定目标值,然后u在减小后又会低于目标值,会始终造成震荡,无法稳定维持在我们的目标值上,这又该怎么解决呢? 3. 微分控制(D) 于是我们引入了微分控制。微分,说白了在离散情况下,就是e的差值,就是t时刻和t-1时刻e的差,即u=kd*(e(t)-e(t-1)) 换一个例子:汽车定速巡航时,如果只用比例控制,车速容易因惯性超过目标值再回调,形成反复加速减速的顿挫感。微分控制的作用就是监测车速变化趋势——当检测到车速正在快速接近目标时(比如从90km/h加速到95km/h),它会自动减小油门,相当于"提前轻踩刹车",防止车速冲过头。就像骑自行车下坡时,看到坡道变缓会提前捏闸减速一样,D控制让系统平稳接近目标,避免震荡。这种"预见性调节"在无人机平衡、机器人控制中同样有所应用,能有效抑制超调,使运动更顺滑。 把上述结合起来,我们就得到了最终的控制公式:(以下公式图片来自于知乎) ![]() 括号内第一项是比例项,第二项是积分项,第三项是微分项,前面仅仅是一个系数。很多情况下,仅仅需要在离散的时候使用,则控制可以化为: ![]() 每一项前面都有系数,这些系数都是需要实验中去尝试然后确定的,为了方便起见,将这些系数进行统一一下: ![]() 这里的Kp,Ki,Kd就是我们pid控制中需要调试的参数了。 三、代码实现 接下来先展示一下实际效果,由于控制效果看起来不明显,我加入了一个小LED,这个LED的亮度与控制量的绝对值abs(u(k))呈正相关,用于展示控制作用量的作用强度。 (↑无外力作用) ![]() (↑施加外力偏移目标值) ![]() (↑施加更大的外力) 可以看到这三次黄色LED的亮度是越来越亮的,代表PID控制的作用强度越来越高(其实即使在无外力作用时,因为参数调节的不精确和其他因素影响,控制精度达不到很高,LED始终在低亮度范围微微闪烁,图1是我捕捉到亮度最暗的时刻了。。。) 代码展示: 注意,对于一个pid控制实例想要复现的话是很难的,因为其原理虽然是相同的,但是受其他各种因素的影响参数不可能一样的,我这个参数也只是简单调试了一下,并没有达到最优的地步,但是pid调参成功真的是很有成就感的,各位可以自己也去试试。后面可能会尝试一下实现MPC控制,敬请期待 |
© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed