This isn't boring. It is the common "thank you" to post a working code.
very old programmers wisdom:
a code is never finished a code is maximum just working (most of the time)
This isn't boring. It is the common "thank you" to post a working code.
very old programmers wisdom:
a code is never finished a code is maximum just working (most of the time)
Is this issue fixed with the latest code you posted?
Evening @cattledog, Yes, the recent deep thoughts along with the magic help given by @StefanL38 has helped me to solve that problem, thank you.
Ok, I am back for further advice, please. Sorry to keep bothering you all.
The next stage of the project is as follows. I would like to be able to read/check the various 'On-Off' times on the LCD, in a conventional time format of hours:mins and also be able to change the On-Off times from the Menu pushbuttons, in a similar fashion to how I currently can change the temperature setpoints. For the first part, I thought the best way would be to save the 'On-Off' times to the EEPROM. I have changed the 'On_Normal_Range' to be a float value in the Global area and have added the EEPROM address 4, however when I run this code, the 'RetrieveSetpoint' displays a value of 0 for the EEPROM address 4.
I have obviously not got things quite right!
I briefly tried to us a 'struct' code but could not get it to compile, so have temporarily removed that as it was probably causing me even more confusion.
Hopefully, there is a relatively simple solution which as yet has eluded me.
I have not considered how I can convert the existing times to and from hours:mins, that will be a latter section of the project.
/* Author : John Marchant G0RJM
Created : 25/01/2024 - 4/11/2024 V2.1.1
Description : A project to display the current date, time and temperature on the 20x4 LCD screen
and create a programmable thermostatic heating control of three zones to include frost protection and override facilities.
Incorporating the facility to change the temperature settings and On-Off settings.
This has been very loosely based on the RTClib ds3231 example along with many code parts borrowed
from several other files/sketches and in collaboration with with the input from several authors from the
Arduino Forum with particular thanks to @alto777, @blh64, @cattledog, @StefanL38 and @UKHeliBob. */
#include "RTClib.h"
#include <OneWire.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ezButton.h>
#include <DallasTemperature.h>
#include <EEPROM.h>
#include <DST_RTC.h>
#define ONE_WIRE_BUS_1 3
#define ONE_WIRE_BUS_2 4
#define ONE_WIRE_BUS_3 5
#define TEMPERATURE_PRECISION 11 // 0.125deg resolution
#define buzzer_pin A0
OneWire oneWire_range(ONE_WIRE_BUS_1);
OneWire oneWire_club(ONE_WIRE_BUS_2);
OneWire oneWire_airgun(ONE_WIRE_BUS_3);
const byte range_relay = 10; // Relay outputs
const byte club_relay = 11;
const byte airgun_relay = 12;
const byte boiler_relay = 13;
float range_temperature;
float club_temperature;
float airgun_temperature;
float range_temperature_setpoint; // C
float club_temperature_setpoint; // C
float airgun_temperature_setpoint; // C
const int frost_setpoint = 12.0; // C
const float deadzone = 1.0; // C
ezButton leftbutton(6); // create ezButton object that is attached to pin 6;
ezButton upbutton(7); // create ezButton object that is attached to pin 7;
ezButton downbutton(8); // create ezButton object that is attached to pin 8;
ezButton rightbutton(9); // create ezButton object that is attached to pin 9;
const int ledPin = 13;
const unsigned menuOnTime = 20000;
const unsigned upButtonTime = 50;
const unsigned downButtonTime = 50;
const unsigned printInterval = 2000;
const unsigned overrideRunTime = 60000;
const unsigned backlightOnTime = 30000;
int value = 0;
int selector = 0;
int EEPROM_address_1 = 0; // Address of the location of range setpoint temperature setting
int EEPROM_address_2 = 4; // Address of the location of club setpoint temperature setting
int EEPROM_address_3 = 8; // Address of the location of airgun setpoint temperature setting
int EEPROM_address_4 = 12; // Address of the location of Range On time setting
unsigned long startMillis = 0;
unsigned long menuOffTime = 0;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
unsigned long previousMillisMenu = 0;
unsigned long previousMillisBacklight = 0;
unsigned long previousMillisOverrideStart = 0;
unsigned long previousMillisOverrideFinish = 0;
unsigned long previousMillisAdjustSetpointUp = 0;
unsigned long previousMillisAdjustSetpointDown = 0;
bool isMenuOn = false; // if = True allows the setup menu to be used
bool isRangeHeatOn = false; // if = True allows the Range heating
bool isClubHeatOn = false; // if = True allows the Club heating
bool isAirgunHeatOn = false; // if = True allows the Airgun heating
bool isSetpointSave = false; // if = True allows the new setpoints to be saved to EEPROM
bool isTimeControlOn = false; // if = True allows normal time control function
bool isHeatingOverride = false; // if = True allows the heating override facility
bool isAdjustSetpointUp = false; // if = True allows the Setpoint increment
bool isAdjustSetpointDown = false; // if = True allows the Setpoint decrement
bool isRangeSetpointAdjust = false; // if = True allows the range setpoint to be adjusted
bool isClubSetpointAdjust = false; // if = True allows the club setpoint to be adjusted
bool isAirgunSetpointAdjust = false; // if = True allows the airgun setpoint to be adjusted
DallasTemperature range_sensor(&oneWire_range);
DallasTemperature club_sensor(&oneWire_club);
DallasTemperature airgun_sensor(&oneWire_airgun);
enum { SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY };
float On_Normal_Range; // 16:00 Normal ON time
const int Off_Normal_Range = 21 * 60UL + 30; // 21:30 Normal OFF time
const int On_Normal_Club = 16 * 60UL + 00; // 16:00 Normal ON time
const int Off_Normal_Club = 21 * 60UL + 30; // 21:30 Normal OFF time
const int On_Normal_Airgun = 16 * 60UL + 00; // 16:00 Normal ON time
const int Off_Normal_Airgun = 21 * 60UL + 30; // 21:30 Normal OFF time
const int On_Sunday = 12 * 60UL + 00; // 12:00 Sunday ON time
const int Off_Sunday = 17 * 60UL + 30; // 17:30 Sunday OFF time
LiquidCrystal_I2C lcd(0X27, 20, 4);
RTC_DS3231 rtc;
DST_RTC dst_rtc; // DST object
// Define US or EU rules for DST comment out as required. More countries could be added with different rules in DST_RTC.cpp
// const char rulesDST[] = "US"; // US DST rules
const char rulesDST[] = "EU"; // EU DST rules
char daysOfTheWeek[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
byte char_temp[8] = { B00100, B01010, B01010, B01110, B01110, B11111, B11111, B01110 }; // for thermometer icon
void setup() {
pinMode(range_relay, OUTPUT);
pinMode(club_relay, OUTPUT);
pinMode(airgun_relay, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(buzzer_pin, OUTPUT);
leftbutton.setDebounceTime(50); // set debounce time to 50 milliseconds
upbutton.setDebounceTime(50); // set debounce time to 50 milliseconds
downbutton.setDebounceTime(50); // set debounce time to 50 milliseconds
rightbutton.setDebounceTime(50); // set debounce time to 50 milliseconds
Serial.begin(9600);
// EEPROM.put(EEPROM_address_1, range_temperature_setpoint); // write the float value to EEPROM ONLY used to initially set up setpoint
// EEPROM.put(EEPROM_address_2, club_temperature_setpoint); // write the float value to EEPROM ONLY used to initially set up setpoint
// EEPROM.put(EEPROM_address_3, airgun_temperature_setpoint); // write the float value to EEPROM ONLY used to initially set up setpoint
EEPROM.put(EEPROM_address_4, 16 * 60UL + 00); // write the float value to EEPROM ONLY used to initially set up Range Normal On Time
RetrieveSetpoint();
startMillis = millis();
Wire.begin();
rtc.begin();
lcd.init();
lcd.backlight();
lcd.createChar(0, char_temp);
lcd.setCursor(2, 0);
lcd.print(F("G0RJM Three Zone"));
lcd.setCursor(1, 1);
lcd.print(F("Temperature Control"));
lcd.setCursor(4, 2);
lcd.print(F("Take it easy!"));
lcd.setCursor(4, 3);
lcd.print(F("Working on it"));
delay(1000);
lcd.clear();
if (rtc.lostPower()) {
Serial.println(F("RTC is NOT running!"));
// Uncomment the following line to set the RTC to the date & time this sketch was compiled
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// rtc.adjust(DateTime(2024,4,24,21,49,00));
/* DST? If we're in it, let's subtract an hour from the RTC time to keep our DST calculation correct. This gives us
Standard Time which our DST check will add an hour back to if we're in DST.
*/
DateTime standardTime = rtc.now();
if (dst_rtc.checkDST(standardTime) == true) { // check whether we're in DST right now. If we are, subtract an hour.
standardTime = standardTime.unixtime() - 3600;
}
rtc.adjust(standardTime);
}
Serial.println(F("G0RJM Three zone Temperature Control"));
range_sensor.begin();
club_sensor.begin();
airgun_sensor.begin();
range_sensor.setResolution(TEMPERATURE_PRECISION);
club_sensor.setResolution(TEMPERATURE_PRECISION);
airgun_sensor.setResolution(TEMPERATURE_PRECISION);
} // End of setup
void loop() {
// ("ABCDEFGHIJ1234567890")
//---------------------------Button control-------------------------//
leftbutton.loop(); // MUST call the loop() function first
upbutton.loop(); // MUST call the loop() function first
downbutton.loop(); // MUST call the loop() function first
rightbutton.loop(); // MUST call the loop() function first
// -------------------------Backlight display-----------------------//
unsigned long currentMillis = millis(); // all time elements are data type unsigned long
if ((isHeatingOverride) || (leftbutton.isPressed() || (rightbutton.isPressed() || (upbutton.isPressed())))) {
lcd.backlight();
previousMillisBacklight = currentMillis;
}
if ((!isHeatingOverride) && (currentMillis - previousMillisBacklight >= backlightOnTime)) {
lcd.noBacklight();
isMenuOn = false;
}
//---------------------------Heating Override-----------------------//
if ((downbutton.isPressed() && (!isMenuOn) && (!isHeatingOverride))) {
if (currentMillis - previousMillisOverrideFinish >= 30000) {
isHeatingOverride = true; // Establishes the heating override
isTimeControlOn = false;
HeatingOverride();
Serial.println(F(" manual start of override"));
previousMillisOverrideStart = currentMillis;
}
}
if (isHeatingOverride) {
if (currentMillis - previousMillisOverrideStart >= overrideRunTime) // Automatically cancels the override
{
Serial.println(F(" auto termination of override"));
HeatingOverrideComplete();
isTimeControlOn = true;
previousMillisOverrideFinish = currentMillis;
}
}
if ((downbutton.isPressed() && (!isMenuOn) && (isHeatingOverride))) // Manually cancels the override
{
if (currentMillis - previousMillisOverrideStart >= 10000) {
Serial.println(F(" manual termination of override"));
HeatingOverrideComplete();
// isTimeControlOn = true;
previousMillisOverrideFinish = currentMillis;
}
}
//------------------------Timed Control Interlock--------------------//
if (downbutton.isPressed()) {
isTimeControlOn = false;
Serial.println(F("Timed Control is OFF"));
} else {
if (!isHeatingOverride) {
isTimeControlOn = true;
Serial.println(F("Timed Control is ON"));
}
}
//------------------------Boiler Interlock--------------------------//
if ((digitalRead(range_relay) == HIGH) || (digitalRead(club_relay) == HIGH) || (digitalRead(airgun_relay) == HIGH)) {
digitalWrite(boiler_relay, HIGH);
} else {
digitalWrite(boiler_relay, LOW);
}
if (!isMenuOn) {
TemperatureDisplay();
HeatingAvailable();
}
//------------------------------Menu-------------------------------//
if (leftbutton.isPressed()) {
isMenuOn = true; // Initiiates the setup menu
SettingMenu();
selector++; // this is done after SettingMenu(), so case 0 will be executed on the first button press
if (selector > 5) {
selector = 0;
}
previousMillisMenu = currentMillis;
}
if (isMenuOn) {
if (currentMillis - previousMillisMenu >= menuOnTime) {
isMenuOn = false;
selector = 6;
delay(2000);
lcd.noBacklight();
}
}
//----------------------------Up Button-----------------------------//
if (upbutton.isPressed()) {
isAdjustSetpointUp = true; // Setpoint adjustment upwards is available
previousMillisAdjustSetpointUp = currentMillis;
}
if (isAdjustSetpointUp) {
if (currentMillis - previousMillisAdjustSetpointUp >= upButtonTime) {
isAdjustSetpointUp = false;
}
}
if (isAdjustSetpointUp && isRangeSetpointAdjust) // If True, this allows the Range setpoint to be adjusted
{
range_temperature_setpoint += 0.1; // Range Setpoint increment
Serial.println(F("range_temperature_setpoint_up"));
RangeDisplay();
Buzzer();
}
if (isAdjustSetpointUp && isClubSetpointAdjust) // If True, this allows the Club setpoint to be adjusted
{
club_temperature_setpoint += 0.1; // Club Setpoint increment
Serial.println(F("club_temperature_setpoint_up"));
ClubDisplay();
Buzzer();
}
if (isAdjustSetpointUp && isAirgunSetpointAdjust) // If True, this allows the Airgun setpoint to be adjusted
{
airgun_temperature_setpoint += 0.1; // Airgun Setpoint increment
Serial.println(F("airgun_temperature_setpoint_up"));
AirgunDisplay();
Buzzer();
}
//----------------------------Down Button---------------------------//
if (downbutton.isPressed()) {
isAdjustSetpointDown = true; // Setpoint adjustment Downwards is available
previousMillisAdjustSetpointDown = currentMillis;
}
if (isAdjustSetpointDown) {
if (currentMillis - previousMillisAdjustSetpointDown >= downButtonTime) {
isAdjustSetpointDown = false;
}
}
if (isAdjustSetpointDown && isRangeSetpointAdjust) // If True, this allows the Range setpoint to be adjusted
{
range_temperature_setpoint -= 0.1; // Range Setpoint decrement
Serial.println(F("range_temperature_setpoint_down"));
RangeDisplay();
Buzzer();
}
if (isAdjustSetpointDown && isClubSetpointAdjust) // If True, this allows the Club setpoint to be adjusted
{
club_temperature_setpoint -= 0.1; // Club Setpoint decrement
Serial.println(F("club_temperature_setpoint_down"));
ClubDisplay();
Buzzer();
}
if (isAdjustSetpointDown && isAirgunSetpointAdjust) // If True, this allows the Airgun setpoint to be adjusted
{
airgun_temperature_setpoint -= 0.1; // Airgun Setpoint decrement
Serial.println(F("airgun_temperature_setpoint_down"));
AirgunDisplay();
Buzzer();
}
//---------------------------Setpoint Save--------------------------//
if (isSetpointSave && isAdjustSetpointUp && isAdjustSetpointDown) // If True, the new temperature setpoints are saved to EEPROM
{
for (int n = 0; n < 1; n++) {
Serial.println(F("Changes saved"));
EEPROM.put(EEPROM_address_1, range_temperature_setpoint); // write the new range setpoint value to EEPROM, only if it has changed
EEPROM.put(EEPROM_address_2, club_temperature_setpoint); // write the new club setpoint value to EEPROM, only if it has changed
EEPROM.put(EEPROM_address_3, airgun_temperature_setpoint); // write the new airgun setpoint value to EEPROM, only if it has changed
delay(2000);
RetrieveSetpoint();
lcd.setCursor(3, 3);
lcd.print(F("Settings saved"));
delay(3000);
lcd.clear();
}
}
//----------------------------Print delay---------------------------//
if (currentMillis - previousMillis >= printInterval) // has enough time passed yet?
{
previousMillis = previousMillis + printInterval; // If yes, set the time del;ay for the next print event
// capture & print data, or print latest data, etc.
// the closing curly brace at end of loop.
//--------------------Daylight Saving Setting---------------------//
DateTime standardTime = rtc.now();
Serial.println(F("Standard Time"));
printTheTime(standardTime);
DateTime theTime = dst_rtc.calculateTime(standardTime); // takes into account DST
Serial.println(F("Time adjusted for Daylight Saving Time"));
printTheTime(theTime);
int currentTime = theTime.hour() * 60UL + theTime.minute();
//--------------------Timed heating setting-----------------------//
if (isTimeControlOn) {
if (theTime.dayOfTheWeek() != SUNDAY) {
// Monday to Saturday so use normal times
if (currentTime < On_Normal_Range || currentTime > Off_Normal_Range) {
// this is outside normal range heating time
isRangeHeatOn = false;
} else {
// this is within normal range heating time
isRangeHeatOn = true;
}
} else {
// Sunday times
if (currentTime < On_Sunday || currentTime > Off_Sunday) {
// this is outside Sunday range heating time
isRangeHeatOn = false;
} else {
// this is within Sunday range heating time
isRangeHeatOn = true;
}
}
if (theTime.dayOfTheWeek() != SUNDAY) {
// Monday to Saturday so use normal times
if (currentTime < On_Normal_Club || currentTime > Off_Normal_Club) {
// this is outside normal club heating time
isClubHeatOn = false;
} else {
// this is within normal club heating time
isClubHeatOn = true;
}
} else {
// Sunday times
if (currentTime < On_Sunday || currentTime > Off_Sunday) {
// this is outside Sunday club heating time
isClubHeatOn = false;
} else {
// this is within Sunday club heating time
isClubHeatOn = true;
}
}
if (theTime.dayOfTheWeek() != SUNDAY) {
// Monday to Saturday so use normal times
if (currentTime < On_Normal_Airgun || currentTime > Off_Normal_Airgun) {
// this is outside normal airgun heating time
isAirgunHeatOn = false;
} else {
// this is within normal airgun heating time
isAirgunHeatOn = true;
}
} else {
// Sunday times
if (currentTime < On_Sunday || currentTime > Off_Sunday) {
// this is outside Sunday airgun heating time
isAirgunHeatOn = false;
} else {
// this is within Sunday airgun heating time
isAirgunHeatOn = true;
}
}
}
//---------------------Date & Time display----------------------//
if ((!isMenuOn) && (!isHeatingOverride)) {
Serial.println(F("Time & date showing on LCD"));
lcd.setCursor(0, 0);
lcd.print(daysOfTheWeek[theTime.dayOfTheWeek()]);
lcd.setCursor(3, 0);
lcd.print(F(":"));
lcd.setCursor(4, 0);
if (theTime.day() < 10) lcd.print('0');
lcd.print(theTime.day(), DEC);
lcd.print(':');
if (theTime.month() < 10) lcd.print('0');
lcd.print(theTime.month(), DEC);
lcd.print(':');
lcd.print(theTime.year(), DEC);
lcd.setCursor(15, 0);
if (theTime.hour() < 10) lcd.print('0');
lcd.print(theTime.hour(), DEC);
lcd.print(':');
if (theTime.minute() < 10) lcd.print('0');
lcd.print(theTime.minute(), DEC);
}
//------------------------Serial print---------------------------//
Serial.print(F("Requesting temperatures..."));
range_sensor.requestTemperatures();
club_sensor.requestTemperatures();
airgun_sensor.requestTemperatures();
Serial.println(F(" done"));
Serial.print(F("Range: "));
Serial.println(range_sensor.getTempCByIndex(0));
Serial.print(F("Club: "));
Serial.println(club_sensor.getTempCByIndex(0));
Serial.print(F("Airgun: "));
Serial.println(airgun_sensor.getTempCByIndex(0));
}
} // End of loop
//----------------------Print time to serial-------------------------//
void printTheTime(DateTime theTimeP) {
Serial.print(theTimeP.year(), DEC);
Serial.print('/');
Serial.print(theTimeP.month(), DEC);
Serial.print('/');
Serial.print(theTimeP.day(), DEC);
Serial.print(' ');
Serial.print(theTimeP.hour(), DEC);
Serial.print(':');
Serial.print(theTimeP.minute(), DEC);
Serial.print(':');
Serial.print(theTimeP.second(), DEC);
Serial.println();
}
//------------------------Retrieve setpoint--------------------------//
void RetrieveSetpoint() {
EEPROM.get(EEPROM_address_1, range_temperature_setpoint); //retrieve the range setpoint from EEPROM
EEPROM.get(EEPROM_address_2, club_temperature_setpoint); //retrieve the club setpoint from EEPROM
EEPROM.get(EEPROM_address_3, airgun_temperature_setpoint); //retrieve the airgun setpoint from EEPROM
EEPROM.get(EEPROM_address_4, On_Normal_Range); //retrieve the Normal Range On Time
Serial.print(F("Range Temperature Setpoint - "));
Serial.print(range_temperature_setpoint);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_1);
Serial.print(F("Club Temperature Setpoint - "));
Serial.print(club_temperature_setpoint);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_2);
Serial.print(F("Airgun Temperature Setpoint - "));
Serial.print(airgun_temperature_setpoint);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_3);
Serial.print(F("Normal Range On Time - "));
Serial.print(On_Normal_Range);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_4);
}
//--------------------------Setting Menu-----------------------------//
void SettingMenu() {
switch (selector) {
case 0:
Serial.println(F("Case 0")); // General menu
MenuScreen();
break;
case 1:
Serial.println(F("Case 1")); // Displays the Range setpoint
RangeDisplay();
Buzzer();
break;
case 2:
Serial.println(F("Case 2")); // Displays the Club setpoint
ClubDisplay();
Buzzer();
break;
case 3:
Serial.println(F("Case 3")); // Displays the Airgun setpoint
AirgunDisplay();
Buzzer();
break;
case 4:
Serial.println(F("Case 4")); // Instructs how to save the new settings
SaveDisplay();
break;
case 5:
Serial.println(F("Case 5")); // Reminds you to save
lcd.clear();
lcd.setCursor(3, 2);
lcd.print(F("Did you save?"));
Buzzer();
}
}
//---------------------------Buzzer----------------------------------//
void Buzzer() {
{
digitalWrite(buzzer_pin, HIGH);
delay(100);
digitalWrite(buzzer_pin, LOW);
}
}
//-------------------------Menu screen-------------------------------//
void MenuScreen() {
lcd.clear();
lcd.print(F(" Setting Menu: "));
lcd.setCursor(0, 1);
lcd.print(F("Range: "));
lcd.print(range_temperature_setpoint, 1);
lcd.write((char)223);
lcd.print('C');
lcd.setCursor(0, 2);
lcd.print(F("Club: "));
lcd.print(club_temperature_setpoint, 1);
lcd.write((char)223);
lcd.print('C');
lcd.setCursor(0, 3);
lcd.print(F("Airgun:"));
lcd.print(airgun_temperature_setpoint, 1);
lcd.write((char)223);
lcd.print('C');
isSetpointSave = false;
}
//-----------------------Setting Displays---------------------------//
void RangeDisplay() {
isRangeSetpointAdjust = true;
isClubSetpointAdjust = false;
isAirgunSetpointAdjust = false;
Serial.println(F("RangeChange"));
lcd.clear();
lcd.print(F(" Setting Menu: "));
lcd.setCursor(0, 1);
lcd.print(F("Range: "));
lcd.print(range_temperature_setpoint, 1);
lcd.write((char)223);
lcd.print('C');
}
//-------------------------------------------------------------------//
void ClubDisplay() {
isClubSetpointAdjust = true;
isRangeSetpointAdjust = false;
isAirgunSetpointAdjust = false;
Serial.println(F("ClubChange"));
lcd.clear();
lcd.print(F(" Setting Menu: "));
lcd.setCursor(0, 2);
lcd.print(F("Club: "));
lcd.print(club_temperature_setpoint, 1);
lcd.write((char)223);
lcd.print('C');
}
//-------------------------------------------------------------------//
void AirgunDisplay() {
isAirgunSetpointAdjust = true;
isRangeSetpointAdjust = false;
isClubSetpointAdjust = false;
Serial.println(F("AirgunChange"));
lcd.clear();
lcd.print(F(" Setting Menu: "));
lcd.setCursor(0, 3);
lcd.print(F("Airgun:"));
lcd.print(airgun_temperature_setpoint, 1);
lcd.write((char)223);
lcd.print('C');
}
//------------------------Save Display-------------------------------//
void SaveDisplay() {
isRangeSetpointAdjust = false;
isClubSetpointAdjust = false;
isAirgunSetpointAdjust = false;
Serial.println(F("SavingChanges"));
lcd.clear();
lcd.print(F("To save the changes"));
lcd.setCursor(2, 1);
lcd.print(F("Press UP & DOWN"));
lcd.setCursor(5, 2);
lcd.print(F("Together"));
isSetpointSave = true;
}
//---------------------Temperature display - ------------------------//
void TemperatureDisplay() {
lcd.setCursor(0, 1); // Range Temperature
lcd.print(F("Range: "));
lcd.print(range_sensor.getTempCByIndex(0), 1);
lcd.write((char)223);
lcd.print('C');
lcd.setCursor(0, 2); // Club Temperature
lcd.print(F("Club: "));
lcd.print(club_sensor.getTempCByIndex(0), 1);
lcd.write((char)223);
lcd.print('C');
lcd.setCursor(0, 3); // Airgun Temperature
lcd.print(F("Airgun:"));
lcd.print(airgun_sensor.getTempCByIndex(0), 1);
lcd.write((char)223);
lcd.print('C');
}
//------------------------Heating Override---------------------------//
void HeatingOverride() {
Serial.println(F("Heating Override is On"));
isRangeHeatOn = true;
isClubHeatOn = true;
isAirgunHeatOn = true;
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print(F(" OVERRIDE IS ON "));
}
//--------------------Heating Override Complete----------------------//
void HeatingOverrideComplete() {
Serial.println(F("Heating Override is complete"));
isHeatingOverride = false;
isRangeHeatOn = false;
isClubHeatOn = false;
isAirgunHeatOn = false;
lcd.setCursor(0, 0);
lcd.print(F(" OVERRIDE IS OFF "));
delay(2000);
lcd.noBacklight();
}
//-----------------------Heating Available---------------------------//
void HeatingAvailable() {
RangeHeatingAvailable();
ClubHeatingAvailable();
AirgunHeatingAvailable();
Serial.println(F("Heating is available"));
}
//-------------------------------------------------------------------//
void RangeHeatingAvailable() {
{
if (isRangeHeatOn) {
NormalHeatingRange();
Serial.println(F("Heating R"));
} else {
FrostPreventionRange();
Serial.println(F("Frost Prev. R"));
}
}
}
//-------------------------------------------------------------------//
void ClubHeatingAvailable() {
{
if (isClubHeatOn) {
NormalHeatingClub();
Serial.println(F("Heating C"));
} else {
FrostPreventionClub();
Serial.println(F("Frost Prev. C"));
}
}
}
//-------------------------------------------------------------------//
void AirgunHeatingAvailable() {
{
if (isAirgunHeatOn) {
NormalHeatingAirgun();
Serial.println(F("Heating A"));
} else {
FrostPreventionAirgun();
Serial.println(F("Frost Prev. A"));
}
}
}
//-------------------Frost Prevention Range--------------------------//
void FrostPreventionRange() {
if ((range_sensor.getTempCByIndex(0) <= (frost_setpoint - deadzone))) {
digitalWrite(range_relay, HIGH);
Serial.println(F("Range frost Heating"));
lcd.setCursor(13, 1);
lcd.print(F(" ON F"));
} else {
if ((range_sensor.getTempCByIndex(0) >= (frost_setpoint + deadzone))) {
digitalWrite(range_relay, LOW);
lcd.setCursor(13, 1);
lcd.print(F(" OFF F"));
}
}
}
//--------------------Frost Prevention Club-------------------------//
void FrostPreventionClub() {
if ((club_sensor.getTempCByIndex(0) <= (frost_setpoint - deadzone))) {
digitalWrite(club_relay, HIGH);
Serial.println(F("Club frost Heating"));
lcd.setCursor(13, 2);
lcd.print(F(" ON F"));
} else {
if ((club_sensor.getTempCByIndex(0) >= (frost_setpoint + deadzone))) {
digitalWrite(club_relay, LOW);
lcd.setCursor(13, 2);
lcd.print(F(" OFF F"));
}
}
}
//---------------------Frost Prevention Airgun-----------------------//
void FrostPreventionAirgun() {
if ((airgun_sensor.getTempCByIndex(0) <= (frost_setpoint - deadzone))) {
digitalWrite(airgun_relay, HIGH);
Serial.println(F("Air frost Heating"));
lcd.setCursor(13, 3);
lcd.print(F(" ON F"));
} else {
if ((airgun_sensor.getTempCByIndex(0) >= (frost_setpoint + deadzone))) {
digitalWrite(airgun_relay, LOW);
lcd.setCursor(13, 3);
lcd.print(F(" OFF F"));
}
}
}
//-------------------Normal Heating Range----------------------------//
void NormalHeatingRange() {
if ((range_sensor.getTempCByIndex(0) <= (range_temperature_setpoint - deadzone))) {
digitalWrite(range_relay, HIGH);
Serial.println(F("Normal Heating R"));
lcd.setCursor(13, 1);
lcd.print(F(" ON T"));
} else {
if ((range_sensor.getTempCByIndex(0) >= (range_temperature_setpoint + deadzone))) {
digitalWrite(range_relay, LOW);
lcd.setCursor(13, 1);
lcd.print(F(" OFF T"));
}
}
}
//--------------------Normal Heating Club ---------------------------//
void NormalHeatingClub() {
if ((club_sensor.getTempCByIndex(0) <= (club_temperature_setpoint - deadzone))) {
digitalWrite(club_relay, HIGH);
Serial.println(F("Normal Heating C"));
lcd.setCursor(13, 2);
lcd.print(F(" ON T"));
} else {
if ((club_sensor.getTempCByIndex(0) >= (club_temperature_setpoint + deadzone))) {
digitalWrite(club_relay, LOW);
lcd.setCursor(13, 2);
lcd.print(F(" OFF T"));
}
}
}
//---------------------Normal Heating Airgun-------------------------//
void NormalHeatingAirgun() {
if ((airgun_sensor.getTempCByIndex(0) <= (airgun_temperature_setpoint - deadzone))) {
digitalWrite(airgun_relay, HIGH);
Serial.println(F("Normal Heating A"));
lcd.setCursor(13, 3);
lcd.print(F(" ON T"));
} else {
if ((airgun_sensor.getTempCByIndex(0) >= (airgun_temperature_setpoint + deadzone))) {
digitalWrite(airgun_relay, LOW);
lcd.setCursor(13, 3);
lcd.print(F(" OFF T"));
}
}
}
All your times are typed as ints, why would you need to type On_Normal_Range as a float.
float On_Normal_Range; // 16:00 Normal ON time
const int Off_Normal_Range = 21 * 60UL + 30; // 21:30 Normal OFF time
const int On_Normal_Club = 16 * 60UL + 00; // 16:00 Normal ON time
const int Off_Normal_Club = 21 * 60UL + 30; // 21:30 Normal OFF time
const int On_Normal_Airgun = 16 * 60UL + 00; // 16:00 Normal ON time
const int Off_Normal_Airgun = 21 * 60UL + 30; // 21:30 Normal OFF time
const int On_Sunday = 12 * 60UL + 00; // 12:00 Sunday ON time
const int Off_Sunday = 17 * 60UL + 30; // 17:30 Sunday OFF time
Evening @cattledog thank you for your reply. I have only changed On_Normal_Range to a float whilst I experiment to get the code correct. I presumed that in order to save the setting to the EEPROM that it needed to be a 'float'.
Once I have that part working, I can then hopefully roll out the changes to the other time settings.
Try adding a delay between the writing and the reading.
You've certainly used a very long one in the Setpoint Save section.
EEPROM.put(EEPROM_address_4, 16 * 60UL + 00);
delay(50);
RetrieveSetpoint();
Evening @cattledog I have put the delay as suggested. This is the 'serial-print'.`
22:02:57.430 -> Club Temperature Setpoint - 25.30 Stored at addr 4
22:02:57.495 -> Airgun Temperature Setpoint - 25.40 Stored at addr 8
22:02:57.560 -> Normal Range On Time - 0.00 Stored at addr 12
22:02:59.739 -> G0RJM Three zone Temperature Control
22:02:59.912 -> Timed Control is ON
22:03:00.128 -> Frost Prev. R
22:03:00.208 -> Frost Prev. C
At this point, the library does not know that you want to put a float in the address, and is treating it as an integer. Cast it as a float.
//EEPROM.put(EEPROM_address_4, 16 * 60UL + 00);
EEPROM.put(EEPROM_address_4, float(16 * 60UL + 00));
Better yet, ditch using a float. Since you are tracking minutes within the day, use an int. 23 * 60 + 59 easily fits in a 16 bit int which will only require 2 bytes of EEPROM to store.
Your code is a good candidate for structs/classes, so you might want to show us what you tried. It might lead to you being able to drive the three areas with the same code, leaving less places for bugs to hide.
Thanks @wildbill I will revisit the 'struct' idea when I have researched it further, as I entered into it in a bit of a hurry and did not really give it a lot of thought.
Thanks @ blh64 that made the situation that I was stuck with an awful lot simpler. On to the next stage which involves calling up the set points to the LCD menu and making changes to the time values before using 'put' to save the new times to the EEPROM.
Firstly, Seasons Greetings to all.
Back for a little more guidance please. The project has moved on very slightly and I have now stumbled into a minor problem with regards to trying to use a button to create a couple of index.
I have used the normal 'millis time function' to create a delay between button pushes, but have obviously got something wrong. It is in the "Menu Selection" area lines 325 to 361.
When I press the "Right button" the system rapidly scrolls through the menu functions without any delay.
This is the serial printout.
6:55:55.084 -> Normal Heating R
16:55:55.084 -> Heating R
16:55:55.118 -> Normal Heating C
16:55:55.118 -> Heating C
16:55:55.151 -> Normal Heating A
16:55:55.151 -> Heating A
16:55:55.184 -> Heating is available
16:55:55.217 -> Backlight is ON
16:55:55.217 -> Temperature setting activated
16:55:55.324 -> Settings deactivated
16:55:55.623 -> Normal Heating R
16:55:55.656 -> Heating R
16:55:55.656 -> Normal Heating C
16:55:55.693 -> Heating C
16:55:55.693 -> Normal Heating A
16:55:55.724 -> Heating A
16:55:55.724 -> Heating is available
16:55:55.756 -> Backlight is ON
16:55:55.834 -> Temperature setting activated
16:55:55.897 -> Settings deactivated
16:55:55.999 -> Standard Time
16:55:56.038 -> 2024/12/23 16:55:15
16:55:56.064 -> Time adjusted for Daylight Saving Time
16:55:56.097 -> 2024/12/23 16:55:15
16:55:56.130 -> Something time controlled is happening here!
16:55:56.163 -> Time & date showing on LCD
16:55:56.195 -> Requesting temperatures... done
16:55:57.091 -> Range: 20.87
16:55:57.091 -> Club: 20.87
Sketch code.
/* Author : John Marchant G0RJM
Created : 25/01/2024 - 22/12/2024 V2.1.2AB1
Description : A project to display the current date, time and temperature on the 20x4 LCD screen
and create a programmable thermostatic heating control of three zones to include frost protection and override facilities.
Incorporating the facility to change the temperature settings and On-Off settings from pushbuttons.
This has been very loosely based on the RTClib ds3231 example along with many code parts borrowed
from several other files/sketches and in collaboration with the input and help from several authors from the
Arduino Forum with particular thanks to @alto777, @blh64, @cattledog, @StefanL38 and @UKHeliBob. */
#include "RTClib.h"
#include <OneWire.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ezButton.h>
#include <DallasTemperature.h>
#include <EEPROM.h>
#include <DST_RTC.h>
#include <LcdMenu.h>
#define ONE_WIRE_BUS_1 3
#define ONE_WIRE_BUS_2 4
#define ONE_WIRE_BUS_3 5
#define TEMPERATURE_PRECISION 11 // 0.125deg resolution
#define heart_beat_pin LED_BUILTIN // digital pin for heart beat LED
OneWire oneWire_range(ONE_WIRE_BUS_1);
OneWire oneWire_club(ONE_WIRE_BUS_2);
OneWire oneWire_airgun(ONE_WIRE_BUS_3);
const byte range_relay = 11; // Relay outputs
const byte club_relay = 12;
const byte airgun_relay = A1;
const byte boiler_relay = A2;
const byte buzzer_pin = A0;
float range_temperature;
float club_temperature;
float airgun_temperature;
float range_temperature_setpoint; // C
float club_temperature_setpoint; // C
float airgun_temperature_setpoint; // C
const int frost_setpoint = 12.0; // C
const float deadzone = 1.0; // C
ezButton leftbutton(6); // create ezButton object that is attached to pin 6;
ezButton upbutton(7); // create ezButton object that is attached to pin 7;
ezButton downbutton(8); // create ezButton object that is attached to pin 8;
ezButton rightbutton(9); // create ezButton object that is attached to pin 9;
ezButton enterbutton(10); // create ezButton object that is attached to pin 10;
const int LONG_PRESS_TIME = 2000; // 1000 milliseconds
const int SHORT_PRESS_TIME = 800; // 1000 milliseconds
const unsigned OffTimed1 = 4000;
const unsigned OffTimed2 = 4000;
const unsigned menuOnTime = 20000;
const unsigned upButtonTime = 100;
const unsigned printInterval = 3000;
const unsigned downButtonTime = 100;
const unsigned backlightOnTime = 15000;
const unsigned overrideRunOnTime = 60000;
int value = 0;
int menuselector = 0;
int timeselector = 0;
int temperatureselector = 0;
int EEPROM_address_1 = 0; // Address of the location of range setpoint temperature setting
int EEPROM_address_2 = 4; // Address of the location of club setpoint temperature setting
int EEPROM_address_3 = 8; // Address of the location of airgun setpoint temperature setting
int EEPROM_address_4 = 12; // Address of the location of Range On time setting
int EEPROM_address_5 = 16; // Address of the location of Range Off time setting
int EEPROM_address_6 = 20; // Address of the location of Club On time setting
int EEPROM_address_7 = 24; // Address of the location of Club Off time setting
int EEPROM_address_8 = 28; // Address of the location of Airgun On time setting
int EEPROM_address_9 = 32; // Address of the location of Airgun Off time setting
int EEPROM_address_10 = 36; // Address of the location of Sunday On time setting
int EEPROM_address_11 = 40; // Address of the location of Sunday Off time setting
unsigned long startMillis = 0;
unsigned long menuOffTime = 0;
unsigned long pressedTime = 0;
unsigned long releasedTime = 0;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
unsigned long last_heart_beat_time; // time in milliseconds of last heart beat status change
unsigned long heart_beat_freq = 1000; // time in milliseconds of heart beat frequency
unsigned long heart_beat_on_off_time; // the time the LED is on and off - 1/2 frequency
unsigned long previousMillisMenu = 0;
unsigned long previousMillisTimeMenu = 0;
unsigned long previousMillisBacklight = 0;
unsigned long previousMillisTimedStart1 = 0;
unsigned long previousMillisTimedStart2 = 0;
unsigned long previousMillisOverrideStart = 0;
unsigned long previousMillisTemperatureMenu = 0;
unsigned long previousMillisAdjustSetpointUp = 0;
unsigned long previousMillisAdjustSetpointDown = 0;
bool isPressed = false; // if = True button has been pressed
bool isClubHeatOn = false; // if = True allows the Club heating
bool isRangeHeatOn = false; // if = True allows the Range heating
bool isBacklightOn = false; // if = True the bAcklight is ON
bool isHeartBeatOn = false; // if = True shows current status of heart beat
bool isLongDetected = false; // if = True allows long button press to be used
bool isAirgunHeatOn = false; // if = True allows the Airgun heating
bool isMenuSelectOn = false; // if = True allows the setup menu to be used
bool isTimeControlOn = false; // if = True allows normal time control function
bool isTimeSettingOn = false; // if = True allows the time to be adjusted
bool isSetpointSaveOn = false; // if = True allows the new setpoints to be saved to EEPROM
bool isAdjustSetpointUp = false; // if = True allows the Setpoint increment
bool isHeatingOverrideOn = false; // if = True allows the heating override facility
bool isAdjustSetpointDown = false; // if = True allows the Setpoint decrement
bool isTemperatureSettingOn = false; // if = True allows the temperature to be adjusted
bool isClubSetpointAdjustOn = false; // if = True allows the club setpoint to be adjusted
bool isRangeSetpointAdjustOn = false; // if = True allows the range setpoint to be adjusted
bool isAirgunSetpointAdjustOn = false; // if = True allows the airgun setpoint to be adjusted
DallasTemperature range_sensor(&oneWire_range);
DallasTemperature club_sensor(&oneWire_club);
DallasTemperature airgun_sensor(&oneWire_airgun);
enum { SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY };
int On_Normal_Range; // 16:00 Normal ON time
int Off_Normal_Range; // 21:30 Normal OFF time
int On_Normal_Club; // 16:00 Normal ON time
int Off_Normal_Club; // 21:30 Normal OFF time
int On_Normal_Airgun; // 16:00 Normal ON time
int Off_Normal_Airgun; // 21:30 Normal OFF time
int On_Sunday; // 12:00 Sunday ON time
int Off_Sunday; // 17:30 Sunday OFF time
LiquidCrystal_I2C lcd(0X27, 20, 4);
RTC_DS3231 rtc;
DST_RTC dst_rtc; // DST object
// Define US or EU rules for DST comment out as required. More countries could be added with different rules in DST_RTC.cpp
// const char rulesDST[] = "US"; // US DST rules
const char rulesDST[] = "EU"; // EU DST rules
char daysOfTheWeek[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
byte char_temp[8] = { B00100, B01010, B01010, B01110, B01110, B11111, B11111, B01110 }; // for thermometer icon
void setup() {
pinMode(range_relay, OUTPUT);
pinMode(club_relay, OUTPUT);
pinMode(airgun_relay, OUTPUT);
pinMode(boiler_relay, OUTPUT);
pinMode(buzzer_pin, OUTPUT);
pinMode(heart_beat_pin, OUTPUT);
heart_beat_on_off_time = heart_beat_freq / 2; // LED is on and off at 1/2 frequency time
leftbutton.setDebounceTime(50); // set debounce time to 50 milliseconds
upbutton.setDebounceTime(50); // set debounce time to 50 milliseconds
downbutton.setDebounceTime(50); // set debounce time to 50 milliseconds
rightbutton.setDebounceTime(50); // set debounce time to 50 milliseconds
enterbutton.setDebounceTime(50); // set debounce time to 50 milliseconds
Serial.begin(9600);
// EEPROM.put(EEPROM_address_1, range_temperature_setpoint); // write the float value to EEPROM ONLY used to initially set up setpoint
// EEPROM.put(EEPROM_address_2, club_temperature_setpoint); // write the float value to EEPROM ONLY used to initially set up setpoint
// EEPROM.put(EEPROM_address_3, airgun_temperature_setpoint); // write the float value to EEPROM ONLY used to initially set up setpoint
// EEPROM.put(EEPROM_address_4, 16 * 60 + 00); // write the value to EEPROM ONLY used to initially set up Range Normal On Time
// EEPROM.put(EEPROM_address_5, 21 * 60 + 30); // write the value to EEPROM ONLY used to initially set up Range Normal Off Time
// EEPROM.put(EEPROM_address_6, 16 * 60 + 00); // write the value to EEPROM ONLY used to initially set up Club Normal On Time
// EEPROM.put(EEPROM_address_7, 21 * 60 + 30); // write the value to EEPROM ONLY used to initially set up Club Normal Off Time
// EEPROM.put(EEPROM_address_8, 16 * 60 + 00); // write the value to EEPROM ONLY used to initially set up Airgun Normal On Time
// EEPROM.put(EEPROM_address_9, 21 * 60 + 30); // write the value to EEPROM ONLY used to initially set up Airgun Normal Off Time
// EEPROM.put(EEPROM_address_10, 12 * 60 + 00); // write the value to EEPROM ONLY used to initially set up Sunday On Time
// EEPROM.put(EEPROM_address_11, 17 * 60 + 30); // write the value to EEPROM ONLY used to initially set up Sunday Off Time
delay(2000);
RetrieveSetpoint();
startMillis = millis();
Wire.begin();
rtc.begin();
lcd.init();
lcd.backlight();
lcd.createChar(0, char_temp);
lcd.setCursor(2, 0);
lcd.print(F("G0RJM Three Zone"));
lcd.setCursor(1, 1);
lcd.print(F("Temperature Control"));
lcd.setCursor(4, 2);
lcd.print(F("Take it easy!"));
lcd.setCursor(4, 3);
lcd.print(F("Working on it"));
delay(1000);
lcd.clear();
if (rtc.lostPower()) {
Serial.println(F("RTC is NOT running!"));
// Uncomment the following line to set the RTC to the date & time this sketch was compiled
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// rtc.adjust(DateTime(2024,4,24,21,49,00));
/* DST? If we're in it, let's subtract an hour from the RTC time to keep our DST calculation correct. This gives us
Standard Time which our DST check will add an hour back to if we're in DST.
*/
DateTime standardTime = rtc.now();
if (dst_rtc.checkDST(standardTime) == true) { // check whether we're in DST right now. If we are, subtract an hour.
standardTime = standardTime.unixtime() - 3600;
}
rtc.adjust(standardTime);
}
Serial.println(F("G0RJM Three zone Temperature Control"));
range_sensor.begin();
club_sensor.begin();
airgun_sensor.begin();
range_sensor.setResolution(TEMPERATURE_PRECISION);
club_sensor.setResolution(TEMPERATURE_PRECISION);
airgun_sensor.setResolution(TEMPERATURE_PRECISION);
} // End of setup
void loop() {
// ("ABCDEFGHIJ1234567890")
unsigned long currentMillis = millis(); // all time elements are data type unsigned long
//---------------------------Button control-------------------------//
leftbutton.loop(); // MUST call the loop() function first
upbutton.loop(); // MUST call the loop() function first
downbutton.loop(); // MUST call the loop() function first
rightbutton.loop(); // MUST call the loop() function first
enterbutton.loop(); // MUST call the loop() function first
Heartbeat();
if (!isMenuSelectOn) {
TemperatureDisplay();
HeatingAvailable();
}
if (isHeatingOverrideOn) {
isTimeControlOn = false;
} else {
isTimeControlOn = true;
}
// -------------------------Backlight display-----------------------//
if ((leftbutton.isPressed() || (upbutton.isPressed() || (downbutton.isPressed() || (rightbutton.isPressed() || (enterbutton.isPressed())))))) {
lcd.backlight();
Serial.println(F("Backlight is ON"));
previousMillisBacklight = currentMillis;
}
if ((!isHeatingOverrideOn) && (!isMenuSelectOn) && (currentMillis - previousMillisBacklight >= backlightOnTime)) {
lcd.noBacklight();
Serial.println(F("Backlight is OFF"));
}
//---------------------------Heating Override-----------------------//
if ((downbutton.isPressed() && (!isMenuSelectOn))) {
pressedTime = millis();
isPressed = true;
isLongDetected = false;
}
if (downbutton.isReleased()) {
isPressed = false;
releasedTime = millis();
long pressDuration = releasedTime - pressedTime;
if (pressDuration < SHORT_PRESS_TIME) { // Manually starts the override
Serial.println(F("A short press is detected"));
HeatingOverride();
Buzzer();
previousMillisOverrideStart = currentMillis;
}
}
if ((isPressed) && (!isLongDetected)) {
long pressDuration = millis() - pressedTime;
if (pressDuration > LONG_PRESS_TIME) { // Manually cancels the override
Serial.println(F("A long press is detected"));
Serial.println(F(" manual termination of override"));
isLongDetected = true;
HeatingOverrideCompleted();
Buzzer();
}
}
if (isHeatingOverrideOn) {
if (currentMillis - previousMillisOverrideStart >= overrideRunOnTime) // Automatically cancels the override
{
Serial.println(F(" auto termination of override"));
HeatingOverrideCompleted();
Buzzer();
}
}
//------------------------Boiler Interlock--------------------------//
if ((digitalRead(range_relay) == HIGH) || (digitalRead(club_relay) == HIGH) || (digitalRead(airgun_relay) == HIGH)) {
digitalWrite(boiler_relay, HIGH);
} else {
digitalWrite(boiler_relay, LOW);
}
//--------------------------Menu Selection-------------------------//
if (rightbutton.isPressed() && (!isMenuSelectOn)) // Initiates the setup menu
{
Serial.println(F(" Temperature setting activated"));
isMenuSelectOn = true;
isTemperatureSettingOn = true; // Initiates the temperature setup menu
lcd.clear();
lcd.print(F("TEMPERATURE SETTING"));
Buzzer();
previousMillisTimedStart1 = currentMillis;
}
if (rightbutton.isPressed() && (isTemperatureSettingOn)) {
if (currentMillis - previousMillisTimedStart1 >= OffTimed1) // Initiates the time setup menu
{
Serial.println(F(" Time setting activated"));
isTimeSettingOn = true;
isTemperatureSettingOn = false;
lcd.clear();
lcd.print(F(" TIME SETTING"));
Buzzer();
previousMillisTimedStart2 = currentMillis;
}
}
if (rightbutton.isPressed() && (isTimeSettingOn)) {
if (currentMillis - previousMillisTimedStart2 >= OffTimed2) // Deactivates the set up menu
{
Serial.println(F(" Settings deactivated"));
lcd.clear();
lcd.print(F(" MENU EXITED"));
isMenuSelectOn = false;
isTimeSettingOn = false;
Buzzer();
}
}
//-------------------------Temperature Menu------------------------//
if (leftbutton.isPressed() && (isTemperatureSettingOn)) {
Serial.println(F(" left button pressed - Temp"));
TemperatureSelector();
temperatureselector++; // this is done after TemperatureSettingMenu(), so case 0 will be executed on the first button press
if (temperatureselector > 5) {
temperatureselector = 0;
}
previousMillisTemperatureMenu = currentMillis;
}
if (isTemperatureSettingOn) {
if (currentMillis - previousMillisTemperatureMenu >= menuOnTime) {
isTemperatureSettingOn = false;
// isMenuSelectOn = false;
temperatureselector = 6;
}
}
//----------------------------Enter Button----------------------------//
if (enterbutton.isPressed()) {
Serial.print(F(" enter button is pressed"));
Buzzer();
}
//----------------------------Up Button-----------------------------//
if (upbutton.isPressed()) {
Serial.println(F(" up button pressed"));
isAdjustSetpointUp = true; // Setpoint adjustment upwards is available
previousMillisAdjustSetpointUp = currentMillis;
}
if (isAdjustSetpointUp) {
if (currentMillis - previousMillisAdjustSetpointUp >= upButtonTime) {
isAdjustSetpointUp = false;
}
}
if (isAdjustSetpointUp && isRangeSetpointAdjustOn) // If True, this allows the Range setpoint to be adjusted
{
range_temperature_setpoint += 0.1; // Range Setpoint increment
Serial.println(F("range_temperature_setpoint_up"));
RangeDisplay();
Buzzer();
}
if (isAdjustSetpointUp && isClubSetpointAdjustOn) // If True, this allows the Club setpoint to be adjusted
{
club_temperature_setpoint += 0.1; // Club Setpoint increment
Serial.println(F("club_temperature_setpoint_up"));
ClubDisplay();
Buzzer();
}
if (isAdjustSetpointUp && isAirgunSetpointAdjustOn) // If True, this allows the Airgun setpoint to be adjusted
{
airgun_temperature_setpoint += 0.1; // Airgun Setpoint increment
Serial.println(F("airgun_temperature_setpoint_up"));
AirgunDisplay();
Buzzer();
}
//----------------------------Down Button---------------------------//
if (downbutton.isPressed()) {
Serial.println(F(" down button pressed"));
isAdjustSetpointDown = true; // Setpoint adjustment Downwards is available
previousMillisAdjustSetpointDown = currentMillis;
}
if (isAdjustSetpointDown) {
if (currentMillis - previousMillisAdjustSetpointDown >= downButtonTime) {
isAdjustSetpointDown = false;
}
}
if (isAdjustSetpointDown && isRangeSetpointAdjustOn) // If True, this allows the Range setpoint to be adjusted
{
range_temperature_setpoint -= 0.1; // Range Setpoint decrement
Serial.println(F("range_temperature_setpoint_down"));
RangeDisplay();
Buzzer();
}
if (isAdjustSetpointDown && isClubSetpointAdjustOn) // If True, this allows the Club setpoint to be adjusted
{
club_temperature_setpoint -= 0.1; // Club Setpoint decrement
Serial.println(F("club_temperature_setpoint_down"));
ClubDisplay();
Buzzer();
}
if (isAdjustSetpointDown && isAirgunSetpointAdjustOn) // If True, this allows the Airgun setpoint to be adjusted
{
airgun_temperature_setpoint -= 0.1; // Airgun Setpoint decrement
Serial.println(F("airgun_temperature_setpoint_down"));
AirgunDisplay();
Buzzer();
}
//---------------------------Save Settings--------------------------//
if (isSetpointSaveOn && isAdjustSetpointUp && isAdjustSetpointDown) // If True, the new temperature & time settings are saved to EEPROM
{
for (int n = 0; n < 1; n++) {
Serial.println(F("Changes saved"));
EEPROM.put(EEPROM_address_1, range_temperature_setpoint); // write the new range setpoint value to EEPROM, only if it has changed
EEPROM.put(EEPROM_address_2, club_temperature_setpoint); // write the new club setpoint value to EEPROM, only if it has changed
EEPROM.put(EEPROM_address_3, airgun_temperature_setpoint); // write the new airgun setpoint value to EEPROM, only if it has changed
EEPROM.put(EEPROM_address_4, On_Normal_Range); // write the new Range Normal On time to EEPROM, only if it has changed
EEPROM.put(EEPROM_address_5, Off_Normal_Range); // write the new Range Normal Off time to EEPROM, only if it has changed
EEPROM.put(EEPROM_address_6, On_Normal_Club); // write the new Club Normal On time to EEPROM, only if it has changed
EEPROM.put(EEPROM_address_7, Off_Normal_Club); // write the new Club Normal Off time to EEPROM, only if it has changed
EEPROM.put(EEPROM_address_8, On_Normal_Airgun); // write the new Airgun Normal On time to EEPROM, only if it has changed
EEPROM.put(EEPROM_address_9, Off_Normal_Airgun); // write the new Airgun Normal Off time to EEPROM, only if it has changed
EEPROM.put(EEPROM_address_10, On_Sunday); // write the new Sunday On time to EEPROM, only if it has changed
EEPROM.put(EEPROM_address_11, Off_Sunday); // write the new Sunday Off time to EEPROM, only if it has changed
delay(2000);
RetrieveSetpoint();
lcd.setCursor(3, 3);
lcd.print(F("SETTINGS SAVED"));
delay(3000);
lcd.clear();
isMenuSelectOn = false; // Deactivates the set up menu
isTimeSettingOn = false;
}
}
//----------------------------Print delay---------------------------//
if (currentMillis - previousMillis >= printInterval) // has enough time passed yet?
{
previousMillis = previousMillis + printInterval; // If yes, set the time delay for the next print event
// capture & print data, or print latest data, etc.
// the closing curly brace is at end of loop.
//--------------------Daylight Saving Setting---------------------//
DateTime standardTime = rtc.now();
Serial.println(F("Standard Time"));
printTheTime(standardTime);
DateTime theTime = dst_rtc.calculateTime(standardTime); // takes into account DST
Serial.println(F("Time adjusted for Daylight Saving Time"));
printTheTime(theTime);
int currentTime = theTime.hour() * 60UL + theTime.minute();
//--------------------Timed heating setting-----------------------//
if (isTimeControlOn) {
Serial.println(F("Something time controlled is happening here!"));
if (theTime.dayOfTheWeek() != SUNDAY) {
// Monday to Saturday so use normal times
if (currentTime < On_Normal_Range || currentTime > Off_Normal_Range) {
// this is outside normal range heating time
isRangeHeatOn = false;
} else {
// this is within normal range heating time
isRangeHeatOn = true;
}
} else {
// Sunday times
if (currentTime < On_Sunday || currentTime > Off_Sunday) {
// this is outside Sunday range heating time
isRangeHeatOn = false;
} else {
// this is within Sunday range heating time
isRangeHeatOn = true;
}
}
if (theTime.dayOfTheWeek() != SUNDAY) {
// Monday to Saturday so use normal times
if (currentTime < On_Normal_Club || currentTime > Off_Normal_Club) {
// this is outside normal club heating time
isClubHeatOn = false;
} else {
// this is within normal club heating time
isClubHeatOn = true;
}
} else {
// Sunday times
if (currentTime < On_Sunday || currentTime > Off_Sunday) {
// this is outside Sunday club heating time
isClubHeatOn = false;
} else {
// this is within Sunday club heating time
isClubHeatOn = true;
}
}
if (theTime.dayOfTheWeek() != SUNDAY) {
// Monday to Saturday so use normal times
if (currentTime < On_Normal_Airgun || currentTime > Off_Normal_Airgun) {
// this is outside normal airgun heating time
isAirgunHeatOn = false;
} else {
// this is within normal airgun heating time
isAirgunHeatOn = true;
}
} else {
// Sunday times
if (currentTime < On_Sunday || currentTime > Off_Sunday) {
// this is outside Sunday airgun heating time
isAirgunHeatOn = false;
} else {
// this is within Sunday airgun heating time
isAirgunHeatOn = true;
}
}
}
//---------------------Date & Time display----------------------//
if ((!isMenuSelectOn) && (!isHeatingOverrideOn)) {
Serial.println(F("Time & date showing on LCD"));
lcd.setCursor(0, 0);
lcd.print(daysOfTheWeek[theTime.dayOfTheWeek()]);
lcd.setCursor(3, 0);
lcd.print(F(":"));
lcd.setCursor(4, 0);
if (theTime.day() < 10) lcd.print('0');
lcd.print(theTime.day(), DEC);
lcd.print(':');
if (theTime.month() < 10) lcd.print('0');
lcd.print(theTime.month(), DEC);
lcd.print(':');
lcd.print(theTime.year(), DEC);
lcd.setCursor(15, 0);
if (theTime.hour() < 10) lcd.print('0');
lcd.print(theTime.hour(), DEC);
lcd.print(':');
if (theTime.minute() < 10) lcd.print('0');
lcd.print(theTime.minute(), DEC);
}
//------------------------Serial print---------------------------//
Serial.print(F("Requesting temperatures..."));
range_sensor.requestTemperatures();
club_sensor.requestTemperatures();
airgun_sensor.requestTemperatures();
Serial.println(F(" done"));
Serial.print(F("Range: "));
Serial.println(range_sensor.getTempCByIndex(0));
Serial.print(F("Club: "));
Serial.println(club_sensor.getTempCByIndex(0));
Serial.print(F("Airgun: "));
Serial.println(airgun_sensor.getTempCByIndex(0));
}
} // End of loop
//----------------------Print time to serial-------------------------//
void printTheTime(DateTime theTimeP) {
Serial.print(theTimeP.year(), DEC);
Serial.print('/');
Serial.print(theTimeP.month(), DEC);
Serial.print('/');
Serial.print(theTimeP.day(), DEC);
Serial.print(' ');
Serial.print(theTimeP.hour(), DEC);
Serial.print(':');
Serial.print(theTimeP.minute(), DEC);
Serial.print(':');
Serial.print(theTimeP.second(), DEC);
Serial.println();
}
//------------------------Retrieve setpoint--------------------------//
void RetrieveSetpoint() {
EEPROM.get(EEPROM_address_1, range_temperature_setpoint); //retrieve the range setpoint from EEPROM
EEPROM.get(EEPROM_address_2, club_temperature_setpoint); //retrieve the club setpoint from EEPROM
EEPROM.get(EEPROM_address_3, airgun_temperature_setpoint); //retrieve the airgun setpoint from EEPROM
EEPROM.get(EEPROM_address_4, On_Normal_Range); //retrieve the Normal Range On Time from EEPROM
EEPROM.get(EEPROM_address_5, Off_Normal_Range); //retrieve the Normal Range Off Time from EEPROM
EEPROM.get(EEPROM_address_6, On_Normal_Club); //retrieve the Normal Club On Time from EEPROM
EEPROM.get(EEPROM_address_7, Off_Normal_Club); //retrieve the Normal Club Off Time from EEPROM
EEPROM.get(EEPROM_address_8, On_Normal_Airgun); //retrieve the Normal Airgun On Time from EEPROM
EEPROM.get(EEPROM_address_9, Off_Normal_Airgun); //retrieve the Normal Airgun Off Time from EEPROM
EEPROM.get(EEPROM_address_10, On_Sunday); //retrieve the Sunday On Time from EEPROM
EEPROM.get(EEPROM_address_11, Off_Sunday); //retrieve the Sunday Off Time from EEPROM
Serial.print(F("Range Temperature Setpoint - "));
Serial.print(range_temperature_setpoint);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_1);
Serial.print(F("Club Temperature Setpoint - "));
Serial.print(club_temperature_setpoint);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_2);
Serial.print(F("Airgun Temperature Setpoint - "));
Serial.print(airgun_temperature_setpoint);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_3);
Serial.print(F("Normal Range On Time - "));
Serial.print(On_Normal_Range);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_4);
Serial.print(F("Normal Range Off Time - "));
Serial.print(Off_Normal_Range);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_5);
Serial.print(F("Normal Club On Time - "));
Serial.print(On_Normal_Club);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_6);
Serial.print(F("Normal Club Off Time - "));
Serial.print(Off_Normal_Club);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_7);
Serial.print(F("Normal Airgun On Time - "));
Serial.print(On_Normal_Airgun);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_8);
Serial.print(F("Normal Airgun Off Time - "));
Serial.print(Off_Normal_Airgun);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_9);
Serial.print(F("Sunday On Time - "));
Serial.print(On_Sunday);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_10);
Serial.print(F("Sunday Off Time - "));
Serial.print(Off_Sunday);
Serial.print(F(" Stored at addr "));
Serial.println(EEPROM_address_11);
}
//---------------------------Heartbeat-------------------------------//
void Heartbeat() {
if (millis() - last_heart_beat_time >= heart_beat_on_off_time) { // time to swap status of the heart beat LED and update it
last_heart_beat_time = millis();
isHeartBeatOn = !isHeartBeatOn; // invert current heart beat status value
digitalWrite(heart_beat_pin, isHeartBeatOn); // update LED with new status
}
}
//---------------------------Menu Select-----------------------------//
void MenuSelect() {
switch (menuselector) {
case 0:
Serial.println(F("Case 0M")); // General menu
lcd.clear();
lcd.print(F("TEMPERATURE SETTING"));
lcd.print(F(" PRESS ENTER"));
TemperatureSettingMenu();
Buzzer();
break;
case 1:
Serial.println(F("Case 1M"));
lcd.clear();
lcd.print(F(" TIME SETTING"));
lcd.print(F(" PRESS ENTER"));
TimeSettingMenu();
Buzzer();
break;
case 2:
Serial.println(F("Case 2M"));
lcd.clear();
lcd.print(F(" PRESS ENTER"));
lcd.print(F(" TO CLEAR"));
Buzzer();
break;
}
}
//-------------------Temperature Setting Menu------------------------//
void TemperatureSettingMenu() {
{
Serial.println(F("Temp. Menu ON"));
isTemperatureSettingOn = true;
}
}
//------------------Temperature Selector---------------------------//
void TemperatureSelector() {
switch (temperatureselector) {
case 0:
Serial.println(F("Case 0Te")); // General menu
TemperatureMenuScreen();
break;
case 1:
Serial.println(F("Case 1Te")); // Displays the Range setpoint
RangeDisplay();
Buzzer();
break;
case 2:
Serial.println(F("Case 2Te")); // Displays the Club setpoint
ClubDisplay();
Buzzer();
break;
case 3:
Serial.println(F("Case 3Te")); // Displays the Airgun setpoint
AirgunDisplay();
Buzzer();
break;
case 4:
Serial.println(F("Case 4Te")); // Instructs how to save the new settings
SaveDisplay();
Buzzer();
break;
case 5:
Serial.println(F("Case 5Te")); // Reminds you to save
lcd.clear();
lcd.setCursor(3, 1);
lcd.print(F("Have you saved"));
lcd.setCursor(4, 2);
lcd.print(F("the settings?"));
Buzzer();
}
}
//----------------------Time Setting Menu----------------------------//
void TimeSettingMenu() {
{
isTimeSettingOn = true;
Serial.println(F("Time Menu ON"));
}
}
//-----------------------Time Selector------------------------------//
void TimeSelector() {
switch (timeselector) {
case 0:
Serial.println(F("Case 0Ti"));
TimeMenuScreen();
break;
}
}
//---------------------------Buzzer----------------------------------//
void Buzzer() {
{
digitalWrite(buzzer_pin, HIGH);
delay(100);
digitalWrite(buzzer_pin, LOW);
}
}
//-------------------Temperature Menu screen------------------------//
void TemperatureMenuScreen() {
lcd.clear();
lcd.print(F(" Setting Menu: "));
lcd.setCursor(0, 1);
lcd.print(F("Range: "));
lcd.print(range_temperature_setpoint, 1);
lcd.write((char)223);
lcd.print('C');
lcd.setCursor(0, 2);
lcd.print(F("Club: "));
lcd.print(club_temperature_setpoint, 1);
lcd.write((char)223);
lcd.print('C');
lcd.setCursor(0, 3);
lcd.print(F("Airgun:"));
lcd.print(airgun_temperature_setpoint, 1);
lcd.write((char)223);
lcd.print('C');
isSetpointSaveOn = false;
}
//---------------------Time Menu screen-----------------------------//
void TimeMenuScreen() {
lcd.clear();
lcd.print(F(" Time Menu: "));
lcd.setCursor(0, 1);
lcd.print(F("Range: "));
}
//-----------------------Setting Displays---------------------------//
void RangeDisplay() {
isRangeSetpointAdjustOn = true;
isClubSetpointAdjustOn = false;
isAirgunSetpointAdjustOn = false;
Serial.println(F("RangeChange"));
lcd.clear();
lcd.print(F(" Setting Menu: "));
lcd.setCursor(0, 1);
lcd.print(F("Range: "));
lcd.print(range_temperature_setpoint, 1);
lcd.write((char)223);
lcd.print('C');
}
//-------------------------------------------------------------------//
void ClubDisplay() {
isClubSetpointAdjustOn = true;
isRangeSetpointAdjustOn = false;
isAirgunSetpointAdjustOn = false;
Serial.println(F("ClubChange"));
lcd.clear();
lcd.print(F(" Setting Menu: "));
lcd.setCursor(0, 2);
lcd.print(F("Club: "));
lcd.print(club_temperature_setpoint, 1);
lcd.write((char)223);
lcd.print('C');
}
//-------------------------------------------------------------------//
void AirgunDisplay() {
isAirgunSetpointAdjustOn = true;
isRangeSetpointAdjustOn = false;
isClubSetpointAdjustOn = false;
Serial.println(F("AirgunChange"));
lcd.clear();
lcd.print(F(" Setting Menu: "));
lcd.setCursor(0, 3);
lcd.print(F("Airgun:"));
lcd.print(airgun_temperature_setpoint, 1);
lcd.write((char)223);
lcd.print('C');
}
//------------------------Save Display-------------------------------//
void SaveDisplay() {
isRangeSetpointAdjustOn = false;
isClubSetpointAdjustOn = false;
isAirgunSetpointAdjustOn = false;
Serial.println(F("SavingChanges"));
lcd.clear();
lcd.print(F("To save the changes"));
lcd.setCursor(2, 1);
lcd.print(F("Press UP & DOWN"));
lcd.setCursor(5, 2);
lcd.print(F("Together"));
isSetpointSaveOn = true;
}
//---------------------Temperature display - ------------------------//
void TemperatureDisplay() {
lcd.setCursor(0, 1); // Range Temperature
lcd.print(F("Range: "));
lcd.print(range_sensor.getTempCByIndex(0), 1);
lcd.write((char)223);
lcd.print('C');
lcd.setCursor(0, 2); // Club Temperature
lcd.print(F("Club: "));
lcd.print(club_sensor.getTempCByIndex(0), 1);
lcd.write((char)223);
lcd.print('C');
lcd.setCursor(0, 3); // Airgun Temperature
lcd.print(F("Airgun:"));
lcd.print(airgun_sensor.getTempCByIndex(0), 1);
lcd.write((char)223);
lcd.print('C');
}
//------------------------Heating Override---------------------------//
void HeatingOverride() {
Serial.println(F(" Heating Override is On"));
Serial.println(F("Timed Control is OFF"));
isRangeHeatOn = true;
isClubHeatOn = true;
isAirgunHeatOn = true;
isHeatingOverrideOn = true;
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print(F(" OVERRIDE IS ON "));
}
//--------------------Heating Override Completed----------------------//
void HeatingOverrideCompleted() {
Serial.println(F(" Heating Override is complete"));
Serial.println(F("Timed Control is ON"));
isRangeHeatOn = false;
isClubHeatOn = false;
isAirgunHeatOn = false;
isHeatingOverrideOn = false;
lcd.setCursor(0, 0);
lcd.print(F(" OVERRIDE IS OFF "));
}
//-----------------------Heating Available---------------------------//
void HeatingAvailable() {
RangeHeatingAvailable();
ClubHeatingAvailable();
AirgunHeatingAvailable();
Serial.println(F("Heating is available"));
}
//-------------------------------------------------------------------//
void RangeHeatingAvailable() {
{
if (isRangeHeatOn) {
NormalHeatingRange();
Serial.println(F("Heating R"));
} else {
FrostPreventionRange();
Serial.println(F("Frost Prev. R"));
}
}
}
//-------------------------------------------------------------------//
void ClubHeatingAvailable() {
{
if (isClubHeatOn) {
NormalHeatingClub();
Serial.println(F("Heating C"));
} else {
FrostPreventionClub();
Serial.println(F("Frost Prev. C"));
}
}
}
//-------------------------------------------------------------------//
void AirgunHeatingAvailable() {
{
if (isAirgunHeatOn) {
NormalHeatingAirgun();
Serial.println(F("Heating A"));
} else {
FrostPreventionAirgun();
Serial.println(F("Frost Prev. A"));
}
}
}
//-------------------Frost Prevention Range--------------------------//
void FrostPreventionRange() {
if ((range_sensor.getTempCByIndex(0) <= (frost_setpoint - deadzone))) {
digitalWrite(range_relay, HIGH);
Serial.println(F("Range frost Heating"));
lcd.setCursor(13, 1);
lcd.print(F(" ON F"));
} else {
if ((range_sensor.getTempCByIndex(0) >= (frost_setpoint + deadzone))) {
digitalWrite(range_relay, LOW);
lcd.setCursor(13, 1);
lcd.print(F(" OFF F"));
}
}
}
//--------------------Frost Prevention Club-------------------------//
void FrostPreventionClub() {
if ((club_sensor.getTempCByIndex(0) <= (frost_setpoint - deadzone))) {
digitalWrite(club_relay, HIGH);
Serial.println(F("Club frost Heating"));
lcd.setCursor(13, 2);
lcd.print(F(" ON F"));
} else {
if ((club_sensor.getTempCByIndex(0) >= (frost_setpoint + deadzone))) {
digitalWrite(club_relay, LOW);
lcd.setCursor(13, 2);
lcd.print(F(" OFF F"));
}
}
}
//---------------------Frost Prevention Airgun-----------------------//
void FrostPreventionAirgun() {
if ((airgun_sensor.getTempCByIndex(0) <= (frost_setpoint - deadzone))) {
digitalWrite(airgun_relay, HIGH);
Serial.println(F("Air frost Heating"));
lcd.setCursor(13, 3);
lcd.print(F(" ON F"));
} else {
if ((airgun_sensor.getTempCByIndex(0) >= (frost_setpoint + deadzone))) {
digitalWrite(airgun_relay, LOW);
lcd.setCursor(13, 3);
lcd.print(F(" OFF F"));
}
}
}
//-------------------Normal Heating Range----------------------------//
void NormalHeatingRange() {
if ((range_sensor.getTempCByIndex(0) <= (range_temperature_setpoint - deadzone))) {
digitalWrite(range_relay, HIGH);
Serial.println(F("Normal Heating R"));
lcd.setCursor(13, 1);
lcd.print(F(" ON T"));
} else {
if ((range_sensor.getTempCByIndex(0) >= (range_temperature_setpoint + deadzone))) {
digitalWrite(range_relay, LOW);
lcd.setCursor(13, 1);
lcd.print(F(" OFF T"));
}
}
}
//--------------------Normal Heating Club ---------------------------//
void NormalHeatingClub() {
if ((club_sensor.getTempCByIndex(0) <= (club_temperature_setpoint - deadzone))) {
digitalWrite(club_relay, HIGH);
Serial.println(F("Normal Heating C"));
lcd.setCursor(13, 2);
lcd.print(F(" ON T"));
} else {
if ((club_sensor.getTempCByIndex(0) >= (club_temperature_setpoint + deadzone))) {
digitalWrite(club_relay, LOW);
lcd.setCursor(13, 2);
lcd.print(F(" OFF T"));
}
}
}
//---------------------Normal Heating Airgun-------------------------//
void NormalHeatingAirgun() {
if ((airgun_sensor.getTempCByIndex(0) <= (airgun_temperature_setpoint - deadzone))) {
digitalWrite(airgun_relay, HIGH);
Serial.println(F("Normal Heating A"));
lcd.setCursor(13, 3);
lcd.print(F(" ON T"));
} else {
if ((airgun_sensor.getTempCByIndex(0) >= (airgun_temperature_setpoint + deadzone))) {
digitalWrite(airgun_relay, LOW);
lcd.setCursor(13, 3);
lcd.print(F(" OFF T"));
}
}
}
If you follow the code, when you get to "Temperature setting activated" you set isMenuSelectionOn to TRUE, but a couple of if() statements down when you get to "Settings deactivated", you reset it back to FALSE so the next time through loop(), you do it again.
Rather than have all these is<something>On variables, I would suggest you rethink about your code in terms of which MODE you are in since they all (?) are mutually exclusive. You can not simultaneously have isMenuSelectionOn and isTemperatureSettingOn and isTimeSettingOn, etc.
Then, based on which mode you are in, you only do certain checks. I haven't studied the code enough to be sure, but it seems like you have
NORMAL_MODE
OVERRIDE_MODE
SETUP_MODE
and then maybe some sub-modes for setup
TIME_SETUP_MODE
TEMPERATURE_SETUP_MODE
You can code these up as enumerations like this which makes your code easier to read
enum modes { NORMAL_MODE, OVERRIDE_MODE, SETUP_MODE };
enum setupmodes { TIME_SETUP_MODE, TEMPERATURE_SETUP_MODE };
You can treat them like constant integers
int mode = NORMAL_MODE;
...
void loop() {
...
if ( mode == NORMAL_MODE ) handleNormalMode();
else if ( mode == OVERRIDE_MODE ) handleOverride();
else if ( mode == SETUP_MODE ) handleSetup();
else Serial.println("oops. unhandled mode");
...
just my $0.02
Another option for executing mutual exclusive modes of operation is to use the switch-case-break-statement.
Which does enable mutual exclusive code-execution.
The switch-case-break-statement reduces the if-conditions to a minimum.
All the code that is not nescessary to execute is simply skipped over.
This means you don't need additional if-conditions like
if ( isMenuSelectionOn == true) {
// in case we are in a different mode don't execute this part of the code
}
Edit: After I tried to follow what your code is doing starting with where in the code is
Serial.print("Normal Heating R");
which leads from function to function to function
then trying to find
Serial.print("Temperature setting activated");
and to find
Serial.print("Settings deactivated");
Where in many many places you added more ane more and more if-conditions
with global variables like
if (rightbutton.isPressed() && (isTimeSettingOn)) {
if (currentMillis - previousMillisTimedStart2 >= OffTimed2) // Deactivates the set up menu
{
Serial.println(F(" Settings deactivated"));
lcd.clear();
lcd.print(F(" MENU EXITED"));
isMenuSelectOn = false;
isTimeSettingOn = false;
Buzzer();
}
}
To me it seems you learned some basic programming like if-conditions and then avoided to learn some medium advanced concepts like "state-machine" with switch-case-break
and added another mode, another if-condition and more if-conditions and more if-conditions.
Instead of re-designing code-flow. Not writing your code from scratch.
Now you are in the situation that there are so many flag-variables and if-conditions that you lost oversight and all these variables and if-conditions interfere with each other without really understanding how they interfere with each other.
Most of your code can be re-used except the many many if-conditions which become obsolete if you use the concept of a state-machine.
Like user @blh64 wrote
There might be some extra-things like in override mode checking for ....
Can you please describe on a pure functional level which means avoid using code to explain it. Explain the functionality with normal words.
What different modes of operation do you have and what is going on in each mode
Please.
Switch statement. Ok. That's what it is.
Switch/case, used alla time
Switch-case-break? No, just no. Nowhere never not here nor there.
a7
You will have to go into details and write very good arguments to convince me why I should name it just "switch"
My reasons to to name it switch-case-break:
If somebody doesn't know anything about this statement naming it switch-case-break gives right from the start a headsup that it is not only the codeline with the switch
To make it all work you must use the combination with "case" and "break"
The "break" is that part that realises the mutual exclusiveness of each "case"
If you forget to add the "break" the mutual exclusiveness is gone.
Now write in detail what reasons do you have to not name it switch-case-break?
I haven't named it with a nonsense-name like "hula-dada-didi"
Anybody that knows how this statement works and what it is still immidiately will recognise it.
Because you are not in charge of naming things. It has a name, use it.
As for the bold text, lose it. Again, please.
a7
Does not convince me.
It uses the same word plus two additional words very close related to the thing.
No confusing, no renaming. I keep it !
If you think my naming violates forum-rules report to a moderator.