|
| 1 | +/****************************************************************************** |
| 2 | + AutoTune Filter REVERSE Example |
| 3 | + Reference: https://github.com/Dlloydev/QuickPID/wiki/AutoTune |
| 4 | + Circuit: https://github.com/Dlloydev/QuickPID/wiki/AutoTune_RC_Filter |
| 5 | + ******************************************************************************/ |
| 6 | + |
| 7 | +#include "QuickPID.h" |
| 8 | + |
| 9 | +const byte inputPin = 0; |
| 10 | +const byte outputPin = 3; |
| 11 | + |
| 12 | +const int inputMax = 1023; |
| 13 | +const int outputMax = 255; |
| 14 | +const int outputMin = 0; |
| 15 | + |
| 16 | +float POn = 1.0; // mix of PonE to PonM (0.0-1.0) |
| 17 | + |
| 18 | +bool printOrPlotter = 0; // on(1) monitor, off(0) plotter |
| 19 | +byte tuningRule = 1; // see reference link |
| 20 | +byte outputStep = 1; |
| 21 | +byte hysteresis = 1; |
| 22 | +int setpoint = 341; // 1/3 of 10-bit ADC range for symetrical waveform |
| 23 | +int output = 85; // 1/3 of 8-bit PWM range for symetrical waveform |
| 24 | + |
| 25 | +float Input, Output, Setpoint; |
| 26 | +float Kp = 0, Ki = 0, Kd = 0; |
| 27 | + |
| 28 | +QuickPID _myPID = QuickPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, POn, QuickPID::REVERSE); |
| 29 | + |
| 30 | +void setup() { |
| 31 | + Serial.begin(115200); |
| 32 | + Serial.println(); |
| 33 | + if (constrain(output, outputMin, outputMax - outputStep - 5) < output) { |
| 34 | + Serial.println(F("AutoTune test exceeds outMax limit, check output, hysteresis and outputStep values")); |
| 35 | + while (1); |
| 36 | + } |
| 37 | + _myPID.AutoTune(tuningRule); |
| 38 | + _myPID.autoTune->autoTuneConfig(outputStep, hysteresis, inputMax - setpoint, output, QuickPID::REVERSE, printOrPlotter); |
| 39 | +} |
| 40 | + |
| 41 | +void loop() { |
| 42 | + |
| 43 | + if (_myPID.autoTune->autoTuneLoop() != _myPID.autoTune->RUN_PID) { // running autotune |
| 44 | + Input = inputMax - avg(_myPID.analogReadFast(inputPin)); // filtered input (reverse acting) |
| 45 | + analogWrite(outputPin, Output); |
| 46 | + } |
| 47 | + |
| 48 | + if (_myPID.autoTune->autoTuneLoop() == _myPID.autoTune->NEW_TUNINGS) { // get new tunings |
| 49 | + _myPID.autoTune->setAutoTuneConstants(&Kp, &Ki, &Kd); // set new tunings |
| 50 | + _myPID.clearAutoTune(); // releases memory used by AutoTune object |
| 51 | + _myPID.SetMode(QuickPID::AUTOMATIC); // setup PID |
| 52 | + _myPID.SetTunings(Kp, Ki, Kd, POn); // apply new tunings to PID |
| 53 | + Setpoint = 500; |
| 54 | + } |
| 55 | + |
| 56 | + if (_myPID.autoTune->autoTuneLoop() == _myPID.autoTune->RUN_PID) { // running PID |
| 57 | + if (printOrPlotter == 0) { // plotter |
| 58 | + Serial.print("Setpoint:"); Serial.print(Setpoint); Serial.print(","); |
| 59 | + Serial.print("Input:"); Serial.print(Input); Serial.print(","); |
| 60 | + Serial.print("Output:"); Serial.print(Output); Serial.println(); |
| 61 | + } |
| 62 | + Input = inputMax - _myPID.analogReadFast(inputPin); // reverse acting |
| 63 | + _myPID.Compute(); |
| 64 | + analogWrite(outputPin, Output); |
| 65 | + } |
| 66 | +} |
| 67 | + |
| 68 | +float avg(int inputVal) { |
| 69 | + static int arrDat[16]; |
| 70 | + static int pos; |
| 71 | + static long sum; |
| 72 | + pos++; |
| 73 | + if (pos >= 16) pos = 0; |
| 74 | + sum = sum - arrDat[pos] + inputVal; |
| 75 | + arrDat[pos] = inputVal; |
| 76 | + return (float)sum / 16.0; |
| 77 | +} |
0 commit comments