DS3231 RTC is regularily resetting to 00:00:00 (Arduino Uno project)

Hi everyone!

This is my first post on the forum.

I’m new to Arduino, but I’ve been messing around with DIY electronics for some time now (mostly audio-related projects).

I’ve developped a system (based on an Arduino Uno board) that allows to open two doors with electric strikes :
The first one is triggered through an Arduino Relay Module when a certain value is provided to one of the Analog pins. The second one is also triggered through an Arduino Relay module (I use a 2 Relay module) when a switch is closed.

The system is active at certain hours in the day (and depending on the day), so I’ve also connected a DS3231 RTC module to the project. I chose a DS3231 because of its accuracy, as the system is not connected to the internet.

The issue I’m facing is that the RTC module regularily resets to its factory values (happens once every 2 days to 4 weeks I would say…)

First I thought that the fact that I was using the electric strike Power Supply (12VDC) to also power the Arduino Uno was the cause (I was thinking that humidity in the strike could create a kind of a short, going up to the PSU, and then back down to the Arduino Uno board, causing the DS3231 to reset).

I’m now using a separate PSU for the Arduino Uno board. But the issue keeps happening.

The RTC modules I’m using are these ones :

https://www.robotshop.com/eu/fr/module-rtc-ds3231-horloge-temps-reel-haute-precision-raspberry-pi.html?gclid=EAIaIQobChMIiszondWK6AIVxZrVCh3sVQhFEAQYAyABEgJFSvD_BwE

I found out that the provided battery was weak so I installed a 2032 battery socket and put new Varta batteries (I have several modules that I swap when one resets, but that is not a long-term solution!)

But the issue still seems to be happening…

So now I’m a little lost.

Here is the code I’m using:

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

// Initialisation du module horloge DS3231 (SDA, CLOCK)
DS3231 rtc(SDA, SCL);

// Initialisation d'une  structure Time-data
Time t;


int sensePin =0;
int relay1Pin =9;
int relay2Pin =10;
const int buttonPin = 6;     // the number of the pushbutton pin

int buttonState = 1;         // variable for reading the pushbutton status


void setup() 

{
  // Setup Serial connection
  Serial.begin(115200);

  // Initialize the rtc object
  rtc.begin();

  // A // quand le DS3231 est déjà réglé
  // rtc.setDOW(SUNDAY);    // Set Day-of-Week to SUNDAY
  // rtc.setTime(13, 35, 40);     // Set the time to 12:00:00 (24hr format)
  // rtc.setDate(7, 3, 2020);   // Set the date to January 1st, 2014

  analogReference(DEFAULT);

  pinMode(A0, INPUT_PULLUP);

  pinMode(relay1Pin, OUTPUT);


  pinMode(buttonPin, INPUT);     // initialize the pushbutton pin as an input:

  pinMode(relay2Pin, OUTPUT);


}

void loop() 


// OUVERTURE PORTE PIETON

{
  // Sensor (prise jack)
  int val = analogRead(sensePin);

  {

    do  
    { 
      digitalWrite(relay1Pin, LOW);
      delay(100); 

      // Get data from the DS3231
      t = rtc.getTime();

      // Send Day-of-Week
      Serial.print(rtc.getDOWStr());
      Serial.print(" ");

      // Send date (inutile ici a priori)
      // Serial.print(rtc.getDateStr());
      // Serial.print(" -- ");

      // Send time
      Serial.println(rtc.getTimeStr());

      // Attendre 1/10ème de sec avant répétition :)
      // delay (100);

    }
    while ( ( (t.dow == SUNDAY) && ( (t.hour < 7) || (t.hour >=18) ) ) || (t.hour < 7) || (t.hour >=22) );

    if ( (val < 673) || (val > 682) ) 
    { 
      digitalWrite(relay1Pin, LOW);
      delay(100);
    }

    if ( (val >= 673) && (val <= 682) ) 
    { 
      digitalWrite(relay1Pin, HIGH);
      delay(2000);
    }

    Serial.println(analogRead(sensePin));
    delay (100);


    // INTERRUPTEUR PORTAIL

    // read the state of the pushbutton value:
    buttonState = digitalRead(buttonPin);

    do  
    { 
      digitalWrite(relay1Pin, LOW);
      delay(10); 

      // Get data from the DS1302
      t = rtc.getTime();

      // Send Day-of-Week
      Serial.print(rtc.getDOWStr());
      Serial.print(" ");

      // Send date (inutile ici a priori)
      // Serial.print(rtc.getDateStr());
      // Serial.print(" -- ");

      // Send time
      Serial.println(rtc.getTimeStr());

      // Attendre 1/10ème de sec avant répétition :)
      // delay (100);

    }
    // while ( ( (t.dow == MONDAY) || (t.dow == TUESDAY) || (t.dow == WEDNESDAY) || (t.dow == THURSDAY) || (t.dow == FRIDAY) || (t.dow == SATURDAY) ) || (t.hour < 7) || (t.hour >=20) );

    while ( ( (t.dow != SUNDAY) && (t.hour < 7) && (t.hour >=20) ) );


    if (buttonState == HIGH) {

      digitalWrite(relay2Pin, HIGH);
    } 
    else {

      digitalWrite(relay2Pin, LOW);
    }

  }
}

And here is the wiring schematic for my project (The RTC isn’t shown, but it is connected to the GND, +3.3v, SDA and SCL pins from the Arduino Uno).

I’m really lost here…

Thank you in advance for your help!

All the best.

which library are you using?
have you checked if you see the same behavior with one of the example from the library, running with your existing wiring?


Please don't use the quote tag for code (see the smileys in your code? ) ==> correct your post above and add code tags around your code:
[code]`` [color=blue]// your code is here[/color] ``[/code].

It should look like this:// your code is here
(Also press ctrl-T (PC) or cmd-T (Mac) in the IDE before copying to indent your code properly)

Thanks J-M-L for your answer.

I corrected the post but couldn't keep the colors in the code (I thought that it would add automatically but it didn't)

I'm using the DS3231 library by Henning Karlsen (DS3231 - Rinky-Dink Electronics)

I haven't tried one of the examples from the library with my complete wiring, I can try and see where it gets me, that's a very good suggestion !

If the examples work reliably with your setup with current etc then you know there is likely something fishy in your code

tupinamba:
I corrected the post but couldn't keep the colors in the code (I thought that it would add automatically but it didn't)

Colours don't add value for the older generation on this forum :wink:

Colours don't add value for the older generation on this forum :wink:

Ha ha, yeah, newbie way of thinking!

If the examples work reliably with your setup with current etc then you know there is likely something fishy in your code

Well, the thing is the system is already installed on site, and I cannot just put an example code in the Arduino as it would result in the doors not being able to open, and there are dozens of persons who need it to open... :-/

So all I can do is an "out of site" test with another arduino and DS3231 module. My question being:

  1. Would a test with only the Arduino board, the DS3231 and an example code from the library be conclusive enough?

  2. Or should I also connect the Relay module and Input triggers to the Arduino board? (but then, what's the point, as the example code won't deal with them)

  3. I've assumed that the relay module boards I'm using (which have diodes, transistors and resistors) were meant to be connected directly to the Arduino board, preventing inductive current issues, and the module pdf documentation seems to agree with that statement... But could the 12v running through the relays when they are triggered interfere in some way with the Arduino board and hence with the DS3231?

  4. I am currently testing the code on an arduino with DS3231, relays and triggers (but no electric strikes connected to the relays) to check if it is stable this way: can this be a valid first step?

Thank you J-M-L and sterretje for your previous answers!

well I've never seen a DS3231 reset itself to 'no time' if it's powered and the coin battery can lasts years...

if relay are of good quality and you have not done anything foolish in terms of wiring, then the low side should not be impacted by what happens on the high side (when you open or close the relay).

I don't use that library, on the web site the author states

This library will default to I2C Fast Mode (400 KHz) when using the hardware I2C interface

The library has not been tested in combination with the Wire library and I have no idea if they can share pins. Do not send me any questions about this. If you experience problems with pin-sharing you can move the DS3231/DS3232 SDA and SCL pins to any available pins on your development board. This library will in this case fall back to a software-based, TWI-/I2C-like protocol which will require exclusive access to the pins used

and I see you include the Wire library...

--> I would suggest to move to the RTCLib, the API is not far from what you are using today so the porting effort should be minimal and see if you experience the same issues.

tupinamba:
I corrected the post but couldn't keep the colors in the code (I thought that it would add automatically but it didn't)

When we copy a properly posted sketch and paste it into our favourite IDE, it will provide our favourite colours and formatting.

Do the actuators have kickback diodes / snubbers installed? Post a link to the actuators.

Hi!

Thank you so much for your answers!

Do the actuators have kickback diodes / snubbers installed? Post a link to the actuators.

By “actuators”, you mean what triggers the Analog inputs, right?

So I have two electric strikes in my setup :

_ The first one is triggered when a TRS jack (with specific resistors between tip-ring and sleeve-ring) is inserted in a Fender guitar style Jack plug. Sleeve is to Ground, tip is to V+, so when the jack is inserted, it sends a specific digital value to the ring, which is connected to A0, and if time and day of week are in the defined range, the first Relay is triggered (circuit closed), which allows 12v to get to the electric strike and open the door.

_ The second electric strike is triggered by a simple switch that sends V+ to A6 when the switch is closed. And if time and day of week are in the defined range, same happens to the second Relay and second electric strike. I’m using a 10k pulldown resistor to ground (as you can see on the file I’ve provided).

There are no kickback diodes or snubbers (?) installed. Could this be an option? And if so, How to connect them?

The idea of changing the library is good, I guess, reading from the author… :wink:

So I’ve done it, but there is an error that remains in the code, and I’ve spent a lot of time to try and fix it all by myself, but I think this is the time I have to ask for the expert eye’s help…

I get this error :

BUSSO_EXT_INT_v5_RTClib_2020_03_10.ino: In function ‘void loop()’:
BUSSO_EXT_INT_v5_RTClib_2020_03_10.ino:89:16: error: ‘now’ was not declared in this scope

And it refers to this line of code:

while ( ( (now.dayOfTheWeek != “Sunday”) && (now.hour < 7) && (now.hour >=20) ) );

I hope this will ring a bell…

Cheers!

#include "RTClib.h"
#include <Wire.h>
// #include <Time.h>

// Initialize DS3231
RTC_DS3231 rtc;

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

// Initialisation d'une  structure Time-data
// Time t;


int sensePin =0;
int relay1Pin =9;
int relay2Pin =10;
const int buttonPin = 6;     // the number of the pushbutton pin

int buttonState = 1;         // variable for reading the pushbutton status


void setup() 

{
 // Setup Serial connection
 Serial.begin(115200);

 // Initialize the rtc object
 rtc.begin();

 // A // quand le DS3231 est déjà réglé
   // If the RTC have lost power it will sets the RTC to the date & time this sketch was compiled in the following line
   rtc.adjust(DateTime(2020, 3, 10, 13, 50, 0));
   // This line sets the RTC with an explicit date & time, for example to set
   // January 21, 2014 at 3am you would call:
   // rtc.adjust(DateTime(2020, 3, 10, 13, 50, 0));

 analogReference(DEFAULT);

 pinMode(A0, INPUT_PULLUP);

 pinMode(relay1Pin, OUTPUT);


 pinMode(buttonPin, INPUT);     // initialize the pushbutton pin as an input:

 pinMode(relay2Pin, OUTPUT);


}

void loop()


// OUVERTURE PORTE PIETON

{
 // Sensor (prise jack)
 int val = analogRead(sensePin);

 {

   do  
   { 
     digitalWrite(relay1Pin, LOW);
     delay(100); 

     // Get data from the DS3231
   DateTime now = rtc.now();

     // Send Day-of-Week
   Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
   Serial.print(" ");

     // Send time
   Serial.print(now.hour(), DEC);
   Serial.print(':');
   Serial.print(now.minute(), DEC);
   Serial.print(':');
   Serial.print(now.second(), DEC);
   Serial.println();

     // Attendre 1/10ème de sec avant répétition :)
     // delay (100);

   }
   
   
[color=orange]   while ( ( (now.dayOfTheWeek == "Sunday") && ( (now.hour < 7) || (now.hour >=18) ) ) || (now.hour < 7) || (now.hour >=22) );[/color]

   if ( (val < 671) || (val > 682) ) 
   { 
     digitalWrite(relay1Pin, LOW);
     delay(100);
   }

   if ( (val >= 671) && (val <= 682) ) 
   { 
     digitalWrite(relay1Pin, HIGH);
     delay(2000);
   }

   Serial.println(analogRead(sensePin));
   delay (100);


   // INTERRUPTEUR PORTAIL

   // read the state of the pushbutton value:
   buttonState = digitalRead(buttonPin);

   do  
   { 
     digitalWrite(relay1Pin, LOW);
     delay(10); 

     // Get data from the DS3231
   DateTime now = rtc.now();

     // Send Day-of-Week
   Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
   Serial.print(" ");
     

     // Send time
   Serial.print(now.hour(), DEC);
   Serial.print(':');
   Serial.print(now.minute(), DEC);
   Serial.print(':');
   Serial.print(now.second(), DEC);
   Serial.println();
   
   Serial.print("Temperature: ");
   Serial.print(rtc.getTemperature());
   Serial.println(" C");
   
     // Attendre 1/10ème de sec avant répétition :)
     // delay (100);

   }

   while ( ( (now.dayOfTheWeek != "Sunday") && (now.hour < 7) && (now.hour >=20) ) );


   if (buttonState == HIGH) {

     digitalWrite(relay2Pin, HIGH);
   } 
   else {

     digitalWrite(relay2Pin, LOW);
   }

 }
}

Possibly because you commented out the declaration that defines ‘now’

// #include <Time.h>

Why?

tupinamba:
By "actuators", you mean what triggers the Analog inputs, right?

I think wrong. I believe that comment refers to the relays.

aarg:
Possibly because you commented out the declaration that defines ‘now’

// #include <Time.h>

Why?

Because I thought this was no longer necessary with the new RTC library, and if I put those lines back in, I get this… :-/

BUSSO_EXT_INT_v5_RTClib_2020_03_10.ino:11:2: error: ‘Time’ does not name a type
BUSSO_EXT_INT_v5_RTClib_2020_03_10.ino: In function ‘void loop()’:
BUSSO_EXT_INT_v5_RTClib_2020_03_10.ino:89:20: error: request for member ‘dayOfTheWeek’ in ‘now’, which is of non-class type ‘time_t() {aka long unsigned int()}’
BUSSO_EXT_INT_v5_RTClib_2020_03_10.ino:89:56: error: request for member ‘hour’ in ‘now’, which is of non-class type ‘time_t() {aka long unsigned int()}’
BUSSO_EXT_INT_v5_RTClib_2020_03_10.ino:89:74: error: request for member ‘hour’ in ‘now’, which is of non-class type ‘time_t() {aka long unsigned int()}’
BUSSO_EXT_INT_v5_RTClib_2020_03_10.ino:89:97: error: request for member ‘hour’ in ‘now’, which is of non-class type ‘time_t() {aka long unsigned int()}’
BUSSO_EXT_INT_v5_RTClib_2020_03_10.ino:89:115: error: request for member ‘hour’ in ‘now’, which is of non-class type ‘time_t() {aka long unsigned int()}’
BUSSO_EXT_INT_v5_RTClib_2020_03_10.ino:142:20: error: request for member ‘dayOfTheWeek’ in ‘now’, which is of non-class type ‘time_t() {aka long unsigned int()}’
BUSSO_EXT_INT_v5_RTClib_2020_03_10.ino:142:54: error: request for member ‘hour’ in ‘now’, which is of non-class type ‘time_t() {aka long unsigned int()}’
BUSSO_EXT_INT_v5_RTClib_2020_03_10.ino:142:72: error: request for member ‘hour’ in ‘now’, which is of non-class type ‘time_t() {aka long unsigned int()}’

aarg:
I think wrong. I believe that comment refers to the relays.

I posted documents I have about the relay modules earlier (no schematic unfortunately). I can see that they have diodes and optocouplers, so I would say that the provide proper isolation, but maybe I’m mistaken…

It seems to me that you are taking a shotgun approach to programming. You need to back off and study the libraries that you're using. Eliminating compilation errors won't eliminate logical or design errors. Without a design and some oversight, a program needs a huge amount of plain luck to work. Rarely does that happen.

aarg:
It seems to me that you are taking a shotgun approach to programming. You need to back off and study the libraries that you're using. Eliminating compilation errors won't eliminate logical or design errors. Without a design and some oversight, a program needs a huge amount of plain luck to work. Rarely does that happen.

I'm afraid you're right...
The thing is I have an unstable system running and crashing regularily, with lots of people depending on it, so I'm really under pressure here... This doesn't help to think before shooting the shotgun! :slight_smile:

And J-M-L gave me hope when he said that

the API is not far from what you are using today so the porting effort should be minimal and see if you experience the same issues

I seems that the effort isn't minimal for me AT ALL! :slight_smile:

I've studied the examples of the RTClib, but I'm afraid I don't get all that there is to get... What I see is how to define and get a Time/Day from the RTC, but not how to use it. And that was what Time.h did in my previous code, right?...

You can use now.day, now.hour, now.whatever is declared just as you did in the other sketch. Take a look at the DS3231 example, it shows you what is declared and how using serialprint. Take those variables and use it to construct what you did with time.h

tupinamba:
And J-M-L gave me hope when he said that
I seems that the effort isn’t minimal for me AT ALL! :slight_smile:

sorry if I misled you. the now variable comes from

     DateTime now = rtc.now();

so it’s a DateTime object.

the day of the week is referred to with a number, obtained by calling dayOfTheWeek() method on the DateTime object and you usually use that as an index in an array you have predefined

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

which usually is better defined as

const char* daysOfTheWeek[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

So if you want to print the name of the day you do:

   Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);

so your code is complaining at this line

while ( ( (now.dayOfTheWeek == "Sunday") && ( (now.hour < 7) || (now.hour >= 18) ) ) || (now.hour < 7) || (now.hour >= 22) );

because now.dayOfTheWeek does not exist as such (it’s a pointer to a function).

if you were to use now.dayOfTheWeek() then that will be a number 0 for Sunday, 1 for Monday etc… so the while would become

while ( ( (now.dayOfTheWeek() == 0) && ( (now.hour < 7) || (now.hour >= 18) ) ) || (now.hour < 7) || (now.hour >= 22) );

that’s what I meant by not too much work :slight_smile:

does this help ?

As well as the syntax errors pointed out by others, you have a scope error with the instantiation inside the do while loop.

DateTime now = rtc.now();

Move it to the be the first line in loop(). This code below compiles

#include "RTClib.h"
#include <Wire.h>
// #include <Time.h>

// Initialize DS3231
RTC_DS3231 rtc;

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

// Initialisation d'une  structure Time-data
// Time t;


int sensePin = 0;
int relay1Pin = 9;
int relay2Pin = 10;
const int buttonPin = 6;     // the number of the pushbutton pin

int buttonState = 1;         // variable for reading the pushbutton status


void setup()

{
  // Setup Serial connection
  Serial.begin(115200);

  // Initialize the rtc object
  rtc.begin();

  // A // quand le DS3231 est déjà réglé
  // If the RTC have lost power it will sets the RTC to the date & time this sketch was compiled in the following line
  rtc.adjust(DateTime(2020, 3, 10, 13, 50, 0));
  // This line sets the RTC with an explicit date & time, for example to set
  // January 21, 2014 at 3am you would call:
  // rtc.adjust(DateTime(2020, 3, 10, 13, 50, 0));

  analogReference(DEFAULT);

  pinMode(A0, INPUT_PULLUP);

  pinMode(relay1Pin, OUTPUT);


  pinMode(buttonPin, INPUT);     // initialize the pushbutton pin as an input:

  pinMode(relay2Pin, OUTPUT);


}

void loop()


// OUVERTURE PORTE PIETON

{
   DateTime now = rtc.now(); 
  // Sensor (prise jack)
  int val = analogRead(sensePin);

  {

    do
    {
      digitalWrite(relay1Pin, LOW);
      delay(100);

      // Get data from the DS3231
      //DateTime now = rtc.now();

      // Send Day-of-Week
      Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
      Serial.print(" ");

      // Send time
      Serial.print(now.hour(), DEC);
      Serial.print(':');
      Serial.print(now.minute(), DEC);
      Serial.print(':');
      Serial.print(now.second(), DEC);
      Serial.println();

      // Attendre 1/10ème de sec avant répétition :)
      // delay (100);

    }

    while ( ( (now.dayOfTheWeek() == 0) && ( (now.hour() < 7) || (now.hour() >= 18) ) ) || (now.hour() < 7) || (now.hour() >= 22) );

    if ( (val < 671) || (val > 682) )
    {
      digitalWrite(relay1Pin, LOW);
      delay(100);
    }

    if ( (val >= 671) && (val <= 682) )
    {
      digitalWrite(relay1Pin, HIGH);
      delay(2000);
    }

    Serial.println(analogRead(sensePin));
    delay (100);


    // INTERRUPTEUR PORTAIL

    // read the state of the pushbutton value:
    buttonState = digitalRead(buttonPin);

    do
    {
      digitalWrite(relay1Pin, LOW);
      delay(10);

      // Get data from the DS3231
      DateTime now = rtc.now();

      // Send Day-of-Week
      Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
      Serial.print(" ");


      // Send time
      Serial.print(now.hour(), DEC);
      Serial.print(':');
      Serial.print(now.minute(), DEC);
      Serial.print(':');
      Serial.print(now.second(), DEC);
      Serial.println();

      Serial.print("Temperature: ");
      Serial.print(rtc.getTemperature());
      Serial.println(" C");

      // Attendre 1/10ème de sec avant répétition :)
      // delay (100);

    }

    //while ( ( (now.dayOfTheWeek() != "Sunday") && (now.hour() < 7) && (now.hour() >= 20) ) );
    while ( ( (now.dayOfTheWeek() != 0) && (now.hour() < 7) && (now.hour() >= 20) ) );

    if (buttonState == HIGH) {

      digitalWrite(relay2Pin, HIGH);
    }
    else {

      digitalWrite(relay2Pin, LOW);
    }
  }
}

J-M-L:
sorry if I misled you. the now variable comes from

(...)

does this help ?

You bet it does! Thank you J-M-L !

cattledog:
As well as the syntax errors pointed out by others, you have a scope error with the instantiation inside the do while loop.

DateTime now = rtc.now();

Move it to the be the first line in loop(). This code below compiles

And thank you cattledog, not only does it work, but both you explanations made me understand what were my mistakes! And that's a really great victory.

I just had to reprogram the RTCs still running with the old code. And I think I may have an explanation, but I'd like to have your opinion on it...

I have actually 2 arduino boards running with the same code, for 2 different entrances. The first one has the jack input to A0 and the switch input going to A6, and the second one only uses the jack input to A0.

They are on 2 completely distinct power grids (2 different buildings).

But when I checked the clocks before resetting them to the right time and day, I noticed they had been both reset to "Monday 00:00:00" with only 1 minute of delay between them...

That's the time it takes for someone to insert a jack for the first entrance, go to the second entrance and insert the same jack...

So I'm thinking I may have someone using a defective jack plug...

Do you think that if, for instance, one jack makes a short between ground and V+, it could reset the RTC?...

(I'm going to try to be sure, but I would really appreciate your opinion about this theory...)

Thank you for your help so far!

There is no extra Resistor or diode in your jack setup ?