If statements possibly being scrubbed?

Hi, so I'm trying to program a temperature controlled heater. The heater is attached with mains and is controlled by a solid state relay.

Initially it was just an on/off control at the set temp (target) but now I've tried to add code that switches the relay on and off in differing bursts to reduce the temperature of the heater in an attempt to reduce overshoot.

So for temperature being between 5 and 10 degrees Fahrenheit below the target, the heater switches on for 3 seconds and off for 3 seconds, repeating. For when it is below 10 degrees of the set point its 3 seconds on, 1 second off.

However when I run the code the relay is switching in really odd burst which I believe is a case of all 3 if statements about the temperature are being ignored when it is ran (The temp is below 10 degrees of the target). To test this I added LEDs to the two if statements which switch on. I also changed the if statements to something that should make it not run i.e target < 80 when the target is 90 or 3>2, but it still runs the statements and the LEDs light up.

When I remove two of the if statements for between 10 <x< 5 and 5 <x< 0 below the target, it appears to run correctly (at temp more than 10 below the target)

Please help me spot what is happening, also apologies for my poor form with the code, it's my first ever project using arduino.

#include <MillisTimer.h>


#include <OneWire.h>

#include <LiquidCrystal.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 7

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);

float tempC = 0;
float tempF = 0;
float target = 90;

float ten = 10;
float five = 5;
float zero = 0;

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#define relay 9

const int upButtonPin = 13;
const int downButtonPin = 8;

bool targetChanged = false;


const long interval1 = 50;
const long interval2 = 1000;
const long interval3 = 3000;
const long interval4 = 6000;

unsigned long time_1a = 0;
unsigned long time_1b = 1000;
unsigned long time_2a = 0;
unsigned long time_2b = 3000;
unsigned long time_3a = 0;
unsigned long time_3b = 3000;
unsigned long time_4a = 0;
unsigned long time_4b = 0;


void setup() {
  sensors.begin();
  lcd.begin(16, 2);
  lcd.clear();
  pinMode(3, OUTPUT);
  analogWrite(3, 0);
  Serial.begin(9600);
  pinMode(relay, OUTPUT);
  digitalWrite(relay, LOW);

digitalWrite(10, LOW);
digitalWrite(6, LOW);

  pinMode(upButtonPin, INPUT_PULLUP);
  pinMode(downButtonPin, INPUT_PULLUP);
  pinMode(10, OUTPUT);
   pinMode(6, OUTPUT);
}

void loop() {
  sensors.requestTemperatures();
  tempC = sensors.getTempCByIndex(0);
  tempF = sensors.toFahrenheit(tempC);


  if (tempF + 10 < target) {


    if (millis() >= time_1a + interval3 + interval2) {
      time_1a += interval3 + interval2; //DELAY
      digitalWrite(relay, HIGH); // HEAT OFF
    }


    if (millis() >= time_1b + interval3 + interval2) {
      time_1b += interval3 + interval2;
      digitalWrite(relay, LOW); //HEATING
    }
  }



  if (tempF + 5 < target && target <= tempF + 10); 
digitalWrite(10, HIGH);  // BLUE

    if (millis() >= time_2a + interval3 + interval3) {
      time_2a += interval3 + interval3;
      digitalWrite(relay, HIGH);
    }
    if (millis() >= time_2b + interval3 + interval3) {
      time_2b += interval3 + interval3;
      digitalWrite(relay, LOW);
    }
  

  if (tempF < target && target <= tempF + 5 ); {
digitalWrite(6, HIGH); //RED

    if (millis() >= time_3a + interval4 + interval4) {
      time_3a += interval4 + interval3;
      digitalWrite(relay, HIGH);
    }
    if (millis() >= time_3b + interval3 + interval4) {
      time_3b += interval3 + interval4;
      digitalWrite(relay, LOW);
    }
  }

  if (tempF >= target) {
    digitalWrite(relay, HIGH);
  }
  checkUpButton();
  checkDownButton();
  if (targetChanged != true) {

    Serial.println(tempC);
    lcd.setCursor(0, 0);
    lcd.print("Setpoint = ");
    lcd.print(target);
    lcd.setCursor(0, 1);
    lcd.print("F: ");
    lcd.print(tempF);
    lcd.print(" degrees");
  }
  {
    checkUpButton();
    checkDownButton();
    if (targetChanged == true)
    {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("New setpoint =");
      lcd.setCursor(0, 1);
      lcd.print(target);
      delay (1200);
      lcd.clear();
    }
  }
}

void checkUpButton()
{
  boolean buttonState = 0;         // current state of the button
  static boolean lastButtonState = 0;     // previous state of the button
  static unsigned long timer = 0;
  unsigned long interval = 50;  // check 20 times a second
  if (millis() - timer >= interval)
  {
    timer = millis();

    // read the pushbutton input pin:
    buttonState = digitalRead(upButtonPin);

    // compare the buttonState to its previous state
    if (buttonState != lastButtonState)
    {
      // if the state has changed, increment the counter
      if (buttonState == LOW)
      {
        // if the current state is LOW then the button went from off to on:
        target++;
        targetChanged = true;
      }
      // save the current state as the last state, for next time through the loop
      lastButtonState = buttonState;
    }
  }
}

void checkDownButton()
{
  boolean buttonState = 0;         // current state of the button
  static boolean lastButtonState = 0;     // previous state of the button
  static unsigned long timer = 0;
  unsigned long interval = 50;  // check 20 times a second
  if (millis() - timer >= interval)
  {
    timer = millis();

    // read the pushbutton input pin:
    buttonState = digitalRead(downButtonPin);

    // compare the buttonState to its previous state
    if (buttonState != lastButtonState)
    {
      // if the state has changed, increment the counter
      if (buttonState == LOW)
      {
        // if the current state is LOW then the button went from off to on:
        target--;
        targetChanged = true;
      }
      // save the current state as the last state, for next time through the loop
      lastButtonState = buttonState;
    }
  }
}

Try using serial prints before the if statement so you. Yes YOU!. Can read the states of your thingies.

I found to reduce issues do not mix floats and ints. 10 is a int. 10.0f is a float.

Not here. if you have float tempF = 0.0f; then you can do tempF + 10 and the compiler will do the right thing.

I've not found that to be the case. shrug

This is the wrong way to use milliseconds, as millis() will eventually overflow and nothing will work. Use subtraction instead, e.g.

if (millis() - start_time > interval) {

If TempF is a float, the compiler always promotes "10" to float, in the expression "TempF + 10".

May be in other ways but adding a float and an int is totally OK and defined in the C++ specification.

Conversions
...
Otherwise, if either operand is float, the other operand is converted to float
...

 //if (tempF + 5 < target && target <= tempF + 10); 
// if (tempF < target && target <= tempF + 5 ); 
if (tempF + 5 < target && target <= tempF + 10) 
if (tempF < target && target <= tempF + 5 )

You are wrongly terminating these conditionals with a ;

@cattledog ➜ sharp eyes !

The PID_v1 library includes a useful example where it keeps a heater on for a variable portion of each 5-second interval to keep a steady temperature.

In Tools->Manage Libraries... look for "PID" by Bret Beauregard. After you install it, go to the example:
File->Examples->PID->PID_RelayOutput

Great spot thank you

No, programmer's precision. Read the code with brain on!

1 Like

my brain was definitely on but I did not have my glasses... :slight_smile: