RTC for timer control

I would like to use the RTC DS3231 as a reference for a millis timer. How can i use the time from the RTC module to do something every 20 hours?

#include <Wire.h> //I2C library
#include <RtcDS3231.h> //RTC library

unsigned long now = 0;
RtcDS3231<TwoWire> rtc(Wire);


void setup() {
  Serial.begin(115200);  //Starts serial connection
  rtc.Begin();     //Starts I2C
}

void handleGetTime() {
  RtcDateTime currentTime = rtc.GetDateTime();    //get the time from the RTC
  char str[20];   //declare a string as an array of chars
  sprintf(str, "%d/%d/%d %d:%d:%d",     //%d allows to print an integer to the string
          currentTime.Year(),   //get year method
          currentTime.Month(),  //get month method
          currentTime.Day(),    //get day method
          currentTime.Hour(),   //get hour method
          currentTime.Minute(), //get minute method
          currentTime.Second()  //get second method
         );
  Serial.println(str); //print the string to the serial port
}
void loop() {
  if (millis() - now >= 1000) {
    handleGetTime();
    now = millis();
  }
}

Dont think i can use a string as a number to compare with

Hello,

Use the Epoch32Time() method from the RtcDateTime class, store its value when you want to start the timer, then in loop(), periodically check if the difference is >= 72000

Hi im using the library "Rtc by makuna" to be compatible with ESP8266.

i tried

unsigned long epoch = rtc.Epoch32Time();

compiler complains the library does not have that member?

Take a look into the data sheet wrt a alarm function provided by the RTC.

I looked into that. i was hoping it would be as easy as rtc.setalarm(20 hours)' but its not. it looks like it requires extra wires and a mess of code

As an alternative you could use the Alarm system of your DS3231

if you use adafruit/RTClib there is a RTC_DS3231 class and a useful DateTime and TimeSpan class to represent the time.

It supports 2 alarms with useful methods:

  bool setAlarm1(const DateTime &dt, Ds3231Alarm1Mode alarm_mode);
  bool setAlarm2(const DateTime &dt, Ds3231Alarm2Mode alarm_mode);
  void disableAlarm(uint8_t alarm_num);
  void clearAlarm(uint8_t alarm_num);
  bool alarmFired(uint8_t alarm_num);

the alarm mode is defined in an enumeration this way

/** DS3231 Alarm modes for alarm 1 */
enum Ds3231Alarm1Mode {
  DS3231_A1_PerSecond = 0x0F, /**< Alarm once per second */
  DS3231_A1_Second = 0x0E,    /**< Alarm when seconds match */
  DS3231_A1_Minute = 0x0C,    /**< Alarm when minutes and seconds match */
  DS3231_A1_Hour = 0x08,      /**< Alarm when hours, minutes
                                   and seconds match */
  DS3231_A1_Date = 0x00,      /**< Alarm when date (day of month), hours,
                                   minutes and seconds match */
  DS3231_A1_Day = 0x10        /**< Alarm when day (day of week), hours,
                                   minutes and seconds match */
};
/** DS3231 Alarm modes for alarm 2 */
enum Ds3231Alarm2Mode {
  DS3231_A2_PerMinute = 0x7, /**< Alarm once per minute
                                  (whenever seconds are 0) */
  DS3231_A2_Minute = 0x6,    /**< Alarm when minutes match */
  DS3231_A2_Hour = 0x4,      /**< Alarm when hours and minutes match */
  DS3231_A2_Date = 0x0,      /**< Alarm when date (day of month), hours
                                  and minutes match */
  DS3231_A2_Day = 0x8        /**< Alarm when day (day of week), hours
                                  and minutes match */
};

So you could set an alarm for "in 20 hours" this way

rtc.setAlarm1( rtc.now() + TimeSpan(0, 20, 0, 0), DS3231_A1_Hour);

if you hook up the alarm pin to an interrupt pin, you can have an ISR triggered when the alarm is raised.

have a look at the DS3231_alarm.ino example for more details

okay,

RtcDateTime epoch = rtc.GetDateTime();
uint32_t epochTime = epoch.Epoch32Time();

i got it now. thankyou!!

while im here, what is Epoch64Time();?

I agree that using the alarm is a better way to do it but slightly more complicated. What is nice with the alarm is that you can make your arduino/esp sleep, then use the alarm interrupt to wake

I assume because when using external alarm, its not running the millis statements in the loop the whole time so the efficiency/power consumption and accuracy dont suffer as much. but im not really worried about that right now.

what is the point of Epoch64Time();?

It may be useful in 2038 :smiley:

but you still didn't answer my question. If the 32bit integer is going to roll over in 2038, can you change the epoch or just start using the 64 as a standard?

i must be doing somthing wrong this code is not working as expected.

#include <Wire.h> //I2C library
#include <RtcDS3231.h> //RTC library

unsigned long now = 0;

unsigned long currentEpoch = 0;
RtcDS3231<TwoWire> rtc(Wire);
RtcDateTime epoch = rtc.GetDateTime();
void setup() {
  Serial.begin(115200);  //Starts serial connection
  rtc.Begin();     //Starts I2C
  RtcDateTime currentTime = RtcDateTime(16, 05, 18, 21, 20, 0); //define date and time object
  rtc.SetDateTime(currentTime); //configure the RTC with object
}

unsigned long now2 = 0;
void handleGetTime() {

  RtcDateTime currentTime = rtc.GetDateTime();    //get the time from the RTC
  char str[20];   //declare a string as an array of chars
  sprintf(str, "%d/%d/%d %d:%d:%d",     //%d allows to print an integer to the string
          currentTime.Year(),   //get year method
          currentTime.Month(),  //get month method
          currentTime.Day(),    //get day method
          currentTime.Hour(),   //get hour method
          currentTime.Minute(), //get minute method
          currentTime.Second()  //get second method
         );
  Serial.println(str); //print the string to the serial port
}
void loop() {
  RtcDateTime epoch = rtc.GetDateTime();
  uint32_t epochTime = epoch.Epoch32Time();
  if (epochTime - now2 >= 1000) {
    Serial.println("hello");
    now2 = epochTime;
  }
  if (millis() - now >= 1000) {
    Serial.println(epochTime);
    handleGetTime();
    now = millis();
  }
}

the serial output is just,

04:38:53.903 -> 946684800
04:38:53.903 -> 2000/1/1 0:0:0
04:38:54.916 -> 946684800
04:38:54.916 -> 2000/1/1 0:0:0
04:38:55.883 -> 946684800
04:38:55.883 -> 2000/1/1 0:0:0
04:38:56.893 -> 946684800
04:38:56.893 -> 2000/1/1 0:0:0
04:38:57.898 -> 946684800
04:38:57.898 -> 2000/1/1 0:0:0
04:38:58.906 -> 946684800
04:38:58.906 -> 2000/1/1 0:0:0
04:38:59.918 -> 946684800
04:38:59.918 -> 2000/1/1 0:0:0
04:39:00.884 -> 946684800
04:39:00.884 -> 2000/1/1 0:0:0
04:39:01.896 -> 946684800
04:39:01.896 -> 2000/1/1 0:0:0
04:39:02.906 -> 946684800
04:39:02.906 -> 2000/1/1 0:0:0
04:39:03.920 -> 946684800
04:39:03.920 -> 2000/1/1 0:0:0
04:39:04.901 -> 946684800
04:39:04.901 -> 2000/1/1 0:0:0
04:39:05.879 -> 946684800
04:39:05.879 -> 2000/1/1 0:0:0
04:39:06.903 -> 946684800
04:39:06.903 -> 2000/1/1 0:0:0
04:39:07.877 -> 946684800
04:39:07.877 -> 2000/1/1 0:0:0
04:39:08.885 -> 946684800
04:39:08.885 -> 2000/1/1 0:0:0
04:39:09.883 -> 946684800
04:39:09.883 -> 2000/1/1 0:0:0
04:39:10.887 -> 946684800
04:39:10.887 -> 2000/1/1 0:0:0
04:39:11.893 -> 946684800
04:39:11.893 -> 2000/1/1 0:0:0
04:39:12.904 -> 946684800
04:39:12.904 -> 2000/1/1 0:0:0
04:39:13.909 -> 946684800
04:39:13.909 -> 2000/1/1 0:0:0

what am i doing wrong???

if epoch == 1463606440 and i subtract 0 from it, its obviously greater than 1000 right? then why does this if statement never print "hello"??

  RtcDateTime epoch = rtc.GetDateTime();
  unsigned long  epochTime = epoch.Epoch32Time();
  if (epochTime - now2 >= 1000) {
    Serial.println("hello");
    now2 = epochTime;
  }

It looks like your rtc isn't connected, in setup() you set the time but then it shows 2000/1/1 0:0:0.

And because of this problem, I suppose that it is printing "Hello" only once, when the arduino is started (and you don't see it because of the time it takes to start the serial monitor), then as you set now2 to epochTime but epochTime doesn't change (because rtc is not connected), then the difference is 0.

And yes, you can use Epoch64Time() if you wish

for some reason when i reset the esp8266 i have to power cycle the RTC module sometimes. its up and working now. but the if statement never runs. however if i put a 2100ms delay before the if statement, it prints hello 1 time and never again.

#include <Wire.h> //I2C library
#include <RtcDS3231.h> //RTC library

unsigned long now = 0;

unsigned long currentEpoch = 0;
RtcDS3231<TwoWire> rtc(Wire);


void setup() {
  Serial.begin(115200);  //Starts serial connection
  rtc.Begin();     //Starts I2C
  RtcDateTime currentTime = RtcDateTime(16, 05, 18, 21, 20, 0); //define date and time object
  rtc.SetDateTime(currentTime); //configure the RTC with object

}
unsigned long now2 = 0;
void handleGetTime() {
  RtcDateTime currentTime = rtc.GetDateTime();    //get the time from the RTC
  char str[20];   //declare a string as an array of chars
  sprintf(str, "%d/%d/%d %d:%d:%d",     //%d allows to print an integer to the string
          currentTime.Year(),   //get year method
          currentTime.Month(),  //get month method
          currentTime.Day(),    //get day method
          currentTime.Hour(),   //get hour method
          currentTime.Minute(), //get minute method
          currentTime.Second()  //get second method
         );
  Serial.println(str); //print the string to the serial port
}
void loop() {

  RtcDateTime epoch = rtc.GetDateTime();
  unsigned long  epochTime = epoch.Epoch32Time();
  if (epochTime - now2 >= 1000) {
    Serial.println("hello");
    now2 = epochTime;
  }
  if (millis() - now > 1000) {
    Serial.println(epochTime);
    //   handleGetTime();
    now = millis();
  }
}
04:54:54.727 -> 1463606403
04:54:55.704 -> 1463606404
04:54:56.706 -> 1463606405
04:54:57.706 -> 1463606406
04:54:58.706 -> 1463606407
04:54:59.707 -> 1463606408
04:55:00.708 -> 1463606409
04:55:01.710 -> 1463606410
04:55:02.706 -> 1463606411
04:55:03.747 -> 1463606412
04:55:04.709 -> 1463606413
04:55:05.741 -> 1463606414
04:55:06.743 -> 1463606415
04:55:07.732 -> 1463606416
04:55:08.740 -> 1463606417
04:55:09.731 -> 1463606418
04:55:10.734 -> 1463606419
04:55:11.747 -> 1463606420
04:55:12.728 -> 1463606421
04:55:13.719 -> 1463606422
04:55:14.749 -> 1463606423
04:55:15.722 -> 1463606424
04:55:16.736 -> 1463606425
04:55:17.752 -> 1463606426
04:55:18.732 -> 1463606427
04:55:19.755 -> 1463606428
04:55:20.753 -> 1463606429
04:55:21.732 -> 1463606430
04:55:22.747 -> 1463606431
04:55:23.749 -> 1463606432
04:55:24.749 -> 1463606433
04:55:25.748 -> 1463606434
04:55:26.736 -> 1463606435
04:55:27.769 -> 1463606436
04:55:28.738 -> 1463606437
04:55:29.753 -> 1463606438
04:55:30.758 -> 1463606439
04:55:31.791 -> 1463606440
04:55:32.775 -> 1463606441
04:55:33.761 -> 1463606442
04:55:34.771 -> 1463606443
04:55:35.744 -> 1463606444
04:55:36.761 -> 1463606445
04:55:37.753 -> 1463606446
04:55:38.762 -> 1463606447
04:55:39.766 -> 1463606448
04:55:40.772 -> 1463606449
04:55:41.757 -> 1463606450
04:55:42.765 -> 1463606451
04:55:43.764 -> 1463606452
04:55:44.752 -> 1463606453
04:55:45.778 -> 1463606454
04:55:46.771 -> 1463606455
04:55:47.786 -> 1463606456
04:55:48.775 -> 1463606457
04:55:49.788 -> 1463606459
04:55:50.785 -> 1463606460
04:55:51.777 -> 1463606461
04:55:52.763 -> 1463606462
04:55:53.805 -> 1463606463
04:55:54.782 -> 1463606464
04:55:55.798 -> 1463606465
04:55:56.811 -> 1463606466
04:55:57.782 -> 1463606467
04:55:58.805 -> 1463606468
04:55:59.804 -> 1463606469
04:56:00.774 -> 1463606470
04:56:01.793 -> 1463606471
04:56:02.774 -> 1463606472
04:56:03.774 -> 1463606473
04:56:04.807 -> 1463606474
04:56:05.816 -> 1463606475
04:56:06.777 -> 1463606476
04:56:07.784 -> 1463606477
04:56:08.785 -> 1463606478
04:56:09.822 -> 1463606479
04:56:10.816 -> 1463606480
04:56:11.803 -> 1463606481
04:56:12.789 -> 1463606482
04:56:13.792 -> 1463606483
04:56:14.788 -> 1463606484
04:56:15.793 -> 1463606485
04:56:16.823 -> 1463606486
04:56:17.797 -> 1463606487
04:56:18.816 -> 1463606488

Did you wait 1000 seconds ?

if i just remove now2 and put 0 it will print as fast as the loop like it should. yes i waited the duration

and if i remove the power from the RTC module it will print too

Does it work with if (epochTime - now2 >= 5) ?

yes it does?

lol i did forget were dealing with seconds. but still it should have printed hello at least one time. unless it printed too fast to capture the print?

it must have just printed too fast. if i remove now2 = epochTime; it behaves expectedly . thanks again