(solved) DS3231' based RTC timer / thermostat please check my compiled sketch

Hi guys and gurus!

Here is some of homemade code that doesn’t work properly. My device is

  • to control a load by time schedule (mode “0”),
  • to control a thermostat by time schedule (mode “1”),
  • to control a thermostat by time schedule excluding week-ends (office heater, mode “2”).

I want the device (code) not to be cancelled by short time electricity’ brown/blackouts, i.e. the thermostat is to keep working after power’s reconnecting, according to time schedule prescribed.

As I suspect, the code below contains some sort of logic mistakes and/or incongruities that results in device misbehavior. It doesn’t switch on/off in time; hysteresis doesn’t work as well - load is switched (if it’s switched) with thermosensor’s discrete of 0,25 C only. So here it is:

// DS3231_test.pde
#include <DS3231.h>
#include <Wire.h>
DS3231 Clock;
bool Century=false;
bool h12;
bool PM;
bool ADy, A12h, Apm;
byte ADay, AHour, AMinute, ASecond, ABits;
byte Year_PR, Month_PR, Date_PR, DoW_PR, Hour_PR, Minute_PR, Second_PR;
byte Mode, Mode_1, Mode_2, Mode_3;
float Temp_PR;
byte ON_Load;                      // time schedule switch ON variable
byte ON_Load_T;                    // thermostat switch ON variable

                                   // modes' variables
                                   
byte Hour_On_0 = 16;               // switch ON hours in mode "0"
byte Minute_On_0 = 40;             // switch ON minutes in mode "0"

byte Hour_Off_0 = 16;              // switch OFF hours in mode "0"
byte Minute_Off_0 = 41;            // switch OFF minutes in mode "0"

byte Hour_On_1 = 6;                // switch ON hours in mode "1"
byte Minute_On_1 = 0;              // switch ON minutes in mode "1"

byte Hour_Off_1 = 23;              // switch OFF hours in mode "1"
byte Minute_Off_1 = 0;             // switch OFF minutes in mode "1"

byte Hour_On_2 = 23;               // switch ON hours in mode "2" 
byte Minute_On_2 = 3;              // switch ON minutes in mode "2" 

byte Hour_Off_2 = 6;               // switch OFF hours in mode "2"
byte Minute_Off_2 = 57;            // switch OFF minutes in mode "2"

byte Hour_On_3 = 23;               // switch ON hours in mode "3" 
byte Minute_On_3 = 3;              // switch ON minutes in mode "3" 

byte Hour_Off_3 = 6;               // switch OFF hours in mode "3"
byte Minute_Off_3 = 57;            // switch OFF minutes in mode "3"

float Temp_ON;                     // switch ON temperature
float Temp_OFF;                    // switch OFF temperature
float Hyst;                        // hysteresis

#define Load 4                     // load control pin, i.e. "D4"
#define IN_MODE_1  6               // input pin to set mode "1", i.e. "D6"
#define IN_MODE_2  7               // input pin to set mode "2", i.e. "D7"
#define IN_MODE_3  8               // input pin to set mode "3", i.e. "D8"



void setup() {
  // Start the I2C interface
  Wire.begin();
  // Start the serial interface
  Serial.begin(9600);

  Temp_ON = 24;
  Hyst = 0,25;
  Temp_OFF = Temp_ON + Hyst;

  pinMode (Load,  OUTPUT);                      // configure load control pin as output
  pinMode (IN_MODE_1,  INPUT_PULLUP);           // configure mode "1" set pin as input
  pinMode (IN_MODE_2,  INPUT_PULLUP);           // configure mode "2" set pin as input
  pinMode (IN_MODE_3,  INPUT_PULLUP);           // configure mode "3" set pin as input
}



void loop() {
  
  // modes set pins' analysis 
  
  Mode_1 = digitalRead (IN_MODE_1);     // mode "1" set pin reading
  Mode_2 = digitalRead (IN_MODE_2);     // mode "2" set pin reading
  Mode_3 = digitalRead (IN_MODE_3);     // mode "3" set pin reading
  
  if (( Mode_1 == 1)&&( Mode_2 == 1)) {Mode = 0;}      // mode "0"
  if (( Mode_1 == 0)&&( Mode_2 == 1)) {Mode = 1;}      // mode "1"
  if (( Mode_1 == 1)&&( Mode_2 == 0)) {Mode = 2;}      // mode "2"
  if (( Mode_1 == 0)&&( Mode_2 == 0)) {Mode = 3;}      // mode "3"
  
  
  // DS3231's data reading
  
  Year_PR = Clock.getYear();            
  Month_PR = Clock.getMonth(Century);   
  Date_PR = Clock.getDate();            
  DoW_PR = Clock.getDoW();              
  Hour_PR = Clock.getHour(h12, PM);     
  Minute_PR = Clock.getMinute();        
  Second_PR = Clock.getSecond();        
  Temp_PR = Clock.getTemperature();     
    
    
  if ( Mode == 0)                                                     // if we have mode "0"
  {
    if ((Hour_On_0 == Hour_PR)&&( Minute_On_0 == Minute_PR))          // switch ON the load         
      { ON_Load = 1;}

    if ((Hour_Off_0 == Hour_PR)&&( Minute_Off_0 == Minute_PR))        // switch OFF the load            
      { ON_Load = 0;}
  }

  
  if ( Mode == 1)                                                      // if we have mode "1"
  {
     if ((Hour_On_1 == Hour_PR)&&( Minute_On_1 == Minute_PR))          // enable termostat analysis       
      { ON_Load_T = 1;}
    if (( ON_Load_T == 1)&&( Temp_PR <= Temp_ON )) {ON_Load = 1;}      // switch ON the load by thermostat
    if (( ON_Load_T == 1)&&( Temp_PR >= Temp_OFF )) {ON_Load = 0;}     // switch OFF the load by thermostat
    
    if ((Hour_Off_1 == Hour_PR)&&( Minute_Off_1 == Minute_PR))         // switch OFF the load by time schedule    
      { ON_Load_T = 0;}
 }

  
  if ( Mode == 2)                                                      // if we have mode "2"
  {
    if (( DoW_PR == 0)||( DoW_PR == 6))                                // week-end analysis ("0" - sunday, "6" - saturday)
    {ON_Load_T = 0;  }                                                 // switch OFF the load
    else                                                               // otherwise run by time schedule and thermostat
    {                                                  
      if ((Hour_On_1 == Hour_PR)&&( Minute_On_1 == Minute_PR))         // enable thermostat analysis         
      { ON_Load_T = 1;}
      if (( ON_Load_T == 1)&&( Temp_PR <= Temp_ON )) {ON_Load = 1;}    // switch ON the load by thermostat
      if (( ON_Load_T == 1)&&( Temp_PR >= Temp_OFF )) {ON_Load = 0;}   // switch OFF the load by thermostat
    
      if ((Hour_Off_1 == Hour_PR)&&( Minute_Off_1 == Minute_PR))       // switch OFF the load by time schedule   
      { ON_Load_T = 0;}
   }
 }

 
  if ( Mode == 3)                                                      // if we have mode "3"
  {
                                                                       // here is to be some logics of mode "3"
  }
  
  if ( ON_Load == 1 ) {digitalWrite(Load, HIGH);}                      // switch ON the load
  else {digitalWrite(Load, LOW);}                                      // switch OFF the load
  

                                                                       // serial monitor output
  Serial.print("20"); 
  Serial.print(Year_PR, DEC);     Serial.print(' ');
  Serial.print(Month_PR, DEC);    Serial.print(' ');
  Serial.print(Date_PR, DEC);     Serial.print(' ');
  Serial.print(DoW_PR, DEC);      Serial.print(' ');
  Serial.print(Hour_PR, DEC);     Serial.print(' ');
  Serial.print(Minute_PR, DEC);    Serial.print(' ');
  Serial.print(Second_PR, DEC);   Serial.print(' ');
  Serial.print("T=");             Serial.print(Temp_PR,2);  Serial.print(' ');
  Serial.print("M=");             Serial.print(Mode, DEC);   Serial.print(' ');
  Serial.print("L=");             Serial.print(ON_Load, DEC); 
  Serial.print('\n');

  delay(1000);
}

schabanow:
Hi guys and gurus!

I need to see a Venn diagram, e= Arduino forum members :wink:

I'm afraid it was just my crooked English' artifact; supposed to be a kind of polite introducing phrase. o_0

Solved. I changed “==” by “<=” in proper logic construction, so now I have my device working as I want. The final version is as follows:

/* 
 Libraries are to be installed: 
 DS3231 by Andrew Wickert - for this sketch
 DS3231M by SV-Zanshin - for RTC setting
 
 This is the DS3231 RTC based timer/thermostat of three operational modes: 
 - mode "0" = a LOAD is controlled by RTC-based time scedule;
 - mode "1" = a THERMOSTAT is controlled by RTC-based time schedule;
 - mode "2" = a THERMOSTAT is controlled by RTC-based time schedule, excluding week-ends.  
 Modes are to be set by jumper pulls to ground corresponding digital pins of Arduino.
*/

#include <DS3231.h>
#include <Wire.h>



DS3231 Clock;
bool Century=false;
bool h12;
bool PM;
bool ADy, A12h, Apm;

byte ADay, AHour, AMinute, ASecond, ABits;
byte Year_PR, Month_PR, Date_PR, DoW_PR, Hour_PR, Minute_PR, Second_PR;
byte Mode, Mode_1, Mode_2, Mode_3;

float Temp_PR;                     // current time variable
byte ON_Load;                      // time schedule switch ON variable
byte ON_Load_T;                    // thermostat switch ON variable

                                   // modes' variables
                                   
byte Hour_On_0 = 15;               // switch ON hours in mode "0"
byte Minute_On_0 = 44;             // switch ON minutes in mode "0"

byte Hour_Off_0 = 15;              // switch OFF hours in mode "0"
byte Minute_Off_0 = 47;            // switch OFF minutes in mode "0"

byte Hour_On_1 = 15;                // switch ON hours in mode "1"
byte Minute_On_1 = 51;              // switch ON minutes in mode "1"

byte Hour_Off_1 = 15;              // switch OFF hours in mode "1"
byte Minute_Off_1 = 54;             // switch OFF minutes in mode "1"

byte Hour_On_2 = 23;               // switch ON hours in mode "2" 
byte Minute_On_2 = 3;              // switch ON minutes in mode "2" 

byte Hour_Off_2 = 6;               // switch OFF hours in mode "2"
byte Minute_Off_2 = 57;            // switch OFF minutes in mode "2"

byte Hour_On_3 = 23;               // switch ON hours in mode "3" 
byte Minute_On_3 = 3;              // switch ON minutes in mode "3" 

byte Hour_Off_3 = 6;               // switch OFF hours in mode "3"
byte Minute_Off_3 = 57;            // switch OFF minutes in mode "3"

float Temp_ON;                     // switch ON temperature
float Temp_OFF;                    // switch OFF temperature
float Hyst;                        // hysteresis

#define Load 4                     // load control pin, i.e. "D4"
#define IN_MODE_1  6               // input pin to set mode "1", i.e. "D6"
#define IN_MODE_2  7               // input pin to set mode "2", i.e. "D7"
#define IN_MODE_3  8               // input pin to set mode "3", i.e. "D8"



void setup() {
  // Start the I2C interface
  Wire.begin();
  // Start the serial interface
  Serial.begin(115200);

  Temp_ON = 29;
  Hyst = 0;
  Temp_OFF = Temp_ON + Hyst;

  pinMode (Load,  OUTPUT);                      // configure load control pin as output
  pinMode (IN_MODE_1,  INPUT_PULLUP);           // configure mode "1" set pin as input
  pinMode (IN_MODE_2,  INPUT_PULLUP);           // configure mode "2" set pin as input
  pinMode (IN_MODE_3,  INPUT_PULLUP);           // configure mode "3" set pin as input
}



void loop() {
  
  // mode setting pins' analysis 
  
  Mode_1 = digitalRead (IN_MODE_1);     // mode "1" set pin reading
  Mode_2 = digitalRead (IN_MODE_2);     // mode "2" set pin reading
  Mode_3 = digitalRead (IN_MODE_3);     // mode "3" set pin reading
  
  if (( Mode_1 == 1)&&( Mode_2 == 1)) {Mode = 0;}      // mode "0"
  if (( Mode_1 == 0)&&( Mode_2 == 1)) {Mode = 1;}      // mode "1"
  if (( Mode_1 == 1)&&( Mode_2 == 0)) {Mode = 2;}      // mode "2"
  if (( Mode_1 == 0)&&( Mode_2 == 0)) {Mode = 3;}      // mode "3"
  
  
  // DS3231's data reading
  
  Year_PR = Clock.getYear();            
  Month_PR = Clock.getMonth(Century);   
  Date_PR = Clock.getDate();            
  DoW_PR = Clock.getDoW();              
  Hour_PR = Clock.getHour(h12, PM);     
  Minute_PR = Clock.getMinute();        
  Second_PR = Clock.getSecond();        
  Temp_PR = Clock.getTemperature();     
    
    
  if ( Mode == 0)                                                     // if we have mode "0"
  {
    if ((Hour_On_0 <= Hour_PR)&&( Minute_On_0 <= Minute_PR))          // switch ON the load         
      { ON_Load = 1;}

    if ((Hour_Off_0 <= Hour_PR)&&( Minute_Off_0 <= Minute_PR))        // switch OFF the load            
      { ON_Load = 0;}
  }

  
  if ( Mode == 1)                                                      // if we have mode "1"
  {
     if ((Hour_On_1 <= Hour_PR)&&( Minute_On_1 <= Minute_PR))          // enable termostat analysis       
      { ON_Load_T = 1;}
    if (( ON_Load_T == 1)&&( Temp_PR <= Temp_ON )) {ON_Load = 1;}      // switch ON the load by thermostat
    if (( ON_Load_T == 1)&&( Temp_PR >= Temp_OFF )) {ON_Load = 0;}     // switch OFF the load by thermostat
    
    if ((Hour_Off_1 <= Hour_PR)&&( Minute_Off_1 <= Minute_PR))         // switch OFF the load by time schedule    
      { ON_Load_T = 0; ON_Load = 0;}
 }

  
  if ( Mode == 2)                                                      // if we have mode "2"
  {
    if (( DoW_PR == 0)||( DoW_PR == 6))                                // week-end analysis ("0" - sunday, "6" - saturday)
    {ON_Load_T = 0;  }                                                 // switch OFF the load
    else                                                               // otherwise run by time schedule and thermostat
    {                                                  
      if ((Hour_On_1 <= Hour_PR)&&( Minute_On_1 <= Minute_PR))         // enable thermostat analysis         
      { ON_Load_T = 1;}
      if (( ON_Load_T == 1)&&( Temp_PR <= Temp_ON )) {ON_Load = 1;}    // switch ON the load by thermostat
      if (( ON_Load_T == 1)&&( Temp_PR >= Temp_OFF )) {ON_Load = 0;}   // switch OFF the load by thermostat
    
      if ((Hour_Off_1 <= Hour_PR)&&( Minute_Off_1 <= Minute_PR))       // switch OFF the load by time schedule   
      { ON_Load_T = 0; ON_Load = 0;}
   }
 }

 
  if ( Mode == 3)                                                      // if we have mode "3"
  {
                                                                       // here is to be some logic of mode "3"
  }
  
  if ( ON_Load == 1 ) {digitalWrite(Load, HIGH);}                      // switch ON the load
  else {digitalWrite(Load, LOW);}                                      // switch OFF the load
  

                                                                       // serial monitor output
  Serial.print("20"); 
  Serial.print(Year_PR, DEC);     Serial.print(' ');
  Serial.print(Month_PR, DEC);    Serial.print(' ');
  Serial.print(Date_PR, DEC);     Serial.print(' ');
  Serial.print(DoW_PR, DEC);      Serial.print(' ');
  Serial.print(Hour_PR, DEC);     Serial.print(' ');
  Serial.print(Minute_PR, DEC);    Serial.print(' ');
  Serial.print(Second_PR, DEC);   Serial.print(' ');
  Serial.print("T=");             Serial.print(Temp_PR,2);  Serial.print(' ');
  Serial.print("M=");             Serial.print(Mode, DEC);   Serial.print(' ');
  Serial.print("L=");             Serial.print(ON_Load, DEC); 
  Serial.print('\n');

  delay(1000);
}

:slight_smile:

guysAndGurus.GIF

guysAndGurus.GIF

Disagree. >:( >:( >:(
:slight_smile: :slight_smile: :slight_smile:

Another one issue has arise. Hope the last one. Code represented above sticks when numbers of hours and minutes "ON" are bigger than corresponding numbers "OFF". The possible solution may be conversion hours and minutes into continuous numbering of minutes of day and night... Thinking...