// include the library code:
//#include <liquidcrystal_i2c.h>
#include <IRremote.h>
//#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include <ezButton.h>
using namespace std;
const int SHORT_PRESS_TIME = 300; // 100 milliseconds
const int LONG_PRESS_TIME = 3000; // 3000 milliseconds
ezButton ONOFFbut(12); // create ezButton object that attach to pin 7;
ezButton TIMERbut(10); // create ezButton object that attach to pin 7;
ezButton Upbut(9); // create ezButton object that attach to pin 7;
ezButton Downbut(8); // create ezButton object that attach to pin 7;
unsigned long ONOFFpressedTime = 0;
unsigned long ONOFFreleasedTime = 0;
unsigned long TIMERpressedTime = 0;
unsigned long TIMERreleasedTime = 0;
unsigned long UppressedTime = 0;
unsigned long UpreleasedTime = 0;
unsigned long DownpressedTime = 0;
unsigned long DownreleasedTime = 0;
unsigned long currentMillis;
// Variables will change:
int yellowState = LOW; // ledState used to set the LED
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousblink = 0; // will store last time LED was updated
// constants won't change:
const long blinkinterval = 1000; // interval at which to blink (milliseconds)
//timer functions
unsigned long StartTime = 0;
unsigned long Interval = 0;
/** the current address in the EEPROM (i.e. which byte we're going to write to next) **/
int address = 0;
// initialize the library with the numbers of the interface pins
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
//inputs
const int TempSensor = 2; // Tempsensor name
const int PIN_RECEIVER = 3; // Signal Pin of IR receiver
const int redPIN = 6; //signal pin for red led
const int yellowPIN = 5; //signal pin for yellow led
const int greenPIN = 4; //signal pin for green led
//Outputs
const byte Relay = 11; // Pin 11 Relay Output
// DS18B20 Temperature chip i/o
//OneWire ds(TempSensor); // TempSensor on pin 2
OneWire ds(TempSensor);
DallasTemperature sensors(&ds);
byte i;
byte present = 0;
byte data[12];
byte addr[8];
word TReading;
byte HighByte, LowByte;
int SignBit, Tc_dec, Tc_100, Whole, Fract;
int HWhole, HFract; //High reading
int LWhole, LFract; //Low reading
boolean Sign, LSign, HSign; //sign for the readings 1= positive
long ReadStartTime;
long ConvTime = 1000; //Time for a conversion to take place at 9 bit resolution
boolean ConvIssued = false; //Signals a reading has been started
int CurrInt, CurrDec;
boolean CurrSign;
String CurrTempDis, CurrIntStr, CurrDecStr;
float CurrTemp;
// General Purpose
int TempReading; // Temp reading as + or - figure
float SetTemp; // Target Temp
boolean AutoMode = false; // system is off to start with
long RelayStatusChange = 0; //timer used to stop flicking the relay on and off too often
long RelayDownTime = 120000; // Downtime before activating therelay again
boolean timerMode= false; // used to tell if user selected timer rather than auto mode
int timerSet = 0; // remaining time for timer mode
long bufferTime = 200000; // allow unit to kick it on startup
//LCD Scrolling message
//Settings
// Button handling variables
int RelaySTATE ;
IRrecv receiver(PIN_RECEIVER);
//------------------------------------------------
void setup()
{
Serial.begin(9600);
digitalWrite(Relay, LOW); // Turn OFF the Relay
pinMode(Relay, OUTPUT);
// set up EEPROM for target temp
address = address + 1;
StartTime = 0;
Interval = 0;
if (address == EEPROM.length()) {
address = 0;
}
SetTemp = EEPROM.read(address) / 10; // recall target temp from EEPROM
if (!SetTemp > 17) {
SetTemp = 18.0;
updateTarget();
}
// set up the LCD's number of rows and columns:
lcd.init(); // initialize the lcd
Wire.begin(); // for the One Wire device
//Serial.begin(57600); // remove the '//' at the start to output to serial
lcd.clear();
lcd.noCursor(); // Tell the library not to flash the cursor
lcd.backlight(); // Turn on the backlight
//Define the pins
pinMode(TempSensor, INPUT);
pinMode(redPIN, OUTPUT);
pinMode(greenPIN, OUTPUT);
pinMode(yellowPIN, OUTPUT);
//digitalWrite(LCDBack, HIGH);
// Print a message to the LCD.
lcd.setCursor(0,0); // First position (0) and first line (0)
lcd.print (" Initialising");
lcd.setCursor(0,1); // First position (0) and second line (1)
lcd.print ("TCLS LOZANO 2024");
delay(1800);
// check the outputs
delay(200);
//digitalWrite(Buzzer, HIGH);
ONOFFbut.setDebounceTime(50); // set debounce time to 50 milliseconds
TIMERbut.setDebounceTime(50); // set debounce time to 50 milliseconds
Upbut.setDebounceTime(50); // set debounce time to 50 milliseconds
Downbut.setDebounceTime(50); // set debounce time to 50 milliseconds
findDevices(); // Call the routine to check if there are any One Wire devices
//LastScroll = millis(); // check the time for the LCD message to be seen
ReadTemp();
//delay(5000-((millis())- (LastScroll))); // this should end up as 1.5 secs
lcd.clear();
//LastScroll=0;
//LCDScrollingMessage();
lcd.setCursor(0,0);
lcd.print("Current:");
Serial.print(SetTemp,1);
receiver.enableIRIn(); // Start the receiver
//RelayStatusChange = 120000;
}
void loop()
/*
This runs after setup and continuously loops or runs
Code can be entered here, or as in this example a means of calling the other routines.
*/
{
ReadTemp(); // Sets ConvIssued. Compares millis() with [ReadStartTime] and [ConvTime] before collecting the reading.
isONOFFPressed(); // Check for a button press (it will call the ProcessButton routine)
isUpPressed(); // Check for a button press (it will call the ProcessButton routine)
isDownPressed(); // Check for a button press (it will call the ProcessButton routine)
isTIMERPressed();
// Checks received an IR signal
if (receiver.decode()) {
translateIR();
receiver.resume(); // Receive the next value
}
//Check_Buttons(); // Check for a button press (it will call the ProcessButton routine)
DisplayTemp(); // Display the current temperature
LEDControl(); // Turn LED on/off
if (AutoMode == true)
{
RelayControl(); // Turn Relay on/off
//Serial.println("Auto mode on");
DisplaySetTemp();
}
else
{
if (timerMode == true)
{
CountDown();
RelayByTimer(); // Turn Relay on/off
//Serial.println("Auto mode on");
DisplayTimer();
}
else
{
lcd.setCursor(0,1);
lcd.print(" OFF ");
} }
}
void ReadTemp()
{
/*
The process of reading the temp involves telling the device to process a reading
There is a setup time between the command and the data being available at the register.
This depends on the resolution, but with the 9 bit resolution it is approx 750mS.
Rather than slow everything down, we issue the command and then return.
When we come back, we check if it has been (long ConvTime = 1000 in mS) between command and current.
If it has we read the register.
*/
if (sensors.getTempC(addr)<0)
{
CurrSign = false;
} else {
CurrSign=true;
}
CurrInt = int(sensors.getTempC(addr));
CurrDec = ((sensors.getTempC(addr) * 100) - (int(sensors.getTempC(addr)) * 100));
if (ConvIssued != true)
{
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion
ConvIssued = true; // We have asked for data
ReadStartTime = millis(); // note the time we asked for temperature (so we know when to come back)
}
if (ConvIssued && (millis() - ReadStartTime) >= ConvTime)
{
/* This is the delay....The program should do the reset, and come back when the time is up.
*/
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
}
else
{
return; //either there was no conversion issued, or time is too soon.
}
for ( i = 0; i < 9; i++) // we need 9 bytes
{
data[i] = ds.read();
}
LowByte = data[0];
HighByte = data[1];
TReading = (HighByte << 8) + LowByte;
SignBit = TReading & 0x8000; // test most sig bit
if (SignBit) // negative
{
Sign = 1;
TReading = (TReading ^ 0xffff) + 1; // 2's comp
}
Tc_100 = (6 * TReading) + TReading / 4; // multiply by (100 * 0.0625) or 6.25
if (SignBit) // negative
{
TempReading = (0 - Tc_100);
}
else
{
TempReading = Tc_100;
}
Whole = Tc_100 / 100; // separate off the whole and fractional portions
Fract = Tc_100 % 100;
// the two lines below force the fraction portion to one (1) decimal place ie 23.7 rather than 23.73
Fract =Fract /10;
Fract = Fract *10;
ConvIssued = false; // means we got a reading back
}
void DisplayTimer()
{
//if (AutoMode == true)
//{
lcd.setCursor(0,1); // First position (0) and second line (1)
lcd.print("OFF in:");
lcd.setCursor(9,1); // First position (0) and second line (1)
if (int(Interval/60000) < 100)
{
if (int(Interval/60000) < 10)
{
lcd.print(" ");
lcd.print(int(Interval/60000));
} else {
lcd.print(" ");
lcd.print(int(Interval/60000));
}
} else {
// lcd.print(" ");
lcd.print(int(Interval / 60000));
}
lcd.print(":");
if (((Interval % 60000) / 1000) < 10)
{
lcd.setCursor(14,1); // First position (0) and second line (1)
lcd.print("0");
lcd.print((Interval % 60000) / 1000);
} else {
lcd.setCursor(14,1); // First position (0) and second line (1)
lcd.print((Interval % 60000) / 1000);
}
Serial.println(int(((Interval / 60000) - (int(Interval / 60000))) * 60));
Serial.println(Interval);
Serial.println(Interval / 60000);
Serial.println((Interval % 60000) / 1000);
//
}
void DisplayTemp()
{
if (CurrDec < 10)
{
CurrDecStr= "0" + CurrDec;
} else {
CurrDecStr = CurrDec;
}
if (CurrInt < 10)
{
CurrIntStr= "0" + CurrInt;
} else {
CurrIntStr = CurrInt;
}
if (CurrSign = false)
{
CurrTempDis = "-" + CurrIntStr + "." + CurrDecStr + "C";
} else {
CurrTempDis = " " + CurrIntStr + "." + CurrDecStr + "C";
}
lcd.setCursor(9,0); // First position (0) and second line (1)
lcd.print(CurrTempDis);
// Serial.println(CurrTempDis);
CurrTemp = (CurrInt + (CurrDec / 100));
// CurrTemp = CurrDec / 100;
}
void RelayByTimer()
{
// digitalWrite(yellowPIN,HIGH); // LED on
if (timerMode == true)
{
// digitalWrite(yellowPIN,HIGH); // LED on
AutoMode = false;
RelaySTATE = digitalRead(Relay);
if (RelaySTATE == 0)
{
digitalWrite(Relay, HIGH);
RelayStatusChange = millis(); //start relay last change timer
bufferTime = 0;
Serial.println("turnned ON via timer");
} else {
// Serial.println("timer ON");
}
}
}
void RelayControl()
{
//Serial.println(sensors.getTempF(addr));
//Serial.println(sensors.getTempC(addr));
RelaySTATE = digitalRead(Relay);
//Relays are ON when the ouput pin is HIGH unless we are setting the temp using the rotarysensor
if (CurrTemp > SetTemp)
{
if ((bufferTime + millis() - RelayStatusChange) > RelayDownTime)
{
Serial.println("RelayStatusChange > RelayDownTime");
Serial.println("CurrTemp > SetTemp");
Serial.println(RelaySTATE);
if (RelaySTATE == 0)
{
digitalWrite(Relay, HIGH);
RelayStatusChange = millis(); //start relay last change timer
bufferTime = 0;
Serial.print("turnned HIGH/ON");
} else {
Serial.print("Already ON");
}
}
} else {
if ((bufferTime + millis() - RelayStatusChange) > RelayDownTime)
{
if (RelaySTATE == 0)
{
Serial.print("Already OFF");
} else {
digitalWrite(Relay, LOW);
RelayStatusChange = millis(); //start relay last change timer
Serial.print("Turned LOW/OFF");
}
}
}
}
void updateTarget()
{
EEPROM.update(address, SetTemp * 10);
Serial.print("EEPROM Updated to ");
Serial.print(SetTemp);
Serial.println("C");
Serial.print("While CurrTemp is ");
Serial.print(CurrTemp);
Serial.println("C");
}
void LEDControl()
{
// This turns on the LED
if (AutoMode == true)
{
digitalWrite(greenPIN,HIGH);
digitalWrite(redPIN,LOW);
// digitalWrite(yellowPIN,HIGH);
} else {
if (timerMode ==true)
{
digitalWrite(greenPIN,HIGH);
digitalWrite(redPIN,LOW);
// digitalWrite(yellowPIN,HIGH);
} else {
digitalWrite(greenPIN, LOW);
digitalWrite(redPIN, HIGH);
}
}
}
void isONOFFPressed()
{
ONOFFbut.loop(); // MUST call the loop() function first
if(ONOFFbut.isPressed())
ONOFFpressedTime = millis();
if(ONOFFbut.isReleased()) {
ONOFFreleasedTime = millis();
long ONOFFpressDuration = ONOFFreleasedTime - ONOFFpressedTime;
// if( ONOFFpressDuration < SHORT_PRESS_TIME )
// Serial.println("A short press is detected");
if( ONOFFpressDuration > LONG_PRESS_TIME )
{
Serial.println("A long press is detected");
if (AutoMode == true)
{
AutoMode = false;
digitalWrite(Relay, LOW);
if (timerMode == true)
{
timerMode = false;
}
digitalWrite(redPIN,HIGH); // LED on
digitalWrite(greenPIN,LOW); // LED on Serial.println("System turned OFF");
} else {
AutoMode = true;
Serial.println("System turned ON");
lcd.setCursor(0,1);
lcd.print(" Turning ON ");
delay(1000);
digitalWrite(redPIN,LOW); // LED on
digitalWrite(greenPIN,HIGH); // LED on
// lcd.clear();
}
} else {
Serial.println("A short press is detected");
}
}
}
void DisplaySetTemp()
{
// this displays the LCD message which is 8 characters long
lcd.setCursor(0,1);
lcd.print("Target: ");
lcd.setCursor(11,1);
lcd.print(SetTemp,1);
lcd.setCursor(15,1);
lcd.print("C");
}
void findDevices()
{
/*
This routine is called once to find any One Wire devices and obtain their address.
Once the address is found it is checked to to see if it is a Temperature Sensor (hex 28 or 0x28)
*/
if ( !ds.search(addr)) {
ds.reset_search();
}
if ( addr[0] != 0x28)
{
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" No Temp Sensor");
lcd.setCursor(0,1);
lcd.print("Check connection");
delay(5000);
return;
}
}
void translateIR()
{
// Checks received an IR signal
// Takes command based on IR code received
switch (receiver.decodedIRData.command) {
case 162:
// lcdPrint("POWER");
Serial.println("A long press is detected");
if (AutoMode == true)
{
AutoMode = false;
digitalWrite(Relay, LOW);
if (timerMode == true)
{
timerMode = false;
}
digitalWrite(redPIN,HIGH); // LED on
digitalWrite(greenPIN,LOW); // LED on Serial.println("System turned OFF");
} else {
AutoMode = true;
Serial.println("System turned ON");
lcd.setCursor(0,1);
lcd.print(" Turning ON ");
delay(1000);
digitalWrite(redPIN,LOW); // LED on
digitalWrite(greenPIN,HIGH); // LED on
}
break;
case 226:
// lcdPrint("MENU");
break;
case 34:
// lcdPrint("TEST");
break;
case 2:
// lcdPrint("PLUS");
SetTemp = SetTemp + 0.5;
updateTarget();
break;
case 194:
// lcdPrint("BACK");
break;
case 224:
// lcdPrint("PREV.");
if (timerMode == true)
{
timerMode = false;
if (RelaySTATE == 0)
{
Serial.print("Already OFF");
} else {
digitalWrite(Relay, LOW);
}
AutoMode = false;
}
break;
case 168:
// lcdPrint("PLAY");
break;
case 144:
// lcdPrint("NEXT");
if (RelaySTATE == 0)
{
StartTime = 0;
}
timerMode = true;
AutoMode = false;
lcd.setCursor(0,1);
lcd.print(" ");
if (StartTime != 0)
{
// Timer already running
Interval += 1800000UL; // Increase the timer Interval by 20 seconds
}
else
{
StartTime = currentMillis;
Interval = 1800000UL; // Start with a 20-second Interval
// digitalWrite(yellowPIN, HIGH); // LED on
}
break;
case 104:
// lcdPrint("num: 0");
break;
case 152:
// lcdPrint("MINUS");
SetTemp = SetTemp - 0.5;
updateTarget();
break;
case 176:
// lcdPrint("key: C");
break;
case 48:
// lcdPrint("num: 1");
break;
case 24:
// lcdPrint("num: 2");
break;
case 122:
// lcdPrint("num: 3");
break;
case 16:
// lcdPrint("num: 4");
break;
case 56:
// lcdPrint("num: 5");
break;
case 90:
// lcdPrint("num: 6");
break;
case 66:
// lcdPrint("num: 7");
break;
case 74:
// lcdPrint("num: 8");
break;
case 82:
// lcdPrint("num: 9");
break;
default:
// lcd.clear();
// lcd.print(receiver.decodedIRData.command);
// lcd.print(" other button");
break;
}
}
void isTIMERPressed()
{
TIMERbut.loop(); // MUST call the loop() function first
currentMillis = millis();
RelaySTATE = digitalRead(Relay);
if(TIMERbut.isPressed())
TIMERpressedTime = millis();
if(TIMERbut.isReleased()) {
TIMERreleasedTime = millis();
long TIMERpressDuration = TIMERreleasedTime - TIMERpressedTime;
// if( ONOFFpressDuration < SHORT_PRESS_TIME )
// Serial.println("A short press is detected");
if( TIMERpressDuration > LONG_PRESS_TIME )
{
if (timerMode == true)
{
timerMode = false;
if (RelaySTATE == 0)
{
Serial.print("Already OFF");
} else {
digitalWrite(Relay, LOW);
}
AutoMode = false;
}
} else {
if (RelaySTATE == 0)
{
StartTime = 0;
}
timerMode = true;
AutoMode = false;
lcd.setCursor(0,1);
lcd.print(" ");
if (StartTime != 0)
{
// Timer already running
Interval += 1800000UL; // Increase the timer Interval by 20 seconds
}
else
{
StartTime = currentMillis;
Interval = 1800000UL; // Start with a 20-second Interval
// digitalWrite(yellowPIN, HIGH); // LED on
}
}
}
}
void CountDown()
{
unsigned long currentblink = millis();
if (currentblink - previousblink >= blinkinterval) {
// save the last time you blinked the LED
previousblink = currentblink;
// if the LED is off turn it on and vice-versa:
if (yellowState == LOW) {
yellowState = HIGH;
Interval -= 1000;
} else {
yellowState = LOW;
Interval -= 1000;
}
// set the LED with the ledState of the variable:
digitalWrite(yellowPIN, yellowState);
}
}
void isUpPressed()
{
Upbut.loop(); // MUST call the loop() function first
if(Upbut.isPressed())
UppressedTime = millis();
if(Upbut.isReleased()) {
UpreleasedTime = millis();
long UppressDuration = UpreleasedTime - UppressedTime;
// if( UppressDuration < SHORT_PRESS_TIME )
// Serial.println("A short press is detected");
// code to execute on long or short press
SetTemp = SetTemp + 0.5;
updateTarget();
if( UppressDuration > LONG_PRESS_TIME )
{
} else {
}
}
}
void isDownPressed()
{
Downbut.loop(); // MUST call the loop() function first
if(Downbut.isPressed())
DownpressedTime = millis();
if(Downbut.isReleased()) {
DownreleasedTime = millis();
long DownpressDuration = DownreleasedTime - DownpressedTime;
// if( DownpressDuration < SHORT_PRESS_TIME )
// Serial.println("A short press is detected");
// code to execute on long or short press
SetTemp = SetTemp - 0.5;
updateTarget();
if( DownpressDuration > LONG_PRESS_TIME )
{
} else {
}
}
}