Pages: [1]   Go Down
Author Topic: DS1307 RTC adjust drift automatically  (Read 3026 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Edison Member
*
Karma: 8
Posts: 1341
If you're not living on the Edge, you're taking up too much space!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Didn't know which category to put this in.  I wrote some code to adjust the drift of my RTC.  You only have to set it once.  Mine drifted about 6 seconds per day.  That's not good enough for me.  Now it's less than 0.1 seconds.  This works especially when the clock is powered off.  Not sure how it works during extreme temperatures.  It's simple check it out.  It's only a few lines more than the original example.  You only need to change the first 3 constants, and calculate the 4th constant over time.  Any improvements?  Any ideas how I can adjust the day overflow?  The way it is now you can use since12 for logging.

Code:
#include "Wire.h"
#define DS1307_ADDRESS 0x68

const int setyearago=1;  //when was the RTC set?
const int setmonth=10;
const int setday=4;
const int spdx100=580;  // secs/day slow error measured over 11 months 580

int second,minute,hour,weekDay,monthDay,month,year;
int errsec,i,j;
long since12,since12wrong;

void ferrsec(){
long t=setyearago*365;
t+=(month-setmonth)*30;
t+=(monthDay-setday);
errsec=t*spdx100/100;
//Serial.println(errsec/60.0);
since12wrong=long(hour)*60*60+minute*60+second;
since12=since12wrong+errsec;
//since12%=(24*60*60); untested and wrong let it overflow
//return;  //skip adjusting
second+=errsec%60;
if(second>=60){
  minute++;
  second-=60;
  }
minute+=errsec/60;
while(minute>=60){
  hour++;  //could overflow past 23
  minute-=60;
  }
if(hour>=24){
  monthDay++;  //still not good enough could overflow monthDay
  hour-=24;
  }
}
void setup(){
  Wire.begin();
  Serial.begin(9600);
}
void loop(){
  printDate();
  delay(1000);
}
byte bcdToDec(byte val){
  return ( (val/16*10) + (val%16) );
}
void printDate(){
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_ADDRESS,7);
  second = bcdToDec(Wire.receive());
  minute = bcdToDec(Wire.receive());
  hour = bcdToDec(Wire.receive() & 0b111111); //24 hour time
  weekDay = bcdToDec(Wire.receive()); //0-6 -> sunday - Saturday
  monthDay = bcdToDec(Wire.receive());
  month = bcdToDec(Wire.receive());
  year = bcdToDec(Wire.receive());
  ferrsec();
  Serial.print(month);
  Serial.print("/");
  Serial.print(monthDay);
  Serial.print("/");
  Serial.print(year);
  Serial.print(" ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.println(second);
}
Logged

If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

Offline Offline
Edison Member
*
Karma: 8
Posts: 1341
If you're not living on the Edge, you're taking up too much space!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Has anyone tried this?  I thought it would be useful for all DS1307 users.  Is there a problem with the code?  Improvements?
Logged

If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

Colorado
Offline Offline
Full Member
***
Karma: 1
Posts: 168
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK, in this thread now, thanks. smiley

I'd like to give this code a try. Can you give me more directions please?  

Say I set my ds1307 to the correct time right now. How would I set the first three params of your sketch before uploading? Like this maybe?

Thanks!

const int setyearago=0;  //when was the RTC set?
const int setmonth=8;
const int setday=22;
« Last Edit: August 22, 2012, 09:48:41 pm by BlueJakester » Logged

Offline Offline
Edison Member
*
Karma: 8
Posts: 1341
If you're not living on the Edge, you're taking up too much space!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You got it.  The 4th constant is a little tricky.  You have to calculate it!  Using your old original sketches to read time, measure how far off it is from the PC time today, and again in 10 days.  Let's say it's 45 seconds slower than it was today.  Divide by the number of days (10), then multiply by 100.  The answer is 450.  That's what you put for spdx100.  That stands for Secs/day x 100 that it is slow.  -450 if it's faster after 10 days running.  Let me know!  The error seems consistent to me, so now there is much less error per day.
Logged

If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

Peoples Republic of Cantabrigia
Online Online
God Member
*****
Karma: 6
Posts: 719
Arduino happiness
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Nice work.

I imagine the DS1307 drift is going to be quite dependent on temperature. But as long as the temperature is relatively constant, you should be good to go.

Some day I'll try to do something similar with an Arduino, a radio receiver for the US time signal and the Chronodot... and then create a auto-correct function for the aging trim in the DS3231.
Logged

Colorado
Offline Offline
Full Member
***
Karma: 1
Posts: 168
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Let me know!  The error seems consistent to me, so now there is much less error per day.
OK, I'll setup the clock and load the sketch this weekend. It will be at least 10 days plus a few more to monitor results before I post back to this thread with my results, but I will.

Thanks for writing and sharing this code!

Jake
« Last Edit: August 24, 2012, 06:37:00 am by BlueJakester » Logged

Offline Offline
Edison Member
*
Karma: 8
Posts: 1341
If you're not living on the Edge, you're taking up too much space!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You could guess after 2 days.  I also wrote some code which is related to this.  It uses GPS to measure and calibrate millis() and the Arduino clock within hours, no need to wait 100 days.  So long as you keep it inside where the temperature is 60-80 degrees it is easy to obtain accuracy of 1ppm, which is about 1 seconds every 11 days.  Or even 10ppm with some effort which is 1 second every 100 days, or 3 seconds per year.  The only hardware you need for this code is GPS.  I also have code which uses Wifly to do the same thing with NIST server.

If you've got the time, I can help you keep it!
Logged

If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

Colorado
Offline Offline
Full Member
***
Karma: 1
Posts: 168
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sounds good. I need to put the ds1307 on a breadboard this weekend and set the time. I'll let you know how it goes.

Thanks!
Logged

Peoples Republic of Cantabrigia
Online Online
God Member
*****
Karma: 6
Posts: 719
Arduino happiness
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

...Or even 10ppm with some effort which is 1 second every 100 days, or 3 seconds per year....

Pardon my ignorance. I thought lower PPMs were better than higher PPMs re: clock drift. Why would an increase to 10PPM drift be preferable to 1PPM? Did you perhaps mean 0.1PPM or 100PPB?

I thought the whole point of adjusting the aging trim in the DS1307 or DS3201 was to minimize the clock drift.
« Last Edit: August 24, 2012, 09:35:27 am by Constantin » Logged

Offline Offline
Edison Member
*
Karma: 8
Posts: 1341
If you're not living on the Edge, you're taking up too much space!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Of course my mistake 0.1ppm
Logged

If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

Colorado
Offline Offline
Full Member
***
Karma: 1
Posts: 168
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

sbright,

I have my cheap ds1307 setup. I'll be installing your code either tonight or tomorrow and will let you know how it works out.

Jake
Logged

Peoples Republic of Cantabrigia
Online Online
God Member
*****
Karma: 6
Posts: 719
Arduino happiness
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks like I'll have to use a GPS receiver since sourcing the radio-based receivers appears difficult, plus I get the benefit of a GPS system, if I want it. The breakout board from adafruit appears enticing, it'll be interesting to see to what extent trimming the oscillator will work. What is the minimum time you think you need to trim with reasonable perfection? For something as accurate as the DS3231, I figured I'd need at least a month.
Logged

Offline Offline
Edison Member
*
Karma: 8
Posts: 1341
If you're not living on the Edge, you're taking up too much space!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Using PPS pin you can measure 1us drift each second.  So you get 1ppm in about...
1 second!

It makes more sense to wait 20 minutes and use 1ms drift method instead.

http://arduino.cc/forum/index.php/topic,120288
Logged

If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

Colorado
Offline Offline
Full Member
***
Karma: 1
Posts: 168
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sbright,

I have your code installed and it appears to be working smiley-grin  I'll monitor it for a few days.

Thanks,
Jeff
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 1
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Guys,

I have modified the Time and DS1307RTC Libraries to do drift correction and store the drift info in the RTC battery backed memory. I’ve also included an Arduino sketch to do the RTC time setting and drift calibration. Take a look at the link below if you’re interested.

Howard

http://limchonghan.wordpress.com/driftcorrectedds1307/
Logged

Pages: [1]   Go Up
Jump to: