Using RTCLib with Arduino Due

Hello everyone,

I am attempting to use the RTCLib with a TinyRTC module that has a DS1307 RTC chip with a backup battery on it. With the following code, using it on an Arduino with the SDA and SLC pins connected, it is able to read and set the time on the module.

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"

#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
   #define Serial SerialUSB
#endif

RTC_DS1307 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void setup () {

#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif

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

  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(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
}

void loop () {
    DateTime now = rtc.now();
    
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(" (");
    Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
    Serial.print(") ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    
    Serial.print(" since midnight 1/1/1970 = ");
    Serial.print(now.unixtime());
    Serial.print("s = ");
    Serial.print(now.unixtime() / 86400L);
    Serial.println("d");
    
    // calculate a date which is 7 days and 30 seconds into the future
    DateTime future (now + TimeSpan(7,12,30,6));
    
    Serial.print(" now + 7d + 30s: ");
    Serial.print(future.year(), DEC);
    Serial.print('/');
    Serial.print(future.month(), DEC);
    Serial.print('/');
    Serial.print(future.day(), DEC);
    Serial.print(' ');
    Serial.print(future.hour(), DEC);
    Serial.print(':');
    Serial.print(future.minute(), DEC);
    Serial.print(':');
    Serial.print(future.second(), DEC);
    Serial.println();
    
    Serial.println();
    delay(3000);
}

However, when I use the same code on the Arduino Due with SDA connected to pin 20 and SLA connected to pin 21, it doesn't work. I knew that the Due has different hardware for I2C communications, so I ran the program below to verify that the Due can pick up the module, and it was able to read the address of the RTC module.

// --------------------------------------
// i2c_scanner
//
// Version 1
//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
//     Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// Version 6, November 27, 2015.
//    Added waiting for the Leonardo serial communication.
// 
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//

#include <Wire.h>


void setup()
{
  Wire.begin();

  Serial.begin(9600);
  while (!Serial);             // Leonardo: wait for serial monitor
  Serial.println("\nI2C Scanner");
}


void loop()
{
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ ) 
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4) 
    {
      Serial.print("Unknown error at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000);           // wait 5 seconds for next scan
}

What I'm not understanding is that if the Due can register that the device is there, why can't the RTC library communicate with it?

What I'm not understanding is that if the Due can register that the device is there, why can't the RTC library communicate with it?

What address did you get?

The TinyRTC board is designed to be used with a 5V board. The Due runs on 3V3. Connecting that board directly to it provides a constant over-voltage to it's I2C pins. The chip has protection diodes to let it not immediately fry but sooner or later it will fail. The communication problems may have the same source but to check that you would have to attach a scope and analyze the signal. I would certainly not maltreat my equipment just analyze a situation that should not happen.

pylon:
What address did you get?

I got 0x50 for the temp sensor and 0x68 for the clock.

pylon:
The TinyRTC board is designed to be used with a 5V board. The Due runs on 3V3. Connecting that board directly to it provides a constant over-voltage to it's I2C pins. The chip has protection diodes to let it not immediately fry but sooner or later it will fail.

I don't know if this is good for the module or not, but I had the VCC hooked up to the 3.3V pin while testing the TinyRTC with an Uno and it seemed to work fine. Did the same for the Due.

pylon:
I would certainly not maltreat my equipment just analyze a situation that should not happen.

I'm not super worried about frying a $3 clone. I figured I'd get the details straight before I went ahead and wired it to my legit Due.

I have this code for a DS1307, it should work for you:

#include "Wire.h"
#define DS1307_ADDRESS 0x68

void setup(){
  Wire.begin();
  Serial.begin(9600);
  
}

void loop(){
  printDate();
  delay(1000);
}

byte bcdToDec(byte val)  {
  return ( (val/16*10) + (val%16) );
}

void printDate(){
  Wire.beginTransmission(DS1307_ADDRESS);
  byte zero = 0x00;
  Wire.write(zero);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_ADDRESS, 7);
  int second = bcdToDec(Wire.read());
  int minute = bcdToDec(Wire.read());
  int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
  int weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
  int monthDay = bcdToDec(Wire.read());
  int month = bcdToDec(Wire.read());
  int year = bcdToDec(Wire.read());
  Serial.print(month);
  Serial.print("/");
  Serial.print(monthDay);
  Serial.print("/");
  Serial.print(year);
  Serial.print(" ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.println(second);
}

And this blog:

I don't know if this is good for the module or not, but I had the VCC hooked up to the 3.3V pin while testing the TinyRTC with an Uno and it seemed to work fine. Did the same for the Due.

Interesting that it did run on 3V3, does that mean you didn't connect a battery? If the Vcc voltage drops below 1.25 * battery voltage (usually around 3.75V) the chip stops the I2C communication. Is it possible that you inserted a battery while changing from UNO to Due?

pylon:
Interesting that it did run on 3V3, does that mean you didn't connect a battery? If the Vcc voltage drops below 1.25 * battery voltage (usually around 3.75V) the chip stops the I2C communication. Is it possible that you inserted a battery while changing from UNO to Due?

The backup battery was in the module. I didn't think about that. Will have to try it when I get a chance.