br3ttb / Arduino-PID-Library

1.93k stars 1.11k forks source link

Output is nan after several hours of successful running #118

Open bellabrez opened 2 years ago

bellabrez commented 2 years ago

Full code is 20220308_my_working_kiln_more_logging_reduce_memory.zip but most relevant bits pasted here. I'm controlling a relay to heat a kiln, and it works perfectly for a few hours, but then after about 3 or 5 hrs Output (here variable is pidOutput) keeps being nan.

In variables section:

#include <PID_v1.h>
const int pidCycle = 2500;             // Time for a complete PID on/off cycle for the heating elements (ms)
double pidInput;             // Input for PID loop (actual temp reading from thermocouple). 
double pidOutput;            // Output for PID loop (relay for heater).
double pidSetPoint;          // Setpoint for PID loop (temp you are trying to reach). 
PID pidCont = {PID(&pidInput, &pidOutput, &pidSetPoint, 800, 47.37, 4.93, DIRECT)};

Setup run once:

void setupPIDs() {
    pidCont.SetSampleTime(pidCycle);
    pidCont.SetOutputLimits(0, pidCycle);
    pidCont.SetMode(AUTOMATIC);
}

Update loop:

    // Update PID's / turn on heaters / update segment info
    if (screenNum < 4) {
      if (millis() - pidStart >= pidCycle) {
        pidStart = millis();
        updatePIDs();
      }
      htrControl();
      updateSeg();
    }

updatePIDs basically just calls pidCont.Compute();

Turn on heaters:

void htrControl() {
  if (pidOutput >= millis() - pidStart) {
    digitalWrite(heaterPin, HIGH);
  }
  else {
    digitalWrite(heaterPin, LOW);
  }
}

I've confirmed pidInput and pidSetPoint are behaving correctly. I'm using an Arduino Uno and am using 79% of program storage and 74% of dynamic memory (at 75% it says warning low memory, may cause stability issue) - not sure if being close to this limit could be my issue.

I've reproduced this issue about 5 times now, but once it did run the full ~10hr with no nans.

Thank you very much for your thoughts!

T81 commented 2 years ago

I do not have something to comment about since I haven't run into something similar. But I can confirm that I have successfully run multiple PIDs in the same program (>5), for days. I use this library since its birth. I am very interested to learn the cause of your issue.

TuxLeon commented 2 years ago

Just a few comments on your code:

  1. The PID Controller is just a small part of your code. Why do you think the error is in PID code?
  2. Your calculation of pidSetPoint looks very complicated and a potential source of this error.
  3. The usage of pidCycle in pidCont.SetOutputLimits(0, pidCycle); makes logicaly no sense for me.
  4. This kind of code if (millis() - pidStart >= pidCycle) is already included in teh PID-Lib unsigned long timeChange = (now - lastTime); if(timeChange>=SampleTime) ... The SampleTime is set to 100ms in PID code. Does this fit with your concept?
drf5n commented 1 year ago

In an Input was ever a nan, it will propagate through into Output and persist. You can check and protect against it in userspace before your compute step:

if(isnan(pidOutput)){
   pidCont.setMode(MANUAL);
   pidOutput = 0;
   pidCont.setMode(AUTOMATIC); // bumpless reset of the PID internal values to match Output.
}