sTune icon indicating copy to clipboard operation
sTune copied to clipboard

Big overshoot in tuning with NoOvershoot_PID

Open Nailik opened this issue 1 year ago • 1 comments

Hi,

i use a relay to power a heater but it seems that the relay is never turned off.

I tried it with various settings at the moment following (not really sure what the best values would be):

// user settings
uint32_t Pid::settleTimeSec = 10;
uint32_t Pid::testTimeSec = 200;  // runPid interval = testTimeSec / samples
const uint16_t Pid::samples = 1000;
const float Pid::inputSpan = 1000;
const uint32_t Pid::outputSpan = 10;
float Pid::outputStart = 0;
float Pid::outputStep = 1000;
float Pid::tempLimit = 100;
uint8_t Pid::debounce = 0;

// variables
float Pid::Input;
float Pid::Output;
float Pid::SetPoint = 80;
float Pid::Kp;
float Pid::Ki;
float Pid::Kd;

//setup
    tuner.Configure(inputSpan, outputSpan, outputStart, outputStep, testTimeSec, settleTimeSec, samples);
    tuner.SetEmergencyStop(tempLimit);

//loop
        tuner.softPwm(PIN_RELAY, Input, Output, SetPoint, outputSpan, debounce);
        status = tuner.Run();

        switch (status) {
            case tuner.sample: // active once per sample during test
                Input = Sensors::temp_1; // get degC (using 3.3v AREF)
                break;
            case tuner.tunings: // active just once when sTune is done
                tuner.GetAutoTunings(&Kp, &Ki, &Kd); // sketch variables updated by sTune
                quickPid.SetOutputLimits(0, outputSpan);
                quickPid.SetSampleTimeUs((testTimeSec * 1000000) / samples);
                Output = 0;
                quickPid.SetMode(QuickPID::Control::automatic); // the PID is turned on
                quickPid.SetProportionalMode(QuickPID::pMode::pOnMeas);
                quickPid.SetAntiWindupMode(QuickPID::iAwMode::iAwClamp);
                quickPid.SetTunings(Kp, Ki, Kd); // update PID with the new tunings
                break;
            case tuner.runPid: // active once per sample after tunings
                Input = Sensors::temp_1; // get degC (using 3.3v AREF)
                quickPid.Compute();
                break;
            default:
                break;
        }

Even when the emergency stop heat is reached the relay is still on.

sec: 105.2992  out: 1000.00  pv: 90.200  pvPk: 76.317  pvPkCount: 0  ipCount: 1  tan: 14.517 ⚠ ↘

 sec: 106.5091  out: 1000.00  pv: 90.600  pvPk: 76.797  pvPkCount: 0  ipCount: 1  tan: 14.497 ⚠ ↘

 sec: 107.7191  out: 1000.00  pv: 91.000  pvPk: 77.275  pvPkCount: 0  ipCount: 1  tan: 14.475 ⚠ ↘

 sec: 108.9292  out: 1000.00  pv: 91.500  pvPk: 77.753  pvPkCount: 0  ipCount: 1  tan: 14.553 ⚠ ↗

 sec: 110.1392  out: 1000.00  pv: 91.800  pvPk: 78.230  pvPkCount: 0  ipCount: 1  tan: 14.430 ⚠ ↘

 sec: 111.3492  out: 1000.00  pv: 92.300  pvPk: 78.705  pvPkCount: 0  ipCount: 1  tan: 14.405 ⚠ ↘

Nailik avatar Sep 30 '22 17:09 Nailik

Maybe change this

quickPid.SetProportionalMode(QuickPID::pMode::pOnMeas);

to this quickPid.SetProportionalMode(QuickPID::pMode::pOnError);

According to the graph that br3ttb wrote in his blog: image The temperature PID isn't suitable for p Means

Also your setting is very odd

const uint32_t Pid::outputSpan = 10; float Pid::outputStep = 1000;

According to your settings you want to turn on relay for 1000ms in 10ms control window, this will lead to: relay always turn on

hope this make you understand what these variables meant

// Prefix Time(sec)
uint32_t settleTimeSec = 5;
// Test Span(sec)
uint32_t testTimeSec = 5000;
// Amount of Samples within Test Span
uint16_t samples = 10000;
// Δ °C to Target Temperature
float inputSpan;
// Full Control Span
float outputSpan = 2000;
// Heat Up Span Within Prefix Time
float outputStart = 0;
// Heat Up Span Within Control Span
float outputStep = 100;

hope this help

FelixWT avatar Feb 06 '23 03:02 FelixWT