# Thermostat project

### Description

There are three buttons on the thermostat, the first one is the menu selector, with which we can move between the thermostat's menus. With the second and third buttons, the values found in the menus can be modified (increased or decreased) depending on what value you want to set in the given menu.

The thermostat's display automatically displays data if you do not touch the device's operating buttons. The displayed values can be scrolled with the arrows. If you are only interested in a single piece of data, press the two modifier buttons at the same time, and the display will only show the menu displayed at that moment.

### Menus and Submenus:

- Runs out_in
  - In this menu, it is possible to turn the heating off or on. If the heating is off, the boilers will not start even if the temperature drops below the set on the thermostat.
- Hofok for primary boiler
  - In this menu, you can set the desired temperature between 0 and 45 degrees Celsius. The thermostat tries to reach the value set here on the PRIMARY set boiler.
- Hofok for secondary boiler
  - In this menu, the desired temperature can be set between 0 and the temperature set on the first boiler. The thermostat tries to reach the value set here on the boiler set to SECONDARY.
- Manual mode selection
  - Here it is possible to switch on the selected boiler manually. In this case, the automatic switches off, and the selected boiler starts. The boiler will operate until you increase the temperature of the room by one degree Celsius or until the manual mode is stopped.
- Selection of primary boiler
  - Here you can choose which boiler you want to choose as primary, the secondary one will be the remaining boiler.
- Select your running mode
  - only primary
    - In this case, only the primary boiler will operate and will try to maintain the set temperature.
  - Auto1
    - Try to heat the room with the primary boiler until the temperature set on the secondary boiler drops below the temperature. In which case the primary one is switched off, and the secondary boiler is switched on, which operates until the temperature set for the secondary boiler is reached, and then turns on the primary one again and tries to heat it up to the temperature set on the primary boiler.
  - Auto2
    - It tries to heat up with the primary boiler until the temperature falls below the temperature set on the secondary boiler. Then it tries to heat up with the secondary boiler to the temperature set for the primary boiler, from where it tries to continue heating with the primary boiler again.
  - Auto3
    - Try to heat the room with the primary boiler. However, if the temperature falls a full degree below the set value and the primary one cannot heat the house, the secondary one will be turned on until it reaches the temperature set by the primary one. (This mode tries to keep the primary set value by using any boiler)

The boiler controller

- This unit is responsible for measuring the temperature of the boiler and the water tank, as well as turning the boilers off and on.
- The boiler controller is in continuous contact with the thermostat, and if this connection is interrupted for some reason, the boilers are switched off and the yellow LED on the left starts to flash. In which case, it is not possible to turn on the boiler manually, but the connection between the thermostat and the controller must be restored.

### Buttons and Their Functions:

1. With this, you can turn on the machine or turn off the heating completely. If no LED lights up on the device, it means that the heating is off. If you want to turn it on, you have to press this button.
2. The second button switches to manual mode and turns on the combination boiler, in which case the thermostat measures the current temperature and heats one degree warmer than that, then switches back to automatic mode.
3. The third button has the same function as the second, only it switches on the gas boiler.

The two boilers cannot be started at the same time, and it is not possible to switch the boilers on permanently manually. The values converted here can also be modified in the thermostat's menu.

### The outer look of the thermostat

This is the two main unit each of them contains a microcontroller, and the two computers are connected to each other via UARTR connection

### The inside of the units

Everything in the inside is soldered together, and I put a hot glue layer over the connections to make them permanent, and reliable

### The Schematics

Just like basically all my Arduino projects, I've connected everything to the microcontroller, so it can be controlled and modified just by code.

### The code of the Master unit

#include <EEPROM.h> #include "LedControl.h" #include <Adafruit_AHTX0.h> int displaytime = 300; //The overall speed of the thermostat display float calibration = 0; //Withthis variable you can calibrate the temperature sensor by adding or extracting from its value //Sensors and the hardware Adafruit_AHTX0 aht; LedControl DP = LedControl(2, 4, 3, 1); int button1 = 5, button2 = 6, button3 = 7; int YellowLed = 9, RedLed = 8; //Main containers for displaying and showing the display data int DPCurrent[7]; //Load the default values for the diplayer struct whichwill contain all the displayable data int Menu[6]; int currentLetter = 0; //The crrently displayed letter int seCurrentLetter = 0; //the currently displayed letter of the value int CurrentDisplayed = 0; //Which container is displayed at the moment int ActiveBurner = 0; //1 is wood burner 2 is gas burner char isstatic = 'n'; int scheduler = 0; bool menu = false, first = true, manual = false; float temperaturesum =0; int menuTimer = 0; int hiszterezis = 50; //Itt allithato a termosztat hiszterezise void setup() { // put your setup code here, to run once: Serial.begin(9600); DP.shutdown(0, false); DP.setIntensity(0, 0.1); DP.clearDisplay(0); aht.begin(); pinMode(button1, INPUT_PULLUP); pinMode(button2, INPUT_PULLUP); pinMode(button3, INPUT_PULLUP); pinMode(RedLed, OUTPUT); pinMode(YellowLed, OUTPUT); DPCurrent[0] = 9999; //This is PERMANENT Menu[0] = EEPROM.get(0, Menu[0]); Menu[1] = EEPROM.get(2, Menu[1]); Menu[2] = EEPROM.get(4, Menu[2]); Menu[3] = 0; Menu[4] = EEPROM.get(6, Menu[4]); Menu[5] = EEPROM.get(8, Menu[5]); } String GetDPCValue(int elem){ String Datawriteout; switch (elem) { case 0: Datawriteout = "hommerseklet..."; break; case 1: Datawriteout = "paratartalomm..."; break; case 2: Datawriteout = "celhommerseklet..."; break; case 3: Datawriteout = "kulonbseg..."; break; case 4: Datawriteout = "aktiv kazan..."; break; case 5: Datawriteout = "hofok vegyes..."; break; case 6: Datawriteout = "hofok puffer..."; } return Datawriteout; } String GetMenuValue(int elem){ String Datawriteout; switch (elem) { case 0: Datawriteout = "futes ki.be..."; break; case 1: Datawriteout = "hofok elsodleges kazanhoz..."; break; case 2: Datawriteout = "hofok mmasodlagos kazanhoz..."; break; case 3: Datawriteout = "mmanual mmode kivalasztasa..."; break; case 4: Datawriteout = "elsodleges kazan kivalasztasa..."; break; case 5: Datawriteout = "futesimmod kivalasztasa..."; } return Datawriteout; } byte segmentABC(char letter){ byte BinaryLetter; switch(letter){ case 'a': BinaryLetter = B01110111; break; case 'b': BinaryLetter = B0011111; break; case 'c': BinaryLetter = B01001110; break; case 'd': BinaryLetter = B00111101; break; case 'e': BinaryLetter = B01001111; break; case 'f': BinaryLetter = B01000111; break; case 'g': BinaryLetter = B01011110; break; case 'h': BinaryLetter = B00010111; break; case 'i': BinaryLetter = B00110000; break; case 'j': BinaryLetter = B01011000; break; case 'k': BinaryLetter = B00110111; break; case 'l': BinaryLetter = B00001110; break; case 'm': BinaryLetter = B00010101; break; case 'n': BinaryLetter = B00010101; break; case 'o': BinaryLetter = B00011101; break; case 'p': BinaryLetter = B01100111; break; case 'q': BinaryLetter = B01110011; break; case 'r': BinaryLetter = B00000101; break; case 's': BinaryLetter = B01011011; break; case 't': BinaryLetter = B00001111; break; case 'v': BinaryLetter = B00011100; break; case 'u': BinaryLetter = B00011100; break; case 'y': BinaryLetter = B00110011; break; case 'z': BinaryLetter = B01101101; break; case '.': BinaryLetter = B10000000; break; case '1': BinaryLetter = B00110000; break; case '2': BinaryLetter = B01101101; break; case '3': BinaryLetter = B01111001; break; default: BinaryLetter = B00000000; } return BinaryLetter; } byte segmentNumbers(char letter){ byte BinaryLetter; switch(letter){ case '0': BinaryLetter = B01111110; break; case '1': BinaryLetter = B00110000; break; case '2': BinaryLetter = B01101101; break; case '3': BinaryLetter = B01111001; break; case '4': BinaryLetter = B00110011; break; case '5': BinaryLetter = B01011011; break; case '6': BinaryLetter = B1011111; break; case '7': BinaryLetter = B01110000; break; case '8': BinaryLetter = B01111111; break; case '9': BinaryLetter = B01111011; break; case '-': BinaryLetter = B00000001; break; } return BinaryLetter; } void displaytimer(char skip = 'n'){ //skip could have 3 values default is n (not to skip), f is skip forward, b is skip backwards if(skip == 'f'){ if(CurrentDisplayed +1 >= sizeof(DPCurrent) / sizeof(DPCurrent[0]) ) CurrentDisplayed = 0; else CurrentDisplayed++; currentLetter = 0; seCurrentLetter = 0; } if(skip == 'b'){ if(CurrentDisplayed -1 < 0 ) CurrentDisplayed = sizeof(DPCurrent) / sizeof(DPCurrent[0]); else CurrentDisplayed--; currentLetter = 0; seCurrentLetter = 0; } String CurrentlyDisplayedText = GetDPCValue(CurrentDisplayed); if(currentLetter < CurrentlyDisplayedText.length()){ DP.clearDisplay(0); for(int j = 0; j <= currentLetter; j++){ DP.setRow(0,j,segmentABC(CurrentlyDisplayedText[currentLetter-j])); } currentLetter++; } if(CurrentDisplayed == 3) DPCurrent[3] = DPCurrent[0] - DPCurrent[2]; if(currentLetter >= CurrentlyDisplayedText.length() && seCurrentLetter > -10 && CurrentDisplayed != 4 && CurrentDisplayed < sizeof(DPCurrent) / sizeof(DPCurrent[0])){ DP.clearDisplay(0); DP.clearDisplay(0); String a; if(DPCurrent[CurrentDisplayed] < 0){ a = "-"; for(int i = 0; i < 4-String(DPCurrent[CurrentDisplayed]*-1).length(); i++){ a += "0"; } a += String(DPCurrent[CurrentDisplayed]*-1); DP.setRow(0,6,segmentNumbers(a[0])); DP.setRow(0,5,segmentNumbers(a[1])); byte modifi = segmentNumbers(a[2]); modifi |= (1 << 7);; DP.setRow(0,4, modifi); DP.setRow(0,3,segmentNumbers(a[3])); DP.setRow(0,2,segmentNumbers(a[4])); } else{ a = ""; for(int i = 0; i < 4-String(DPCurrent[CurrentDisplayed]).length(); i++){ a += "0"; } a += String(DPCurrent[CurrentDisplayed]); DP.setRow(0,5,segmentNumbers(a[0])); byte modifi = segmentNumbers(a[1]); modifi |= (1 << 7);; DP.setRow(0,4, modifi); DP.setRow(0,3,segmentNumbers(a[2])); DP.setRow(0,2,segmentNumbers(a[3])); } if(CurrentDisplayed != 1){ DP.setRow(0,1,B01100011); DP.setRow(0,0,segmentABC('c')); }else{ DP.setRow(0,1,segmentABC('r')); DP.setRow(0,0,segmentABC('h')); } seCurrentLetter--; } bool securrentready = false; if(currentLetter >= CurrentlyDisplayedText.length() && CurrentDisplayed == 4){ DP.clearDisplay(0); String securrentText = ""; switch(DPCurrent[4]){ case 0: securrentText = "nincs aktiv..."; break; case 1: securrentText = "vegyes kazan."; break; case 2: securrentText = "gaz kazan."; } if(seCurrentLetter < CurrentlyDisplayedText.length()){ for(int j = 0; j <= seCurrentLetter; j++){ DP.setRow(0,j,segmentABC(securrentText[seCurrentLetter-j])); } seCurrentLetter++; if(seCurrentLetter >= securrentText.length()) securrentready = true; } } if((currentLetter >= CurrentlyDisplayedText.length() && (securrentready || seCurrentLetter <= -10)) || CurrentDisplayed >= sizeof(DPCurrent) / sizeof(DPCurrent[0]) ){ if(skip == 'n'){ if(CurrentDisplayed +1 > sizeof(DPCurrent) / sizeof(DPCurrent[0]) ) CurrentDisplayed = 0; else CurrentDisplayed++; } currentLetter = 0; seCurrentLetter = 0; } } char BlinkYellow(char isstatic = 'n'){ digitalWrite(YellowLed, HIGH); while(digitalRead(button2) == LOW || digitalRead(button3) == LOW){ if(digitalRead(button2) == LOW && digitalRead(button3) == LOW){ digitalWrite(YellowLed, LOW); if(isstatic == 'n') isstatic = 'c'; else isstatic = 'n'; while(digitalRead(button2) == LOW || digitalRead(button3) == LOW); break; } } digitalWrite(YellowLed, LOW); return isstatic; } void displayTheTextValue(String &Writeout){ DP.clearDisplay(0); if(seCurrentLetter < Writeout.length()){ for(int j = 0; j <= seCurrentLetter; j++){ DP.setRow(0,j,segmentABC(Writeout[seCurrentLetter-j])); } seCurrentLetter++; }else{ seCurrentLetter = 0; } } void displayTheNumberValue(){ DP.clearDisplay(0); String a; if(Menu[CurrentDisplayed] < 0){ a = "-"; for(int i = 0; i < 4-String(Menu[CurrentDisplayed]*-1).length(); i++){ a += "0"; } a += String(Menu[CurrentDisplayed]*-1); DP.setRow(0,6,segmentNumbers(a[0])); DP.setRow(0,5,segmentNumbers(a[1])); byte modifi = segmentNumbers(a[2]); modifi |= (1 << 7);; DP.setRow(0,4, modifi); DP.setRow(0,3,segmentNumbers(a[3])); DP.setRow(0,2,segmentNumbers(a[4])); } else{ a = ""; for(int i = 0; i < 4-String(Menu[CurrentDisplayed]).length(); i++){ a += "0"; } a += String(Menu[CurrentDisplayed]); DP.setRow(0,5,segmentNumbers(a[0])); byte modifi = segmentNumbers(a[1]); modifi |= (1 << 7);; DP.setRow(0,4, modifi); DP.setRow(0,3,segmentNumbers(a[2])); DP.setRow(0,2,segmentNumbers(a[3])); } DP.setRow(0,1,B01100011); DP.setRow(0,0,segmentABC('c')); } void menuController(char skip = 'n', int change = 0){ while(digitalRead(button1) == LOW); if(menuTimer >= 200) CurrentDisplayed = 6; //Sets the amount of time you can spend inside a menu if(first){ DP.clearDisplay(0); DP.setRow(0,6, segmentABC('m')); DP.setRow(0,5, segmentABC('m')); DP.setRow(0,4, segmentABC('e')); DP.setRow(0,3, segmentABC('n')); DP.setRow(0,2, segmentABC('u')); delay(1500); DP.clearDisplay(0); CurrentDisplayed = 0; currentLetter = 0; seCurrentLetter = 0; first = false; } if(skip == 'f'){ CurrentDisplayed++; currentLetter = 0; seCurrentLetter = 0; } if(currentLetter < GetMenuValue(CurrentDisplayed).length() && menu != false){ DP.clearDisplay(0); for(int j = 0; j <= currentLetter; j++){ DP.setRow(0,j,segmentABC(GetMenuValue(CurrentDisplayed)[currentLetter-j])); } currentLetter++; } if(currentLetter >= GetMenuValue(CurrentDisplayed).length() && menu != false){ digitalWrite(YellowLed, HIGH); if(change != 0) seCurrentLetter = 0; String Writeout; if(CurrentDisplayed == 0){ //When the first menu is selected if(change > 0) Menu[0] = 1; Menu[0]; if(change < 0) Menu[0] = 0; Menu[0]; switch (int(Menu[0])){ case 1: Writeout = "be kapcsolva"; break; case 0: Writeout = "ki kapcsolva"; break; } displayTheTextValue(Writeout); } if(CurrentDisplayed == 1){ //When the Second menu is selected if(change > 0) { if( (Menu[1] - 50) <= 4500) Menu[1] += 50;} if(change < 0) { if( (Menu[1] - 50) >= 500) Menu[1] -= 50; if(Menu[2] > Menu[1]) Menu[2] = Menu[1]-100;} displayTheNumberValue(); } if(CurrentDisplayed == 2){ //When the third menu is selected if(change > 0) { if((Menu[1]-100) > (Menu[2])) Menu[2] += 50;} if(change < 0) { if( (Menu[2] - 50) >= 500) Menu[2] -= 50;} displayTheNumberValue(); } if(CurrentDisplayed == 3){ //Manual mode selector (fouth menu) if(change > 0 && Menu[3] < 2) { Menu[3] += 1;} if(change < 0 && Menu[3] > 0) { Menu[3] -= 1;} switch (int(Menu[3])){ case 0: Writeout = "kikapcsolva"; break; case 1: Writeout = "vegyes aktiv"; break; case 2: Writeout = "gaz aktiv"; break; } displayTheTextValue(Writeout); } if(CurrentDisplayed == 4){ //Primary burner selector (fourth menu) if(change > 0) Menu[4] = 1; if(change < 0) Menu[4] = 0; switch(Menu[4]){ case 0: Writeout = "vegyes kazan"; break; case 1: Writeout = "gaz kazan"; break; } displayTheTextValue(Writeout); } if(CurrentDisplayed == 5){ //Automation behaviour selector (fith menu) if(change > 0 && Menu[5] < 3) { Menu[5] += 1;} if(change < 0 && Menu[5] > 0) { Menu[5] -= 1;} switch (int(Menu[5])){ case 0: Writeout = "csak elsodleges"; break; case 1: Writeout = "auto 1"; break; case 2: Writeout = "auto 2"; break; case 3: Writeout = "auto 3"; break; } displayTheTextValue(Writeout); } } if(CurrentDisplayed == 6){ saveChanges(); DP.clearDisplay(0); DP.setRow(0,7, segmentABC('m')); DP.setRow(0,6, segmentABC('m')); DP.setRow(0,5, segmentABC('e')); DP.setRow(0,4, segmentABC('n')); DP.setRow(0,3, segmentABC('t')); DP.setRow(0,2, segmentABC('v')); DP.setRow(0,1, segmentABC('e')); delay(1500); DP.clearDisplay(0); menu = false; digitalWrite(YellowLed, LOW); first = true; CurrentDisplayed = 0; } } void burnerOnoff(){ DPCurrent[4] = ActiveBurner; if(ActiveBurner > 0){ digitalWrite(RedLed, HIGH); }else { digitalWrite(RedLed, LOW); } } void takeAction(){ if(Menu[0] > 0){ if(Menu[3] > 0){ //Takes action if manual mode is ON if(DPCurrent[0] >= DPCurrent[2]){ Menu[3] = 0; ActiveBurner = 0; DPCurrent[2] = 0; manual = false; }else { ActiveBurner = Menu[3]; } }else if(Menu[5] == 0){ DPCurrent[2] = Menu[1]; //Sets the target heat on the screen if((DPCurrent[0] < Menu[1] - hiszterezis) && DPCurrent[0] < Menu[1]){ ActiveBurner = Menu[4]+1; }else if(DPCurrent[0] > Menu[1]) ActiveBurner = 0; }else if(Menu[5] == 1){ DPCurrent[2] = Menu[1]; if((DPCurrent[0] < Menu[1] - hiszterezis) && (DPCurrent[0] < Menu[1]) && (DPCurrent[0] > Menu[2])){ DPCurrent[2] = Menu[1]; ActiveBurner = Menu[4]+1; }else if((DPCurrent[0] < Menu[2] - hiszterezis) && DPCurrent[0] < Menu[2]){ DPCurrent[2] = Menu[2]; switch (Menu[4]+1){ case 1: ActiveBurner = 2; break; case 2: ActiveBurner = 1; break; } } else if(DPCurrent[0] > Menu[2]){ ActiveBurner = Menu[4]+1;} else if(DPCurrent[0] > Menu[1]) {ActiveBurner = 0; } }else if(Menu[5] == 2){ DPCurrent[2] = Menu[1]; if((DPCurrent[0] < Menu[1] - hiszterezis) && DPCurrent[0] < Menu[1] && DPCurrent[0] > Menu[2]){ DPCurrent[2] = Menu[1]; if(ActiveBurner == 0) ActiveBurner = Menu[4]+1; }else if((DPCurrent[0] < Menu[2] - hiszterezis) && DPCurrent[0] < Menu[2]){ DPCurrent[2] = Menu[1]; switch (Menu[4]+1){ case 1: ActiveBurner = 2; break; case 2: ActiveBurner = 1; break; } } else if((DPCurrent[0] > Menu[1])) ActiveBurner = 0; } else if(Menu[5] == 3){ DPCurrent[2] = Menu[1]; if((DPCurrent[0] < Menu[1] - hiszterezis) && DPCurrent[0] < Menu[1] && DPCurrent[0] > Menu[1] - hiszterezis*2){ DPCurrent[2] = Menu[1]; ActiveBurner = Menu[4]+1; }else if((DPCurrent[0] < Menu[1] - hiszterezis*2) && DPCurrent[0] < Menu[1]){ DPCurrent[2] = Menu[1]; switch (Menu[4]+1){ case 1: ActiveBurner = 2; break; case 2: ActiveBurner = 1; break; } } else if(DPCurrent[0] > Menu[1]) ActiveBurner = 0; } } else{ ActiveBurner = 0; } burnerOnoff(); } void saveChanges(){ if(Menu[3] > 0 && manual == false){ //If manual mode is on if(DPCurrent[2] != DPCurrent[0]+100){ DPCurrent[2] = DPCurrent[0]+100; manual = true; } } if(Menu[3] == 0){ manual = false; } int value; // Temporary variable to store the read value EEPROM.get(0, value); if(value != Menu[0]) { EEPROM.put(0, Menu[0]); } EEPROM.get(2, value); if(value != Menu[1]) { EEPROM.put(2, Menu[1]); } EEPROM.get(4, value); if(value != Menu[2]) { EEPROM.put(4, Menu[2]); } EEPROM.get(6, value); if(value != Menu[4]) { EEPROM.put(6, Menu[4]); } EEPROM.get(8, value); if(value != Menu[5]) { EEPROM.put(8, Menu[5]); } }; int messagetimer = 0; int connectionActivity = 0; int blinker = 0; void loop() { if(messagetimer == 10 && !Serial.available()){ String SMessage = "A"; SMessage += String(ActiveBurner % 10); // Ensure ActiveBurner is a single digit SMessage += String(Menu[3] % 10); // Ensure Menu[0] is a single digit SMessage += String(Menu[0] % 10); Serial.println(SMessage); }else if(messagetimer == 14){ if(Serial.available()){ String RMessage = Serial.readString(); Serial.println(RMessage); if(RMessage[0] == 'B'){ connectionActivity = 0; digitalWrite(YellowLed, LOW); if(RMessage[1] == '0') Menu[3] = 0; if(RMessage[1] == '1') Menu[3] = 1; if(RMessage[1] == '2') Menu[3] = 2; if(RMessage[2] == '0') Menu[0] = 0; if(RMessage[2] == '1') Menu[0] = 1; String a = RMessage.substring(3, 7); DPCurrent[5] = int(a.toInt()); a = RMessage.substring(7, 11); DPCurrent[6] = int(a.toInt()); saveChanges(); }else{ if(connectionActivity < 300) connectionActivity++; } } messagetimer = 0; if(connectionActivity < 300) connectionActivity++; } if(connectionActivity > 5){ if(blinker >= 1 && blinker < 2){digitalWrite(YellowLed, HIGH);} if(blinker >= 1 && blinker > 2){digitalWrite(YellowLed, LOW); blinker = 0;}; blinker++; } if(scheduler <= 50){ sensors_event_t humidity, temp; aht.getEvent(&humidity, &temp); temperaturesum += temp.temperature + calibration; DPCurrent[1] = int((humidity.relative_humidity)*100); scheduler++; }else{ DPCurrent[0] = int((temperaturesum / scheduler)*100); temperaturesum =0; scheduler = 0; } if(menu == false){ messagetimer++; takeAction(); displaytimer(isstatic); for(int i = 0; i < displaytime; i++){ if(digitalRead(button2) == LOW){ isstatic = BlinkYellow(isstatic); if(isstatic == 'n') displaytimer('b'); delay(100); break;} if(digitalRead(button3) == LOW){ isstatic = BlinkYellow(isstatic); if(isstatic == 'n') displaytimer('f'); delay(100); delay(1); break;} if(digitalRead(button1) == LOW){ menuTimer = 0; menu = true; break; } delay(1); } } else{ menuController(); for(int i = 0; i < displaytime; i++){ if(digitalRead(button1) == LOW){ while(digitalRead(button1) == LOW) digitalWrite(YellowLed, LOW); menuTimer = 0; menuController( 'f'); break;} if(digitalRead(button2) == LOW){ while(digitalRead(button2) == LOW) digitalWrite(YellowLed, LOW); menuTimer = 0; menuController( 'n', -1); break;} if(digitalRead(button3) == LOW){ while(digitalRead(button3) == LOW) digitalWrite(YellowLed, LOW); menuTimer = 0; menuController( 'n', 1); break;} delay(1); } menuTimer += 1; } }

### The code of the Slave unit

int autoLed = 2, woodBurnerLed = 3, gasBurnerLed = 4; int autoButton = 5, woodburnerButton = 6, gasBurnerButton = 7; int woodBurnerRelay = 8, gasBurnerRelay = 9; int blinker = 0; bool owerride = false; int manual = 0; int connectionActivity = 0; int timer = 0; int turnedOn = 0; bool heating = false; int burnTemp = 0, pufferTemp = 0; int ThermistorPin = 5; int ThermistorPin2 = 3; int Vo; float R1 = 10000; float logR2, R2, T, Tc, Tf; float c1 = 1.1384e-03, c2 = 2.3245e-04, c3 = 9.489e-08; void setup() { // put your setup code here, to run once: pinMode(autoLed, OUTPUT); pinMode(woodBurnerLed, OUTPUT); pinMode(gasBurnerLed, OUTPUT); pinMode(autoButton, INPUT_PULLUP); pinMode(woodburnerButton, INPUT_PULLUP); pinMode(gasBurnerButton, INPUT_PULLUP); pinMode(woodBurnerRelay, OUTPUT); digitalWrite(woodBurnerRelay, HIGH); delay(1); pinMode(gasBurnerRelay, OUTPUT); digitalWrite(gasBurnerRelay, HIGH); Serial.begin(9600); } void burnersonoff(){ if(heating){ if(turnedOn == 0){ digitalWrite(woodBurnerLed, LOW); digitalWrite(gasBurnerLed, LOW); digitalWrite(woodBurnerRelay, HIGH); digitalWrite(gasBurnerRelay, HIGH); }else if(turnedOn == 1){ digitalWrite(woodBurnerLed, HIGH); digitalWrite(woodBurnerRelay, LOW); digitalWrite(gasBurnerLed, LOW); digitalWrite(gasBurnerRelay, HIGH); }else if(turnedOn == 2){ digitalWrite(gasBurnerLed, HIGH); digitalWrite(gasBurnerRelay, LOW); digitalWrite(woodBurnerLed, LOW); digitalWrite(woodBurnerRelay, HIGH); } } } void loop() { if (Serial.available()) { String message = Serial.readString(); if(message[0] == 'A'){ connectionActivity = 0; if(owerride == false){ if(message[1] == '0'){ turnedOn = 0; }else if(message[1] == '1'){ turnedOn = 1; }else if(message[1] == '2'){ turnedOn = 2; } if(message[2] == '0'){ manual = 0; }else if (message[2] == '1'){ manual = 1; }else if(message[2] == '2'){ manual = 2; } if(message[3] == '1'){ heating = true; }else heating = false; }else owerride = false; String Message = "B"; Message += manual; if(heating) Message += "1"; else Message += "0"; String a = ""; for(int i = 0; i < 4-String(burnTemp).length(); i++){ a += "0"; } a += String(burnTemp); Message += a; a = ""; for(int i = 0; i < 4-String(pufferTemp).length(); i++){ a += "0"; } a += String(pufferTemp); Message += a; Serial.println(Message); }else{ if(connectionActivity < 200) connectionActivity++; } burnersonoff(); }else{ if(connectionActivity < 200) connectionActivity++; } if(connectionActivity > 30){ if(blinker >= 1 && blinker < 2){analogWrite(autoLed, 255);} if(blinker >= 1 && blinker > 2){analogWrite(autoLed, 0); blinker = 0;}; blinker++; turnedOn = 0; burnersonoff(); } for(int i = 0; i < 500; i++){ if(connectionActivity < 30){ if(digitalRead(autoButton) == LOW) { while(digitalRead(autoButton) == LOW); if(manual > 0) manual = 0; else heating = !heating; turnedOn = 0; burnersonoff(); owerride = true;} if(digitalRead(woodburnerButton) == LOW) { while(digitalRead(woodburnerButton) == LOW); if(manual == 1 && turnedOn == 1){manual = 0; turnedOn = 0;}else { manual = 1; turnedOn = 1;} heating = true; burnersonoff(); owerride = true;} if(digitalRead(gasBurnerButton) == LOW) { while(digitalRead(gasBurnerButton) == LOW); if(manual == 2 && turnedOn == 2){manual = 0; turnedOn = 0;}else { manual = 2; turnedOn = 2;}heating = true; burnersonoff(); owerride = true;} if(manual == 0 && heating){ analogWrite(autoLed, 255); }else analogWrite(autoLed, 0); } delay(1); } Vo = analogRead(ThermistorPin); if(Vo <= 0) Vo = 0; R2 = R1 * (1023.0 / (float)Vo - 1.0); logR2 = log(R2); T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2)); Tc = T - 273.15; burnTemp = int(Tc*100); Vo = analogRead(ThermistorPin2); if(Vo <= 0) Vo = 0; R2 = R1 * (1023.0 / (float)Vo - 1.0); logR2 = log(R2); T = (1.0 / (c1 + c2*logR2 + c3*logR2*logR2*logR2)); Tc = T - 273.15; pufferTemp = int(Tc*100); }
×