Hi, I have wasted a considerable amount of time trying to get a DS3231 module to work, I have a genuine Maxim Module MPMB1 - so no fake issues, new battery, Maxim recommend the Adafruit library, so loaded that, and yet still it lost time on power off.
Inside the time setting function in the library the OSF bit is tested and the !EOSC bit is cleared. this is the correct behavious according to the datasheet, and yet it did not keep time. very strange.
I decided I needed to explore the status registers both before and after setting the time, so came up with this code based on the DS3231 example from the Adafruit RTClib.
I would recommend getting hold of the data sheet and understanding the function of these two registers DS3231 datasheet - from MAXIM
Hope it helps someone else, it displays the control and status registers bit by bit before and after the time set (or not if power not lost)
I am sure some of those with more experience could produce more elegant code, and I know there are read register routines in the library, but they are not public, and I did not want to change the library.
/* Date and time functions using a DS3231 RTC connected via I2C and Wire lib
Original library by JeeLabs http://news.jeelabs.org/code/, released to the public domain
This is a fork of JeeLab's fantastic real time clock library for Arduino. supplied by Adafruit
*/
#include "RTClib.h"
#include <Wire.h>
#define DS3231_address 0x68
#define DS3231_control_reg 0x0E
#define DS3231_status_reg 0x0F
RTC_DS3231 rtc;
byte Status_reg_b4;
byte Control_reg_b4;
byte Status_reg_aft;
byte Control_reg_aft;
void setup ()
{
Serial.begin(57600);
Wire.begin();
while (!Serial); // wait for serial port to connect. Needed for native USB
if (! rtc.begin())
{
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
Serial.println("********************************************************");
Serial.println("trying to diagnose DS3231 that seems to loose time.");
Serial.println("this snapshots the registers before the OSF check in 'lost power' function,");
Serial.println("then snapshots again after the function has fired (or not).");
Serial.print("PC date/time of this run: ");Serial.print(F(__DATE__));Serial.print("");
Serial.println(F(__TIME__));
Serial.println();
Control_reg_b4=state_of_register(DS3231_address,DS3231_control_reg,1);
Status_reg_b4=state_of_register(DS3231_address,DS3231_status_reg,1);
if (rtc.lostPower())
{
Serial.println("RTC lost power, let's set the time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
else {Serial.println("OSF flag in status reg not set - no power loss");}
Serial.println("State of registers;");
Control_reg_aft=state_of_register(DS3231_address,DS3231_control_reg,1);
Status_reg_aft=state_of_register(DS3231_address,DS3231_status_reg,1);
display_reg();
Serial.println();
// just print data row once - so you can see the time held by DS3231 at restart
DateTime now = rtc.now();
Serial.print("RTC Data: ");
Serial.print(now.day(), DEC);Serial.print('/');Serial.print(now.month(), DEC);Serial.print('/');Serial.print(now.year(), DEC);
Serial.print("\t");
Serial.print(now.hour(), DEC);Serial.print(':');Serial.print(now.minute(), DEC);Serial.print(':');Serial.print(now.second(), DEC);
Serial.print("\tTemp: ");Serial.print(rtc.getTemperature());
Serial.println(" C");
Serial.print("PC date/time of this run: ");Serial.print(F(__DATE__));Serial.print(" ");Serial.println(F(__TIME__));
}
void loop ()
{
// do nothing!
}
byte state_of_register(byte device_address, byte this_register, int bytes)
{
Wire.beginTransmission(device_address);
Wire.write(this_register);
Wire.requestFrom(device_address, bytes);
Wire.endTransmission();
return(Wire.read());
}
void display_reg()
{
String Control_bit_name[8]= {"A1F ","A2F ","BSY ","EN32kHz","NA ","NA ","NA ","OSF "};
String Control_bit_descr [8]={"Alarm 1 Flag","Alarm 2 Flag","Busy","Enable 32kHz Output","not used","not used","not used","Oscillator Stop Flag"};
String Status_bit_name[8]= {"A1IE ","A2IE ","INTCN ","RS1 ","RS2 ","CONV ","BBSQW ","!EOSC "};
String Status_bit_descr [8]= {"Alarm 1 Interrupt Enable","Alarm 2 Interrupt Enable","Interrupt Control","Rate Select","Rate Select","Convert Temperature","Battery-Backed Square-Wave Enable","Enable Oscillator"};
Serial.println(" \tB4\tAfter");
for (int i=7;i>=0;i--)
{
Serial.print(" Status.bit ");
Serial.print(i);
Serial.print(" ");
Serial.print(Status_bit_name[i]);
Serial.print(" =\t");
Serial.print(Status_reg_b4>>i & 1);
Serial.print("\t");
Serial.print(Status_reg_aft>>i & 1);
Serial.print ("\t");
Serial.println(Status_bit_descr[i]);
}
Serial.println();
for (int i=7;i>=0;i--)
{
Serial.print(" Control.bit ");
Serial.print(i);
Serial.print(" ");
Serial.print(Control_bit_name[i]);
Serial.print(" =\t");
Serial.print(Control_reg_b4>>i & 1);
Serial.print("\t");
Serial.print(Control_reg_aft>>i & 1);
Serial.print ("\t");
Serial.println(Control_bit_descr[i]);
}
}