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)
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
cosmos275:
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.
If you have to use millis(), this is what I would do:
#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.
#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.
CrossRoads:
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
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.