Trouble using external RTC with Arduino Zero

I'm having trouble getting a DS3231 RTC to work with an Arduino Zero(actually a Pixel micro) and the Time/TimeZone libraries.

It seems the Pixel has an address conflict with DS1307 libraries which causes the USB port to fail at compile time.

I've been able to use the DS3231 libraries successfully but just not with the Time and TimeZone libraries.
In trying to run the TimeZone library example HardwareRTC.ino and I get errors with the "SetSyncProvider(RTC.get)" statement.

Here is what I am seeing when I try to use the DS3231 libraries in place of the failing DS1307 libraries:

/var/folders/qf/rvfd4hfd2bgcny7cn9bctqpr0000gn/T/arduino_modified_sketch_657096/HardwareRTC.ino: In function 'void setup()':
HardwareRTC:41: error: request for member 'get' in '1073746944u', which is of pointer type 'Rtc*' (maybe you meant to use '->' ?)
     setSyncProvider(RTC.get);   // the function to get the time from the RTC
                         ^
exit status 1
request for member 'get' in '1073746944u', which is of pointer type 'Rtc*' (maybe you meant to use '->' ?)

I'd appreciate some advice how get past this problem.

If RTC is a pointer then you would normally use -> and not . as the error says.

Sorry but using the union doesn't help. Then I get this error:

error: 'union Rtc' has no member named 'get'
    setSyncProvider(RTC->get);

I just don't know how to associate SyncProvider for the DS3231RTC library

It seems the Pixel has an address conflict with DS1307 libraries which causes the USB port to fail at compile time.

Can you please explain more about this as it does not make sense to me. I have looked at the Pixel information here https://www.kickstarter.com/projects/rabidprototypes/pixel-the-arduino-compatible-smart-display/description

There may be a bigger issue of using an external rtc which is a 5v device with this 3.3v device but that's a different discussion.

Here is what I am seeing when I try to use the DS3231 libraries in place of the failing DS1307 libraries:

Which ds3231 library are you using? There are several available with the same name, but all with different syntax.

rtc.get is syntax from the standard Margolis DS1307 and is also used by the Christensen library for the DS3231 (which is called ds3232.h because it also is for that device). Timezone example HardwareRTC is using this syntax. It may not be the syntax of your ds3231 library.

Thanks for the reply.

I think you are correct about the "get" syntax with the libraries I have tried. I just don't know enough to deal with the problem.

My project entails using the Pixel and a DS3231 RTC with goal of adding both local and UTC time to my working sketch. I need a battery backed RTC as this project will not be attached to a computer and not continuously powered on . Jack Christensen's TimeZone library will provide the time format that I want but, so far, I cannot find a RTC library that both works with the Pixel AND with the Timezone library. Most of the DS3231 libraries I've tried will work the Pixel and DS3231 RTC module but not Timezone.

The DS1307 libraries will compile the HardwareRTC sketch but upon upload cause the Pixel to fail with no error and the uploaded program does not run. Inspecting the Arduino IDE I find the USB port is no longer connected and a reset is required to regain the port connection.

It's not a voltage issue as both the hardware RTC and the Pixel use 3.3V.

All the 1307 libraries I've tried do the same thing.

I've tried several DS3231 and DS3232RTC libraries by Jarzebski. pamisisi, Petre Rodan, Rinky-Dink Electronics and others.

I just tried the DS3232 library by Jack Christensen and the included example sketches and they fail at the
"get" syntax BUT with different errors that point to hardware files in the IDE for the AMTEL ATSAMD21.

This makes sense as I've thought all along it's a hardware incompatibility.
I just don't how to deal with it. Here is the error.

In file included from /Users/Pete/Library/Arduino15/packages/arduino/tools/CMSIS/4.0.0-atmel/Device/ATMEL/samd21/include/samd21.h:55:0,
                 from /Users/Pete/Library/Arduino15/packages/arduino/tools/CMSIS/4.0.0-atmel/Device/ATMEL/samd.h:91,
                 from /Users/Pete/Library/Arduino15/packages/arduino/tools/CMSIS/4.0.0-atmel/Device/ATMEL/sam.h:581,
                 from /Users/Pete/Library/Arduino15/packages/arduino/hardware/samd/1.6.6/cores/arduino/Arduino.h:47,
                 from sketch/HardwareRTC.ino.cpp:1:
/Users/Pete/Library/Arduino15/packages/arduino/tools/CMSIS/4.0.0-atmel/Device/ATMEL/samd21/include/samd21g18a.h:486:38: error: expected ')' before '*' token
 #define RTC               ((Rtc      *)0x40001400U) /**< \brief (RTC) APB Base Address */
                                      ^
/Users/Pete/Documents/Arduino/libraries/DS3232RTC/DS3232RTC.h:155:18: note: in expansion of macro 'RTC'
 extern DS3232RTC RTC;
                  ^
/Users/Pete/Library/Arduino15/packages/arduino/tools/CMSIS/4.0.0-atmel/Device/ATMEL/samd21/include/samd21g18a.h:486:38: error: expected ')' before '*' token
 #define RTC               ((Rtc      *)0x40001400U) /**< \brief (RTC) APB Base Address */
                                      ^
/Users/Pete/Documents/Arduino/libraries/DS3232RTC/DS3232RTC.h:155:18: note: in expansion of macro 'RTC'
 extern DS3232RTC RTC;
                  ^
/var/folders/qf/rvfd4hfd2bgcny7cn9bctqpr0000gn/T/arduino_modified_sketch_554721/HardwareRTC.ino: In function 'void setup()':
HardwareRTC:40: error: request for member 'get' in '1073746944u', which is of pointer type 'Rtc*' (maybe you meant to use '->' ?)
     setSyncProvider(RTC.get);   // the function to get the time from the RTC
                         ^
exit status 1
request for member 'get' in '1073746944u', which is of pointer type 'Rtc*' (maybe you meant to use '->' ?)

Jack Christensen's TimeZone library will provide the time format that I want but, so far, I cannot find a RTC library that both works with the Pixel AND with the Timezone library. Most of the DS3231 libraries I've tried will work the Pixel and DS3231 RTC module but not Timezone.

The DS1307 libraries will compile the HardwareRTC sketch but upon upload cause the Pixel to fail with no error and the uploaded program does not run. Inspecting the Arduino IDE I find the USB port is no longer connected and a reset is required to regain the port connection.

It's not a voltage issue as both the hardware RTC and the Pixel use 3.3V.

All the 1307 libraries I've tried do the same thing.

I'm not sure if you are running into problems with the rtc libraries or the integration with the time/timezone libraries with the setSycnhProvider().

Have you tried using RTClib.h? It has ds1307 and ds3231 objects, and is not integrated with the time library. But, linking that library into setSynchProvider() for use with the time libraries is possible.

Can you get the time library to run with out setSynchProvider() but just using a setTime instruction in the sketch? Can you get the time library to run with the TimeSerial example which takes keyboard input to set the time?

Another route to go might be to use the internal RTC with an external battery. It should be possible to work out how to use the syntax from the internal rtc library commands to get a time for setSynchProvider() and the time/timezone libraries.

Yes, I've tried the RTClib and it works fine with Pixel. It will display a random time and date in the correct format in the HardwareRTC sketch if I comment out the setSyncProvider(RTC.get); line, of course.

00:07:00 Thu 01 Jan 1970 UTC
02:35:16 Sun 07 Feb 2106 EDT

This I realize is because I'm not linking SyncProvider to anything. I've tried various things in all the libraries which none work. If you know how to do this with the RTClib or any library please let me know and I'll give it a try.

Here is the HardwareRTC sketch with the RTClib.

//#include <DS1307RTC.h>   //http://www.arduino.cc/playground/Code/Time
#include <RTClib.h>
RTC_DS3231 rtc;
#include <Time.h>        //http://www.arduino.cc/playground/Code/Time
#include <Timezone.h>    //https://github.com/JChristensen/Timezone
#include <Wire.h>        //http://arduino.cc/en/Reference/Wire (supplied with the Arduino IDE)

//US Eastern Time Zone (New York, Detroit)
TimeChangeRule myDST = {"EDT", Second, Sun, Mar, 2, -240};    //Daylight time = UTC - 4 hours
TimeChangeRule mySTD = {"EST", First, Sun, Nov, 2, -300};     //Standard time = UTC - 5 hours
Timezone myTZ(myDST, mySTD);

//If TimeChangeRules are already stored in EEPROM, comment out the three
//lines above and uncomment the line below.
//Timezone myTZ(100);       //assumes rules stored at EEPROM address 100

TimeChangeRule *tcr;        //pointer to the time change rule, use to get TZ abbrev
time_t utc, local;

#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

void setup(void)
{
    Serial.begin(115200);
   // setSyncProvider(RTC.get);   // the function to get the time from the RTC
  
    if(timeStatus()!= timeSet) 
        Serial.println("Unable to sync with the RTC");
    else
        Serial.println("RTC has set the system time");      
}

void loop(void)
{
    Serial.println();
    utc = now();
    printTime(utc, "UTC");
    local = myTZ.toLocal(utc, &tcr);
    printTime(local, tcr -> abbrev);
    delay(10000);
}

//Function to print time with time zone
void printTime(time_t t, char *tz)
{
    sPrintI00(hour(t));
    sPrintDigits(minute(t));
    sPrintDigits(second(t));
    Serial.print(' ');
    Serial.print(dayShortStr(weekday(t)));
    Serial.print(' ');
    sPrintI00(day(t));
    Serial.print(' ');
    Serial.print(monthShortStr(month(t)));
    Serial.print(' ');
    Serial.print(year(t));
    Serial.print(' ');
    Serial.print(tz);
    Serial.println();
}

//Print an integer in "00" format (with leading zero).
//Input value assumed to be between 0 and 99.
void sPrintI00(int val)
{
    if (val < 10) Serial.print('0');
    Serial.print(val, DEC);
    return;
}

Here is the sketch which shows how to use RTClib commands with setSyncProvider. Its for an UNO, and there may be the issue with the return value from setSyncProvider() being uint32_t instead of the long int which maybe used by the 32 bit mcu.

#include <Wire.h>         //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)
#include "RTClib.h"
#include <Time.h>         //http://www.arduino.cc/playground/Code/Time  
RTC_DS1307 RTC;

uint32_t syncProvider()
{
  return RTC.now().unixtime();
}

void setup(void)
{
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  setSyncProvider(syncProvider);   // the function to get the time from the RTC
  if(timeStatus() != timeSet) 
    Serial.println("Unable to sync with the RTC");
  else
    Serial.println("RTC has set the system time");      
}

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

void timeDateDisplay(void)
{
 
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(' ');
  Serial.print(month());
  Serial.print("/");
  Serial.print(day());
  Serial.print("/");
  Serial.print(year()); 
  Serial.println(); 
  Serial.print("Unix Time ");
  Serial.println(now());
  Serial.println();
}

void printDigits(int digits)
{
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(':');
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

If you know how to do this with the RTClib or any library please let me know and I'll give it a try.

In a previous thread I provided the setSyncProvider function for the Jarzebski DS3231 library but you were evidently not successful with that. I only have experience with the Time library and using the setSyncProvider() with RTC modules running on the AT328.

The AT328 world the approach is straight forward. You define a function called syncProvider() which returns a uint32_t unix time stamp from the RTC. Different libraries have different ways of getting that number.

uint32_t  syncProvider()
{
//magic library words to get a unix time from the RTC
// return that unix time
}

Then you call setSyncProvider(syncProvider). I don't quite understand why syncProvider is used without () in the expression, but that's how it works.

At issue, as pointed out, is a long int used by the 32 bit mcu is returned by the SetSyncProvider call.

I don't have the skills/knowledge how to deal with that.

When I try the sketch here cattledog presents, I get

In file included from /Users/Pete/Library/Arduino15/packages/arduino/tools/CMSIS/4.0.0-atmel/Device/ATMEL/samd21/include/samd21.h:55:0,
                 from /Users/Pete/Library/Arduino15/packages/arduino/tools/CMSIS/4.0.0-atmel/Device/ATMEL/samd.h:91,
                 from /Users/Pete/Library/Arduino15/packages/arduino/tools/CMSIS/4.0.0-atmel/Device/ATMEL/sam.h:581,
                 from /Users/Pete/Library/Arduino15/packages/arduino/hardware/samd/1.6.6/cores/arduino/Arduino.h:47,
                 from sketch/sketch_sep03b.ino.cpp:1:
/Users/Pete/Library/Arduino15/packages/arduino/tools/CMSIS/4.0.0-atmel/Device/ATMEL/samd21/include/samd21g18a.h:486:38: error: expected ')' before '*' token
 #define RTC               ((Rtc      *)0x40001400U) /**< \brief (RTC) APB Base Address */
                                      ^
/var/folders/qf/rvfd4hfd2bgcny7cn9bctqpr0000gn/T/arduino_modified_sketch_592304/sketch_sep03b.ino:4:12: note: in expansion of macro 'RTC'
 RTC_DS1307 RTC;
            ^
/Users/Pete/Library/Arduino15/packages/arduino/tools/CMSIS/4.0.0-atmel/Device/ATMEL/samd21/include/samd21g18a.h:486:38: error: expected ')' before '*' token
 #define RTC               ((Rtc      *)0x40001400U) /**< \brief (RTC) APB Base Address */
                                      ^
/var/folders/qf/rvfd4hfd2bgcny7cn9bctqpr0000gn/T/arduino_modified_sketch_592304/sketch_sep03b.ino:4:12: note: in expansion of macro 'RTC'
 RTC_DS1307 RTC;
            ^
/var/folders/qf/rvfd4hfd2bgcny7cn9bctqpr0000gn/T/arduino_modified_sketch_592304/sketch_sep03b.ino: In function 'uint32_t syncProvider()':
sketch_sep03b:8: error: request for member 'now' in '1073746944u', which is of pointer type 'Rtc*' (maybe you meant to use '->' ?)
  return RTC.now().unixtime();
             ^
/var/folders/qf/rvfd4hfd2bgcny7cn9bctqpr0000gn/T/arduino_modified_sketch_592304/sketch_sep03b.ino: In function 'void setup()':
sketch_sep03b:15: error: request for member 'begin' in '1073746944u', which is of pointer type 'Rtc*' (maybe you meant to use '->' ?)
  RTC.begin();
      ^
sketch_sep03b:16: error: 'setSyncProvider' was not declared in this scope
  setSyncProvider(syncProvider);   // the function to get the time from the RTC
                              ^
sketch_sep03b:17: error: 'timeStatus' was not declared in this scope
  if(timeStatus() != timeSet) 
                ^
sketch_sep03b:17: error: 'timeSet' was not declared in this scope
  if(timeStatus() != timeSet) 
                     ^
/var/folders/qf/rvfd4hfd2bgcny7cn9bctqpr0000gn/T/arduino_modified_sketch_592304/sketch_sep03b.ino: In function 'void timeDateDisplay()':
sketch_sep03b:32: error: 'hour' was not declared in this scope
  Serial.print(hour());
                    ^
sketch_sep03b:33: error: 'minute' was not declared in this scope
  printDigits(minute());
                     ^
sketch_sep03b:34: error: 'second' was not declared in this scope
  printDigits(second());
                     ^
sketch_sep03b:36: error: 'month' was not declared in this scope
  Serial.print(month());
                     ^
sketch_sep03b:38: error: 'day' was not declared in this scope
  Serial.print(day());
                   ^
sketch_sep03b:40: error: 'year' was not declared in this scope
  Serial.print(year()); 
                    ^
sketch_sep03b:43: error: 'now' was not declared in this scope
  Serial.println(now());
                     ^
exit status 1
request for member 'now' in '1073746944u', which is of pointer type 'Rtc*' (maybe you meant to use '->' ?)
[\code]

I downloaded Arduino boards files to compile for the Zero. Selecting the programming port, I can get your TimeZone sketch with setSyncProvider() to compile with the following changes:

  1. include TimeLib.h which is the current name for the time library.
  2. do not capitalize rtc when declaring the ds3231 object, I think it is a keyword for the internal rtc. You ccould also use RTC_DS3231 myRtc; if you find that less confusing.
  3. make the syncProver return a long int
  4. add sPrintDigits which was missing from the to the code you posted.
//#include <DS1307RTC.h>   //http://www.arduino.cc/playground/Code/Time
#include <RTClib.h>
RTC_DS3231 rtc; //do not capitalize rtc
//#include <Time.h>        //http://www.arduino.cc/playground/Code/Time
#include <TimeLib.h>
#include <Timezone.h>    //https://github.com/JChristensen/Timezone
#include <Wire.h>        //http://arduino.cc/en/Reference/Wire (supplied with the Arduino IDE)

//US Eastern Time Zone (New York, Detroit)
TimeChangeRule myDST = {"EDT", Second, Sun, Mar, 2, -240};    //Daylight time = UTC - 4 hours
TimeChangeRule mySTD = {"EST", First, Sun, Nov, 2, -300};     //Standard time = UTC - 5 hours
Timezone myTZ(myDST, mySTD);

//If TimeChangeRules are already stored in EEPROM, comment out the three
//lines above and uncomment the line below.
//Timezone myTZ(100);       //assumes rules stored at EEPROM address 100

TimeChangeRule *tcr;        //pointer to the time change rule, use to get TZ abbrev
time_t utc, local;

#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

  long int syncProvider()  //function to return a long int not uint32_t
{
  return rtc.now().unixtime(); //syntax for RTClib.h
}

void setup(void)
{
    Serial.begin(115200);
    setSyncProvider(syncProvider);   // the function to get the time from the RTC and link to time library
  
    if(timeStatus()!= timeSet) 
        Serial.println("Unable to sync with the RTC");
    else
        Serial.println("RTC has set the system time");      
}

void loop(void)
{
    Serial.println();
    utc = now();
    printTime(utc, "UTC");
    local = myTZ.toLocal(utc, &tcr);
    printTime(local, tcr -> abbrev);
    delay(10000);
}

//Function to print time with time zone
void printTime(time_t t, char *tz)
{
    sPrintI00(hour(t));
    sPrintDigits(minute(t));
    sPrintDigits(second(t));
    Serial.print(' ');
    Serial.print(dayShortStr(weekday(t)));
    Serial.print(' ');
    sPrintI00(day(t));
    Serial.print(' ');
    Serial.print(monthShortStr(month(t)));
    Serial.print(' ');
    Serial.print(year(t));
    Serial.print(' ');
    Serial.print(tz);
    Serial.println();
}

//Print an integer in "00" format (with leading zero).
//Input value assumed to be between 0 and 99.
void sPrintI00(int val)
{
    if (val < 10) Serial.print('0');
    Serial.print(val, DEC);
    return;
}

//Print an integer in ":00" format (with leading zero).
//Input value assumed to be between 0 and 99.
void sPrintDigits(int val)
{
    Serial.print(':');
    if(val < 10) Serial.print('0');
    Serial.print(val, DEC);
}

Thank you! Thank you for taking the time to help me. I really do appreciate you folks.

I did have to add the following to get the Serial Monitor to display anything. Maybe the RTC needed to start?

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

Sorry but the toolbar with code button has disappeared.

BTW... why do some libraries not turn red when added? They still work or appear to.

yes, RTClib.h requires the call rtc.begin(). It's in all the example sketches from that library and was in the sketch I provided in reply #7.

The Timezone HarwareRTC sketch was developed using the Christensen (and Margolis ds1307) library which does not require that call. When you switched to use RTClib.h, I didn't pick up the missing rtc.begin();

BTW... why do some libraries not turn red when added? They still work or appear to

You'll drive yourself crazy trying to figure out when and why the red color is applied to certain "keywords". There are different keyword files for the ide and each libraries. As you found, it makes no functional difference.

Is the code now working as wanted?

Yes. It now accesses the RTC and time libraries to return the time in my wanted format. I can move forward with my project.

Thanks.