/*version 03/10/2023
this is a three (room, fridge, freezer) temperature sensor (DS18B20)code
to monitor & control compressor & defrost operations for a fridge  
the three sensors can be connected to one bus input to arduino as each
should have its own IP address according to its datasheet, yet in wokwi
simulator it doesn't so, I connected three separate sensors.
Any -127°C temperature or "nan" readings mean a sensor faulty connection*/

/*Features
1-continuously measuring 3 locations (room, fridge, freezer) temperatures
2-the value of freezer temperature controls start/stop of the compressor
3-defrosting is activated once a day for a preset period
4-during defrosting, cooling is suspended
5-if freezer temperature rises above preset value for more than preset time,
without affecting other activities, a relay will be energized, 
then de-energized when the temperature drops down again

/*any pin not declared as input or output in void setup, while used in void loop may/may not
function as intended, so it is a must to declare pins in void setup, since this will activate all
necessary pullup resistors for LEDs &/or relays*/

/*unsigned long millis function is used to overcome delay() function which suspends the
code until time elapses*/

/*there are three main timers in this code for controlling the different functions
1-startup timer which delays the start of the compressor only once after every power failure
to enable the release of the compressed freon within the cooling cycle & to avoid a heavy
start of a loaded compressor
2-millis reset timer < 49 days (anything less than 1176 hours)in order to prevent millis
overflow function, which is important to ensure code stability in spite of accumulated operating
hours
3-defrost timer once every 24 hours to melt the ice
4-period of defrost, an average of 20 minutes per defrost cycle*/

/*also, a reset (every < 1176 hours) of unsigned long is installed to avoid
overflow of this function, otherwise the code will not perform well after 49 days*/ 

/*the delay functions in this code are intended to easily read the LCD display*/

/*you can edit the wokwi right-hand diagram by inserting text in diagram.json
within any location using the below code while changing "text3,4,5 etc." & "top" & "left"
values & new text name
      "type": "wokwi-text",
      "id": "text2",
      "top": -369.45,
      "left": 857.75,
      "attrs": { "text": "fridge" } */

/*while in run mode, you can click on any sensor & change the temperature
to monitor the real effect within the code instructions*/

/*you can copy the code sketch.ino & diagram.json & paste both in a blank
new sheet to test other changes while the original is saved*/ 

/*click on any component & you can rotate it by ctrl & r*/

/*you can add components like transistors by selecting a custom chip & renaming the pins in chip.json
this chip is just an image & will not perform as NPN unless the pins are programmed in another process*/





#include <DallasTemperature.h> //library for DS18B20 sensors

OneWire oneWire1(52); //room temperature sensor
DallasTemperature sensors1(&oneWire1);

OneWire oneWire2(24); //fridge temperature sensor
DallasTemperature sensors2(&oneWire2);

OneWire oneWire3(22); //freezer temperature sensor
DallasTemperature sensors3(&oneWire3);

const int compressorRelay  = 25;
const int defrostRelay     = 23;  
const int coolfailRelay    = 41;   

unsigned long previousMillisStartdefrosting;

unsigned long previousMillisDefrosting;

unsigned long previousMilliscounter;

unsigned long startcoolfail=0;

bool Startdefrosting = false;

bool Defrosting = false;

bool enablereading = false;

bool coolfailRelayHigh=false;

int counter =0; 
float countertime=0;
float totaltime;


#include <LiquidCrystal.h>
//LCD robot setup pins
const int pin_RS = 8; 
const int pin_EN = 9; 
const int pin_d4 = 4; 
const int pin_d5 = 5; 
const int pin_d6 = 6; 
const int pin_d7 = 7; 
const int pin_BL = 10; 
LiquidCrystal lcd( pin_RS,  pin_EN,  pin_d4,  pin_d5,  pin_d6,  pin_d7);


extern volatile unsigned long timer0_millis;


int totalColumns  = 16;
int totalRows     = 2;


String scrollingMessage = "Three temperature sensors 10/10/2023;room, fridge, freezer & total operating time controller...";

void scrollMessage(int row, String message, int delayTime, int totalColumns) {
  for (int i=0; i < totalColumns; i++) {
    message = " " + message;  
  } 
  message = message + " "; 
  for (int position = 0; position < message.length(); position++) {
    lcd.setCursor(0, 0);
    lcd.print(message.substring(position, position + totalColumns));
    delay(delayTime);
  }
}

void setup(void)

{

Serial.begin(9600);
 
lcd.begin(16, 2);

lcd.setCursor(0, 0);
  lcd.print("SETUP CONTROLLER");
delay(1000);


lcd.setCursor(0, 1);
 
  lcd.print("......WAIT......");
delay(1000);

 Serial.println("Measuring 3 sensors' temperatures");

pinMode( compressorRelay, OUTPUT);  
pinMode (defrostRelay, OUTPUT);  

pinMode(coolfailRelay, OUTPUT);
digitalWrite(coolfailRelay,LOW);


  sensors1.begin();

  sensors2.begin();

  sensors3.begin();

}

void loop(void)

{
digitalWrite (compressorRelay, LOW);

digitalWrite (defrostRelay, LOW);
  
delay(5000); // a delay to absorb any power fluctuations on startup & freon pressure balance (≥10minutes) 

label: /*above this line, can be placed in setup as it is needed only once &
label & goto can be deleted from the code*/

unsigned long currentMillis = millis();

totaltime = (countertime * 300000) +millis(); 

//millis reset to avoid overflow (to be ≥20 days in milliseconds <49 days)

if(millis() >= 300000)

 {noInterrupts ();
 countertime ++;
  timer0_millis=0;

 previousMilliscounter=0;

 previousMillisDefrosting=0;

 previousMillisStartdefrosting=0;

 currentMillis=0;

 previousMillisDefrosting=0;

 interrupts();}

sensors1.requestTemperatures();

sensors2.requestTemperatures();

sensors3.requestTemperatures();

  float room    = sensors1.getTempCByIndex(0);

  float fridge  = sensors2.getTempCByIndex(0);

  float freezer = sensors3.getTempCByIndex(0);

//sensor reading display delay


 if( currentMillis - previousMillisDefrosting >= 2000){

  enablereading = !enablereading;

  previousMillisDefrosting = currentMillis;

  }

  if(enablereading){

   Serial.print("room=");

   Serial.print(room);

   Serial.print(", ");

   Serial.print("fridge=");

   Serial.print(fridge);

   Serial.print(", ");

   Serial.print("freezer=");

   Serial.print(freezer);

   Serial.print(", ");

   Serial.print("m=");

   Serial.print(millis());

   Serial.print(", ");

   Serial.print("cm=");

   Serial.print(currentMillis);

   Serial.print(", ");

   Serial.print("pmsd=");

   Serial.print(previousMillisStartdefrosting);

   Serial.print(", ");

   Serial.print("pmd=");

   Serial.print(previousMillisDefrosting);

   Serial.print(", ");

   Serial.print("sd=");

   Serial.print(Startdefrosting);
    Serial.print(", ");
   
   Serial.print("total time=");

   Serial.print(totaltime/60000);
   Serial.print("min");
 
 
   Serial.println();

lcd.clear();
 lcd.setCursor(0, 0);
  lcd.print("....GOOD DAY....");
delay(200);
lcd.clear();
delay(200);
lcd.print("....GOOD DAY....");
delay(200);
lcd.clear();
delay(200);
lcd.print("....GOOD DAY....");
delay(200);
lcd.clear();
delay(200);
lcd.print("....GOOD DAY....");
delay(200);
lcd.clear();
delay(200);
lcd.print("....GOOD DAY....");
delay(200);
 

 if(freezer>15){
  
  digitalWrite(coolfailRelay,HIGH);
      
 lcd.clear();
                  delay(300);
                  lcd.print("...COOL  FAIL...");
     
     delay(3000);

lcd.setCursor(0, 1);
lcd.print(" FREEZER >15  C");
lcd.setCursor(13,1); //column,row
   lcd.print((char)223); // ° symbol
   delay(2000);
lcd.setCursor(0,1);
lcd.print("COMPRESSOR START");
delay(1000);
lcd.setCursor(0, 1);
lcd.print("TEMPERATURE DROP");
delay(1000);
lcd.setCursor(0, 1);
lcd.print("CHECK COMPRESSOR");
delay(1000);
lcd.setCursor(0, 1);
lcd.print("                ");
delay(1000);
lcd.setCursor(0, 1);
lcd.print("CHECK COMPRESSOR");
              
delay(1000);

lcd.setCursor(0, 1);
lcd.print("                ");
delay(1000);
lcd.setCursor(0, 1);
lcd.print("CHECK COMPRESSOR");
delay(1000);
lcd.setCursor(0, 1);
lcd.print("                ");
delay(1000);
lcd.setCursor(0, 1);
lcd.print("CHECK COMPRESSOR");
     
     }


lcd.setCursor(0, 0);
  
  scrollMessage(1, scrollingMessage, 250, totalColumns); //scrollMessage(int row, String message, int delayTime, int totalColumns)
  
lcd.setCursor(0,0);
   lcd.print("Time in hours    ");
   lcd.setCursor(14,1);

   //lcd.print((char)223);
   lcd.setCursor(0,1);
lcd.print("Temp.-55to+125 C");
lcd.setCursor(14,1); //column,row
   lcd.print((char)223); // ° symbol
   delay(2000);

   lcd.setCursor(0,0);
   lcd.print("Room   =       C");
   lcd.setCursor(14,0); //column,row
   lcd.print((char)223); // ° symbol
   lcd.setCursor(8,0);
   lcd.print(room);
   
   lcd.setCursor(0,1);
   lcd.print("Fridge =       C");
   lcd.setCursor(14,1);
   lcd.print((char)223);
   lcd.setCursor(8,1);
  lcd.print(fridge);

delay(2000);

   lcd.setCursor(0,0);
   lcd.print("Fridge =       C");
   lcd.setCursor(14,0);
   lcd.print((char)223);
   lcd.setCursor(8,0);
   lcd.print(fridge);

   lcd.setCursor(0,1);
   lcd.print("Freezer=       C");
   lcd.setCursor(14,1);
   lcd.print((char)223);
   lcd.setCursor(8,1);
   lcd.print(freezer);

delay(2000);

lcd.setCursor(0,0);
   lcd.print("Freezer=       C");
   lcd.setCursor(14,0);
   lcd.print((char)223);
   lcd.setCursor(8,0);
   lcd.print(freezer);

 lcd.setCursor(0,1);; //column/row

                  lcd.print("Time=         Hr");
                 
                  lcd.setCursor(5,1); //column/row
                  
                  lcd.print(totaltime/3600000);
                  delay(2000);


lcd.setCursor(0,0); //column/row

                  lcd.print("Time=         Hr");
                 
                  lcd.setCursor(5,0); //column/row
                  
                 lcd.print(totaltime/3600000);
               
lcd.setCursor(0,1);
   lcd.print("Room   =       C");
   lcd.setCursor(14,1); //column,row
   lcd.print((char)223);
   lcd.setCursor(8,1);
   lcd.print(room);

  delay(2000);
   }

  if(!enablereading)  {

   lcd.setCursor(0,0);

   lcd.print("Room   =       C");

   lcd.setCursor(14,0);
   lcd.print((char)223);
   lcd.setCursor(8,0);
   lcd.print(room);
    //delay(2000);
   lcd.setCursor(0,1);
   lcd.print("Fridge =       C");
   lcd.setCursor(14,1);
   lcd.print((char)223);
   lcd.setCursor(8,1);
   lcd.print(fridge);
 delay(2000);

    lcd.setCursor(0,0);
   lcd.print("Fridge =       C");
   lcd.setCursor(14,0);
   lcd.print((char)223);
   lcd.setCursor(8,0);
   lcd.print(fridge);
lcd.setCursor(0,1); //column/row

                  lcd.setCursor(0,1);
    lcd.print("Freezer=       C");
   lcd.setCursor(14,1);
   lcd.print((char)223);
   lcd.setCursor(8,1);
   lcd.print(freezer);
 delay(2000);


lcd.setCursor(0,0); //column/row

                  lcd.setCursor(0,0);
    lcd.print("Freezer=       C");
   lcd.setCursor(14,0);
   lcd.print((char)223);
   lcd.setCursor(8,0);
   lcd.print(freezer);
 //delay(2000);

lcd.setCursor(0,1); //column/row

                  lcd.print("Time=         Hr");
                 
                  lcd.setCursor(5,1); //column/row
                  
                 lcd.print(totaltime/3600000); //in hours

                 delay(3000);

lcd.setCursor(0,0); //column/row

                  lcd.print("Time=         Hr");
                 
                  lcd.setCursor(5,0); //column/row
                  
                 lcd.print(totaltime/3600000); //in hours

                 lcd.setCursor(0,1);
   lcd.print("Room   =       C");
   lcd.setCursor(14,1); //column,row
   lcd.print((char)223);
   lcd.setCursor(8,1);
   lcd.print(room);

   delay(2000);
            

   }

/* this condition will triger the coolfailRelay if freezer temperature >5°C for >5minutes*/

      if(freezer>5){
      if(!coolfailRelayHigh){if(millis()-startcoolfail>120000){
      digitalWrite(coolfailRelay,HIGH);
      coolfailRelayHigh=true;
     
     lcd.clear();
                  delay(300);
                  lcd.print("...COOL FAIL...");
     
     delay(3000);
     
     
     
     
      }
      }
      }else{digitalWrite(coolfailRelay,LOW);
      coolfailRelayHigh=false;
      startcoolfail=millis();}

/*energize defrostRelay led once every 24-hours each for 20 minutes
without affecting lcd display scrolling text or compressorRelay
led functionality
the below line represents the 24 hour timer during which an action will start & stop once
& one counter to count two actions on/off*/


 if(currentMillis - previousMilliscounter >= 26000){
    counter = 2;
    previousMilliscounter= currentMillis;}

 // defrostRelay ON period

if ( currentMillis - previousMillisStartdefrosting >= 2000 && (counter == 2 || counter == 1) )

   {

    counter --;
    digitalWrite( compressorRelay
  , LOW);
    previousMillisStartdefrosting = currentMillis;

    Startdefrosting = !Startdefrosting;      

   }

   if( !Startdefrosting)

    {

      digitalWrite( defrostRelay, LOW);    }
      
      if((freezer>=0)) 

    {
      digitalWrite(defrostRelay,LOW);
      digitalWrite( compressorRelay
    , HIGH);
      }
lcd.clear();
lcd.setCursor(0,0); //column,row


        for(byte n=0;n<5;n++) {

lcd.print("..COOLING DOWN..");
                  delay(300);
                  lcd.clear();
 delay(300);}

        

    if((freezer<-10 && freezer<0) && digitalRead(defrostRelay) == LOW )

    {digitalWrite( compressorRelay  , HIGH);}

    if((freezer<-10 ))

    {digitalWrite( compressorRelay  , LOW);}

    if( Startdefrosting)                    

  {
   digitalWrite( compressorRelay  ,LOW);
    digitalWrite( defrostRelay,HIGH);  
 
 // }

  lcd.clear();
lcd.setCursor(0,0); //column/row
 lcd.print("...DEFROSTING...");
                  delay(300);
                  lcd.clear();
                  delay(300);
                  lcd.print("...DEFROSTING...");
                  delay(300);
                  lcd.clear();
                  delay(300);
                  lcd.print("...DEFROSTING...");
                  delay(300);
                  lcd.clear();
                  delay(300);
                  lcd.print("...DEFROSTING...");
                  delay(300);
                  lcd.clear();
                  delay(300);
                  lcd.print("...DEFROSTING...");
                  delay(300);
                  lcd.clear();
                  delay(300);
                  lcd.print("...DEFROSTING...");

  }       
goto label;

}
freezer
fridge
room
cooling
defrosting
alarm