DS1307RTC library and Wire2

I'm trying to use the DS1307RTC library on Wire2 (SCL2/SDA2)

Adding in the header:

#define Wire Wire2

seems to have no effect for DS1307RTC library ?
(curiously this does work for other I2C devices e.g. OLED)

So my question is : How to direct DS1307RTC library to look for RTC on Wire2 I2C bus, instead of the base Wire I2C bus?

TIA

Hi @ninja2.

I'm not sure I understood correctly what you mean by this. Please add a forum reply here that provides a more detailed description to help us to understand it. Which file did you add that line of code to?

hi @ptillisch , thanks for prompt reply,

I've written this up in detail on PJRC forum but got no responses after many days. Rather a big post so I'm hoping you don't mind reading it over there.

My sketch is structured using 13 tabs:
[...]
EEP.cpp + EEP.h (for 32K EEPROM on DS3231)
[...]
RTC.cpp + RTC.h (for DS1307 or DS3231
[...]
To tell the MCU the RTC+EEPROM are on Wire2 I added

#define Wire Wire2

to EEP.h and RTC.h

OK, this is your problem. The DS1307RTC.cpp source file of the "DS1307RTC" library is a completely separate "translation unit" from the source files of your sketch that contain #include directives for the EEP.h and RTC.h header files that contain your definition of the Wire macro. So the definition of the Wire macro has absolutely no effect on the code in the DS1307RTC.cpp translation unit.

You would need to put the macro definition in the DS1307RTC.cpp or DS1307RTC.h files of the library.

The DS1307 library that accompanies the TimeLib library is fixed for "Wire".
You could change the source code of that DS1307 library as ptillisch wrote. I would replace "Wire" with "_WIRE" and then add a "#define _WIRE Wire2".
There are other libraries that can select a I2C bus.

But please stay away from reserved words. If "Wire2" is already defined, then "Wire" is probably also defined. Using a "#define" can be dangerous. The compiler might not give a warning or error if it is used in the wrong way.

Why do you need two I2C buses ? Is the DS3231 together with the MPU-9250 the only problem because they are both at 0x68 ? If you bought your MPU-9250 from AliExpress/Ebay/Amazon/TEMU, then it might be fake and you better buy a real sensor.

Ahah, OK. Let's see if I got it right:

  1. the #define worked for my EEPROM tabs (EEP) because they are just local tabs and compiled within the one translation unit, whereas
  2. it didn't work for the DS1307RTC library because libraries are compiled as a separate translation unit?

What if, instead of editing the library, I copy (& rename) the library as tabs in my sketch, edit the tabs and #include them instead of the library?

Good clue, thanks

because I can, it's a hobby :slight_smile:

Each .cpp file is its own translation unit, whether they are in the sketch or a library.

All the .ino files of a sketch are a single translation unit. The reason is that the Arduino preprocessor concatenates all the .ino files into a single file and then compiles the resulting .cpp file as C++.

You can think of an #include directive as being replaced by the contents of the header files. So although the header files are not compiled by themselves, a copy of the code in the header file is compiled as part of each of the translation units of the files that contain an #include directive for the header file.

Maybe this demonstration will make things more clear:

SomeSketch.ino

#include "Foo.h"
void setup() {
  Serial.begin(9600);
  while(!Serial) {}
  printMessage();
}
void loop() {}

Foo.h

#define FOO_MESSAGE "Hello!"
void printMessage();

Foo.cpp

#include <Arduino.h>

#ifndef FOO_MESSAGE
#define FOO_MESSAGE "Goodbye!"
#endif
void printMessage() {
  Serial.println(FOO_MESSAGE);
}

What do you expect you will see printed in Serial Monitor when you run that sketch on your board?

It won't make any difference if you leave the code as it is now. But you can certainly copy the library files into your sketch and then make the previously mentioned modification to the library files.

1 Like

If you're not married to the idea of using the DS1307RTC library, the RTC_DS1307 class in RTClib allow passing a pointer to a TwoWire instance in its constructor, and has a begin() method that delays calling wire->begin() until then - DS1307RTC does a Wire.begin() in the constructor that makes me uneasy.

1 Like

This is the key. With this in mind I created a variant of the RTCread example provided with the DS1307RTC library, and then copied DS1307RTC.cpp and .h as tabs DSx.cpp and DSx.h in the sketch, did some ediiting followed by experiments adding

#define _WIRE Wire2

and eventually ... it's working on Wire2 :slight_smile:

I've attached in a ZIP of my RTCread sketch for Wire2, for info + in case it's useful.

RTCtest.zip (2.8 KB)

1 Like

Actually adding the MPU is my next step, and as I understand the collision at 0x68 does require they be on different I2C buses (ignoring that my Sparkfun MPU can be hard-wire changed to 0x69).

I do have a couple of AliEpxress MPU in the background that I haven't tried yet. Are they all fakes, or just some?

That question keeps us awake at night.

understood :neutral_face:

I've since noticed if I

#define _WIRE WireX

with different values for WireX in 2 or more .cpp, the compiler warns that I'm redefining _WIRE.

So apparently "translation units" don't seem to apply to pre-processing instructions. Is that right?

I don't know, it is better to never redefine a #define.
You can make it a variable, for example a pointer or "by reference" to a Wire object, and pass it in the begin() function to the class.

I was not able to reproduce it. This is the minimal test sketch I used:

SomeSketch.ino:

void setup() {}
void loop() {}

bar.cpp:

#define BAZ_QUX pippo

foo.cpp:

#define BAZ_QUX pluto

Do you get the warning when you compile that sketch? If not, please provide a minimal demonstration sketch that does produce the warning.

I didn't explain this very well, as I have multiple .cpp/.h pairs. But your example got me on the right track. Below is my example using 5 tabs that gives the warnings. In the original sketch I found that moving the #define _WIRE lines from .h to .cpp removed the warnings, and that raises the big question:
Are .h files part of the translation unit for the associated .cpp ?

#include "BB.h"
#include "CC.h"

void setup() {
  Serial.print("x = "); Serial.println(x);
  Serial.print("y = "); Serial.println(y);  
  }

void loop() {
  delay(1);
}

BB.cpp

#include "BB.h"

int x = 1;

BB .h

#ifndef BB_H_
#define BB_H_

#define _WIRE Wire_BB

extern int x;

#endif

CC.cpp

#include "CC.h"

int y = 2;

CC.h

#ifndef CC_H_
#define CC_H_

#define _WIRE Wire_CC

extern int y;

#endif

gives these warnings

In file included from C:\Users\...\Documents\ARDUINO\SKETCHES\AAtest\AAtest.ino:2:
C:\Users\cj\Documents\ARDUINO\SKETCHES\AAtest\CC.h:4: warning: "_WIRE" redefined
    4 | #define _WIRE Wire_CC
      | 
In file included from C:\Users\ ... \Documents\ARDUINO\SKETCHES\AAtest\AAtest.ino:1:
C:\Users\cj\Documents\ARDUINO\SKETCHES\AAtest\BB.h:4: note: this is the location of the previous definition
    4 | #define _WIRE Wire_BB

From the compiler's perspective, there is no such thing as an association between a .h and a .cpp file. We often pair them because it is a convenient way to organize the code for the benefit of humans, but there is no technical significance to the practice.

You can think of an #include directive as being replaced by the contents of the file. So the code in the header file becomes part of every translation unit that contains an #include directive for that file.

So the code in your AAtest.ino file is equivalent to this:

#ifndef BB_H_
#define BB_H_

#define _WIRE Wire_BB

extern int x;

#endif

#ifndef CC_H_
#define CC_H_

#define _WIRE Wire_CC

extern int y;

#endif

void setup() {
  Serial.print("x = "); Serial.println(x);
  Serial.print("y = "); Serial.println(y);  
  }

void loop() {
  delay(1);
}

You can see that the translation unit of AAtest.ino contains two definitions of the _WIRE macro.

2 Likes

Ahah, that is such an important clarification. Indeed I was thinking they were related from the compiler's perspective ... not any more.

Thank you @ptillisch (again), your expertise is much appreciated !

You are welcome. I'm glad if I was able to be of assistance.

Regards,
Per