Checking to see if an RTC DS3231 is present and running

Hi all,

I'm using the jeelabs RTClib to run a DS3231 rtc.
Everything is working fine except for a small piece of the example code that is supposed to detect the presence of the chip over I2C. It returns true even when no chip is present.

	if (! rtc.begin()) {
		Serial.println("Couldn't find RTC");
		while (1);
	}

The begin function from the library is this:

boolean RTC_DS3231::begin(void) {
  Wire.begin();
  return true;
}

In the implementation for the DS1307 in the same library, there is an "isrunning" function:

uint8_t RTC_DS1307::isrunning(void) {
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire._I2C_WRITE((byte)0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 1);
  uint8_t ss = Wire._I2C_READ();
  return !(ss>>7);
}

I read somewhere that this wont work for the 3231 and is therefore not implemented.

As a solution I am currently checking to see if there is something on the I2C bus at 0x68, the address for this device. Just wondering why the example doesn't work and/or if there is a better way. It would also be nice to know if it is running.

Many thanks.

I read somewhere that this wont work for the DS3231 and is therefore not implemented.

Check the OSF (oscillator stopped flag) bit of DS3231 register 0x0F for a similar test.

jremington:
Check the OSF (oscillator stopped flag) bit of DS3231 register 0x0F for a similar test.

Many thanks for the reply.

I'm a little out of my depth. I'm not sure how I would check a specific bit.
Is this is what is being done here (from the same library)?

bool RTC_DS3231::lostPower(void) {
  return (read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG) >> 7);
}

... I don't understand the ">> 7"

Addresses are:
#define DS3231_ADDRESS 0x68
#define DS3231_CONTROL 0x0E
#define DS3231_STATUSREG 0x0F

... I don't understand the ">> 7"

Shift result right 7 bits. The top bit of the byte becomes the bottom bit and all the rest are lost.

In your case, that shifts the OSF flag to the bottom bit.

1. The presence of the DS3231 RTC Module can be known by executing the following instructions:

Wire.beginTransmission (deviceAddress);
//Wire.write(0x0E); //pointing Control Register
//Wire.write(0x80);
byte busStatus = Wire.endTransmission();
if(busStatus == 0)
{
  Serial.println("DS3231 Clock Module is Present...!");
}
else
{
  Serial.println("DS3231 Clock Module is not Present...!");
  while(1);   //wait for ever
}

2. How to know if the RTC is running or not?
As I understand that the best way of getting the answer of the above question is to read the time from RTC and show it on the Serial/LCD Monitor. I don't see any suitable status flag in the register set of the RTC that certifies the running state of the RTC. The OSF flag is always 0 indicating that the RTC is not at STOP condition; clock oscillator is always ON as long as there is power in the RTC Module.

3. The Clock Codes

#include <Wire.h>     //needed because DS3231 uses I2C Bus
#include <RTClib.h>   //needed becuase we have ready-made functions of this librray
#include<LiquidCrystal_I2C.h>  //neded by LCD
LiquidCrystal_I2C lcd(0x27, 16, 2); //lcd address; 16 characters 2 line

RTC_DS3231 rtc;     //the object rtc is created from the class RTC_DS3231
char daysOfTheWeek[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
#define deviceAddress 0x68
void setup()
{

  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);

  if (! rtc.begin())   //DS3231 is intialized
  {
    while (1);        //initialization failed
  }
  //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));//auto update from computer time
  rtc.adjust(DateTime(2018, 4, 10, 12, 35, 17));//set date-time manualy:yr,mo,dy,hr,mn,sec
  //checking if DS3231 Module is preset
  Wire.beginTransmission (deviceAddress);
  //Wire.write(0x0E); //pointing Control Register
 // Wire.write(0x80);
  byte busStatus = Wire.endTransmission();
  if (busStatus == 0)
  {
    Serial.println("DS3231 Clock Module is Present...!");
  }
  else
  {
    Serial.println("Ds3231 Clock Module is not Present...!");
    while (1);  //wait for ever
  }

}

void  loop()
{
  //--read Date and Tme from DS3231 using the method now()---------------------;
  //--store the Date and Time into another user define object bamed nowTime
  DateTime nowTime = rtc.now();

  //---show Day and Date on Top Line of LCD--------------
  int x = nowTime.dayOfTheWeek(); //dyOfTheWeek() is a pre-defined method
  lcd.print(daysOfTheWeek[x]);    //days of the Week[] is the user defined array
  lcd.print(": ");

  lcd.print(nowTime.day());
  lcd.print("/");

  lcd.print(nowTime.month());
  lcd.print("/");

  lcd.print(nowTime.year());

  Wire.beginTransmission(deviceAddress); //START, Roll Cal
  Wire.write(0x00); //set SEC Register address
  Wire.endTransmission(); //Execute the above queued data, ACK, STOP

  Wire.requestFrom(deviceAddress, 3);   //SEC, MIN, and HRS to read from RTC as BCD
  byte bcdSeconds = Wire.read();
  byte bcdMinutes = Wire.read();
  byte bcdHours = Wire.read();
  bcdHours = bcdHours & 0b00011111;

  lcd.setCursor(0, 1);
  //show HRS--
  Serial.write((bcdHours >> 4) + 0x30);
  Serial.write((bcdHours & 0x0F) + 0x30);
  Serial.write(':');

  lcd.write((bcdHours >> 4) + 0x30);
  lcd.write((bcdHours & 0x0F) + 0x30);
  lcd.write(':');

  //show MIN--
  Serial.write((bcdMinutes >> 4) + 0x30);
  Serial.write((bcdMinutes & 0x0F) + 0x30);
  Serial.print(':');
  
  lcd.write((bcdMinutes >> 4) + 0x30);
  lcd.write((bcdMinutes & 0x0F) + 0x30);
  lcd.print(':');

  //shiw SEC
  Serial.write((bcdSeconds >> 4) + 0x30);
  Serial.write((bcdSeconds & 0x0F) + 0x30);
  
  lcd.write((bcdSeconds >> 4) + 0x30);
  lcd.write((bcdSeconds & 0x0F) + 0x30);

  lcd.setCursor(0, 0);
  Serial.println();
}

The OSF flag is always 0 indicating that the RTC is not at STOP condition

No it is not. Best to consult the DS3231 data sheet:

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.

jremington:
No it is not. Best to consult the DS3231 data sheet:

Therefore, the running condition of the RTC can be ascertained by monitoring the OSF bit of the Control/Status Register at address 0x0F.

Wire.beginTransmission (deviceAddress);
Wire.write(0x0F); //pointing at Control/Status Register that contains OSF flag bit at bit-7 position
Wire.endTransmission();

Wire.requestFrom(deviceAddress, 1); //request to get the content of Control/Status Register
byte y = Wire.read();
if((y & 0x80) != 0x80)  //checking if OSF is LH; (OSFxxxxxxx & 10000000) --> 80 (STOP) or 00 (RUN)
{
   Serial.println("RTC is at running condition...!");  //(OSF) = 0
}
else
{
   Serial.println("RTC is not running ...!");  //(OSf) = 1
   while (1);  //wait for ever
}