RTC with Daylight saving

This is a section of code that I am using to check for DST upon power up (edited for simplicity).
If I put it in void setup() it just returns DST as zero. If, however I put it in void loop() it returns DST as 3 or 10 as required.
Where am I going wrong?

DateTime now = rtc.now();
int ny = now.year();
int nm = now.month();
int nd = now.day();
int nh = now.hour();
int nmin = now.minute();
int ns = now.second();
int dow = now.dayOfTheWeek();
int winter = 10;
int summer = 3;
int DST;
if (nm >= 1 && nm <= 2 )DST = winter;
if (nm == 3 && nd <= 24)DST = winter;
if (nm >= 3 && nd >= 25)DST = summer;
if (nm >= 4 && nm <= 9)DST = summer;
if (nm == 10 && nd <= 24)DST = summer;
if (nm >= 10 && nd >= 25)DST = winter;
if (nm >= 11 && nm <= 12)DST = winter;

Please post a complete sketch illustrating the problem

It sounds very much like you have DST declared as a global variable such that it has a default value of zero, but then declare and use a second variable named DST which has a different scope

However, without seeing your complete sketch or sketches, who knows ?

This works but I would like to move lines 91-109 to void setup()

#include <SoftwareSerial.h>
SoftwareSerial BTserial(2, 3); // RX | TX

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "RTClib.h"

RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32

#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define red 8
#define green 9
#define blue 10
#define relay 11

void setup() {
  pinMode(red, OUTPUT);
  pinMode(green, OUTPUT);
  pinMode(blue, OUTPUT);
  pinMode(relay, OUTPUT);
  digitalWrite(red , LOW);
  digitalWrite(green , LOW);
  digitalWrite(blue , LOW);
  digitalWrite(relay , HIGH);
  Serial.begin(9600);
  BTserial.begin(9600);
  delay(3000);

  //                 YEAR DOM MONTH HOUR MINS SEC
  //rtc.adjust(DateTime(2021, 6, 3, 16, 59, 0));
  //rtc.adjust(DateTime(2021, 3, 28, 1, 58, 50));//SPRING TEST
  // rtc.adjust(DateTime(2021, 10, 31, 2, 58, 50));//AUTUMN TEST
  DateTime now = rtc.now();
  delay(30);
  int winter = 10;
  int summer = 3;
  int ny = now.year();
  int nm = now.month();
  int nd = now.day();
  int nh = now.hour();
  int nmin = now.minute();
  int ns = now.second();
  int dow = now.dayOfTheWeek();

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)// Check your I2C address and enter it here, in Our case address is 0x3C
  display.clearDisplay();
  display.display(); // this command will display all the data which is in buffer
  display.setTextColor(WHITE, BLACK);
  display.drawRect(117, 25, 3, 3, WHITE);     // Put degree symbol ( ° )
  draw_text(0, 25, "TEMPERATURE =", 1);
  draw_text(122, 25, "C", 1);
}

void loop() {
  DateTime now = rtc.now();
  /*============Display Date=================*/
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.print(daysOfTheWeek[now.dayOfTheWeek()]);

  char currentDate [16];
  uint8_t thisDay, thisMonth ;
  thisDay = now.day();
  thisMonth = now.month();
  sprintf (currentDate, "%02d/%02d/", thisDay, thisMonth); //add leading zeros to the day and month

  display.setTextSize(1);
  display.setCursor(62, 0);
  display.print(currentDate);

  display.setTextSize(1);
  display.setCursor(102, 0);
  display.print(now.year(), DEC);

  int heat;
  static int boost;

  int ny = now.year();
  int nm = now.month();
  int nd = now.day();
  int nh = now.hour();
  int nmin = now.minute();
  int ns = now.second();
  int dow = now.dayOfTheWeek();
  int  temperature_celsius =   rtc.getTemperature();
  int math_temp = temperature_celsius ;
  int DST;
  int winter = 10;
  int summer = 3;
  if (nm >= 1 && nm <= 2 )DST = winter;
  if (nm == 3 && nd <= 24)DST = winter;
  if (nm >= 3 && nd >= 25)DST = summer;
  if (nm >= 4 && nm <= 9)DST = summer;
  if (nm == 10 && nd <= 24)DST = summer;
  if (nm >= 10 && nd >= 25)DST = winter;
  if (nm >= 11 && nm <= 12)DST = winter;

  if ( nh >= 0 && nh <= 6 )heat = 17 + boost;
  if ( nd == 1 && nh == 7  )heat = 17 + boost;
  if ( nd == 7 && nh == 7  ) heat = 17 + boost;
  if ( nd >= 2 && nd <= 6 &&  nh == 7  )heat = 18 + boost ;
  if ( nd == 1 && nh == 8 ) heat = 18 + boost;
  if ( nd == 7 && nh == 8  )heat = 18  + boost;
  if ( nd == 1 &&  nh >= 9 && nh <= 17  )heat = 19 + boost;
  if ( nd == 7 &&  nh >= 9 && nh <= 17  )heat = 19 + boost;
  if ( nd >= 2 && nd <= 6 &&  nh >= 8 && nh <= 17  ) heat = 19 + boost;
  if ( nh >= 18 && nh <= 22  )heat = 20 + boost;
  if ( nh == 23  )heat = 17 + boost;

  if (nm == 3 && nd >= 25 && dow == 0 && nh == 1 && nmin == 59 && ns <= 5 && DST == 3) {
    DST = 10;
    //    spring();

  }
  if (nm == 10 && nd >= 25 && dow == 0 && nh == 2 && nmin == 59 && ns <= 5 && DST == 10) {
    DST = 3;
    //  autumn();

  }
  if (((nmin % 1) == 0) && ns == 0)  {
    delay(300);
    Serial.println("---checking for heat requirement--- ");
    Serial.print("Required heat = ");
    Serial.print(heat);
    Serial.print(".  Actual heat = ");
    Serial.print(temperature_celsius);
    Serial.print(".  Boost = ");
    Serial.print(boost);

    if (heat <= math_temp) { //cold
      digitalWrite(blue , HIGH);
      digitalWrite(red , LOW);
      digitalWrite(relay , HIGH);
      Serial.println(".   DO NOT HEAT ");
      delay(1000);

    }
    if (heat > math_temp) { //hot
      digitalWrite(blue , LOW);
      digitalWrite(red , HIGH);
      digitalWrite(relay , LOW);
      Serial.println(".   PLEASE HEAT ME ");
      delay(1000);
    }
  }
  int boostbutton = 0;
  int bm;
  int bs;

  if (BTserial.available() ) { // Checks whether data is comming from the serial port
    boostbutton = BTserial.read(); // Reads the data from the serial port
  }

  if (boostbutton == '1') {
    bm = nmin;
    bs = ns;
    boost = 5;
    Serial.print("BOOST ON    ");
    Serial.print(boost);
    Serial.print("  ");
    Serial.print("nm/bm ");
    Serial.print(nmin);
    Serial.print("/");
    Serial.print(bm);
    Serial.print(".  ns/bs ");
    Serial.print(ns);
    Serial.print("/");
    Serial.println(bs);
    delay(1000);
    DateTime now = rtc.now();
    delay(30);
    int ns = now.second();
    bs = ns;
    digitalWrite(green , HIGH);


  }
  if (boostbutton == '0') {
    bm = nmin;
    bs = ns;
    boost = -3;
    Serial.print("HEATING OFF    ");
    Serial.print(boost);
    Serial.print("  ");
    Serial.print("nm/bm ");
    Serial.print(nmin);
    Serial.print("/");
    Serial.print(bm);
    Serial.print(".  ns/bs ");
    Serial.print(ns);
    Serial.print("/");
    Serial.println(bs);
    delay(1000);
    DateTime now = rtc.now();
    delay(30);
    int ns = now.second();
    bs = ns;


  }
  if (boostbutton == '3') {

    Serial.print("CURRENT TEMPERATURE    ");
    Serial.println(temperature_celsius);
    delay(1000);
    BTserial.println(temperature_celsius);
    delay(10);


  }
  if (bs == ns) {

    //  if (bm == nmin && bs == ns) {
    Serial.println("BOOST over  ");
    boostbutton = 0;
    boost = 0;
    delay(600);
  }

  Serial.print("nmin/bm ");
  Serial.print(nmin);
  Serial.print("/");
  Serial.print(bm);
  Serial.print(".  ns/bs ");
  Serial.print(ns);
  Serial.print("/");
  Serial.print(bs);
  Serial.print("  DST ");
  Serial.print(DST);
  Serial.print("  nm ");
  Serial.println(nm);

  delay(900);


  /*================Display Time================*/
  char buffer [16];
  uint8_t thisSec, thisMin, thisHour;
  thisSec = now.second();
  thisMin = now.minute();
  thisHour = now.hour();
  sprintf (buffer, "%02d:%02d:%02d", thisHour, thisMin, thisSec);

  display.setTextSize(2);
  display.setCursor(15, 9);
  display.print(buffer);


  /*=============Display Temperature=====================*/
  display.setTextSize(1);
  display.setCursor(82, 25);
  display.print(rtc.getTemperature());

  display.display();

}

void draw_text(byte x_pos, byte y_pos, char *text, byte text_size) {
  display.setCursor(x_pos, y_pos);
  display.setTextSize(text_size);
  display.print(text);
  display.display();
}

You can do that, but declare the DST variable as a global so that you can set its value in setup() and use it throughout the sketch

I have tried that but DST defaults to 10 even in June (6)

Post your best attempt

#include <SoftwareSerial.h>
SoftwareSerial BTserial(2, 3); // RX | TX

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "RTClib.h"

RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32

#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define red 8
#define green 9
#define blue 10
#define relay 11

int DST;

void setup() {
  pinMode(red, OUTPUT);
  pinMode(green, OUTPUT);
  pinMode(blue, OUTPUT);
  pinMode(relay, OUTPUT);
  digitalWrite(red , LOW);
  digitalWrite(green , LOW);
  digitalWrite(blue , LOW);
  digitalWrite(relay , HIGH);
  Serial.begin(9600);
  BTserial.begin(9600);
  delay(3000);

  //                 YEAR DOM MONTH HOUR MINS SEC
  //rtc.adjust(DateTime(2021, 6, 3, 16, 59, 0));
  //rtc.adjust(DateTime(2021, 3, 28, 1, 58, 50));//SPRING TEST
  // rtc.adjust(DateTime(2021, 10, 31, 2, 58, 50));//AUTUMN TEST
  DateTime now = rtc.now();
  delay(30);

  int ny = now.year();
  int nm = now.month();
  int nd = now.day();
  int nh = now.hour();
  int nmin = now.minute();
  int ns = now.second();
  int dow = now.dayOfTheWeek();

  int winter = 10;
  int summer = 3;
  if (nm >= 1 && nm <= 2 )DST = winter;
  if (nm == 3 && nd <= 24)DST = winter;
  if (nm >= 3 && nd >= 25)DST = summer;
  if (nm >= 4 && nm <= 9)DST = summer;
  if (nm == 10 && nd <= 24)DST = summer;
  if (nm >= 10 && nd >= 25)DST = winter;
  if (nm >= 11 && nm <= 12)DST = winter;

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)// Check your I2C address and enter it here, in Our case address is 0x3C
  display.clearDisplay();
  display.display(); // this command will display all the data which is in buffer
  display.setTextColor(WHITE, BLACK);
  display.drawRect(117, 25, 3, 3, WHITE);     // Put degree symbol ( ° )
  draw_text(0, 25, "TEMPERATURE =", 1);
  draw_text(122, 25, "C", 1);
}

void loop() {
  DateTime now = rtc.now();
  /*============Display Date=================*/
  display.setTextSize(1);
  display.setCursor(0, 0);
  display.print(daysOfTheWeek[now.dayOfTheWeek()]);

  char currentDate [16];
  uint8_t thisDay, thisMonth ;
  thisDay = now.day();
  thisMonth = now.month();
  sprintf (currentDate, "%02d/%02d/", thisDay, thisMonth); //add leading zeros to the day and month

  display.setTextSize(1);
  display.setCursor(62, 0);
  display.print(currentDate);

  display.setTextSize(1);
  display.setCursor(102, 0);
  display.print(now.year(), DEC);

  int heat;
  static int boost;

  int ny = now.year();
  int nm = now.month();
  int nd = now.day();
  int nh = now.hour();
  int nmin = now.minute();
  int ns = now.second();
  int dow = now.dayOfTheWeek();
  int  temperature_celsius =   rtc.getTemperature();
  int math_temp = temperature_celsius ;
//  int DST;
//  int winter = 10;
//  int summer = 3;
//  if (nm >= 1 && nm <= 2 )DST = winter;
//  if (nm == 3 && nd <= 24)DST = winter;
//  if (nm >= 3 && nd >= 25)DST = summer;
//  if (nm >= 4 && nm <= 9)DST = summer;
//  if (nm == 10 && nd <= 24)DST = summer;
//  if (nm >= 10 && nd >= 25)DST = winter;
//  if (nm >= 11 && nm <= 12)DST = winter;

  if ( nh >= 0 && nh <= 6 )heat = 17 + boost;
  if ( nd == 1 && nh == 7  )heat = 17 + boost;
  if ( nd == 7 && nh == 7  ) heat = 17 + boost;
  if ( nd >= 2 && nd <= 6 &&  nh == 7  )heat = 18 + boost ;
  if ( nd == 1 && nh == 8 ) heat = 18 + boost;
  if ( nd == 7 && nh == 8  )heat = 18  + boost;
  if ( nd == 1 &&  nh >= 9 && nh <= 17  )heat = 19 + boost;
  if ( nd == 7 &&  nh >= 9 && nh <= 17  )heat = 19 + boost;
  if ( nd >= 2 && nd <= 6 &&  nh >= 8 && nh <= 17  ) heat = 19 + boost;
  if ( nh >= 18 && nh <= 22  )heat = 20 + boost;
  if ( nh == 23  )heat = 17 + boost;

  if (nm == 3 && nd >= 25 && dow == 0 && nh == 1 && nmin == 59 && ns <= 5 && DST == 3) {
    DST = 10;
    //    spring();

  }
  if (nm == 10 && nd >= 25 && dow == 0 && nh == 2 && nmin == 59 && ns <= 5 && DST == 10) {
    DST = 3;
    //  autumn();

  }
  if (((nmin % 1) == 0) && ns == 0)  {
    delay(300);
    Serial.println("---checking for heat requirement--- ");
    Serial.print("Required heat = ");
    Serial.print(heat);
    Serial.print(".  Actual heat = ");
    Serial.print(temperature_celsius);
    Serial.print(".  Boost = ");
    Serial.print(boost);

    if (heat <= math_temp) { //cold
      digitalWrite(blue , HIGH);
      digitalWrite(red , LOW);
      digitalWrite(relay , HIGH);
      Serial.println(".   DO NOT HEAT ");
      delay(1000);

    }
    if (heat > math_temp) { //hot
      digitalWrite(blue , LOW);
      digitalWrite(red , HIGH);
      digitalWrite(relay , LOW);
      Serial.println(".   PLEASE HEAT ME ");
      delay(1000);
    }
  }
  int boostbutton = 0;
  int bm;
  int bs;

  if (BTserial.available() ) { // Checks whether data is comming from the serial port
    boostbutton = BTserial.read(); // Reads the data from the serial port
  }

  if (boostbutton == '1') {
    bm = nmin;
    bs = ns;
    boost = 5;
    Serial.print("BOOST ON    ");
    Serial.print(boost);
    Serial.print("  ");
    Serial.print("nm/bm ");
    Serial.print(nmin);
    Serial.print("/");
    Serial.print(bm);
    Serial.print(".  ns/bs ");
    Serial.print(ns);
    Serial.print("/");
    Serial.println(bs);
    delay(1000);
    DateTime now = rtc.now();
    delay(30);
    int ns = now.second();
    bs = ns;
    digitalWrite(green , HIGH);


  }
  if (boostbutton == '0') {
    bm = nmin;
    bs = ns;
    boost = -3;
    Serial.print("HEATING OFF    ");
    Serial.print(boost);
    Serial.print("  ");
    Serial.print("nm/bm ");
    Serial.print(nmin);
    Serial.print("/");
    Serial.print(bm);
    Serial.print(".  ns/bs ");
    Serial.print(ns);
    Serial.print("/");
    Serial.println(bs);
    delay(1000);
    DateTime now = rtc.now();
    delay(30);
    int ns = now.second();
    bs = ns;


  }
  if (boostbutton == '3') {

    Serial.print("CURRENT TEMPERATURE    ");
    Serial.println(temperature_celsius);
    delay(1000);
    BTserial.println(temperature_celsius);
    delay(10);


  }
  if (bs == ns) {

    //  if (bm == nmin && bs == ns) {
    Serial.println("BOOST over  ");
    boostbutton = 0;
    boost = 0;
    delay(600);
  }

  Serial.print("nmin/bm ");
  Serial.print(nmin);
  Serial.print("/");
  Serial.print(bm);
  Serial.print(".  ns/bs ");
  Serial.print(ns);
  Serial.print("/");
  Serial.print(bs);
  Serial.print("  DST ");
  Serial.print(DST);
  Serial.print("  nm ");
  Serial.println(nm);

  delay(900);


  /*================Display Time================*/
  char buffer [16];
  uint8_t thisSec, thisMin, thisHour;
  thisSec = now.second();
  thisMin = now.minute();
  thisHour = now.hour();
  sprintf (buffer, "%02d:%02d:%02d", thisHour, thisMin, thisSec);

  display.setTextSize(2);
  display.setCursor(15, 9);
  display.print(buffer);


  /*=============Display Temperature=====================*/
  display.setTextSize(1);
  display.setCursor(82, 25);
  display.print(rtc.getTemperature());

  display.display();

}

void draw_text(byte x_pos, byte y_pos, char *text, byte text_size) {
  display.setCursor(x_pos, y_pos);
  display.setTextSize(text_size);
  display.print(text);
  display.display();
}

Presumably because this test returns true

  if (nm == 3 && nd >= 25 && dow == 0 && nh == 1 && nmin == 59 && ns <= 5 && DST == 3)

What do you see if you print the value of the variables being tested ? Are they what you expect ?

One thing that I would do is to use if/else for a series of mutually exclusive conditions. Otherwise there is a chance that a condition is met early in the list and a variable is changed that causes a subsequent condition to be true when it would not originally have been

I removed those lines and it still defaults to 10

The code in post#4 works perfectly. I can change the time on the RTC to just before DST and the clock goes forwards or backwards 1 hour as required.
I just need to move the winter/summer check out of the void loop()

Strangely, if I blank out this line as shown DST defaults to 3

  if (nm >= 1 && nm <= 2 )DST = winter;
  if (nm == 3 && nd <= 24)DST = winter;
  if (nm >= 3 && nd >= 25)DST = summer;
  if (nm >= 4 && nm <= 9)DST = summer;
  if (nm == 10 && nd <= 24)DST = summer;
 // if (nm >= 10 && nd >= 25)DST = winter;
  if (nm >= 11 && nm <= 12)DST = winter;

Why do you want to move it out of loop() ? Suppose that you do allow for DST in setup(), what happens later in the year when the clock goes forward or back ?

Did you try printing the values that the tests are based on as suggested ?

This sets DST after a power down but I don't want it setting DST during normal working conditions.

This sets DST on the last Sunday in March/October so I need it in the void loop()

Yes. All values are correct

You have to put rtc.now() AFTER rtc.begin().

Not even when DST begins or ends ?

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.