直流电机闭环PID控制
程序员文章站
2022-06-22 18:56:27
int32_t sp=0,pv=0,pv_1=0,e=0,e_i=0,e_d = 0,out=0; float Kp = 20.0; float Ki = 0.01; float Kd = 10.0; sp = 10000; while (1) { //error pv=TIM2->CNT; e = sp - pv; //derivative = e - e_i,in case sp changes,use pv e_d = pv_1 - pv;......
PID
P—比例控制系统的响应快速性,快速作用于输出,好比"现在"(现在就起作用,快),I—积分控制系统的准确性,消除过去的累积误差,好比"过去"(清除过去积怨,回到准确轨道),D—微分控制系统的稳定性,具有超前控制作用,好比"未来"(放眼未来,未雨绸缪,稳定才能发展)。当然这个结论也不可一概而论,只是想让初学者更加快速的理解PID的作用。(注1)
资料有很多,可参考
1,https://blog.csdn.net/tingfenghanlei/article/details/85028677
2,https://zh.wikipedia.org/wiki/PID%E6%8E%A7%E5%88%B6%E5%99%A8
理论看着很晦涩,敲写代码发现很常规。积分微分只是出来吓人的。注意Kp等参数根据负载特性调节。此代码示例为基础实现,也可增加滤波器优化。
int32_t sp=0,pv=0,pv_1=0,e=0,e_i=0,e_d = 0,out=0;
/* tune according to load characteristics */
float Kp = 20.0;
float Ki = 0.01;
float Kd = 10.0;
sp = 10000;
while (1)
{
//error
pv=TIM2->CNT;
e = sp - pv;
//derivative = e - e_i,in case sp changes,use pv
e_d = pv_1 - pv;
//Integral when error within threshold
if(e < Integral_TH && e > (-1 * Integral_TH)){
e_i += e;
}
if(e_i > Integral_HIGH ){
e_i = Integral_HIGH;
}
else if(e_i < (-1 * Integral_HIGH)){
e_i = -1 * Integral_HIGH;
}
if(e == 0){
e_i = 0;
}
//PID
out = (int32_t)(Kp * e + Ki * e_i + Kd * e_d);
pv_1 = pv;
if(out > PWM_PERIOD ){
out = PWM_PERIOD + 1;
}
else if(out < PWM_LOW && out > 0){
out = PWM_LOW;
}
else if(out < (-1 * PWM_PERIOD)){
out = -1 * PWM_PERIOD - 1;
}
else if(out >(-1 * PWM_LOW) && out < 0){
out = -1 * PWM_LOW;
}
//out to pwm
if(out >= 0){
TIM3->CCR1 = 0;
TIM3->CCR2 = out;
}
else{
TIM3->CCR1 = -1 * out;
TIM3->CCR2 = 0;
}
// printf("OUT:%d|PV:%d|e:%d|e_i:%d\r\n",out,pv,e,e_i);
HAL_Delay(1);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
此篇是基于直流电机增加编码器实现闭环控制,类似的场景还有闭环步进电机(mechaduino),参见https://github.com/jcchurch13/Mechaduino-Firmware。
本文地址:https://blog.csdn.net/zh0umu/article/details/107911138
下一篇: 关于Kotlin中SAM转换的那些事