Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Big overshoot in tuning with NoOvershoot_PID #24

Open
Nailik opened this issue Sep 30, 2022 · 1 comment
Open

Big overshoot in tuning with NoOvershoot_PID #24

Nailik opened this issue Sep 30, 2022 · 1 comment

Comments

@Nailik
Copy link

Nailik commented Sep 30, 2022

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 Nailik changed the title Heater never turned off Big overshoot in tuning with NoOvershoot_PID Sep 30, 2022
@FelixWT
Copy link

FelixWT commented Feb 6, 2023

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants