固定采样周期的优化
问题
固定采样周期的情况下,每次都要将时间常数参与到运算中进行乘除运算,增加了计算量;
解决思路
固定周期的调用PID那么 t t t 为常数,将常数合入到 K I K_I KI, K D K_D KD中,公式表示可为:
u ( k ) = K P ⋅ e ( k ) + K I ⋅ ∑ j = 0 k e ( j ) + K D ⋅ [ e ( k ) − e ( k − 1 ) ] u\left(k\right)\;=K_P\cdot e(k)+K_I\cdot\sum_{j=0}^ke(j)+K_D\cdot\lbrack e\left(k\right)-e(k-1)\rbrack u(k)=KP⋅e(k)+KI⋅j=0∑ke(j)+KD⋅[e(k)−e(k−1)]
那么对于固定周期的PID控制
代码实现:
void Compute()
{
/*Compute all the working error variables*/
float err = setPoint - input;
errSum += err;
float dErr = err - lastErr;
/*Compute PID output*/
output = kp * err + ki * errSum + kd * dErr;
/*record var for next time*/
lastErr = err;
}
显然,以固定间隔调用PID算法可以简化一些数学计算,这样运行效率会更高;
大多数情况下,利用单片机的定时器中断去定时调用不失为一个简单,高效的选择。
但是,将常数合入到 K I K_I KI, K D K_D KD中后, K I K_I KI, K D K_D KD的参数由于时间系数的加成,在设置时参数之前可能会相差较大,显得稍微有些奇怪,所以在设置PID参数时引入采样时间;
void SetTunings(double Kp, double Ki, double Kd, int SampleTime)//采样时间的单位为毫秒
{
float SampleTimeInSec = ((float)SampleTime)/1000;
kp = Kp;
ki = Ki * SampleTimeInSec;
kd = Kd / SampleTimeInSec;
}