This is an open loop PID autotuner using a novel s-curve inflection point test method. Tuning parameters are typically determined in about ½Tau on a first-order system with time delay. Full 5Tau testing and multiple serial output options are provided. See WiKi for test results and more.
This open-loop tuning method is used when the controller action is set to directIP
or reverseIP
. This method works best on processes that respond with an S-shaped reaction curve to a stepped output. Being an open-loop test, there is no setpoint and PID correction involved. The process gain, dead time, time constant and more is determined by doing a shortened step test that ends just after the inflection point has been reached. From here, the apparent maximum PV (input) is mathematically determined and the controller's tuning parameters are calculated. Test duration is typically only ½Tau.
Accurate determination of the inflection point was given high priority for this test method. To accomplish this, a circular buffer for the input readings is created that's sized to 6% of the samples value. The buffer is used as a moving tangent line where the "head" of the tangent is based on the average of all readings in the buffer and the "tail" is based on the oldest instantaneous value in the buffer. The tangent line moves along the reaction curve one sample at a time. The slope of the tangent line is checked at every sample. When the sign of the change in slope changes (i.e. slope goes from increasing to decreasing or from decreasing to increasing), this is the point of inflection (where the tangent turns red here). After 1⁄16 samples has occurred with the new slope direction, then it's known that the point of inflection has been reached. Final calculations are made and the test ends.
-
First, the PID controller is placed in
manual
mode. -
The tuner action is set to
directIP
orreverseIP
, then configure sTune: -
tuner.Configure(inputSpan, outputSpan, outputStart, outputStep, testTimeSec, settleTimeSec, samples);
-
Its expected that the user is already familiar with the controller and can make a rough estimation of what the system's time constant would be. Use this estimate for the
testTimeSec
constant. -
The
samples
constant is used to define the maximum number of samples used to perform the test. To get an accurate representation of the curve, the suggested range is 200-500. -
settleTimeSec
is used to provide additional settling time prior to starting the test. -
inputSpan
andoutputSpan
represent the maximum operating range of input and output. Examples:- If your input works with temp readings of 20C min and 220C max, then
inputSpan = 200;
If the output uses 8-bit PWM and your using its full range, thenoutputSpan = 255;
If the output is digital relay controlled by millis() with window period of 2000ms, thenoutputSpan = 2000;
- If your input works with temp readings of 20C min and 220C max, then
-
outputStart
is the initial control output value which is used for thesettleTimeSec
duration and sample 0. -
outputStep
is the stepped output value used for sample 1 to test completion. -
after test completion, the setup can be updated for the next test and
tuner.Configure()
can be called again.
-
The
outputStep
value is applied at sample 1 and inflection point discovery begins. -
Dead time is determined when the averaged input has increased (or decreased) beyond one resolution value from the starting instantaneous input value.
-
When the point of inflection is reached, the test ends. The apparent
pvMax
is calculated using: -
pvMax = pvIp + slopeIp * kexp; // where kexp = 4.3004 = (1 / exp(-1)) / (1 - exp(-1))
-
The process gain
Ku
and time constantTu
are determined and the selected tuning rule's constants are used to determineKp, Ki, Kd, Ti and Td
. Also,controllability
and other details are provided (see comments insTune.cpp
). -
In the user's sketch, the PID controller is set to automatic, the tuning parameters are applied the PID controller is run.
A full test to pvMax is used when the controller action is set to direct5T
or reverse5T
. Use this method if the IP
testing isn't a good fit to the process or if you'd like to get test data for the complete input response. Here, it is assumed the test will complete at about 3.5τ, from which point the apparent pvMax
is estimated and the tuning parameters are calculated.
sTune(float *input, float *output, TuningRule tuningRule, Action action, SerialMode serialMode);
input
andoutput
are pointers to the variables holding these values.tuningRule
provides selection of 10 various tuning rules as described in the table below.action
provides choices for controller action (direct or reverse) and whether to perform a fast inflection point test (IP) or a full 5 time constant test (5T). Choices aredirectIP
,direct5T
,reverseIP
andreverse5T
.serialMode
provides 6 choices for serial output.
Serial Mode | Description |
---|---|
serialOFF |
No serial output will occur. |
printALL |
Prints test data while settling and during the test run. A summary of results is printed when testing completes. |
printSUMMARY |
A summary of results is printed when testing completes. |
printDEBUG |
Same as printALL but includes printing diagnostic data during test run. |
printPIDTUNER |
➩ Prints test data in csv format compatible with pidtuner.com. ➩ Requires the controller action being set to direct5T or reverse5T ➩ Just copy the serial printer data and import (paste) into PID Tuner for further analysis, model identification, fine PID tuning and experimentation. ➩ Note that Kp , Ti and Td is also provided for PID Tuner. |
printPLOTTER |
Plots pvAvg data for use with Serial Plotter. |
sTune tuner = sTune(&Input, &Output, tuner.ZN_PID, tuner.directIP, tuner.printALL);
/* ZN_PID directIP serialOFF
DampedOsc_PID direct5T printALL
NoOvershoot_PID reverseIP printSUMMARY
CohenCoon_PID reverse5T printDEBUG
Mixed_PID
ZN_PI
DampedOsc_PI
NoOvershoot_PI
CohenCoon_PI
Mixed_PI
*/
This function applies the sTune test settings.
void Configure(const float inputSpan, const float outputSpan, float outputStart, float outputStep,
uint32_t testTimeSec, uint32_t settleTimeSec, const uint16_t samples);
void SetEmergencyStop(float e_Stop);
void SetControllerAction(Action Action);
void SetSerialMode(SerialMode SerialMode);
void SetTuningMethod(TuningMethod TuningMethod);
float GetKp(); // proportional gain
float GetKi(); // integral gain
float GetKd(); // derivative gain
float GetTi(); // integral time
float GetTd(); // derivative time
float GetProcessGain(); // process gain
float GetDeadTime(); // process dead time (seconds)
float GetTau(); // process time constant (seconds)
uint8_t GetControllerAction();
uint8_t GetSerialMode();
uint8_t GetTuningMethod();
void GetAutoTunings(float * kp, float * ki, float * kd);
When the test ends, sTune determines how difficult the process is to control.
float controllability = _Tu / _td + epsilon;