摘要
本文主要记录在电子设计大赛训练时,做电源时需要对电路中某些输出量进行稳定控制,PID控制算法可以很好的实现该功能,其中增量式更符合对电源的电压电流量的控制。本文主要粗略对其进行介绍再使用Python实现一个电压输出稳定控制
1.增量式PID算法介绍
以下仅限与对增量式PID控制算法的介绍,对于PID控制算法的概述(General Introduction)见“PID控制器入门概要”
增量式PID控制将当前时刻的控制量和上一时刻的控制量做差,以差值为新的控制量,是一种递推式的算法。
其公式表示为:
Δ u ( k ) = K p ( e ( k ) − e ( k − 1 ) ) + K i e ( k ) + K d ( e ( k ) − 2 e ( k − 1 ) + e ( k − 2 ) ) (1) \Delta u(k) = K_p (e(k) - e(k-1)) + K_i e(k) + K_d(e(k) - 2e(k-1) + e(k-2)) \tag{1}
Δ u ( k ) = K p ( e ( k ) − e ( k − 1 ) ) + K i e ( k ) + K d ( e ( k ) − 2 e ( k − 1 ) + e ( k − 2 ) ) ( 1 )
其中:
K p K_p K p 为比例系数
K i K_i K i 为积分系数
K d K_d K d 为微分系数
因此若要使用增量式PID算法需要保存e ( k − 1 ) , e ( k − 2 ) e(k-1),e(k-2) e ( k − 1 ) , e ( k − 2 ) 两个时刻的输出值,在加上输出回馈值e ( k ) e(k) e ( k ) 的积分
注意:增量式PID的运算结果为u ( k ) u(k) u ( k ) 同u ( k − 1 ) u(k-1) u ( k − 1 ) 之间的差值,因此输出结果需叠加,即为:
u ( k ) = u ( k − 1 ) + Δ ( k ) u(k) = u(k-1) + \Delta(k)
u ( k ) = u ( k − 1 ) + Δ ( k )
厘清u ( k ) , u ( k − 1 ) , Δ u , e ( k ) , e ( k − 1 ) , e ( k − 2 ) u(k),u(k-1),\Delta u,e(k),e(k-1),e(k-2) u ( k ) , u ( k − 1 ) , Δ u , e ( k ) , e ( k − 1 ) , e ( k − 2 )
2.使用Python语言进行实现
下面使用Python语言进行展示,得到输出曲线
假设如下案例,现有一DCDC升压(BOOST)电路,需要将15V的初始电压提升到30V,控制方式为驱动MOS管周期内导通与关断时间比值即可。但现在只关注电压输入与控制后输出的结果,不考虑PWM占空比,定时器计数等问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import numpyimport pandasimport matplotlib.pyplotdef main (): Setpoint = 30.0 out = 0.0 k_p = 0.05 k_i = 0.2 k_d = 0.1 e_k1 = 0.0 e_k2 = 0.0 time = range (1 , 50 , 1 ) output = numpy.arange(1.0 , 51.0 , 1.0 ) for i in time: e_k = Setpoint - out outk = k_p * (e_k - e_k1) + k_i * e_k + k_d * (e_k - 2 * e_k1 + e_k2) e_k2 = e_k1 e_k1 = e_k out = out + outk print (out) output[i] = out matplotlib.pyplot.plot(range (1 , 51 , 1 ), output) matplotlib.pyplot.show() print (output)if __name__ == '__main__' : main()
通过不断改变K p , K i , K d K_p,K_i,K_d K p , K i , K d 三个值最终可以得到一个十分合适的输出曲线:
观察该曲线可以发现系统可以很达到了稳定状态,且到达稳定点的时间也很快
观察如下数值结果:
可以看到在数值上达到预期值的效果也十分理想,误差小于0.001
3.其他的一些问题
当我在做DC-DC电源转换器直流稳压源时,发现由于系统反应过于迅速以至于转换器来不及反应导致系统无法达到预期目的,因此需要将参数调小并留有一定的系统反应时间。
4.近一年后
在使用过程中我又对上述的PID计算代码进行了进一步封装,使用的时候可以向PID计算过程直接传递 Kp, Ki, Kd 参数,使用起来更为方便,且封装后的代码可以针对不同的过程使用,不必考虑其他问题,诸如:
变量的存储空间是否会相互影响
是否要考虑计算的内容是否为有特定单位的有意义的物理量
计算时的变量是否可见可读
代码封装之后,所有的PID计算全部进行了归一化,输出结果的范围为 [ − 1 , 1 ] [-1,1] [ − 1 , 1 ] ,使用时需要自行缩放到需要的有物理意义的结果。这样作的好处之一就是,Matlab仿真的结构可以直接使用这个代码进行处理(Simulink仿真的PID计算输出均为归一化的结果)。
封装后的函数原型如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 float pidCalc (float Now_out, float Target, struct strPID Parameter ,float UpperLimit ,float LowerLimit) ;