Question about using a relay and the PID Library.

Hi all. I want to use the PID library with a relay. But in the other direction as the result of the relay being on will reduce the input not increase it like with temperature. I know I need to change the value of “DIRECT” to “REVERSE”.
My question is should I also change the > to < in the if statement? “Output > millis()”

The sample code works if I use it to control the temparature but not if I want to go the other diretion.

/********************************************************
 * PID RelayOutput Example
 * Same as basic example, except that this time, the output
 * is going to a digital pin which (we presume) is controlling
 * a relay.  the pid is designed to Output an analog value,
 * but the relay can only be On/Off.
 *
 *   to connect them together we use "time proportioning
 * control"  it's essentially a really slow version of PWM.
 * first we decide on a window size (5000mS say.) we then
 * set the pid to adjust its output between 0 and that window
 * size.  lastly, we add some logic that translates the PID
 * output into "Relay On Time" with the remainder of the
 * window being "Relay Off Time"
 ********************************************************/

#include <PID_v1.h>

#define PIN_INPUT 0
#define RELAY_PIN 6

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

//Specify the links and initial tuning parameters
double Kp=2, Ki=5, Kd=1;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);

int WindowSize = 5000;
unsigned long windowStartTime;

void setup()
{
  windowStartTime = millis();

  //initialize the variables we're linked to
  Setpoint = 100;

  //tell the PID to range between 0 and the full window size
  myPID.SetOutputLimits(0, WindowSize);

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
}

void loop()
{
  Input = analogRead(PIN_INPUT);
  myPID.Compute();

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

}

No, don't change that line. Just the DIRECT/REVERSE direction.

How do you know it doesn't work? What do you observe it doing?

The relay does not come on and it should. Even if I set the Setpoint way below the input it stays off all the time.

The PID is trying to get Input to match Setpoint. The DIRECT mode means "to make Input go higher (like using a heater to control temperature) you increase the value of Output." The REVERSE mode means "to make Input go lower (like using a refrigerator to control temperature) you increase the value of Output."

if (Output > millis() - windowStartTime)
  digitalWrite(RELAY_PIN, HIGH);
else 
  digitalWrite(RELAY_PIN, LOW);

This means "For the first 'Output' milliseconds of the window, set the relay pin HIGH and for the remainder of the window set the relay pin LOW."

WARNING: Most relay modules have Active LOW inputs. That means a LOW turns the relay ON and HIGH turns the relay OFF. The changes the meaning of the code to: "For the first 'Output' milliseconds of the window, set the relay OFF and for the remainder of the window set the relay ON." If turning the relay ON raises the Input you want REVERSE. If turning the relay ON lowers the Input, you want DIRECT.

johnwasser:
The PID is trying to get Input to match Setpoint. The DIRECT mode means “to make Input go higher (like using a heater to control temperature) you increase the value of Output.” The REVERSE mode means “to make Input go lower (like using a refrigerator to control temperature) you increase the value of Output.”

if (Output > millis() - windowStartTime)

digitalWrite(RELAY_PIN, HIGH);
else
 digitalWrite(RELAY_PIN, LOW);




This means "For the first 'Output' milliseconds of the window, set the relay pin HIGH and for the remainder of the window set the relay pin LOW."

WARNING: Most relay modules have Active LOW inputs. That means a LOW turns the relay ON and HIGH turns the relay OFF. The changes the meaning of the code to: "For the first 'Output' milliseconds of the window, set the relay OFF and for the remainder of the window set the relay ON." If turning the relay ON raises the Input you want REVERSE. If turning the relay ON lowers the Input, you want DIRECT.

Hi John. Thanks for the reply. I know the relay is working as I can control it on its own without PID controlling it. I found this thread and in there the OP stated the < was the wrong way around and that is the way the sample is. https://forum.arduino.cc/index.php?topic=142526.0

So that is why I am asking if the > should be the other way around. So I want to drop the temperature by switching on a AC unit. So what way should the <> be as that other post confused me now.

I also sit with an issue that I can not pulse the Air Con pump like you do an SSR. So the on and off times should be long durations not microseconds like when the SSR fires to push up the temperature.

OK I think I know why the relay did not switch on. I made the window size 20000 as my reaction time is 20 seconds. So my P value was 2. I made it 3000 now and now the relay switches on. The correct way of the > < is > and not as in the sample. I still need to figure out a way to stop the relay pulsing the AC Pump. Do I just make the window size even bigger ?