Set RTC to compile time, but RTC not retaining time after power cycle.

I'm revisiting an annoying problem I've had for a while, having my DS3231 RTC keep the correct time during power off. Plus each time I compile I need the RTC (fresh new or existing pre-set) to be set to compile time, even if it is already running. Most of the examples I have use something similar to:

if (! RTC.isrunning()) 
 {
   Serial.println("RTC is NOT running!");
   following line sets the RTC to the date & time this sketch was compiled
  RTC.adjust(DateTime(__DATE__, __TIME__));
}

My full code is as follows:

// Daily Alarm Test using DS3231 RTC
//
#include <Wire.h>
#include "RTClib.h"
#include <LiquidCrystal_I2C.h>
#include <Time.h>
#include <TimeAlarms.h>
LiquidCrystal_I2C lcd(0x27,20,4); 
RTC_DS1307 RTC;
time_t syncProvider() 
{  return RTC.now().unixtime(); }
 
void setup () {
  Wire.begin();
  RTC.begin();
  setSyncProvider(syncProvider);
 //if (! RTC.isrunning()) 
 //{
   //Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
  RTC.adjust(DateTime(__DATE__, __TIME__)); //Set RTC to compile time
//  }

 Alarm.alarmRepeat(8,0,0, Event1);  // Daily event time 24 Hr
 lcd.init(); 
 lcd.backlight();
 lcd.setCursor(0, 0);
 pinMode(7, OUTPUT); // Daily test output to controller zone
 digitalWrite(7, HIGH); //Turn on Q3 Transistor
} 

void loop () {
clockDisplay();
Alarm.delay(1000); 
}

void clockDisplay(){
  DateTime now = RTC.now();
  char buf[20];  // -------------------- RTC Time --------------------
  sprintf(buf, "%02d:%02d:%02d %02d/%02d/%4d", now.hour(), now.minute(), now.second(), now.month(), now.day(), now.year());
  lcd.setCursor(0,0);
  lcd.print(buf);

 char buf1[20];  // ------------------  Arduino Time -----------------
 sprintf(buf1, "%02d:%02d:%02d %02d/%02d/%4d", hour(), minute(), second(), month(), day(), year());
 lcd.setCursor(0,1);
 lcd.print(buf1);
}  

void Event1(){ // *********** Daily Alarm Output ****************
  digitalWrite(7, LOW);  //alarm test output
  delay(4000);
  digitalWrite(7, HIGH); }

Could it be that the DS3231 doesn't set correctly using the DS1307 commands, etc.?
These are new RTC units, the battery voltages are 3.29-3.3V

Could it be that the DS3231 doesn't set correctly using the DS1307 commands, etc.?

Sounds like a dead backup battery (or one not charging if rechargeable.). Try sample code.

http://playground.arduino.cc/Code/time

  • The I2C 'DS3231' interface is very straight forward and
    virtually identical to the register addresses of the popular DS1337
    and DS1307 RTCs, which means that existing code for the Arduino,
    Basic Stamp, Cubloc, and other controllers should work with no modification.
    For reference purposes see >> https://www.adafruit.com/products/255

That example was not much help to me.
Every time I close the Serial Monitor, I'm prompted "waiting for sync message", it doesn't display the time until the Unix time is re-entered.
Like: T1375316871

Maybe I'm missing something.

if (! RTC.isrunning())

Not applicable to the 3231. It's a flag set on the 1307.

Take a look at the data sheet.

I found a code example that solved my problem here: Arduino Love electronics RTC – DS3231 wiring example and tutorial. – Marc Lane's Blog

DateTime now = RTC.now();
DateTime compiled = DateTime(__DATE__, __TIME__);
if (now.unixtime() < compiled.unixtime()) {
Serial.println("RTC is older than compile time! Updating");
// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));

Tests so far are good.

Linus/Unix issue?
http://forum.arduino.cc/index.php?topic=179213.msg1334184#msg1334184

Your code appears to set the arduino date/time back to the compile-time values each time it starts. I don't think you ever actually set the time IN theDS3231 nor are you telling the Arduino to READ the time from the RTC (as the syncprovider).

A sketch I wrote:

#include "arduino.h"

#include "Wire.h"
#include <Time.h>
#include "DS3231RTC.h"

DS3231RTC RTC3231;
tmElements_t tm;
void setup()
{
  Serial.begin(9600);
  tm.Year=2013 - 1970;
  tm.Month = 7;
  tm.Day = 30;
  tm.Hour= 19;
  tm.Minute = 57;
  tm.Second = 0;
  
//  RTC3231.write(tm);
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if(timeStatus()!= timeSet) 
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time"); 
 
}
 
void loop()
{
  Serial.print("Temp: ");Serial.print(RTC3231.getTemp()*1.8+32); Serial.println();
  Serial.print("Time: ");
          Serial.print(month()); Serial.print(" ");
          Serial.print(day()); Serial.print(" ");
          Serial.print(year()); Serial.print(" ");
          Serial.print(hour()); Serial.print(" ");
          Serial.print(minute()); Serial.print(" ");
          Serial.print(second()); Serial.print(" ");
          Serial.println();
  delay(1000);
}

I downloaded GitHub - trunet/DS3231RTC: An arduino library for DS3231 Real-time clock to support the DS3231

The RTC time is set initially with:

RTC3231.write(tm)

Moderator edit:
</mark> <mark>[code]</mark> <mark>

</mark> <mark>[/code]</mark> <mark>
tags added.

the idea is to set DATE and TIME just the once
then remove the code

I have exactly the same problem: RTC works fine as long as it is powered via Vcc however, it does not retain the time when powered off.

I have RTC module ZS-042 and I have:

  1. removed the diode of the battery charging circuit
  2. put a CR2032
  3. checked the charge of the battery with a 400ohms load and reads fine (3V)
  4. I have checked DS3231's leg-14 and it gives 3V

Could it be I have got a faulty RTC unit?

Take a look at the value set in Bit 7 of Control Register 0Eh. It should be set to 0.

From the data sheet:

Control Register (0Eh)
Bit 7: Enable Oscillator (EOSC). When set to logic 0,
the oscillator is started. When set to logic 1, the oscillator
is stopped when the DS3231 switches to VBAT. This
bit is clear (logic 0) when power is first applied. When
the DS3231 is powered by VCC, the oscillator is always
on regardless of the status of the EOSC bit. When
EOSC is disabled, all register data is static

http://datasheets.maximintegrated.com/en/ds/DS3231.pdf

Hi,

I use this library:

But is there a way to set the time into the rtc 'live' while running?

Everytime I use: (for example)

setTime(13, 12, 11, 2, 11, 2014);
RTC.set(now());

the program 'hangs' and time is not progressing anymore....after a reset time is displayed again as before but not updated/adjusted.

Using only setTime seems like to work but I think it's not saved/written to the rtc......

I can not confirm what you observe. Here is a sketch which uses setTime to set the clock on the Arduino and then uses RTC.set(now()) to set the RTC with that time. The RTC does not hang.

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

tmElements_t tm;

void setup() {

  Serial.begin(9600);

  Serial.println("Setting time on Arduino");
  setTime(13, 12, 11, 2, 11, 2014);//setting AVR time
  displayAVR_Time();
  Serial.println();
  Serial.println("Settting time on RTC from Arduino");
  RTC.set(now());//setting RTC to AVR_Time
  displayRTC_Time();
  Serial.println();

  Serial.println("DS3231RTC Read Test");
  Serial.println("-------------------");
}

void loop() {

  displayAVR_Time();
  displayRTC_Time();
  Serial.println();
  delay(1000);
}

void displayAVR_Time(void)
{
  Serial.print("AVR Time = ");
  Serial.print(hour());
  Serial.write(':');
  print2digits(minute());
  Serial.write(':');
  print2digits(second());
  Serial.print(", Date (D/M/Y) = ");
  Serial.print(day());
  Serial.print('/');
  Serial.print(month());
  Serial.print('/');
  Serial.print(year()); 
  Serial.println(); 
}

void displayRTC_Time()
{
  RTC.read(tm);//TimeElements variable
  Serial.print("RTC Time = ");
  print2digits(tm.Hour);
  Serial.write(':');
  print2digits(tm.Minute);
  Serial.write(':');
  print2digits(tm.Second);
  Serial.print(", Date (D/M/Y) = ");
  Serial.print(tm.Day);
  Serial.write('/');
  Serial.print(tm.Month);
  Serial.write('/');
  Serial.print(tmYearToCalendar(tm.Year));
  Serial.println();
}

void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}

Using it within the setup() it works just fine, but for example on some button presses it doesn't.

Would like to adjust the clock 'live' and not by programming it again....

Creamers,

There are many examples found with Google search about using a button or buttons to adjust the time on an RTC.

Check them out, and if you want to pursue this further, please start a new thread about changing the time setting on an RTC from button presses, and be sure to post your code using the code tags.

Hi cattledog,

thanks to your suggestion I have set now bit-7 of 0E register to zero.

What I observe now is that when I turn Vcc off the clock stops ticking, so when Vcc is on again the clock starts ticking from the minute that I switched Vcc off.

I have also set bit-7 of register 0F to zero to check Oscillator Stop Flag (OSF). I can see it keeps zero after turning Vcc off/on.

Any idea of why the clock stop ticking when it goes from Vcc to VBat?

Tamadite,

If you have done it correctly, I don't think the problem is in your settings. You have the oscillator enabled, and the device does not think the oscillator stops, that is, the oscillator stop flag is not being set when Vcc is removed.

If you disable the oscillator, does the flag get set?
If you remove Vcc and the battery, does the flag get set?

Did the module work correctly before you removed the diode and changed the battery?

I have the same module, and it works fine with a LIR 2032 and the diode in place. I have seen advice about cutting the trace between the diode and R5 to avoid overcharging, but so far i have not seen any problems.

cattledog,

yes to your two first questions.

Concerning the third, I would say that everything worked fine until the CR2032 that came with it exploded for obvious reasons. However, I cannot not categorically say that it worked. I would rather say that I noticed the problem after the battery exploded.

The timer failed with Vbat also with the diode connected (after the explosion).

What I am going to do now is to order a new one from a provider that sales it with a LIR2032.

Thanks for supporting my troubleshooting!

I do not know if am suffering an overdose of bad luck. I have got my new DS3231 with a LIR2032 battery but I do still have the same problems as with the old one that is, the time gets lost when the power supply gets unplugged.

This is the status of the registers I get when I unplug the power supply:

0x0E: 28d (00011100)
0x0F: 8d (00001000)

Any idea?

@Tamadite--

Sorry to hear that your problems persist with the new module. Is it the same ZS 042 module Please post the code that you are using to initially set the time on the RTC. If you are using a ds3231/3232 library, please reference the source for that library.

If you leave the power connected to the Arduino and run a different sketch which doesn't use the RTC and then come back to a sketch using time from the RTC, is the time correct?

When you say that the "time gets lost" does it mean that it restarts from the time when the power was removed?

Are you sure that the new battery is good? Is there a way that you can test it in some other battery powered device?.

I have also seen postings about defects in the battery holders which have poor grounds

@cattledog

yes, I use module ZS042. I have tested the charge of the battery with a 400ohms load showing more than 3volts so it seems the battery is Ok.

I have also checked the battery voltage on the circuit -not on the battery holder, showing also the same good battery value (>3V).

When I run a different sketch that does not make use of the RTC to later load up back the sketch that exploits the RTC's features, then I can observe the clock is still on time, no changes/deviations.

"time gets lost" was a good question! Actually what I can observe is that when I do a power cycle (unplug/plug power) on the unit, the clock starts from the original configuration time that is, if the clock got originally set at 21:00 and then I do a power cycle at 21:10 then the clock starts again at 21:00. On certain occasions it gets completely off that is, it starts at a what seems to be a random/garbage time. Unfortunately I cannot reproduce this behavior; it just happens. None of these behaviors set the bit-7 of 0F register to 1.

I have also noticed that I get bit-7 of register 0F to flag 1 only when I take off the battery while the unit is unplugged. No any other circumstance makes bit-7 to flag 1.

Here you go the sketches I use to read and write registers on the RTC. As you can see, I only use the <Wire.h> library to read/configure:

// === replace 0x0F by 0x0E to read 0E register ===
// Reads register 0Fh

#include <Wire.h>
 
void setup()
{
  Wire.begin();
  Serial.begin(9600);
  
  Wire.beginTransmission(0x68); // 104 is DS3231 device address
  Wire.write(0x0F); // start at register 0F
  Wire.endTransmission();
  Wire.requestFrom(0x68, 1); // request one byte
  if(Wire.available()) {
    Serial.println("Reading data...");
    byte b;
    b = Wire.read();
    Serial.print("Current Register Value (0F): ");
    Serial.println(b);
  }else{
    Serial.println("RTC not availabe!");
  }
  Wire.endTransmission();
}
 
void loop()
{}
// Clears bit-7 of register 0Fh

#include <Wire.h>
 
void setup()
{
  Wire.begin();
  Serial.begin(9600);
  
  Wire.beginTransmission(0x68); // 104 is DS3231 device address
  Wire.write(0x0F); // start at register 0F
  Wire.endTransmission();
  Wire.requestFrom(0x68, 1); // request one byte
  
  if(Wire.available()) {
    Serial.println("Reading data...");
    byte b;
    b = Wire.read();
    Serial.print("Current Register Value (0F): ");
    Serial.println(b);
    b = b << 1;
    b = b >> 1;   // clears bit-7
    Wire.beginTransmission(0x68); // 104 is DS3231 device address
    Wire.write(0x0F); // start at register 0F
    Serial.print("New Register Value (0F): ");
    Serial.println(b);
    Wire.write(0b00001000); // write register   
  }else{
    Serial.println("RTC not availabe!");
  }
  Wire.endTransmission();
}
 
void loop()
{}
// Clears bit-7 of register 0Eh

#include <Wire.h>
 
void setup()
{
  Wire.begin();
  Serial.begin(9600);
  
  Wire.beginTransmission(0x68); // 104 is DS3231 device address
  Wire.write(0x0E); // start at register 0E
  Wire.endTransmission();
  Wire.requestFrom(0x68, 1); // request one byte
  
  if(Wire.available()) {
    Serial.println("Reading data...");
    byte b;
    b = Wire.read();
    Serial.print("Current Register Value (0E): ");
    Serial.println(b);
    b = b << 1;
    b = b >> 1;   // clears bit-7
    Wire.beginTransmission(0x68); // 104 is DS3231 device address
    Wire.write(0x0E); // start at register 0E
    Serial.print("New Register Value (0E): ");
    Serial.println(b);
    Wire.write(0b00011100); // write register   
  }else{
    Serial.println("RTC not availabe!");
  }
  Wire.endTransmission();
}
 
void loop()
{}

On the sketch that exploits the RTC features, I make use of <Wire.h>, <RTClib.h> and <Time.h> libraries. For instance:

RTC_DS1307 RTC;		
DateTime now;	

void setup() {
  Wire.begin();
  RTC.begin();
  now = RTC.now();
  RTC.adjust(DateTime(__DATE__, __TIME__));
}

void loop()
{}