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
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 calling RTC.now after you call setSyncProvider

User avatar
ashton1
 
Posts: 13
Joined: Sat Mar 23, 2013 9:59 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by ashton1 »

I'm happy with the ~5 min sync from startup. I'm looking at the Time.h library commands and the only sync variable is setSyncInterval(interval); // number of seconds between re-sync.

If I could force sync on startup, I could set the interval to = 24 hrs. I'm not sure how many of these timing features will slow down my running project. I may take a peek inside the library.

User avatar
ashton1
 
Posts: 13
Joined: Sat Mar 23, 2013 9:59 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by ashton1 »

Stange, the alarm is not triggering. I have the alarm time set after the sync takes place. I have watched the times
Can't be much wrong.

See latest code:

Code: Select all

// Daily alarm test using a DS1307 RTC
#include <Wire.h>
#include "RTClib.h"
#include <LiquidCrystal_I2C.h>
#include <Time.h>
#include <TimeAlarms.h>
LiquidCrystal_I2C lcd(0x27,20,4); 
RTC_DS1307 RTC;

time_t syncProvider()     //this does the same thing as RTC_DS1307::get()
{
  return RTC.now().unixtime();
}
 
void setup () {
 //setTime(17,26,0,7,4,2013);
 RTC.begin(); 
 setSyncProvider(syncProvider);
//  RTC.now;  // Test to force initial sync, no.
 Alarm.alarmRepeat(18,31,0, Alarm1);  // every day
 lcd.init(); 
 lcd.backlight();
 lcd.setCursor(0, 0);
 pinMode(13, OUTPUT); 
} 
void loop () {
 clockDisplay();
 Alarm.delay(1000); 
}

void clockDisplay(){
  DateTime now = RTC.now();
  char buf[20];  // -------------------- RTC Time --------------------
  sprintf(buf, "%02d:%02d  %02d/%02d/%4d", now.hour(), now.minute(), now.month(), now.day(), now.year());
  lcd.print(buf);
 lcd.setCursor(0,1);

 char buf1[20];  // ------------------  Arduino Time -----------------
 sprintf(buf1, "%02d:%02d:%02d %02d/%02d/%4d", hour(), minute(), second(), month(), day(), year());
 lcd.print(buf1);
 lcd.setCursor(0,0);
}  

void Alarm1(){
  digitalWrite(13, HIGH);  //alarm test output - On
  delay(4000);
  digitalWrite(13, LOW); } // Off

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'm not sure why you're having this 5-minute sync issue. Here's my sketch - I commented out all references to RTC.now(), and I'm just printing out the time as returned by the Time library.

It just comes right up and starts spitting out the current time.

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(57600);
    Wire.begin();
    RTC.begin();
    setSyncProvider(syncProvider);     //reference our syncProvider function instead of RTC_DS1307::get()

  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 loop () {
     
    Serial.print(year(), DEC);
    Serial.print('/');
    Serial.print(month(), DEC);
    Serial.print('/');
    Serial.print(day(), DEC);
    Serial.print(' ');
    Serial.print(hour(), DEC);
    Serial.print(':');
    Serial.print(minute(), DEC);
    Serial.print(':');
    Serial.print(second(), DEC);
    Serial.println();


  
  /*  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 »

Where did you get this LiquidCrystal_I2C library?
Maybe try taking that out and see if your problems go away?

User avatar
ashton1
 
Posts: 13
Joined: Sat Mar 23, 2013 9:59 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by ashton1 »

The 5 Minutes time is hard coded in the Time.h library, Time.cpp file, with this code:

Code: Select all

static tmElements_t tm;          // a cache of time elements
static time_t       cacheTime;   // the time the cache was updated
static time_t       syncInterval = 300;  // time sync will be attempted after this many seconds
I don't believe the I2C LCD library has anything to do with this, I have been using it for everything imaginable for a year with no probs. The I2C communications with the RTC & LCD are fine otherwise I'd have errors or comm fail.
The below code is a simple TimeAlarms.h daily alarm demonstration, it always works. I'll try converting my test to Serial and test it.

Code: Select all

//This sketch  triggers a daily alarm output
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Time.h>
#include <TimeAlarms.h>
LiquidCrystal_I2C lcd(0x27,20,4); 

void setup() 
{
  setTime(19,05,0,7,04,13); // set time (h,m,s,d,m,yy)
  // create the alarms 
  Alarm.alarmRepeat(19,7,0, Event1);  // (h,m,s, Event1)
  lcd.init(); 
  lcd.backlight();
  lcd.setCursor(0, 0); 
  pinMode(13, OUTPUT); }

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

void Event1(){
  digitalWrite(13, HIGH);  //alarm output on
  delay(5000);
  digitalWrite(13, LOW); } // Off

void digitalClockDisplay()
{
char buf[20];
  sprintf(buf, "%02d:%02d:%02d %02d/%02d/%4d", hour(), minute(), second(), month(), day(), year());
  lcd.print(buf);
  lcd.setCursor(0,0);
}

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 »

Aha! Figured it out. Your sketch wasn't initializing the I2C library:
Add a call to Wire.begin() right before the RTC.begin() :

Code: Select all

void setup () {
  Serial.begin(57600);
setTime(17,26,0,7,4,2013);
Wire.begin();                          //initialize the I2C driver
RTC.begin(); 
setSyncProvider(syncProvider);
  RTC.now;  // Test to force initial sync, no.
Alarm.alarmRepeat(18,31,0, Alarm1);  // every day
lcd.init(); 
lcd.backlight();
lcd.setCursor(0, 0);
pinMode(13, OUTPUT); 
} 

User avatar
ashton1
 
Posts: 13
Joined: Sat Mar 23, 2013 9:59 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by ashton1 »

db

I tested your code - great, then added my LCD display to it and retested -- great. The time syncs instantly!

So after reading your last reply, I added your initial time set code and added the Wire.Begin():

Code: Select all

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__));
  }
My code now works perfect as planned. Latest version below. Now I can sleep. Your the Best!

Code: Select all

// Daily alarm test using a DS1307 RTC
#include <Wire.h>
#include "RTClib.h"
#include <LiquidCrystal_I2C.h>
#include <Time.h>
#include <TimeAlarms.h>
LiquidCrystal_I2C lcd(0x27,20,4); 
RTC_DS1307 RTC;

time_t syncProvider()     //this does the same thing as RTC_DS1307::get()
{
  return RTC.now().unixtime();
}
 
void setup () {
  Wire.begin();
  RTC.begin();
  setSyncProvider(syncProvider);
   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(22,34,0, Event1);  // every day
 lcd.init(); 
 lcd.backlight();
 lcd.setCursor(0, 0);
 pinMode(13, OUTPUT);
} 
void loop () {
 clockDisplay();
 Alarm.delay(1000); 
}

void clockDisplay()
{

  DateTime now = RTC.now();
  char buf[20];  // -------------------- RTC Time --------------------
  sprintf(buf, "%02d:%02d  %02d/%02d/%4d", now.hour(), now.minute(), now.month(), now.day(), now.year());
  lcd.print(buf);
 lcd.setCursor(0,1);

 char buf1[20];  // ------------------  Arduino Time -----------------
 sprintf(buf1, "%02d:%02d:%02d %02d/%02d/%4d", hour(), minute(), second(), month(), day(), year());
 lcd.print(buf1);
 lcd.setCursor(0,0);
}  

void Event1(){
  digitalWrite(13, HIGH);  //alarm test output
  delay(4000);
  digitalWrite(13, LOW); }

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 »

Nifty! Glad to help :D

User avatar
ashton1
 
Posts: 13
Joined: Sat Mar 23, 2013 9:59 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by ashton1 »

I have something strange going on.

I was testing a couple other sketches relating to RTC, then came back to the above and uploaded my above reliable code.

Now the Arduino time and RTC time are not synchronized with my PC on compile/load. I have had the battery out of the RTC also, but its time now ~ 16 minutes slow, seems to be stored at point of each power loss (batt out).

This worked perfectly since 8-Apr. Could the code I tested have caused this? It had memory address references, see below.

Any suggestions?

Code: Select all

// #############################################################################
// #
// # Scriptname : DS1307_Test.pde
// # Author     : Peter Schmelzer, Oliver Kraus
// # Date       : 2011-04-08
// # Version    : 1.21
// # License    : cc-by-sa-3.0
// #
// # Description:
// # Test file for the DS1307new library. Assumes that you have a DS1307 
// # connected to the I2C-Bus of your Arduino and that it has a battery backup.
// # 
// #############################################################################
// *********************************************
// INCLUDE
// *********************************************
#include <Wire.h>                       // For some strange reasons, Wire.h must be included here
#include <DS1307new.h>

// *********************************************
// DEFINE
// *********************************************

// *********************************************
// VARIABLES
// *********************************************
uint16_t startAddr = 0x0000;            // Start address to store in the NV-RAM
uint16_t lastAddr;                      // new address for storing in NV-RAM
uint16_t TimeIsSet = 0xaa55;            // Helper that time must not set again

// *********************************************
// SETUP
// *********************************************
void setup()
{
  pinMode(2, INPUT);                    // Test of the SQW pin, D2 = INPUT
  digitalWrite(2, HIGH);                // Test of the SQW pin, D2 = Pullup on

  Serial.begin(9600);

/*
   PLEASE NOTICE: WE HAVE MADE AN ADDRESS SHIFT FOR THE NV-RAM!!!
                  NV-RAM ADDRESS 0x08 HAS TO ADDRESSED WITH ADDRESS 0x00=0
                  TO AVOID OVERWRITING THE CLOCK REGISTERS IN CASE OF
                  ERRORS IN YOUR CODE. SO THE LAST ADDRESS IS 0x38=56!
*/
  RTC.setRAM(0, (uint8_t *)&startAddr, sizeof(uint16_t));// Store startAddr in NV-RAM address 0x08 

/*
   Uncomment the next 2 lines if you want to SET the clock
   Comment them out if the clock is set.
   DON'T ASK ME WHY: YOU MUST UPLOAD THE CODE TWICE TO LET HIM WORK
   AFTER SETTING THE CLOCK ONCE.
*/
//  TimeIsSet = 0xffff;
//  RTC.setRAM(54, (uint8_t *)&TimeIsSet, sizeof(uint16_t));  

/*
  Control the clock.
  Clock will only be set if NV-RAM Address does not contain 0xaa.
  DS1307 should have a battery backup.
*/
  RTC.getRAM(54, (uint8_t *)&TimeIsSet, sizeof(uint16_t));
  if (TimeIsSet != 0xaa55)
  {
    RTC.stopClock();
        
    RTC.fillByYMD(2011,4,8);
    RTC.fillByHMS(22,7,0);
    
    RTC.setTime();
    TimeIsSet = 0xaa55;
    RTC.setRAM(54, (uint8_t *)&TimeIsSet, sizeof(uint16_t));
    RTC.startClock();
  }
  else
  {
    RTC.getTime();
  }

/*
   Control Register for SQW pin which can be used as an interrupt.
*/
  RTC.ctrl = 0x00;                      // 0x00=disable SQW pin, 0x10=1Hz,
                                        // 0x11=4096Hz, 0x12=8192Hz, 0x13=32768Hz
  RTC.setCTRL();

  Serial.println("DS1307 Testsketch");
  Serial.println("Format is \"hh:mm:ss dd-mm-yyyy DDD\"");

  uint8_t MESZ;

  MESZ = RTC.isMEZSummerTime();
  Serial.print("MEZ=0, MESZ=1 : ");
  Serial.println(MESZ, DEC);    
  Serial.println();
}

// *********************************************
// MAIN (LOOP)
// *********************************************
void loop()
{
  RTC.getTime();
  if (RTC.hour < 10)                    // correct hour if necessary
  {
    Serial.print("0");
    Serial.print(RTC.hour, DEC);
  } 
  else
  {
    Serial.print(RTC.hour, DEC);
  }
  Serial.print(":");
  if (RTC.minute < 10)                  // correct minute if necessary
  {
    Serial.print("0");
    Serial.print(RTC.minute, DEC);
  }
  else
  {
    Serial.print(RTC.minute, DEC);
  }
  Serial.print(":");
  if (RTC.second < 10)                  // correct second if necessary
  {
    Serial.print("0");
    Serial.print(RTC.second, DEC);
  }
  else
  {
    Serial.print(RTC.second, DEC);
  }
  Serial.print(" ");
  if (RTC.day < 10)                    // correct date if necessary
  {
    Serial.print("0");
    Serial.print(RTC.day, DEC);
  }
  else
  {
    Serial.print(RTC.day, DEC);
  }
  Serial.print("-");
  if (RTC.month < 10)                   // correct month if necessary
  {
    Serial.print("0");
    Serial.print(RTC.month, DEC);
  }
  else
  {
    Serial.print(RTC.month, DEC);
  }
  Serial.print("-");
  Serial.print(RTC.year, DEC);          // Year need not to be changed
  Serial.print(" ");
  switch (RTC.dow)                      // Friendly printout the weekday
  {
    case 1:
      Serial.print("MON");
      break;
    case 2:
      Serial.print("TUE");
      break;
    case 3:
      Serial.print("WED");
      break;
    case 4:
      Serial.print("THU");
      break;
    case 5:
      Serial.print("FRI");
      break;
    case 6:
      Serial.print("SAT");
      break;
    case 7:
      Serial.print("SUN");
      break;
  }
  Serial.print(" seconds since 1.1.2000:");
  Serial.print(RTC.time2000, DEC);
  uint8_t MESZ = RTC.isMEZSummerTime();
  Serial.print(" MEZ=0, MESZ=1 : ");
  Serial.print(MESZ, DEC);  
  
  Serial.print(" - Address in NV-RAM is: ");
  RTC.getRAM(0, (uint8_t *)&lastAddr, sizeof(uint16_t));
  Serial.print(lastAddr, HEX);
  lastAddr = lastAddr + 1;              // we want to use it as addresscounter for example
  RTC.setRAM(0, (uint8_t *)&lastAddr, sizeof(uint16_t));
  RTC.getRAM(54, (uint8_t *)&TimeIsSet, sizeof(uint16_t));
  if (TimeIsSet == 0xaa55)              // check if the clock was set or not
  {
    Serial.println(" - Clock was set!");
  }
  else
  {
    Serial.println(" - Clock was NOT set!");
  }    
  delay(1000);                          // wait a second
}

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 »

You want to handle setting the time the way it's done in the example sketches:

Code: Select all

  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__));
  }
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.

User avatar
ashton1
 
Posts: 13
Joined: Sat Mar 23, 2013 9:59 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by ashton1 »

I solved part of this problem. I found that when the RTC is running, there is no date/time update via serial from the compiler Pc.

In the below code

Code: Select all

if (! RTC.isrunning()) {  // Is RTS running or not
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__)); 
  }
The below line, actually sets the RTC. It is not executed, unless (! RTC.isrunning()), meaning unless(Not RTC.isrunning()). The ! is a Logical negation operator in C/C++.

Code: Select all

RTC.adjust(DateTime(__DATE__, __TIME__));
So If the RTC Is running, regardless of time, the above line is never run, it is not set or synchronized with the compiler PC time.

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.

I'm working on an instant sync of the Arduino time.

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 »

Out of curiosity, why are you trying to adjust the time on the RTC every time you compile?

If you remove the power from the RTC prior to compiling and downloading, my suggested code will reset the time.

Calling setSerialProvider will immediately synchronize the time on the arduino with the RTC, regardless of the 5-minute timeout hardcoded into the Time library.

User avatar
ashton1
 
Posts: 13
Joined: Sat Mar 23, 2013 9:59 am

Re: DS1307 RTC with Time and TimeAlarms library

Post by ashton1 »

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 kept going back to my own project and the time was years, hours, minutes off. When I'd load/compile my own project, it wasn't updating to the correct current time/date, because my borrowed code thought since the RTC was 'running' it was accurate. I'm sure I am not the only person dealing with this issue.

So really in my real world, if I have multiple Arduinos with RTCs running things, and I plug into any/all of them to update the sketch, I Do want the RTC to be updated also to the correct time, not to walk away after an update with the RTC at a random time.

I'm going to be testing the DS1307new library https://code.google.com/p/ds1307new/downloads/list that includes a Summertime Calculation (DST). It may be worth while to US developers with time-sensitive, clock, or data logging projects.

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 »

For what it's worth, the Chronodot uses the DS3231, a much more accurate RTC than the D1307. It is also 100% code-compatible with the DS3107.

But, if you want to reset a clock that's been running for a while, the simple thing to do is to pull the battery out just before you recompile and reload the code.

Alternately, you could add code to allow you to reset the time over serial - just type it in...

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

Return to “Arduino Shields from Adafruit”