Pages: [1] 2   Go Down
Author Topic: POOR MAN'S RTC  (Read 1056 times)
0 Members and 1 Guest are viewing this topic.
Seattle, WA
Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Disclaimer: I'm pretty new to all this.

Hi, I'd like to make a time of day based event, such on a certain hour (or several), something happens.  Down the road maybe an RTC makes sense, but it would be cool to make one from scratch.

Here's what I got so far (Thanks to guix to help me get started)

Code:
unsigned long  time_old;
unsigned long  time_new;
int hours = 0;

void setup()
{
  time_old = millis();
}

void loop()
{
  time_new = millis();  
   if(time_new - time_old >= (60 * 60 * 1000UL ))
   {
     hours++;
   }

   if(hours == 4)
   {
     //do something
   }

   if(hours>= 24)
   {
     time_old = time_new;
   }
  
}

Will this work? Will this keep time at all accurately?  Will it not if I use delay() in my "do something" section?

Also, if I power cycle the Uno at noon, would it reset the clock?
Logged

California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3360
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Will this work? Will this keep time at all accurately?/
Quote
Depends on how you define "accurately"

Quote
Will it not if I use delay() in my "do something" section?

Not likely, but it depends on how you are using delay and how you are using the time.
Logged

Virginia, USA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 93
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is a time library on the playground. I have not used this but it may be what you are looking for.

http://playground.arduino.cc/Code/Time
Logged

Seattle, WA
Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hmm, a minute per day accurate maybe?

So, I reduced the counter so I could debug... doesn't seem to work.  I'd expect every 10 seconds for hours to increment, then print to serial, etc. every 10 seconds, but what happens is after 10 seconds, it prints 1 to 24 really fast, then nothing.  Any ideas?  Thanks

Code:
unsigned long  time_old;
unsigned long  time_new;
int hours = 0;

void setup()
{
  time_old = millis();
  Serial.begin(9600);
}

void loop()
{
  time_new = millis();
  
   if(time_new - time_old >= (10 * 1000UL )) //shortened for debug
   {
     hours++;
     Serial.println(hours);
   }
 
   if(hours == 4)
   {
     //do something
   }
  
   if(hours>= 24)
   {
     time_old = time_new;
   }
  
}

Edit: adding " hours = 0;" to the last IF makes the same thing repeat every 10 seconds, not 240 smiley-sad
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 602
Posts: 33371
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Also, if I power cycle the Uno at noon, would it reset the clock
Everything gets reset in a power cycle. If it is not exactly at noon then hours will not match real time.
Logged

Seattle, WA
Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, got it, needed to reset time_old each ~hour.

Code:

if(time_new - time_old >= (1 * 1000UL )) //shortened for debug
   {
     hours++;
     time_old = time_new;  //new line
     Serial.println(hours);
   }
Logged

0
Offline Offline
Shannon Member
****
Karma: 200
Posts: 11694
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Will this work? Will this keep time at all accurately?  Will it not if I use delay() in my "do something" section?


With the standard Uno, no it won't be accurate enough for a clock, since the Uno uses a
ceramic resonator rather than a quartz crystal as its time base.  It is possible to resolder
a quartz crystal and caps in place of the resonator, but it is a pretty fiddly job.  The
Duemilanova (previous standard version of Arduino) used a quartz crystal, but alas the
Uno doesn't.

Calling delay() has little effect on your code if the delays are short - the checks for the hour will be held up
but the time accounting will still work.
Logged

[ I won't respond to messages, use the forum please ]

Seattle, WA
Offline Offline
Newbie
*
Karma: 0
Posts: 45
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

won't be accurate enough for a clock, since the Uno uses a
ceramic resonator rather than a quartz crystal as its time base....
 
.....the checks for the hour will be held up
but the time accounting will still work.

Cool, this will be enough to get me going and maybe later I can get a real RTC.  Is there not a Arduino model currently being produced with a quartz?

Thanks!
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Will this keep time at all accurately?

It will drift, by the duration of the main loop.

The best is through an interrupt.

If you have to use millis(), this is what I would do:

Code:
#define PR_1s 1000ul //duration of 1 second, in ms
#define PR_1m (60 * PR_1s) //duration of 1 minute
#define PR_1h (60 * PR_1m) //duration of 1 hour
#define PR_ERROR 0 //error term

#define PR PR_1m //duration set to 1 minute

void loop(void) {
  static time = millis(); //reset current time
  if (millis() - time >= PR) {//desired time has elapsed
    time += PR + PR_ERROR; //update time, with error correction
    //do something
  }
}

The code is self-contained and allows you to correct for timing errors.

Its accuracy is only determined by the crystal.
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 524
Posts: 26442
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

On the other hand, a DS1307 & crystal are pretty inexpensive
http://www.dipmicro.com/store/DS1307N
http://www.dipmicro.com/store/XC4-32768
Use two 4.7K pullups on the SCL, SDA lines

Battery & holder
http://www.dipmicro.com/store/BAT-CR2032
http://www.dipmicro.com/store/BH120591-1

So, about $1.25 total?
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I would change it slightly:

Code:
#define PR_1s 1000ul //duration of 1 second, in ms
#define PR_1m (60 * PR_1s) //duration of 1 minute
#define PR_1h (60 * PR_1m) //duration of 1 hour
#define PR_ERROR 0 //error term

#define PR PR_1m //duration set to 1 minute

unsigned char rtc_tick(void) {
  static unsigned long time = millis(); //reset current time
  if (millis() - time >= PR) {//desired time has elapsed
    time += PR + PR_ERROR; //update time, with error correction
    return 1; //return a tick
  } else return 0;
}

Whenever the duration defined by PR has passed, rtc_tick() returns 1, making time counting quite easy.
Logged

SE USA
Offline Offline
Faraday Member
**
Karma: 41
Posts: 3783
@ssh0le
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

On the other hand, a DS1307 & crystal are pretty inexpensive

they are expensive in terms of memory, everyone uses the wire library to control the things, which directly states "I am going to eat your ram!" just to return a string you could write on a band-aid
Logged


Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 212
Posts: 13531
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@dhenry
nice implementation !

minor point, I would use uint8_t  instead of unsigned char as return type to indicate it is really an int. Or boolean true / false? ==> in short it depends.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4762
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

On the other hand, a DS1307 & crystal are pretty inexpensive
http://www.dipmicro.com/store/DS1307N
http://www.dipmicro.com/store/XC4-32768
Use two 4.7K pullups on the SCL, SDA lines

Battery & holder
http://www.dipmicro.com/store/BAT-CR2032
http://www.dipmicro.com/store/BH120591-1

So, about $1.25 total?

It's the other $40 I spend to justify shipping that gets me....
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Dallas, TX USA
Offline Offline
Faraday Member
**
Karma: 63
Posts: 2645
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

1307 boards are cheap off ebay.
A bit over $2 USD including shipping:
http://www.ebay.com/sch/i.html?_odkw=i2c+rtc&LH_BIN=1&_sop=15&_osacat=0&_from=R40&_trksid=p2045573.m570.l1313&_nkw=1307+module&_sacat=0

The boards even come with an eeprom and have a spot for a 18sB20 1 wire temperature sensor.
(some even come with it already soldered in).

One of those, the Time library along with TimeAlarms library and you are good to go.

--- bill
Logged

Pages: [1] 2   Go Up
Jump to: