I am using SDA1, SCL1 for my DS3232 with RTClib on Due. It works on a Mega2560 on SDA, SCL. I ran I2c_test with success after I inserted #define Wire Wire1 However with ds3231.ino this define doesnot work. Looking at RTClib.cpp it looks like I can pass a parameter to Wire.begin(). I have tried sda1, scl1 and Wire1. They didnot work. Thanks for the help.

  • 1
    Given you're talking about 5V and 3.3V Arduinos with what sounds like a single RTC breakout, it would be good to know exactly how you're hooking this up. If ds3231.ino is one of the examples, you can show what changes you made to the example, then anyone with a Due and one of those modules can recreate your situation for testing.
    – timemage
    Commented Sep 24, 2021 at 18:26
  • What happens if you use the unmodified ds3231.ino example with line 333 of rtclib.h changed to reference &Wire1 rather than &Wire? (Ref github.com/adafruit/RTClib/blob/master/src/RTClib.h). Are you able to post your sketch and serial monitor output?
    – RowanP
    Commented Sep 24, 2021 at 21:28
  • Does the unmodified ds3231.ino example sketch work if your RTC is connected to the Due Wire port (rather than Wire1)?
    – RowanP
    Commented Sep 24, 2021 at 21:33
  • ds3231.ino is from RTClib. It does run on I2C port 1 (pins 20, 21), But not on port 2 (SDA1, SCL1) aka Wire1. I2C_Test.ino finds response at 0x50 and 0x68 meaning at least time keeping is working on the ds3231. Adding #define Wire Wire1 to ds3231 shows no effect. Examining RTCLib.cpp shows this define for #ifdef AVR #include <avr/pgmspace.h> #elif defined(ESP8266) #include <pgmspace.h> #elif defined(ARDUINO_ARCH_SAMD) // nothing special needed #elif defined(ARDUINO_SAM_DUE) #define PROGMEM #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) #define Wire Wire1 #endif Commented Sep 25, 2021 at 10:54
  • @Marlin Turbett, that's good, so ds3231.ino unmodified runs Ok on pins 20 and 21 (Wire). Are you able to try modifying line 333 of rtclib.h to reference &Wire1 and retry it on the Wire1 port? I'm not sure that simply #defining in your script is going to have a positive impact on the library behavior.
    – RowanP
    Commented Sep 29, 2021 at 3:52

1 Answer 1


The unmodified RTCLib DS3231 sample code running on Arduino Due defaults to the Wire I2C connection on pins 20 SDA and 21 SCL. Due connection via Wire I2C pins To enable the same sketch to connect to a device connected to the Wire1 I2C connection on pins 70 SDA1 and 71 SCL1, I changed line 333 of RTClib.h to reference &Wire1 rather than &Wire. Photo of code snippet in RTCLib.h Due connection via Wire1 I2C pins Successful test output from the Wire1 connection is shown. Serial Monitor Output

Update: OP @Marlin Turbett pointed out that adding #define Wire Wire1 to RTClib.h also works. I agree. The modification of line 333 of RTClib.h which I suggested originally is I think the minimal change to get the desired behaviour. But using substitution to achieve the same change also works. A global change across the whole library may be a bigger hammer than might be desirable.

#define substitution works in single compilation units, so the #define needs to be in the same compilation unit as the text to be overwritten. In this case in the library, not the sketch.

The technique of using #define directives to overwrite which Wire port is referenced in RTClib is used selectively by the library depending on arduino architecture (see RTClib.cpp lines 46-73, below).

#include "RTClib.h"
#if defined(__AVR__) && !defined(TWCR) && defined(USICR)
#include <TinyWireM.h>
#define Wire TinyWireM
#include <Wire.h>

#ifdef __AVR__
#include <avr/pgmspace.h>
#elif defined(ESP8266)
#include <pgmspace.h>
#elif defined(ARDUINO_ARCH_SAMD)
// nothing special needed
#elif defined(ARDUINO_SAM_DUE)
#define PROGMEM
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define Wire Wire1

#if (ARDUINO >= 100)
#define _I2C_WRITE write ///< Modern I2C write
#define _I2C_READ read   ///< Modern I2C read
#include <WProgram.h>
#define _I2C_WRITE send   ///< Legacy I2C write
#define _I2C_READ receive ///< legacy I2C read

I don't know why the library code at lines 60 to 64 (for ARDUINO_SAM_DUE) was not effective, and I hope to do some more testing. Maybe others here can shed some light?

Update 2: Noting the link from @Edgar Bonet in the comments to the new example sketch customWire_DS3231onSAMD21.ino in RTClib 1.14.1 which specifically caters for multiple i2c ports. Nice one.

  • 1
    Thank you. That works. Lines 54 to 64 in RTClib.cpp looks like it substitutes Wire1 for Wire on Due. However, that is not working for me. Commented Oct 1, 2021 at 14:39
  • Great! If you can; please give the answer the tick to show it answers your question.
    – RowanP
    Commented Oct 1, 2021 at 17:24
  • While tour fix works I put #define Wire Wire1 in RTClib.h. This works too. My opinion at this point is my Arduino setup for the Due can't fine the $defines that are already in the library. Commented Oct 14, 2021 at 12:46
  • 1
    Re “I don't know why the library code at lines 60 to 64 (for ARDUINO_SAM_DUE) was not effective”: This #define is vestigial from before the library allowed selecting a custom I2C interface. It serves no purpose anymore. Commented Oct 23, 2021 at 8:52
  • 1
    I just submitted a pull request to remove this confusing, dead pre-processor code. Commented Oct 25, 2021 at 13:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.