Closed 7eter closed 2 years ago
This is a good point, however I'd like to implement a more accurate approach. I'm not completely sure if this will work (compiled but untested), but this should do the trick:
void ArduPID::compute()
{
if (timer.fire() && modeType == ON)
{
kp = pIn;
ki = iIn * (timer.timeDiff * 1000.0);
kd = dIn / (timer.timeDiff * 1000.0);
if (direction == BACKWARD)
{
kp *= -1;
ki *= -1;
kd *= -1;
}
lastInput = curInput;
lastSetpoint = curSetpoint;
lastError = curError;
curInput = *input;
curSetpoint = *setpoint;
curError = curSetpoint - curInput;
double dInput = *input - lastInput;
if (pOnType == P_ON_E)
pOut = kp * curError;
else if (pOnType == P_ON_M)
pOut = -kp * dInput;
dOut = -kd * dInput; // Derrivative on measurement
double iTemp = iOut + (ki * ((curError + lastError) / 2.0)); // Trapezoidal integration
iTemp = constrain(iTemp, windupMin, windupMax); // Prevent integral windup
double outTemp = bias + pOut + dOut; // Output without integral
double iMax = constrain(outputMax - outTemp, 0, outputMax); // Maximum allowed integral term before saturating output
double iMin = constrain(outTemp - outputMin, outputMin, 0); // Minimum allowed integral term before saturating output
iOut = constrain(iTemp, iMin, iMax);
double newOutput = bias + pOut + iOut + dOut;
newOutput = constrain(newOutput, outputMin, outputMax);
*output = newOutput;
}
}
This new compute()
function will determine how much leeway the integral term has before saturating the output and constrains the I term appropriately. Hopefully this will not introduce unwanted oscillations - do you have an easy setup/project to test with?
Any thoughts on this?
This is a good point, however I'd like to implement a more accurate approach. I'm not completely sure if this will work (compiled but untested), but this should do the trick:
Sounds very promising! Sadly I don't have a fast setup to test it right now. I used your library for a simple heater. And only for Temperatures close to the set point and it works flawlessly. Right now I don't have access to the setup. But if ill ever get a new control setup I'll definitely test your updated library. Thanks!
This issue is a low priority for me rn - life is quite busy at the moment. That being said, I'm not sure if my approach is best - I'll have to think about it more when I get time. Because of this, I haven't updated the master branch yet. I would be interested in your thoughts (plus anyone else who sees this) while I think about it.
It's been a log time, but I finally had a minute to update. I think this is fixed in 0.2.0. Let me know if this is not the case.
In the linked explaination the method to prevent windup was Back calculation. Limiting the the I to a certain value doest prevent windup. Of course it gives a somewhat better results than with no limit - but a more efficient way would be to introduce clamping by pausing the integration in the wrong direction during saturated controller output. For example by placing the following above output clamping in line122: