DS1307 RTC with Time and TimeAlarms library

Adafruit Ethernet, Motor, Proto, Wave, Datalogger, GPS Shields - etc!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
spiney
 
Posts: 214
Joined: Mon Jul 09, 2012 6:35 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by spiney »

Adafruit support Bill directed me to this thread because I was having similar problems. I have used the code posted in adafruit_support_rick » 19 Mar 2013 16:16. I too have moved the RTC adjust out of the if statement (but I saw the later comment) and ditched the Serial printing of the date and time, replacing it with the alarm calls from the alarm example. It works except it too does not sync, not after 10 minutes either. I have altered the computer time to prove the operation of RTC adjust and sync.
I suspect that there are some more posts on this subject that I cannot see - caught a glimpse once. But I would be glad for help in getting the sync to work. Here is the modified code.

Code: Select all

    // Date and time functions using a DS1307 RTC connected via I2C and Wire lib

    #include <Wire.h>
    #include "RTClib.h"
    #include <Time.h>
    #include <TimeAlarms.h>

    RTC_DS1307 RTC;

    time_t syncProvider()     //this does the same thing as RTC_DS1307::get()
    {
      return RTC.now().unixtime();
    }

    void setup () {
        Serial.begin(9600);
        Wire.begin();
        RTC.begin();
        setSyncProvider(syncProvider);     //reference our syncProvider function instead of RTC_DS1307::get()
RTC.adjust(DateTime(__DATE__, __TIME__));
      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(__DATE__, __TIME__));
      }
    
 Alarm.alarmRepeat(8,30,0, MorningAlarm);  // 8:30am every day
  Alarm.alarmRepeat(17,45,0,EveningAlarm);  // 5:45pm every day 
  Alarm.alarmRepeat(dowSaturday,8,30,30,WeeklyAlarm);  // 8:30:30 every Saturday 

 
  Alarm.timerRepeat(15, Repeats);            // timer for every 15 seconds    
  Alarm.timerOnce(10, OnceOnly);             // called once after 10 seconds 
}

void  loop(){  
  digitalClockDisplay();
  Alarm.delay(1000); // wait one second between clock display
}

// functions to be called when an alarm triggers:
void MorningAlarm(){
  Serial.println("Alarm: - turn lights off");    
}

void EveningAlarm(){
  Serial.println("Alarm: - turn lights on");           
}

void WeeklyAlarm(){
  Serial.println("Alarm: - its Monday Morning");      
}

void ExplicitAlarm(){
  Serial.println("Alarm: - this triggers only at the given date and time");       
}

void Repeats(){
  Serial.println("15 second timer");         
}

void OnceOnly(){
  Serial.println("This timer only triggers once");  
}

void digitalClockDisplay()
{
  // digital clock display of the time
  Serial.println(day());
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println(); 
}

void printDigits(int digits)
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

   /* void loop () {
     // RTC.adjust(DateTime(__DATE__, __TIME__));
        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(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.unixtime() + 7 * 86400L + 30);
       
        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);
    }
    */

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by adafruit_support_rick »

I think the call to setSyncProvider needs to go AFTER the RTC.adjust. Give this a try.

Code: Select all

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

        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(__DATE__, __TIME__));
        }

        setSyncProvider(syncProvider);     //reference our syncProvider function instead of RTC_DS1307::get()
 
        Alarm.alarmRepeat(8,30,0, MorningAlarm);  // 8:30am every day
        Alarm.alarmRepeat(17,45,0,EveningAlarm);  // 5:45pm every day 
        Alarm.alarmRepeat(dowSaturday,8,30,30,WeeklyAlarm);  // 8:30:30 every Saturday 

        Alarm.timerRepeat(15, Repeats);            // timer for every 15 seconds    
        Alarm.timerOnce(10, OnceOnly);             // called once after 10 seconds 
}

User avatar
spiney
 
Posts: 214
Joined: Mon Jul 09, 2012 6:35 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by spiney »

Thank you Rick.
That has worked. But will it sync regularly or only when setup runs?

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by adafruit_support_rick »

The way it works is this: the internal Arduino clock is used for the actual time of day. When you call setSyncProvider in setup(), the internal arduino clock is set to the time retrieved from the RTC by your syncProvider() function.

After that, every call to now() checks to see how long it's been since the internal time was synchronized with the RTC. If the length of time since the last synchronization exceeds a certain interval, then syncProvider is called again to resynchronize the internal clock with the RTC.

The default synchronization interval is 300 seconds (5 minutes). So, if you do nothing else, the internal clock will be re-synchronized with the RTC every 5 minutes, so long as you are regularly calling Time library functions (like now(), hour(), minute(), second(), day(), isPM(), etc., etc.).

You can change the synchronization interval by calling setSyncInterval( <interval in seconds> ).

If you're using TimeAlarms, the TimeAlarms functions take care of calling now(), so you don't have to worry about it.

User avatar
spiney
 
Posts: 214
Joined: Mon Jul 09, 2012 6:35 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by spiney »

Thank you very much.
Very satisfying progress today, thanks to Adafruit support. :D

User avatar
spiney
 
Posts: 214
Joined: Mon Jul 09, 2012 6:35 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by spiney »

I have just got back to this project after a couple of months away and a broken computer.
I have tried to run RicK's code 22 May but now I get 'time_t' does not name a type - line8
I had to add Time and TimeAlarms libraries from the Arduino site again could I have an incorrect library?

Code: Select all

        // Date and time functions using a DS1307 RTC connected via I2C and Wire lib

        #include <Wire.h>
        #include "RTClib.h"
        #include <Time.h>
        #include <TimeAlarms.h>

        RTC_DS1307 RTC;

        time_t syncProvider()     //this does the same thing as RTC_DS1307::get()
        {
          return RTC.now().unixtime();
        }

  /*      void setup () {
            Serial.begin(9600);
            Wire.begin();
            RTC.begin();
            setSyncProvider(syncProvider);     //reference our syncProvider function instead of RTC_DS1307::get()
    RTC.adjust(DateTime(__DATE__, __TIME__));
          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(__DATE__, __TIME__));
          }
   */
 void setup () {
            Serial.begin(9600);
            Wire.begin();
            RTC.begin();

            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(__DATE__, __TIME__));
            }

            setSyncProvider(syncProvider);     //reference our syncProvider function instead of RTC_DS1307::get()

            Alarm.alarmRepeat(8,30,0, MorningAlarm);  // 8:30am every day
            Alarm.alarmRepeat(17,45,0,EveningAlarm);  // 5:45pm every day
            Alarm.alarmRepeat(dowSaturday,8,30,30,WeeklyAlarm);  // 8:30:30 every Saturday

            Alarm.timerRepeat(15, Repeats);            // timer for every 15 seconds   
            Alarm.timerOnce(10, OnceOnly);             // called once after 10 seconds
    }
   
    Alarm.alarmRepeat(8,30,0, MorningAlarm);  // 8:30am every day
      Alarm.alarmRepeat(17,45,0,EveningAlarm);  // 5:45pm every day
      Alarm.alarmRepeat(dowSaturday,8,30,30,WeeklyAlarm);  // 8:30:30 every Saturday


      Alarm.timerRepeat(15, Repeats);            // timer for every 15 seconds   
      Alarm.timerOnce(10, OnceOnly);             // called once after 10 seconds
    }

    void  loop(){ 
      digitalClockDisplay();
      Alarm.delay(1000); // wait one second between clock display
    }

    // functions to be called when an alarm triggers:
    void MorningAlarm(){
      Serial.println("Alarm: - turn lights off");   
    }

    void EveningAlarm(){
      Serial.println("Alarm: - turn lights on");           
    }

    void WeeklyAlarm(){
      Serial.println("Alarm: - its Monday Morning");     
    }

    void ExplicitAlarm(){
      Serial.println("Alarm: - this triggers only at the given date and time");       
    }

    void Repeats(){
      Serial.println("15 second timer");         
    }

    void OnceOnly(){
      Serial.println("This timer only triggers once"); 
    }

    void digitalClockDisplay()
    {
      // digital clock display of the time
      Serial.println(day());
      Serial.print(hour());
      printDigits(minute());
      printDigits(second());
      Serial.println();
    }

    void printDigits(int digits)
    {
      Serial.print(":");
      if(digits < 10)
        Serial.print('0');
      Serial.print(digits);
    }

       /* void loop () {
         // RTC.adjust(DateTime(__DATE__, __TIME__));
            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(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.unixtime() + 7 * 86400L + 30);
           
            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);
        }
        */

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by adafruit_support_rick »

time_t is defined in Time.h. Take a look at your copy of time.h; you should see this near the top:

Code: Select all

#ifndef _Time_h
#define _Time_h

#include <inttypes.h>

typedef unsigned long time_t;
Check that you don't have a conflict with some other library named Time - for instance, if some other library defines the symbol _Time_h, then this Time.h won't be included.

Where have you installed the libraries? You should not be installing user libraries in the Arduino application folder. They should go in your sketchbook folder under 'libraries'.

Also, although it doesn't really matter in Arduino, it's sort of a convention to include user libraries using quotes, and system libraries (like Wire.h) using "<>":

Code: Select all

        #include <Wire.h>
        #include "RTClib.h"
        #include "Time.h"
        #include "TimeAlarms.h"

User avatar
spiney
 
Posts: 214
Joined: Mon Jul 09, 2012 6:35 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by spiney »

Thank you for your reply.
Being green, I don't know the answers to your questions. I Downloaded Time and TimeAlarm libraries and then from within the Arduino application used Sketch/Import Library/Add library and pointed to the download file. I see that under C:/Programs/Arduino/libraries Time and TimeAlarm do not exist.
The lines you mention do exist in Time.h I could see the lines only in my Download file - couldn't open Time.h from within the Arduino app.
I see that Adafruit_RGBLCDShield is under C:/Programs/Arduino/Libraries Perhaps that is wrong?
System libraries come with the download of the Arduino app and User libraries are those from the likes of Adafruit?
Pardon my ignorance, please.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by adafruit_support_rick »

Spiney wrote: I Downloaded Time and TimeAlarm libraries and then from within the Arduino application used Sketch/Import Library/Add library and pointed to the download file.
Ah! That's your problem. "Sketch/Import Library/Add library" does not do what you think it does. All it does is to add the #include lines to your sketch. It doesn't put a downloaded library where it needs to go.

Have a look at our tutorial on Arduino LIbraries:
http://learn.adafruit.com/adafruit-all- ... nstall-use

User avatar
spiney
 
Posts: 214
Joined: Mon Jul 09, 2012 6:35 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by spiney »

Thank you.
I think I may have messed up the system because I have been saving the sketches either in a Temp file or in files on Network storage. I have found Documents/Arduino/Libraries and Time, AlarmTime and Adafruit_MCP23017 are in there - but not Adafruit_RGBLCDShield.
I shifted a sketch which previously worked into the Documents/Arduino folder but that still gives multiple error codes (Which I have forgotten how to copy for the forum), one of which grumbles about multiple definitions of Adafruit_MCP23017
I am unable to remove the libraries added under Sketch/Import Library/add library. Does that matter?
Should I delete all the Arduino folders and start over? (leaving my sketches, and then copy them into the Documents/Arduino folder?

User avatar
spiney
 
Posts: 214
Joined: Mon Jul 09, 2012 6:35 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by spiney »

OK. Further to the previous post.
I have downloaded the Adafruit_RGBLCDShield library again and installed it with the others and that has got me going again.
Please do remind me how to copy error codes though.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by adafruit_support_rick »

Just select them all, copy, and paste into here. Paste inside of the Code tags.

User avatar
spiney
 
Posts: 214
Joined: Mon Jul 09, 2012 6:35 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by spiney »

Sommat odd with my computer. I can select all but copy does not work, neither right click nor Edit/Copy

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by adafruit_support_rick »

Try using Ctrl-C to copy.

User avatar
lcstyle
 
Posts: 76
Joined: Sun Oct 26, 2008 10:55 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by lcstyle »

Sorry to RES / Bump old thread, but Thank you all for the time and energy put into figuring out exactly how the RTC works in conjunction with the arduino's clock.

I'm recapping all of the data contained in this 3 page thread for anyone interested.

I think at least part of the (my) confusion lies around the following 3 variables:
  1. Confusion around how the Arduino's clock and the RTC interact
  2. How the Adafruit DS1307 RTC's "custom" library interacts with TIME and TimeAlarms libraries and functions
  3. Using the Adafruit DS1307 library, trying to do an RTC.GET doesn't work for the SetSyncProvider call, obviously the following code is the missing link:
the adafruit RTClib.h doesn't have RTC.GET as shown in other time library examples for use in your setSyncProvider call, you have to define one manually.
Perhaps this information could be added to the ds1307 tutorial, and the RTC.GET function should be added to the Adafruit DS1307 Lib to avoid any further confusion.

Code: Select all

RTC_DS1307 rtc;
  setSyncProvider(syncProvider); 
time_t syncProvider()     //this does the same thing as RTC_DS1307::get()
{
  return rtc.now().unixtime();
}
A few key pieces of information gathered:
  1. Try calling RTC.now after you call setSyncProvider to sync immediately.
  2. the Time.h library provides setSyncInterval(interval); // number of seconds between re-sync, if you wish to specify a different sync interval
  3. When you first apply power to the RTC, the clock oscillator is disabled. RTC.isrunning() checks a status bit on the DS1307, and reports whether or not the oscillator is running. This code assumes it will automatically download and run immediately after compilation. If the RTC has been reset, it will set the compilation time as the current time.
  4. If the RTC Is running, regardless of time, the code that sets/updates the RTC time on compile is never run, it is not set or synchronized with the compiler PC time. This is because of item C above.
    To force the compiler PC time update of the RTC with each compile, the RTC.adjust line could be used alone. After making this change however, the Arduino clock is not synchronized for 5 Min/300 seconds, as is hard coded into the Time.h library.
  5. the call to setSyncProvider needs to go AFTER the RTC.adjust.
  6. Your questions are NEVER STUPID OR A WASTE OF TIME, they help everyone else who might be stuck
    by Ashton1 on Fri Apr 12, 2013 10:50 am
    I know some of my minute issues are nearly a waste of forum space, but this issue is annoying on my end when testing many different sketches/codes from 2009 newer, some having hard time set values. I
The other missing piece of the puzzle is who exactly calls now()? Does it have to be explicitly called somewhere? That was answered here:
by adafruit_support_rick on Wed May 22, 2013 3:39 pm
The way it works is this: the internal Arduino clock is used for the actual time of day. When you call setSyncProvider in setup(), the internal arduino clock is set to the time retrieved from the RTC by your syncProvider() function.

After that, every call to now() checks to see how long it's been since the internal time was synchronized with the RTC. If the length of time since the last synchronization exceeds a certain interval, then syncProvider is called again to resynchronize the internal clock with the RTC.

The default synchronization interval is 300 seconds (5 minutes). So, if you do nothing else, the internal clock will be re-synchronized with the RTC every 5 minutes, so long as you are regularly calling Time library functions (like now(), hour(), minute(), second(), day(), isPM(), etc., etc.).

You can change the synchronization interval by calling setSyncInterval( <interval in seconds> ).

If you're using TimeAlarms, the TimeAlarms functions take care of calling now(), so you don't have to worry about it.
and finally:
adafruit_support_rick wrote:
sfjohnson722 wrote:or perhaps more accurate, to use the TimeAlarms to gather the time from the RTC
That's exactly what the Time/TimeAlarms library does. When you call setSyncProvider, the arduino time is synchronized with the RTC time.

By default, the times are re-synchronized whenever now() is called and it's been more than 5 minutes since the last sync.

So, you can follow the regular adafruit DS1307 example code. After calling RTC.begin(), call setSyncProvider(syncProvider), then follow the TimeAlarms example for setting alarms.

Code: Select all

#include "RTClib.h"
#include <Time.h>   // if using time or timealarms
#include <TimeAlarms.h>// if using time or timealarms

RTC_DS1307 RTC;

void setup () {
    Serial.begin(57600);
    Wire.begin();

#ifdef AVR
  Wire.begin();
#else
  Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
#endif
  rtc.begin();

  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));
  }
  
  setSyncProvider(syncProvider);   // the function to get the time from the RTC
  rtc.now();
  if(timeStatus()!= BANNED) 
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");     
}

// syncProvider function is:

time_t syncProvider()     //this does the same thing as RTC_DS1307::get()
{
  return rtc.now().unixtime();
}


Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino Shields from Adafruit”