在这里插入代码片
```struct Pid_struct_def {
uint32_t iPidSamples;
uint32_t ulSampleCount;
float fCurrentCo; //!< pid output (pwm) Pid输出(pwm)
float lastError; //!< used for D term 用于D项
float cumulError; //!< cumulative error 累积误差
float pedestal; //!< opening setting for the valve 阀门开度设定
float fTemporaryCo; // holds the Co for a step down setpoint 保持Co为降阶设定值
float lastKi; //!< Ki coeff used last cycle, needed to update cumul_error if changing Ki coeff使用上一个周期,如果更改,需要更新cumul_error
float lastCurrent; //!< measured valve current 测量阀电流
bool bHighPIDs;
};
void updateP1Pid(struct Pid_struct_def *my_pid, float setpoint, float cv, bool *stepDown, uint16_t *StepUp){
...............
pedestal = DispenseConfig.V1Pedestal/65535.0F;//DispenseConfig.V1Pedestal = 11666 pedestal = 0.17
保存上一次偏差
//error = safeDiv((setpoint - cv), sensorSerial.FullScale[1], (setpoint - cv)/50.0F);
// safe full scale conversion, use 50 for safe full scale
saveError = error = safeDiv((setpoint - cv), 50.0F, (setpoint - cv)/50.0F); // safe full scale conversion, use 50 for safe full scale
if (error > error_max)
error = error_max;
if (error < -error_max)
error = -error_max;
if (fabs(averageError) > (pidTuningParams.HiBandUpCloseErrThreshold / 10)) // 高波段上误差阈值 was 2
{
error += 1.0F;
}
//fabs,求双精度浮点数的绝对值
if (( (setpoint - Sensors.fP2PidPsia) < UltraLowPidCoefs.fPsiaThreshold) ) { // && (!my_pid->bHighPIDs || !Status.FLAGS.ByBits.bVerifying)) {
if ( fabs(error) < pidTuningParams.UltraLoBandUpCloseErrThreshold) { // was 0.0025F
Kp = UltraLowPidCoefs.UpClose.fKp;
Ki = UltraLowPidCoefs.UpClose.fKi;
Kd = UltraLowPidCoefs.UpClose.fKd;
}
else {
Kp = UltraLowPidCoefs.Up.fKp;
Ki = UltraLowPidCoefs.Up.fKi;
Kd = UltraLowPidCoefs.Up.fKd;
}
}
else if (( (setpoint - Sensors.fP2PidPsia) < LowPidCoefs.fPsiaThreshold) ) { // && (!my_pid->bHighPIDs || !Status.FLAGS.ByBits.bVerifying)) {
if ( fabs(error) < pidTuningParams.LoBandUpCloseErrThreshold) { // was 0.0025F
Kp = LowPidCoefs.UpClose.fKp;
Ki = LowPidCoefs.UpClose.fKi;
Kd = LowPidCoefs.UpClose.fKd;
}
else {
Kp = LowPidCoefs.Up.fKp;
Ki = LowPidCoefs.Up.fKi;
Kd = LowPidCoefs.Up.fKd;
}
}
else {
// use the high PID coefficients
if ( fabs(error) < pidTuningParams.HiBandUpCloseErrThreshold) { // was 0.01F
Kp = HighPidCoefs.UpClose.fKp;
Ki = HighPidCoefs.UpClose.fKi;
Kd = HighPidCoefs.UpClose.fKd;
}
else {
Kp = HighPidCoefs.Up.fKp;
Ki = HighPidCoefs.Up.fKi;
Kd = HighPidCoefs.Up.fKd;
}
}
error = saveError; 将上一次偏差
//使调优独立于出口sigproc
Ki = Ki * sigprocParam.sigprocTimerTic[1]; // Make tuning independant of outlet sigproc
Kd = Kd * sigprocParam.sigprocTimerTic[1]; // Make tuning independant of outlet sigproc
if((setpoint > LowPidCoefs.fPsiaThreshold) && (Status.FLAGS.ByBits.uState == DS_VERIFY_COLLECT))//验证收发
{
Kp = VerifyPIDMultiplier.fKp * Kp;
Ki = VerifyPIDMultiplier.fKi * Ki;
Kd = VerifyPIDMultiplier.fKd * Kd;
}
Pterm = Kp * error;
// check for Nan //检查Nan
if (my_pid->cumulError != my_pid->cumulError) //累积误差
my_pid->cumulError = 0.0F;
// iTerm always needs a windup limit // term总是需要一个windup limit
if (0 != Ki) {
cumul_limit_pos = (1.0F - pedestal)/Ki;//pedestal = 0.17 超低10 低18 高66.6
cumul_limit_neg = ( - pedestal)/Ki;
}
else {
cumul_limit_pos = 100; // doesn't really matter 这并不重要
cumul_limit_neg = 100; // doesn't really matter
}
//累积误差
if (my_pid->cumulError > cumul_limit_pos)
my_pid->cumulError = cumul_limit_pos;
if (my_pid->cumulError < cumul_limit_neg)
my_pid->cumulError = cumul_limit_neg;
//加载之前的累积误差
iTerm = Ki * ( my_pid->cumulError + error); // 更新i系数 // load the previous cumulative error
dTerm = Kd * (error - my_pid->lastError); 更新D系数// // 计算误差变化率
my_pid->fCurrentCo = pedestal + Pterm + iTerm + dTerm;
if (my_pid->fCurrentCo > 1.0F)
my_pid->fCurrentCo = 1.0F;
if (my_pid->fCurrentCo < 0.0F)
my_pid->fCurrentCo = 0.0F;
my_pid->cumulError += error; // save for next round //保存到下一轮
my_pid->lastError=error; // 更新上一次误差
my_pid->lastKi = Ki;
从而实现PID自动定位
PID知识点
最新推荐文章于 2024-09-14 14:58:05 发布