3

I have been using ds3231 rtc module for keep tracking and make alarm along with backup battery. when I used it for first time it worked fine. but now it doesn't keep track my time when the power lose it from main power but I have checked that my battrey is in safe. So I search in lot of forums they said EOSC bit was set high that would be stoped the clock as it stops the internal oscillator. also want to set it into low then only rtc keep track of the time

but in another some forums they instructed that put this following code for set it to low

DS3231 RTC;

  Wire.beginTransmission(0x68);
  Wire.write(0xF);                            // Address the Status register
  Wire.write(0x00);                           //  Zero the Status register
  Wire.endTransmission(); 
  Wire.beginTransmission(0x68);
  Wire.write(0xE);                            // Address the Status register
  Wire.write(0x00);                           //  Zero the Status register
  Wire.endTransmission(); 

  RTC.setA2Time( ADay, AHour, AMin, 0x00, true, false, false);
  delay(100);
  RTC.turnOnAlarm( 2 );

in another place showed the following code

// clear /EOSC bit to ensure that the clock runs on battery power
  Wire.beginTransmission(0x68); // address DS3231
  Wire.write(0x0E); // select register
  Wire.write(0b00011100); // write register bitmap, bit 7 is /EOSC
  Wire.endTransmission();

but now problem is that where should I want to place this code and how to past it in proper manner for keep tracking the time when ds3231 loses power too? please any know about this problem because I finded so many people are strugling with this issue when they come forward to use this ds3231 rtc module. if any body know about how to solve this issue plese consider to share your idea this will definately help full for evryone because there is no one properly answer for this issue

3
  • I would recommend you to go with this (RTClib) library to test your module. If it works fine than you can look in related function to check how things are working there and by that way you can fix your code.
    – Arslan
    Commented Jul 13, 2022 at 9:25
  • To understand the DS3231 register structure you have to look here on page 11 analog.com/media/en/technical-documentation/data-sheets/…. The example code fragment you gave Wire.write(0xE); . . . Wire.write(0x00); sets the control register (0Eh) to zero which enables the oscillator by unsetting bit /EOSC. However, I guess your problem is somewhere else because nothing should normally disable the oscillator once it is enabled.
    – 6v6gt
    Commented Dec 10, 2022 at 10:59
  • Which library are you using for the DS3231 and to set the alarms? It is so that the same DS3231 register which controls the oscillator (0x11) also controls the alarm interrupts. If the library is carelessly written, it could, as a side effect, disable the oscillator when changing the alarm configuration. Adding code to enable the oscillator may not help much unless you can guarantee to run it the moment the oscillator is disabled and would, anyway, only be a work around..
    – 6v6gt
    Commented Dec 10, 2022 at 12:07

2 Answers 2

1

From the DS3231 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.

Status Register (0Fh)

Bit 7: Oscillator Stop Flag (OSF). A logic 1 in this bit indicates that the oscillator either is stopped or was stopped for some period and may be used to judge the validity of the timekeeping data. This bit is set to logic 1 any time that the oscillator stops. The following are examples of conditions that can cause the OSF bit to be set:

  1. The first time power is applied.
  2. The voltages present on both VCC and VBAT are insufficient to support oscillation.
  3. The EOSC bit is turned off in battery-backed mode.
  4. External influences on the crystal (i.e., noise, leakage,etc.). This bit remains at logic 1 until written to logic 0.

I dug out an old D3231 board. It had a battery in it but was last set ~3 years ago and I am not sure how old the battery was when I first put it in the board. The battery cannot keep the clock running. When I attached it to an Arduino UNO and booted up, the clock’s registers read as follows (just pay attention to the time and the EOSC bit and the OSF flag):

CLOCK: 00:01:15 (24h clock) Sunday, 01/01/2000 Temperature=21C Aging offset=0

Alarm #1: 00:00:00 (24h clock) DY/DT=18[DoM mode] Alarm selection: when date, hours, minutes and seconds match

Alarm #2: 00:00 (24h clock) DY/DT=20[DoM mode] Alarm selection: when date, hours, minutes match

CONTROL byte=00011100 /EOSC is ON /BBSQW is Disabled /CONV is clear /INTCN mode is Match /Alarm 1 is Disabled /Alarm 2 is Disabled

STATUS byte=10000000 /OSF is ON /EN32KHZ Disabled /BSY is OFF /A1F is OFF /A2F is OFF

The clock is now running because with VCC supplied by the Arduino, the oscillator will always run. When I read the clock, I can see the time advancing, but it started from 00:00:00

Now, I remove power and after a minute or so, power up the UNO and the clock, and read the clock. It is again running, but the time had not advanced – it simply restarted from 00:00:00. EOSC is ON. OSF is ON.

With no VBAT, the time was not preserved.

A fresh battery is inserted and I power up. The clock is again running, again, restarted at 00:00:00. EOSC is ON. OSF is ON.

After a couple of minutes, I power down (with the fresh battery still in the clock). When I boot up and read the clock, it is running AND it kept running on battery power, so the current time is accurate. EOSC is ON. OSF is ON.

EOSC was always enabled (read as 0) – that is the POR value. Unless your program explicitly sets the bit to 1, EOSC will reliably be enabled. If you do disable EOSC (set to 1), the oscillator will NOT run off of the battery backup (VCC off and VBAT on). With EOSC disabled, and if there is enough juice in the battery, it will hold the time (and other registers) when VCC is switched off and VBAT is on. When VCC is on, the oscillator will always run.

But, what about the OSF flag?

Reading the data sheet, you can see that the OSF flag gets set when the oscillator stops, which can occur from a number of conditions.

It is designed so that the software can legitimately suspect that the time is not accurate, But, OSF is set as the POR value.

You need to enable EOSC AND CLEAR OSF, every time you do a clean power up and every time OSF got set because you unplugged (no VCC) and changed batteries. Also, remember, that with VCC, the oscillator will run regardless of the state of the EOSC bit.

Do not ignore OSF, it is an important flag and it should not be getting set regularly. In fact, once you insert a battery and clear OSF, it should not be set again until the battery drains. If it is getting set regularly, you have problems elsewhere.

Some software reads OSF and if it is set, the software will balk and tell you as much, as it should. Since OSF is set on POR, it will be set whenever you remove VCC and VBAT and then power up again.

You need to explicitly clear OSF AND know why it got set.

This code snippet, enables EOSC AND clears OSF.

 // enable EOSC and clear OSF flag 
 // *** The other bits in these two registers are writtten
 // with POR Values or '0' if POR value=X.
  Wire.beginTransmission(0x68); // address DS3231
  Wire.write(0x0E); // select CONTROL register
  Wire.write(0b000011100); // write register (bit 7 is EOSC)
  Wire.endTransmission();
  Wire.beginTransmission(0x68); 
  Wire.write(0x0F); // select STATUS register
  Wire.write(0b00001000); // write register (bit 7 is OSF)
  Wire.endTransmission();

Hope it helps.

-1

I also have a DS3231 RTC in my robot project. Here's my complete setup code. This can be placed anywhere in setup(): I don't think you have to mess with individual registers to get what you want.

    if (rtc.begin()) //02/19/19 this now returns FALSE if RTC doesn't respond
    {
        Serial.println("Found RTC...");
        delay(100);
        bRTCLostPower = rtc.lostPower(); //added 10/17/18
        mySerial.printf("rtc.lostPower() reports %d\n", bRTCLostPower);

        if (rtc.lostPower())
        {
            Serial.println("RTC lost power.  Setting RTC to last compile time");
            rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));// sets RTC to last compile date/time
        }

#ifdef FORCE_RTC_TO_LAST_COMPILE_TIME
        Serial.println("Forcing RTC to last compile time");
        rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));// sets RTC to last compile date/time
#endif 

        DateTime now = rtc.now();
        char buffer[100];
        memset(buffer, '\0', 100);
        mySerial.printf("Retrieving Date/Time from RTC with rtc.now() =  %ld\n", now.unixtime());
        GetDayDateTimeStringFromDateTime(now, buffer);
        Serial.print("Date/Time: "); Serial.println(buffer);
        RTC_Avail = true;
    }
    else
    {
        Serial.println("Couldn't find RTC. Real-time clock functions won't be available");
        RTC_Avail = false; //use this instead
    }

    if (RTC_Avail && rtc.lostPower())
    {
        DateTime Comp_dt = DateTime(F(__DATE__), F(__TIME__)); //__DATE__ & __TIME__ are environment variables)
        uint8_t mydayofweek = Comp_dt.dayOfTheWeek();  //returns 0 for Sunday, 6 for Saturday dayOfTheWeek
        int mymonth = Comp_dt.month();
        int myday = Comp_dt.day();
        int myyear = Comp_dt.year();
        int myhour = Comp_dt.hour();
        int mymin = Comp_dt.minute();
        int mysec = Comp_dt.second();
        long unixtime = Comp_dt.unixtime();
        char* dayofweek = (char*)daysOfTheWeek[mydayofweek];

        Serial.print("day of week value = "); Serial.println(mydayofweek);
        Serial.print("day of week value = "); Serial.println(Comp_dt.dayOfTheWeek());

        mySerial.printf("RTC lost power - setting to datetime of last compile %ld (%s %4d/%02d/%02d at %02d:%02d:%02d)\n",
            unixtime, dayofweek, myyear, mymonth, myday, myhour, mymin, mysec);

        rtc.adjust(Comp_dt);
    }
1
  • 1
    what do you mean by an individual register? Commented Oct 20, 2020 at 13:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.