这是linuxCNC的PID自整定的代码,对于理解PID的整定过程有帮助。
参数的选择可参考:
简述PID原理及临界比例度法参数整定_阿尘啊的博客-CSDN博客_临界比例度法整定pid参数
下面代码中,PID方法的Kp的选择是1/0.6 = 1.66。
/*
* Perform an auto-tune operation. Sets up a limit cycle using the specified
* tune effort. Averages the amplitude and period over the specified number of
* cycles. This characterizes the process and determines the ultimate gain
* and period, which are then used to calculate PID.
*
* CO(t) = P * [ e(t) + 1/Ti * (f e(t)dt) - Td * (d/dt PV(t)) ]
*
* Pu = 4/PI * tuneEffort / responseAmplitude
* Ti = 0.5 * responsePeriod
* Td = 0.125 * responsePeriod
*
* P = 0.6 * Pu
* I = P * 1/Ti
* D = P * Td
*/
static void
Pid_AutoTune(Pid *this, long period)
{
hal_float_t error;
// Calculate the error.
error = *this->pCommand - *this->pFeedback;
*this->pError = error;
// Check if enabled and if still in tune mode.
if(!*this->pEnable || !*this->pTuneMode){
this->state = STATE_TUNE_ABORT;
}
switch(this->state){
case STATE_TUNE_IDLE:
// Wait for tune start command.
if(*this->pTuneStart)
this->state = STATE_TUNE_START;
break;
case STATE_TUNE_START:
// Initialize tuning variables and start limit cycle.
this->state = STATE_TUNE_POS;
this->cycleCount = 0;
this->cyclePeriod = 0;
this->cycleAmplitude = 0;
this->totalTime = 0;
this->avgAmplitude = 0;
*(this->ultimateGain) = 0;
*(this->ultimatePeriod) = 0;
*this->pOutput = *(this->bias) + fabs(*(this->tuneEffort));
break;
case STATE_TUNE_POS:
case STATE_TUNE_NEG:
this->cyclePeriod += period;
if(error < 0.0){
// Check amplitude.
if(-error > this->cycleAmplitude)
this->cycleAmplitude = -error;
// Check for end of cycle.
if(this->state == STATE_TUNE_POS){
this->state = STATE_TUNE_NEG;
Pid_CycleEnd(this);
}
// Update output so user can ramp effort until movement occurs.
*this->pOutput = *(this->bias) - fabs(*(this->tuneEffort));
}else{
// Check amplitude.
if(error > this->cycleAmplitude)
this->cycleAmplitude = error;
// Check for end of cycle.
if(this->state == STATE_TUNE_NEG){
this->state = STATE_TUNE_POS;
Pid_CycleEnd(this);
}
// Update output so user can ramp effort until movement occurs.
*this->pOutput = *(this->bias) + fabs(*(this->tuneEffort));
}
// Check if the last cycle just ended. This is really the number
// of half cycles.
if(this->cycleCount < *(this->tuneCycles))
break;
// Calculate PID.
*(this->ultimateGain) = (4.0 * fabs(*(this->tuneEffort)))/(PI * this->avgAmplitude);
*(this->ultimatePeriod) = 2.0 * this->totalTime / *(this->tuneCycles);
*(this->ff0Gain) = 0;
*(this->ff2Gain) = 0;
if(*(this->tuneType) == TYPE_PID){
// PID.
*(this->pGain) = 0.6 * *(this->ultimateGain);
*(this->iGain) = *(this->pGain) / (*(this->ultimatePeriod) / 2.0);
*(this->dGain) = *(this->pGain) * (*(this->ultimatePeriod) / 8.0);
*(this->ff1Gain) = 0;
}else{
// PI FF1.
*(this->pGain) = 0.45 * *(this->ultimateGain);
*(this->iGain) = *(this->pGain) / (*(this->ultimatePeriod) / 1.2);
*(this->dGain) = 0;
// Scaling must be set so PID output is in user units per second.
*(this->ff1Gain) = 1;
}
// Fall through.
case STATE_TUNE_ABORT:
default:
// Force output to zero.
*this->pOutput = 0;
// Abort any tuning cycle in progress.
*this->pTuneStart = 0;
this->state = (*this->pTuneMode)? STATE_TUNE_IDLE: STATE_PID;
}
}
版权声明:本文为topwwl1原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。