PID not working as expected

Hello,

I’m beginning with arduino and I’m trying to use the PID Adaptive Tuning Example with a relay to control a water heating element but I must be missing something because the PID doesn’t switch between the aggressive and conservative mode.
I want to use this mode to make it reach it’s temperature faster.

I tried mixing the 2 examples we can find on the site:
PID Adaptive
PID relay output example

What should I be looking for to make this work?
Thanks

#include <LiquidCrystal.h>
#include <PID_v1.h>

//LM35 Temperature Sensor
int tempPin = 1;



#define SSRHEAT  12   
#define PUMP  11 

int WindowSize = 5000;
unsigned long windowStartTime;


//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Define the aggressive and conservative Tuning Parameters
double aggKp=200, aggKi=1, aggKd=1;
double consKp=1.4, consKi=220, consKd=55;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, aggKp, aggKi, aggKd, DIRECT);


// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);

  
void setup() { 
  pinMode(SSRHEAT, OUTPUT);
pinMode(PUMP, OUTPUT);


Input = analogRead(tempPin);
 float mv = (Input/1024.0)*5000; 
  float cel = mv/10;
  
Setpoint = 93;

windowStartTime = millis();

  //tell the PID to range between 0 and the full window size
  myPID.SetOutputLimits(0, WindowSize);
  myPID.SetMode(AUTOMATIC);
  
  lcd.begin(16, 2);
lcd.print("Hello");
delay(1000);
  lcd.clear();
}

void loop() {

Input = analogRead(tempPin);
 float mv = (Input/1024.0)*5000; 
  float cel = mv/10;
 float adcel= cel-16;

  double gap = abs(Setpoint-cel); //distance away from setpoint
  
  if (gap<10)
  {  //we're close to setpoint, use conservative tuning parameters
    myPID.SetTunings(consKp, consKi, consKd);
     lcd.setCursor(0, 0);
   
      lcd.print(gap);
     lcd.setCursor(0, 1);
     lcd.print("Temp = "); 
     lcd.print(cel);
     lcd.print(" C"); 
      
  }
  
  else
  {
     //we're far from setpoint, use aggressive tuning parameters
     myPID.SetTunings(aggKp, aggKi, aggKd);
    lcd.setCursor(0, 0);
   
   lcd.print(gap);
     lcd.setCursor(0, 1);
     lcd.print("Temp = "); 
     lcd.print(cel);
     lcd.print(" C");

  }

    myPID.Compute();

  /************************************************
   * turn the output pin on/off based on pid output
   ************************************************/
  unsigned long now = millis();
  if(now - windowStartTime>WindowSize)
  { //time to shift the Relay Window
    windowStartTime += WindowSize;
  }
  if(Output > now - windowStartTime) digitalWrite(SSRHEAT,HIGH);
  else digitalWrite(SSRHEAT,LOW);

   
delay(500);
}

I must be missing something because the PID doesn't switch between the aggressive and conservative mode.

How do you know it doesn't?

You get bonus points for posting your code correctly.
You lose some of them for not properly indenting your code first. (Use Tools + Auto Format).

 float mv = (Input/1024.0)*5000;
  float cel = mv/10;

  double gap = abs(Setpoint-cel); //distance away from setpoint

The name cel does not provide a clue how that is supposed to relate to Setpoint.

Thanks Paul for your reply.

The cel value is the temperature in Celsius.
I found this piece of code when I looked how to get the temperature from the sensor in Celsius.

I added to my code a line that is displayed on the LCD when it is in aggressive mode or conservative,
it correctly changes when we reach the gap limit,
also the gap value between the setpoint and the temperature measured is right.

It seems the part controlling the relay is not working.
For example when I'm testing it, it displays that it is in aggressive mode but the relay isn't activated.
(I tested that the relay is working with the "blink" exemple)

For example when I’m testing it, it displays that it is in aggressive mode but the relay isn’t activated.

What value do you get for Output? Input is the value read from the analog pin (NOT the temperature calculated from the sensor’s measured value. Setpoint is 93, which looks vaguely like a temperature. Given that the input and setpoint are in completely different units, I would not expect much of Output.

How do you think the Output value relates to time?

About the Input and Cel, it was using the raw measured value from the sensor and not the value in Celsius of Cel.

I replaced Input everywhere it was necessary by Cel:

PID myPID(&cel, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);

In the serial console I get the following info:

Input:
165
cel:
80.57
Output:
5000.00

Setpoint is 93°C and the value of cel is the good value of the temperature.

Output reports the value of WindowSize.

Output reports the value of WindowSize.

So, I guess that what that means is that for the next period of time, until you Compute() again, the relay should be on, since the desired temperature has not been met.

I'm not sure that aggressive vs. conservative parameters mean anything, when the relay can be on or off only.

I have a very hard time seeing any advantage in using a PID to control a process as slow as heating water. I would think a simple on/off control with a small hysteresis would work just as well, and be a lot simpler.

Regards,
Ray L.

I was thinking of using that aggressive/conservative function because I want to control the heating of a coffee water boiler, with a standard PID it takes a loooong time to heat as it uses the settings to maintain the temperature during all the heating process.

I tried something like RayLivingston is speaking about and it seems to work.