DS1307 RTC detection

Recently I upgraded my 'Light & Timer switch' project from ds1307new 1.0 to ds1307new 1.20 (http://code.google.com/p/ds1307new/). One of the advantages of the 1.20 version is support for the RAM in the DS1307. While testing I found that the function for retrieving data from RAM hangs if the DS1307 is not present. In this case the time retrieval functions return nonsense, but do not block.

Because of the undesired hanging behaviour, I implemented a DS1307 detection routine which reports a missing or unresponsive DS1307 by a message over Serial and a fast blinking LED.

int ds1307Present() {
  int value1 = getSecs();
  delay(1100);
  int value2 = getSecs();
  if (value1 == 0 && value2 == 0) return 0;
  return 1;
}

int getSecs() {
  Wire.beginTransmission(DS1307_CTRL_ID);
  Wire.send(0x00);                     
  Wire.endTransmission();
  Wire.requestFrom(DS1307_CTRL_ID, 1);
  return Wire.receive();
}

The assumption is that either the RTC is running, so two samples more than a second apart can't both be 0, or the stop clock bit is set and neither sample can be 0.

The question is, is this a correct assumption for the DS1307 RTC?

Project page: http://fjkraan.home.xs4all.nl/digaud/arduino/index.html

The assumption is that either the RTC is running, so two samples more than a second apart can’t both be 0, or the stop clock bit is set and neither sample can be 0.

That is indeed the assumption of your code, but there are some more possibilities I think

  1. the RTC is not present - not tested -

  2. the RTC is present but not visible due to communication failure on Wire level - not tested - (pullups ?)

  3. the RTC is present but not visible due to broken RTC - not tested -

  4. the RTC is present and not running - covered in your test

  5. the RTC is present and running - covered in your test

(4,5) are covered but it would be nice if you could cover some of the other errors too! especially 1 and 2

That said I think your code is allready a really valueble test that should be added to the I2C scanner of Nick Gammon.

Actually the two situations I really tested were 1 and 5 and I tried to incorporate 4. I didn't think of 2 and 3.

Wire.endtransmission gives a return value. That give also some info..

int x = Wire.endTransmission(); Serial.println(x, DEC);

From the lib code : 0 => succes 1 => bufferoverflow - length packet > 32 bytes 2 => TW_MT_SLA_NACK error: address send, nack received 3 => TW_MT_DATA_NACK error: data send, nack received 4 => other twi error

I was hoping there was a more generic detection method than checking that the seconds counter works :-)

The return value of a Wire.endTransmission() when no DS1307 is connected is 2. It seems safe to halt the firmware if the initial check returns a not 0.

Thanks for the info!

You might want to consider the case where more than one device is on the bus, one of which is a DS1307?

You might want to consider the case where more than one device is on the bus, one of which is a DS1307?

Yes, that would be wise. My current check is:

int ds1307Present() {
  Wire.beginTransmission(DS1307_CTRL_ID);
  Wire.send(0x00);                     
  if (Wire.endTransmission() == 0) return TRUE;
  return FALSE;
}

The acknowledgement on sending the address is apparently the first indicator a device is not responding.

Hi

I have uploaded a new version of the DS1307new library to http://code.google.com/p/ds1307new/downloads/list

  • getRAM does not halt if device is not available
  • New procedure "isPresent" returns 0 if the DS1307 is not available

Oliver