PID + Relay Temperature Control

Hello Dear Friends :v:
I am trying to Create PID Temperature Relay Control for Gas Water Heater
I am Using this Skech :

#include <PID_v1.h>

// Libraries for the DS18B20 sensor
#include <OneWire.h>
#include <DallasTemperature.h>

// DS18B20 on PIN 6 on the Arduino
#define ONE_WIRE_BUS D7

//Solid state relay on PIN 5 on the Arduino
#define RELAY_PIN D1

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

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

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

int WindowSize = 10000;
unsigned long windowStartTime;

void setup()
{
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);
  Serial.begin(115200);
  Serial.println("Starting");
  windowStartTime = millis();

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

  //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()
{
  sensors.requestTemperatures();
  Input = sensors.getTempCByIndex(0);
  Serial.print("Temperature: ");
  Serial.println(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);

}

Problem :
When Relay turning on, sometimes turned on state too short, and water heater don't have a time to turn gas for heat water

Question :

How make delay for save RELAY state HIGH for 5 second

Thank you !

could you simply add a delay() for 5 seconds, e.g.

if (Output < millis() - windowStartTime) {
    digitalWrite(RELAY_PIN, HIGH);
   delay(5000);
}

PID seems like overkill for an application like this.

1 Like

yes, but how it will affect to PID ? (

PID's are more suitable when you have "analog" inputs and outputs. For example, if you had a valve that controls the gas flow to control temperature then a PID would be ideal as it would find the ideal gas flow to maintain a constant temperature.

What you are trying to do is to turn something on or off (digital) using a PID, which is not something it can do very well because neither the ON nor the OFF position holds the temperature setpoint. It is doable, but you have set delays and other code to prevent over-reactions.

As someone suggested, it would be more accurate and easier to have simple IF-statements that turns on your heater when the temperature is lower than your min target and turns it off when higher than your high value.

1 Like

Let's assume the PID is set up and tuned appropriately. The "analog" output of your PID is a digital output operating with a time proportioned window set to 10000ms. However, you need 5000ms for the water heater to turn on.

Perhaps something like this could work (untested)...

#include <PID_v1.h>

// Libraries for the DS18B20 sensor
#include <OneWire.h>
#include <DallasTemperature.h>

// DS18B20 on PIN 6 on the Arduino
#define ONE_WIRE_BUS D7

//Solid state relay on PIN 5 on the Arduino
#define RELAY_PIN D1

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

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

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

int WindowSize = 10000;
unsigned long windowStartTime;

// heater startup
const word heaterStartMs = 5000;
bool heaterStartup = false;
double prevOutput = 0;
unsigned long prevMs = 0;
unsigned long currentMs, elapsedMs;


void setup()
{
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW);
  Serial.begin(115200);
  Serial.println("Starting");
  windowStartTime = millis();

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

  //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()
{
  currentMs = millis();
  elapsedMs = (currentMs - prevMs);

  if (Output == 0) heaterStartup = false;
  if (prevOutput == 0 && Output) {
    heaterStartup = true;
    prevMs = currentMs;
  }

  sensors.requestTemperatures();
  Input = sensors.getTempCByIndex(0);
  Serial.print("Temperature: ");
  Serial.println(Input);
  prevOutput = Output;
  myPID.Compute();

  if (elapsedMs >= heaterStartMs) {

    /************************************************
       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);
  }
}
1 Like

I agree with you for 100% , i will try to get analog valve for gas , if you now can you recommend some valve for me ?

By the way

I am warming water with gas , then hot water go to radiator and air flow through in it

This sketch working , i launch it and after 5-7 min i get stable output on Air output

But i understand , this method control with Relay is not good

Thank you

Thank you dear dlloyd, Tomorrow I will try this sketch and let you now

The code by dlloyd should work with your sketch if you want to keep using the existing valve.

As far as a valve, I'm not sure where to get one, but you are looking for a "Proportional Fluid Valve". It might take time to find one.

As a safety feature, you also need a propane-specific shut-off valve in line with the proportional valve to achieve a 100% closed state.

1 Like

Gas-burning water heaters typically use off-on cycles typically use frequencies on the scale of minutes rather than milliseconds because much of the energy is wasted in the start up- and shut-down periods, and the heaters are designed for maximum efficiency at a certain flame level. You probably won't be able to find an analog valve. Some PID temperature controllers typically have an adjustable period of 0-9999 seconds to reduce the number of cycles.

1 Like

You must not try and fit a valve that varies the gas rate to the boiler -that is not permitted in most countries .

PID control won’t work because of the huge lags in the system and the stored heat in the water radiators and the non linear response of the system ( it takes more heat to heat the house if it’s colder outside ) . Also you have multiple rooms …
You are better off with ON/OFF control
And looking at optimal start systems based on looking at outside temperature and/or backing off the set point based on rate of temperature rise or varying the circulating water temperature ( boiler set point)ba based d on outside temperature

1 Like

I've used PID temperature controllers on gas for 500 gallon and 10000 gallon tanks. You need to match the system time constant to the PID time constant, and switching frequency. PID wth kp=large, ki=0, kd=0 degenerates to ON/OFF control, you can change the PID setpoint based on ambient temp and time, etc. PID is terrible if you don't match the sampling/update time to the process.

Heating a tank is different to heating a house tho - as the stored heat in the rads continues to heat the house when they are off and the rate of rise in temperature of the house varies with outside temperature - so
Lags are huge and loop gain varies with outside temperature .
You also have different rooms - where does your measured temperature reside ? .

( big lags in the system means you have to make the loop response very slow )

Time delay for heater - 5 second didn't work , its turning on and off when its want, but its ok, because, how I see, after some time the sketch what I have posted hire, in first post, learning it self to how much time save Relay state on for correct working...

After around 5 min PID correctly working and I get correct temperature from my Heating System Air output

Problem :
But gas water heating system turning on and off around 10 times in 1 minute
(I now why its happaning, because heater power is more then need for this heat dissipation)

Of course I can calibrate gas valve manualy, but what will be if gas pressure will change ? or heat dissipation will be changed ?

So I decided to add Valve for control gas flow (PWM) in my setup with solenoid(on/off, Relay) -

And do next thing with logic :

After that when PID will be configured, and system will work stable, I will count gas heater turn on/off quantity (in 1 minute for examle) and if it will be more than 0 then I will give signal to gas flow walve to decrease angle( decrease gas flow) to permissible minimum, then I will compare the temperature If output is same with setpoint , if yes then go drink beer, if no then( and it will be less than setpoint) then, increase gas flow

So What you think about that guys ?

P.S. If its good idea, I need help to write this code :smiley:

Thank you !

How fast do you want it to turn things on and off in a minute?

If the system heats up too fast for your liking, one good answer is to change your heater to a smaller heater. If a relay lasts 100K cycles at rated load, a 10 cycle per minute design divides out to be less than 4 days of operation.

Pics, code and schematic?

I don't want to do it fast, I didn't say that, As I say in previous post , I want to make minimum switchings, for save live for components, and to make stable working of system

I'm asking how fast you want to make switchings. Once per minute? Once per 10 minutes? The water heater in my house holds 40 gallons, and does not overheat with minutes of operation of its 34kBTU gas burner. A properly sized heater should hold the designed temperature when running at 100% duty cycle at the minimum designed ambient temperature.

1 Like

minumum times , 0 if it posible

As I say :

But gas water heating system turning on and off around 10 times in 1 minute
(I now why its happaning, because heater power is more then need for this heat dissipation)

Of course I can calibrate gas valve manualy, but what will be if gas pressure will change ? or heat dissipation will be changed ?

Do not alter the appliance by adding a control valve on the gas supply to it - This can be dangerous and possibly illegal ( depending which country you are in) . ( it may fail to light correctly , might make CO etc ) . Boiler going on /off many times a minute Can also be dangerous ( burner not stabilising and clearing startup flue products before going off , condensation etc etc )

Look at where your temperature sensor is - the outlet (air?) temperature is not the temperature of the room - if the boiler sees hot air it will switch off .

As I said this isn’t really a good PID application , hard to get working and an over kill. It’s not a fix for a badly matched boiler either !

2 Likes

So 6 seconds is too fast, and something like 86400 or more is a target.

How strong is your burner, in numbers? My electric stove controls a 7000BTU coil with about a 10s cycle. My 40gal water heater's burner is 35,500BTU. If I wanted it to cycle 10x faster on something similar, I'd need a 350,000BTU burner, or if I'd want 10x slower, I might test a 3,500BTU burner, and see if it was strong enough to achieve and maintain temperature. I doubt that it would be possible to modulate the gas pressure/flow to produce efficient, safe flames at large heat ratios.

You should size the burner to the task, rather than attempt modulate the gas to the burner from, for example, a 35,500BTU 6 second burn cycle down to a 350BTU 600 second burn.

1 Like