最近刚玩了下pid
PID大家都知道,无非是比例,积分和微分
比例:是对当前误差的处理
积分:是对过去误差的处理
微分:是对未来预期的误差处理
PID的算法一般是位置式PID和增量型PID。
位置式PID的话一般用于绝对位置式的,例如水位的高低,。
增量型PID一般用于瞬态的,例如速度方面的。
温控PID的一般采用位置型PID,
其公式为
Sum_I+=err*I
out=err*P + Sum_I + (err-errLast)*D
芯片选择为STM32F103,主频为72M,使用PWM调节占空比,最大输出值3600为最大输出。
/**
* @brief PID算法实现
* @param actual_val:实际值
* @note 无
* @retval 通过PID计算后的输出
*/
uint32_t PID_realize(int16_t actual_val,PID_T* pid)
{
/*计算实际值与目标值的误差*/
pid->err =actual_val- pid->target_val;
DATA=pid->err - pid->err_last; // 计算两次控温时温度偏差
pid->err_last = pid->err;
TdControlPar(pid);
/* 误差传递 */
pid->err_last = pid->err;
// if (abs(pid->err)<=500)//控温区域
if (abs(pid->err)<=200)//控温区域
{
pid->integral += pid->err*pid->Ki; //积分累加
if(pid->integral>(MAX_PWMOUT*DIVISION)) //积分最大限制
{
pid->integral = MAX_PWMOUT*DIVISION;
}
else if(pid->integral<(-MAX_PWMOUT*DIVISION)) //积分最小限制
{
pid->integral = -MAX_PWMOUT*DIVISION;
}
// pid->output_val=(pid->err*MAX_PWMOUT/pid->Kp)+(pid->integral/120)+pid->BIOS;
KP_SUM = (pid->err*MAX_PWMOUT/pid->Kp);
KI_SUM = (pid->integral/DIVISION);
// KD_SUM = DATA*pid->Kd;
// pid->output_val= KP_SUM+KI_SUM+ KD_SUM+pid->BIOS;
pid->output_val= KP_SUM+KI_SUM+pid->BIOS;
}
else //不在控温区域
{
pid->integral = 0; //积分清0
if(pid->err>0) //实际值比目标值温度高
{
// pid->output_val=MAX_PWMOUT/2;
pid->output_val=MAX_PWMOUT;
}
else //实际值比目标值温度低
{
pid->output_val =-MAX_PWMOUT;
}
}
/*返回当前输出值*/
return pid->output_val;
}
/**
* @brief 加热制冷控温处理
* @param targetTemp : 设置的目标值温度*100
* @retval li_actualTemp : 读取到的实际温感值*100
* @note none
*/
int16_t SetTempPID(int16_t targetTemp,PID_T* pid,int16_t actualTemp)
{
int16_t li_actualTemp;
int16_t li_PWMOut;
pid->target_val=targetTemp; //目标值
/* 读取实际温度值 */
li_actualTemp=actualTemp;
/* 进行 pid 运算 */
li_PWMOut=PID_realize(li_actualTemp,pid);
if(li_PWMOut>=MAX_PWMOUT) //PWM输出最大值限制
{
li_PWMOut=MAX_PWMOUT;
}
else if(li_PWMOut<=-MAX_PWMOUT) //PWM输出最小值限制
{
li_PWMOut=0-MAX_PWMOUT;
}
if(li_PWMOut>0) //需要降温
{
li_PWMOut=abs(li_PWMOut);
li_PWMOut =MAX_PWMOUT- li_PWMOut;
gi_PWMOutPut= li_PWMOut;
TEC_Control(TEC_DirCool,li_PWMOut);
}
else //需要升温
{
li_PWMOut=abs(li_PWMOut);
li_PWMOut = MAX_PWMOUT- li_PWMOut;
gi_PWMOutPut= li_PWMOut;
TEC_Control(TEC_DirHeat,li_PWMOut);
}
return li_actualTemp;
}
在pid温控中,设置温控范围大小,此范围外则全功率输出,达到温控区间,按照pid计算输出
积分用来消除静差,做了限制积分饱和的处理。
通过pid的输出值,来判断TEC的方向。若output>0,则温控方向是降温。output<0,则温控方向是升温。