DS1307 RTC on user defined I2C interface

  1. For my project I require two I2C interfaces (one for the TMP102 Temperature Sensor and one for a DS1307 Real Time Clock module). The PCB I have designed for the project has the RTC physically connected to the second, user defined I2C interface. I am using the Sparkfun ESP32 Thing microprocessor.

  2. I have a test sketch (modified from elsewhere) which scans for I2C devices. To do this I have defined the pins for the second I2C connection and then created two ‘TwoWire’ instances (I2Cone – the default I2C instance, and I2Ctwo, the user defined two wire instance).

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com  
Code adapted from: https://randomnerdtutorials.com/esp32-i2c-communication-arduino-ide/
*********/

// Library
#include <Wire.h>
#include <RTClib.h>

// I2C
#define I2C_SCL_RTC 26
#define I2C_SDA_RTC 27

TwoWire I2Cone = TwoWire(0);
TwoWire I2Ctwo = TwoWire(1);

// RTC
RTC_DS1307 rtc; // set up an RTC instance

void setup() {
  Serial.begin(9600);
  Serial.println("\nI2C Scanner");

  I2Cone.begin(21, 22);
  I2Ctwo.begin(I2C_SDA_RTC,I2C_SCL_RTC,100000); // don't use address in the freq position - creates an error

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

  if (! rtc.isrunning()) { //// **Where I think my code errors.**
    Serial.println("RTC is NOT running!");
  } else if (rtc.isrunning()) {
    Serial.println("RTC IS running!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

} // end setup
 
void loop() {
  byte error, address;
  int nDevices;
  Serial.println("Scanning...");
  nDevices = 0;
  for(address = 1; address < 127; address++ ) {
    I2Ctwo.beginTransmission(address);
    error = I2Ctwo.endTransmission();
    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address<16) {
        Serial.print("0");
      }
      Serial.println(address,HEX);
      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");
  }

  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();

   delay(5000);          
}
  1. The sketch confirms that the DS1307 RTC I2C device is present at returning addresses of 0x50 and 0x68 using the user defined I2C interface (I2Ctwo).

  2. In the sketch I have created an RTC_DS1307 instance named ‘rtc.’ This is using the ‘RTClib’ library – Version 2.0.2 (latest).

  3. When I call rtc.begin() an error message returned (‘Couldn’t find RTC’). This is because rtc.begin() defaults to the default ‘Wire’ I2C interface.

  4. Others have had this problem. Two fixes are detailed here: arduino due - Second I2C on Due RTClib, can't start - Arduino Stack Exchange'

a. The first fix is to change the pointer in RTClib.h for the DS1307 class definition from the default ‘&Wire’ to the new wire instance (e.g. &I2Ctwo). When I make this change I get the following error:

call to 'boolean RTC_DS1307::begin(TwoWire)' uses the default argument for parameter 1, which is not yet defined*”

b. The second fix is to add a #define for the second I2C interface. I have tried using two definitions (#define Wire I2Ctwo and #define TwoWire I2Ctwo). Errors are returned as follows:

When using #define Wire I2Ctwo the error message is: ‘call to 'boolean RTC_DS1307::begin(TwoWire)' uses the default argument for parameter 1, which is not yet defined*’ – same as previous error.

When using #define TwoWire I2Ctwo: ‘error: 'I2Ctwo' has not been declared #define TwoWire I2Ctwo

  1. I have checked the other files in RTClib of relevance (RTClib.cpp and DS1307.h). Nothing in either of these files appears relevant to this problem.

  2. RTClib.h includes the file ‘Adafruit_I2CDevice.h’ from the Adafruit_BusIO library. In the class ‘Adafruit_I2CDevice’ it has the pointer to ‘&Wire.’ I added the #define Wire I2Ctwo and changed the point from &Wire to &I2Ctwo. The result is the same error. This line of fixing the problem appears to have got me nowhere so I looked for other approaches.

  3. I tried the RTClib example sketch: ‘customWire_DS3231onSAMD21.’ When I run it the following error occurs: ‘sercom0' was not declared in this scope.’

  4. Basically at this point I am stuck. The task seems easy, redirect the RTC to look at the second I2C interface but after several days I have not been able to solve this. Any assistance would be greatly appreciated.

Thank you

Cameron

1 Like

The ESP has 2 I2C hardware ports. Inter-Integrated Circuit (I2C) - ESP32 - — ESP-IDF Programming Guide latest documentation (espressif.com)

I've, a long time ago, put I2C devices onto each I2C port of an ESP32.

1 Like

After all your problems, weren't it easier to connect both modules to the same I2C bus?

1 Like

Probably not true. I2C is not merely an interface, it is a bus, on which your RTC and tmp can happily ride together, just like everybody else's do. This should apply equally to your processer. Your tmp's address is probably 0x48.

1 Like

Thanks DrDiettrich,

That will be the fall back position if I can't get the RTC to connect to the second I2C bus.

Thanks Nick. Agree - poor terminology on my behalf.

If I can't get the RTC to work on the second I2C bus I will take this approach. Unfortunately I designed my PCB around the two I2C buses so it won't be as physically tidy as originally planned.

Fixed - and a simple one too :smiling_face_with_tear:

Looking through the closed issues on Github for RTCLib found the following comment:

So I changed rtc.begin() to rtc.begin(&I2Ctwo) where 'I2Ctwo' is the name of the second I2C bus.

The code compiled and when uploaded to the ESP32 it also executed correctly.

Problem fixed!

Well, there you go. I have never used my ESP32, I never knew it had two I2C buses, and I certainly don't understand why it would....

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.