SimpleStat Thermostat Platform v1-02

Hello all, I have been working on a project for a while, and figured it was far enough along to be added to the gallery. I finished the final revision of the code for version 1.02 of SimpleStat, the thermostat setup meant for an Arduino, for this I used a Mega 2560. All the parts are very common with the exception of a digital temperature module, a DS18B20 (Datasheet). I got this sensor module from a 37 Sensor Kit from Amazon for about $25. Anyway, this is a project I made simply out of boredom with no real purpose to me. Below is the code and attached is the parts list, and a Fritzing breadboard layout. Becuase I've heard a lot about preferring schematics over layouts I also took the time to put together a schematic and put that below as well. For this project, I also used a different IDE, PROGRAMINO, which is a paid IDE for Arduino. I am currently on the trial but I plan to buy and I recommend it for any partially advanced users, I do not recommend it for beginners though as it is quite a bit more complicated.

The Code:

/******************************************************************
 Created on 10.07.2016 at 15:30:45
 Project     : Arduino SimpleStat v1.02
 Libraries   : LiquidCrystal, DallasTemperature, OneWire
 Author      : Michael P. (Mike4449)
 Description : Simple thermostat for various applications, measured in Celsius
 License     : Creative Commons Attribution 2.0 Generic (CC BY 2.0)
 Part List   : See parts.txt
******************************************************************/

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

//Custom characters for the LCD
byte sys_COOL[8] = {
  0b00000,
  0b01110,
  0b01000,
  0b01000,
  0b01000,
  0b01110,
  0b00000,
  0b00000
};

byte sys_HEAT[8] = {
  0b00000,
  0b01010,
  0b01010,
  0b01110,
  0b01010,
  0b01010,
  0b00000,
  0b00000
};

byte sys_IDLE[8] = {
  0b00000,
  0b01110,
  0b01010,
  0b01010,
  0b01010,
  0b01110,
  0b00000,
  0b00000
};

byte sys_SYMBOL[8] = {
  0b11100,
  0b10100,
  0b11100,
  0b00000,
  0b00000,
  0b00000,
  0b00000,
  0b00000
};

byte fan_OFF[8] = {
  0b00000,
  0b00100,
  0b00100,
  0b11111,
  0b00100,
  0b00100,
  0b00000,
  0b00000
};

byte fan_ON[8] = {
  0b00000,
  0b00010,
  0b10100,
  0b01110,
  0b00101,
  0b01000,
  0b00000,
  0b00000
};

//Variables to increase readability later on
const uint8_t COOL = 0;
const uint8_t HEAT = 1;
const uint8_t OFF = 2;
const uint8_t SYMBOL = 3;
const uint8_t fanOFF = 4;
const uint8_t fanON = 5;

//Setup the LCD and the sensors
OneWire oneWire(22); // The temperature sensor is on pin 22
DallasTemperature tempSensor(&oneWire);

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//The circuit components
const uint8_t GRN_LED = 51;
const uint8_t TEMP_SET = A14;
const uint8_t HEAT_PIN = 23;
const uint8_t COOL_PIN = 24;

//Control the min/max temperature settings in Celsius
const uint8_t MIN = 7;
const uint8_t MAX = 33;

void setup() {
  lcd.begin(16, 2);
  tempSensor.begin();

  lcd.createChar(COOL, sys_COOL);
  lcd.createChar(HEAT, sys_HEAT);
  lcd.createChar(OFF, sys_IDLE);
  lcd.createChar(SYMBOL, sys_SYMBOL);
  lcd.createChar(fanOFF, fan_OFF);
  lcd.createChar(fanON, fan_ON);

  pinMode(GRN_LED, OUTPUT);
  pinMode(TEMP_SET, INPUT);
  pinMode(HEAT_PIN, OUTPUT);
  pinMode(COOL_PIN, OUTPUT);

  lcd.print("Starting");
}

void loop() {
  static uint8_t setTemp;
  static uint8_t curTemp;
  static boolean COOLING = false;
  static boolean HEATING = false;
  static boolean OFF = false;
  static boolean counter = 0; // so the mode does not switch all the time

  setTemp = getSet();
  curTemp = getCur();

  //Run the two values through an 'if-statement filter' to decide what to do
  if (curTemp < setTemp) {
    HEATING = true;
    COOLING = false;
    OFF = false;
  }
  else if (curTemp > setTemp) {
    HEATING = false;
    COOLING = true;
    OFF = false;
  }
  else if (curTemp == setTemp) {
    HEATING = false;
    COOLING = false;
    OFF = true;
  }
  else {
    HEATING = false;
    COOLING = false;
    OFF = true;    
  }

  updateLCD(HEATING, COOLING, OFF, curTemp, setTemp); // show data on the LCD

  delay(1000);
  counter++;

  if (counter == 300) { // will happen every 5 min or so, stops the stat from bouncing between modes while allowing the LCd to update
    updateStat(HEATING, COOLING, OFF);
  }
}

uint8_t getSet() {
  uint16_t rawRead = analogRead(TEMP_SET);
  uint8_t newRead;

  newRead = map(rawRead, 0, 1023, MIN, MAX);

  return newRead;
}

uint8_t getCur() {
  tempSensor.requestTemperatures();

  uint8_t tempNow = tempSensor.getTempCByIndex(0);

  return tempNow;
}

void updateStat(boolean heat, boolean cool, boolean off) {
  if (heat) {
    digitalWrite(HEAT_PIN, HIGH);
    digitalWrite(COOL_PIN, LOW);
    digitalWrite(GRN_LED, HIGH);
  }
  else if (cool) {
    digitalWrite(HEAT_PIN, LOW);
    digitalWrite(COOL_PIN, HIGH);
    digitalWrite(GRN_LED, HIGH);
  }
  else if (off) {
    digitalWrite(HEAT_PIN, LOW);
    digitalWrite(COOL_PIN, LOW);    
    digitalWrite(GRN_LED, LOW);
  }
}

void updateLCD(boolean heat, boolean cool, boolean off, uint8_t temp, uint8_t set) {
  lcd.clear();

  lcd.print("SET: ");
  lcd.print(set);
  lcd.write((byte)SYMBOL);
  lcd.print("C");

  lcd.setCursor(0, 1);
  lcd.print("CUR: ");
  lcd.print(temp);
  lcd.write((byte)SYMBOL);
  lcd.print("C");

  // update the fan symbol, is it on or off?
  lcd.setCursor(14 ,0);
  if (off == false) {
    lcd.write((byte)fanON);
  }
  else {
    lcd.write((byte)fanOFF);
  }

  // update the mode symbol, what mode is it in?
  lcd.setCursor(15, 0);
  if (heat) {
    lcd.write((byte)HEAT);
  }
  else if (cool) {
    lcd.write((byte)COOL);
  }
  else if (off) {
     lcd.write((byte)OFF);  
  }  

  // update the mode text, what is the mode?
  if (heat) {
    lcd.setCursor(12, 1);
    lcd.print("HEAT");
  }
  else if (cool) {
    lcd.setCursor(12, 1);
    lcd.print("COOL");
  }
  else if (off) {
    lcd.setCursor(13, 1);
    lcd.print("OFF");  
  }      
}

SimpleStat_v1-02.ino (5.07 KB)

parts.txt (200 Bytes)