More Help With My Thermostat

My thermostat doesn't switch the relays on and off properly. As best as I can tell the code says to do it the way I want.

What it is supposed to do
Cooling Mode

Turn off the red LED
Turn on the Blue LED
Display the current temp and set temp
If the set temp is higher than the current temp
then turn off the heat relay
turn on the fan relay
turn on the cool relay

if the set temp is lower than the current temp
then turn off the cool relay
turn off the heat relay
turn off the cool relay

Heating Mode

Turn off the blue LED
Turn on the red LED
Display the current and set temp
If the set temp is lower than the current temp
then turn on the fan relay
turn on the heat relay
turn off the cool relay

If the set temp is higher than the current temp
then turn off the heat relay
turn off the fan relay
turn off the cool relay

What it does
Cooling Mode

Current and set temps are displayed
Blue LED comes on and the red LED goes off
if the set temp is lower than the current temp
heat relay comes on
fan relay comes on
cool relay goes off

if the set temp is higher than the current temp
heat relay stays on
cooling relay comes on
fan relay goes off

Heating Mode

Displays current and set temp
Blue LED goes off and red LED comes on
If set temp is lower than current temp
heat relay comes on
fan relay comes on
cool relay stays off

if set temp is higher than current temp
heat relay stays on
fan relay stays on
cool relay stays off

As seen here -----> Trouble with thermostat code (arduino) - YouTube

/* A fair portion of the code here is from Arduinotronics and I would have been lost with out it. This is my first “big” Arduino project. So, there is probably a ton of things that can be improved on and tweeked. I would love to know your thoughts and see your improvements! If you would like to share your thoughts with me on this please email me at modsbyus at modsbyus dot com and make the subject line RE: Arduino Thermostat Thoughts, or write a comment on the tutorial at http://www.modsbyus.com/diy-arduino-thermostat/ */

#include <OneWire.h> //This temperature sensor requires a 4.7k Ohm resistor across its pins 2 and three!!!!
#include <DallasTemperature.h>
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>  // F Malpartida's NewLiquidCrystal library
#define I2C_ADDR    0x20  // Define I2C Address where the PCF8574A is

#define BACKLIGHT_PIN     7
#define En_pin  4
#define Rw_pin  5
#define Rs_pin  6
#define D4_pin  0
#define D5_pin  1
#define D6_pin  2
#define D7_pin  3

#define  LED_OFF  0
#define  LED_ON  1
LiquidCrystal_I2C  lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);


int sensorPin = A0;    // select the input pin for the 10K potentiometer
int sensorValue = 0;  // variable to store the value coming from the sensor
int setTemp = 0; // variable to store temp desired
int SSRCPin = 5; //Turn on A/C unit
int SSRHPin = 6; //Turn on heat (electric or gas)
int hcLED = 4; //indicator for Cooling mode
int SwitchPin = 3; // To switch between Cooling and Heating
int SSRFan = 7; // To turn on and off the air handler fan
char* heat;
float currentTemp = 0;



//This temperature sensor requires a 4.7k Ohm resistor across its pins 2 and three!!!! Thats the middle pin and the GND pin
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

DeviceAddress insideThermometer = { 0x28, 0xAF, 0x51, 0x6C, 0x04, 0x00, 0x00, 0x22 };
// DeviceAddress outsideThermometer = { 0x28, 0x20, 0x04, 0xA8, 0x02, 0x00, 0x00, 0x4D };

void setup(void)
{
// Start up the library
sensors.begin();
// set the resolution to 9 bit (good enough?)
sensors.setResolution(insideThermometer, 9);
// sensors.setResolution(outsideThermometer, 9);

lcd.begin (16,2); // columns, rows. use 16,2 for a 16x2 LCD, etc.
pinMode(SSRFan, OUTPUT); //set airhandler fan pin as output
digitalWrite(SSRFan, LOW);
pinMode(SSRHPin, OUTPUT); 
digitalWrite(SSRHPin, LOW);
pinMode(SSRCPin, OUTPUT); 
digitalWrite(SSRCPin, LOW);
pinMode(hcLED, OUTPUT); 
digitalWrite(hcLED, LOW);
pinMode(SwitchPin, INPUT);
}

void printTemperature(DeviceAddress deviceAddress)
{
  
sensors.requestTemperatures();  // was in loop

float tempC = sensors.getTempC(deviceAddress);
if (tempC == -127.00) {
lcd.print("Error");
} else {
// lcd.print(tempC);
// lcd.print("/");
currentTemp = (DallasTemperature::toFahrenheit(tempC));
lcd.print(currentTemp);
}

}


void loop(void)
{
 
delay(500);

  sensorValue = analogRead(sensorPin);  
  
  setTemp = sensorValue / 10.24; //Gives us a set temp range between 0 and 99 degrees 

//lcd.clear(); // start with a blank screen
lcd.setCursor(0,0);
lcd.print("Current:");
lcd.setCursor(0,1);
lcd.print("Set:");
//lcd.setCursor(0,3);
//lcd.print("Heat: ");



lcd.setCursor(8,0);
printTemperature(insideThermometer);
lcd.setCursor(6,1);
lcd.print(setTemp);
//lcd.setCursor(7,3);
//lcd.print(heat);

//Cooling Mode

  digitalWrite(SSRFan, LOW);
  digitalWrite(SSRHPin, LOW);
  digitalWrite(SSRCPin, LOW);
int val = digitalRead(SwitchPin) ;// val represents digitalRead(SwitchPin);
// If the value of  is 1 then make hcLED low (off) which sets the relay in a normally closed state. Hence, turning on the blue LED.
  if (val == 1)
  {
  digitalWrite(hcLED, LOW);
  }
  
  /* If the SwitchPin reads 1 and the current temperature is greater than the set temperature (if its hot) turn on the A/C and internal fan */
  if (val == 1 && (currentTemp > setTemp))
 { 
  digitalWrite(SSRFan, HIGH);
  digitalWrite(SSRHPin, LOW);
  digitalWrite(SSRCPin, HIGH);
  }
  
  /* Otherwise, if the SwitchPin reads 1 and the current temperature is less than the set temperature (the set temperature has been reached), turn off the A/C and internal fan */
 else if (val == 1 && (currentTemp < setTemp))
 {
   digitalWrite(SSRCPin, LOW);
   digitalWrite(SSRFan, LOW);
   digitalWrite(SSRHPin, LOW);
 }
// Heating Mode

  digitalWrite(SSRFan, LOW);
  digitalWrite(SSRHPin, LOW);
  digitalWrite(SSRCPin, LOW);
// If the value of  is 0 then make hcLED HIGH (on) which sets the relay in a normally open state. Hence, turning on the RED LED
if (val == 0)
  {
  digitalWrite(hcLED, HIGH);
  }
  
  /* If the SwitchPin reads 0 and the current temperature is less than the set temperature (if its cold) turn on the HEAT and internal fan */
  if (val == 0 && (currentTemp < setTemp))
  {
  digitalWrite(SSRFan, HIGH);
  digitalWrite(SSRCPin, LOW);  
  digitalWrite(SSRHPin, HIGH);
  }
  
  /* If the SwitchPin reads 0 and the current temperature is greater than the set temperature (the set temperature has been reached) turn off the HEAT and internal fan */
  else if (val == 0 && (currentTemp > setTemp))
  {
    digitalWrite(SSRHPin, LOW);
    digitalWrite(SSRFan, LOW);
    digitalWrite(SSRCPin, LOW);
}


 }

You are expecting people to spend a lot of time studying your problem. Can you not focus things down to a more specific question?

...R

Robin2:
You are expecting people to spend a lot of time studying your problem. Can you not focus things down to a more specific question?

...R

I have broken my issue down as much as I can. I am having a problem with both the heating section and the cooling section. Basically, What I need help with is the pins stated to go high or low based on the set temp/current temp. They wont do what they're told. I didn't post my entire code because I need help with all of it. Just the parts that turn on/off the SSRCPin, SSRHPin, SSRFPins. The rest is just there in case someone finds that it may be relevant or helpful to the issue. I have given a detailed description of my problem, I hope that helps break down what I need help with.

Is this what you are asking for?
This is the portion of code I need help with.

//Cooling Mode

  digitalWrite(SSRFan, LOW);
  digitalWrite(SSRHPin, LOW);
  digitalWrite(SSRCPin, LOW);
int val = digitalRead(SwitchPin) ;// val represents digitalRead(SwitchPin);
// If the value of  is 1 then make hcLED low (off) which sets the relay in a normally closed state. Hence, turning on the blue LED.
  if (val == 1)
  {
  digitalWrite(hcLED, LOW);
  }
  
  /* If the SwitchPin reads 1 and the current temperature is greater than the set temperature (if its hot) turn on the A/C and internal fan */
  if (val == 1 && (currentTemp > setTemp))
 { 
  digitalWrite(SSRFan, HIGH);
  digitalWrite(SSRHPin, LOW);
  digitalWrite(SSRCPin, HIGH);
  }
  
  /* Otherwise, if the SwitchPin reads 1 and the current temperature is less than the set temperature (the set temperature has been reached), turn off the A/C and internal fan */
 else if (val == 1 && (currentTemp < setTemp))
 {
   digitalWrite(SSRCPin, LOW);
   digitalWrite(SSRFan, LOW);
   digitalWrite(SSRHPin, LOW);
 }
// Heating Mode

  digitalWrite(SSRFan, LOW);
  digitalWrite(SSRHPin, LOW);
  digitalWrite(SSRCPin, LOW);
// If the value of  is 0 then make hcLED HIGH (on) which sets the relay in a normally open state. Hence, turning on the RED LED
if (val == 0)
  {
  digitalWrite(hcLED, HIGH);
  }
  
  /* If the SwitchPin reads 0 and the current temperature is less than the set temperature (if its cold) turn on the HEAT and internal fan */
  if (val == 0 && (currentTemp < setTemp))
  {
  digitalWrite(SSRFan, HIGH);
  digitalWrite(SSRCPin, LOW);  
  digitalWrite(SSRHPin, HIGH);
  }
  
  /* If the SwitchPin reads 0 and the current temperature is greater than the set temperature (the set temperature has been reached) turn off the HEAT and internal fan */
  else if (val == 0 && (currentTemp > setTemp))
  {
    digitalWrite(SSRHPin, LOW);
    digitalWrite(SSRFan, LOW);
    digitalWrite(SSRCPin, LOW);
}

Just looking through those four descriptions and working out what's different between your desired and actual behaviour is hard work. Made harder by the fact you describe them in different orders. After a few minutes of trying to figure out the exact differences I gave up and just concluded it's not working right.

I suggest you pick one scenario where it behaves wrongly and investigate why it's doing what it's doing.

Is your sketch running in the mode you intend?

Is it correctly determining whether the current temp is higher than, lower than or equal to the set temp?

Is it executing the code which you intend to set the output states appropriate for that scenario?

I'd suggest using print statements in your sketch to get answers to the questions above.

Thank you. Ill try using some print statements and see where that takes me. I will also try to clean up the code a bit. Based on my LED indicator, it is in the right mode. Ill post back with updated code and my findings.

You seem to have the code for heating mode immediately following the code for cooling mode without any test to see which state the system is in.

It may make the code easier to follow if you put the actions into separate methods such as

void(tooHot) {
  // do the tooHot switching
}

void(tooCold) {
 // do the tooCold switching
}

And in your main code you could have (rough example) (not sure if my syntax is correct)

if (val == 1) {
   tooHot();
}
else {
  tooCold();
}

PLUS putting in diagnostic print statements as recommended elsewhere.

...R

Robin2:
You seem to have the code for heating mode immediately following the code for cooling mode without any test to see which state the system is in.

It may make the code easier to follow if you put the actions into separate methods such as

void(tooHot) {

// do the tooHot switching
}

void(tooCold) {
// do the tooCold switching
}




And in your main code you could have (rough example) (not sure if my syntax is correct)


if (val == 1) {
   tooHot();
}
else {
  tooCold();
}



PLUS putting in diagnostic print statements as recommended elsewhere.

...R

Ok, So, I got it working before finding your last response. It was that I had some wires swapped on the relays.
However, I really liked your suggestions and followed them. Now I have a new problem.
After following your example, only the first portion of the main loop statement will run. It will not execute the if statements. :astonished:

void loop(void)
{
  Serial.println("Begin main Loop");
 int FanVal = digitalRead(FanPin);
int val = digitalRead(SwitchPin) ;

delay(500);

  sensorValue = analogRead(sensorPin);  
  
  setTemp = sensorValue / 10.24; //Gives us a set temp range between 0 and 99 degrees 

//lcd.clear(); // start with a blank screen
lcd.setCursor(0,0);
lcd.print("Current:");
lcd.setCursor(0,1);
lcd.print("Set:");
//lcd.setCursor(0,3);
//lcd.print("Heat: ");



lcd.setCursor(8,0);
printTemperature(insideThermometer);
lcd.setCursor(6,1);
lcd.print(setTemp);
//lcd.setCursor(7,3);
//lcd.print(heat);
 Serial.print("FanPin: ");
Serial.println(FanVal);
Serial.print("SwitchPin: ");
Serial.println(val);

if (val == 1)
{
 void coolong() ;
}

else if (val == 0)
{
  void heating() ;
}

else if (val == 0 || 1 && FanVal == 1)
{
  void fan() ;
}
Serial.println("Finished Loop... Restarting Loop");
}


//Cooling Mode

void cooling()
{
  Serial.print("Begin Cooling Loop");
int val = digitalRead(SwitchPin) ;// val represents digitalRead(SwitchPin);

// If the value of  is 1 then make hcLED low (off) which sets the relay in a normally closed state. Hence, turning on the blue LED.
  
  digitalWrite(hcLED, HIGH);
  
  
  /* If the SwitchPin reads 1 and the current temperature is greater than the set temperature (if its hot) turn on the A/C and internal fan */
  if (currentTemp > setTemp + 5)
 { 
   
  digitalWrite(SSRFan, HIGH);
  Serial.println("Cooling Mode Fan On, Current Higher than Set");
  digitalWrite(SSRHPin, LOW);
  Serial.println("Cooling Mode Heat Off, Current Higher than Set");
  digitalWrite(SSRCPin, HIGH);
  Serial.println("Cooling Mode Cool On, Current Higher than Set");
  }
  
  /* Otherwise, if the SwitchPin reads 1 and the current temperature is less than the set temperature (the set temperature has been reached), turn off the A/C and internal fan */
 else if (currentTemp < setTemp - 3)
 {
   digitalWrite(SSRFan, LOW);
  Serial.println("End Cooling Mode Fan Off, Current Lower than Set");
  digitalWrite(SSRHPin, LOW);
  Serial.println("End Cooling Mode Heat Off, Current Lower than Set");
  digitalWrite(SSRCPin, LOW);
  Serial.println("End Cooling Mode Cool Off, Current Lower than Set");
 }
}
// Heating Mode

void heating()
{
Serial.print("Begin Heating Loop");
  digitalWrite(hcLED, LOW);
 
  
  /* If the SwitchPin reads 0 and the current temperature is less than the set temperature (if its cold) turn on the HEAT and internal fan */
  if (currentTemp < setTemp - 5)
  {
  digitalWrite(SSRFan, HIGH);
  Serial.println("Heating Mode Fan On, Current Lower than Set");
  digitalWrite(SSRCPin, LOW);  
  Serial.println("Heating Mode Cool Off, Current Lower than Set");
  digitalWrite(SSRHPin, HIGH);
  Serial.println("Heating Mode Heat On, Current Lower than Set");
  }
  
  /* If the SwitchPin reads 0 and the current temperature is greater than the set temperature (the set temperature has been reached) turn off the HEAT and internal fan */
  else if (currentTemp > setTemp + 3)
  {
    digitalWrite(SSRHPin, LOW);
    Serial.println("End Heating Mode heat Off, Current Lower than Set");
    digitalWrite(SSRFan, LOW);
    Serial.println("End Heating Mode Fan Off, Current Lower than Set");
    digitalWrite(SSRCPin, LOW);
    Serial.println("End Heating Mode Fan Off, Current Lower than Set");
}
}
void fan()
{
  Serial.print("Begin Fan Only Loop");

//Fan Only Mode
if (FanVal == HIGH)
{
digitalWrite(SSRFan, HIGH);
}
 }

My Serial Output

Begin main Loop
FanPin: 0
SwitchPin: 1
Finished Loop... Restarting Loop

This declares a prototype for a non-existant function rather than calling one. Get rid of the void and fix the typo:

 void coolong() ;

That did the trick! Thanks for your patients!