NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Support Forum » RealTimeClock

April 26, 2009
by smolnn
smolnn's Avatar

Hi,

Is there a simple way to use my NerdKit as a really customizable "alarm clock"?

What I have seen in the ATMega168 datasheet: real time clock functionality is available, just need a ~32kHz clock crystal, and set some flags. (Have the crystal, but seems the linux utility is not capable to change the necessary flags.)

Any help appreciated.

Regards, Stephen

April 27, 2009
by mrobbins
(NerdKits Staff)

mrobbins's Avatar

Hi Stephen,

Since you asked so nicely, we just made a video called Crystal Real Time Clock which should help get you started with using the included 14.7456 MHz crystal as a wall-clock source. Let us know if that helps!

Mike

April 27, 2009
by mcai8sh4
mcai8sh4's Avatar

I'm liking this new tutorial, as soon as I get some free time, I'll try a binary display clock... watch this space for more questions when I get stuck :)

Thanks

April 27, 2009
by mrobbins
(NerdKits Staff)

mrobbins's Avatar

Glad to hear. Our plan was to try to follow up in the coming weeks with applications around this basic project, but I'd rather have you all do that so we can actually know we're teaching something useful! Sometimes it's hard for us to know whether we're including enough detail, etc.

Mike

April 27, 2009
by mcai8sh4
mcai8sh4's Avatar

I like the fact that everything isn't just done for us. It helps us (or me anyway) to get a better understanding of what we're doing.

My plan is to finish playing with the led marquee (simple enough to rebuild at a later date) then start playing around with this clock example. Once I'm happy with it I can then look into using LEDS to display the time (eventually I'll prob have to 'flicker' the leds to save on battery life, but I'll worry about this later).

Regarding the amount of detail your giving us, I think it's about right. I certainly don't understand everything I've done yet, but I'm seeing results, so I'm happy to continue. Anything that needs more explanation is always answered quickly once the question is asked.

I like the look of the new display, I think I may have to order one of those, and another MCU and bits so that I can have a couple of things running at the same time (plus it makes the shipping more economical).

Keep up the great work.

April 27, 2009
by DonNYC
DonNYC's Avatar

Thank you. Thank you. Thank you.

This is just what I need.

I will post my project/code when I get it working.

Beerbot here I come!

May 02, 2009
by smolnn
smolnn's Avatar

Hi Mike,

Thanks for the project and the code. It delivers the clock functionality, but drains more power what can be done with putting the device in power-save and running on lower frequency. (For any long term home automation project.) What I was trying to ask is the following: I have seen this:

http://www.avrfreaks.net/index.php?func=viewItem&item_id=64&module=Freaks%20Tools

http://www.avrfreaks.net/index.php?module=Freaks%20Files&func=viewFile&id=24&showinfo=1

The point is that this puts the device into powersave and using only a ~32kHz clock crystal for counting and runs the microcontroller on 4MHz. According to the DataSheet ATMega168 also contains an RTC module, so the idea should work. But for that the internal 8MHz oscillator should be utilized (as we have only pins 9, 10 available in PDIP housing) which requires some "fuse" bits to be reprogrammed, and the linux utility was not capable to reprogram those "fuse" bits (or at least I was not able to do that and was not sure exactly how to approach this). (ATMega data sheet table 27-7. page 289)

Do you think it is possible to reach this complexity with the provided tools? (Especially without loosing the microcontroller for a total bootloader refresh? As I understand this can be a danger.)

Regards, Stephen

May 02, 2009
by wayward
wayward's Avatar

This is exactly as far as I got with my Vicious Alarm Clock project some time ago; I wanted to drop the external crystal and get two more IO pins by using the internal oscillator. The MCU would of course run in power saving mode, waking up only on interrupt from the external RTC, to update the display and to sound the alarm. The problem is that we can't reprogram the fuses with the programmer we got with our NerdKit; we'll need a more involved one.

May 04, 2009
by digiassn
digiassn's Avatar

Any standard DAPA for the AVR should allow for programming the fuses, and the bootloader code and makefile that sets your fuses is already included on your Nerdkit CD, which seems to work better than other bootloader code I have found. Do a search for "AVR DAPA" or "AVR GCC DAPA" and you will find the schematics. I did a similar setup, although mine is a little different due to some other features that I have added for power and status indicators.

Keep in mind, if you change the clock speed, you will need to make sure you adjust accordingly in some of the libraries, such as the delays, otherwise your timing will be off. I'm also not sure off hand, but that might affect the USB ISP as well.

November 21, 2010
by JackScumm
JackScumm's Avatar

Hi,

I wonder if any of you could help me with my problem. I'm also making an alarm clock by using the real time clock tutorial as a starting point. My problem is that I get a drift of approx. 1 minute / day. That is my alarm clock runs too fast. Since I don't want for variable the_time to overflow (as described in the comments of the code) I reset it to 0 after it reaches 100. Could my that cause my problem?

Regards /Jack

November 21, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

Hi Jack,

That might be the problem depending on how you handled the resetting to zero. If you post the relevant snippets of code you modified we might be able to help you find an issue if there is one.

Humberto

November 27, 2010
by JackScumm
JackScumm's Avatar

Hi,

Here is the code that resets to zero.

void add_time() {

    while (the_time > 100) {
        seconds++;
        the_time = the_time - 100;

        if (seconds == 60) {
            minutes_r++;
            seconds = 0;
        }

        if (minutes_r == 10) {
            minutes_l++;
            minutes_r = 0;
        }

        if (minutes_l == 6) {
            hours_r++;
            minutes_l = 0;
        }

        if (hours_r == 10) {
            hours_l++;
            hours_r = 0;
        }

        if (hours_l == 2 && hours_r == 4) {
            hours_l = 0;
            hours_r = 0;
        }
    }
}

What I'm aiming at is to keep track of seconds and from that calculate minutes and hours. hours_l is the left hour digit on a 24 hour digital display, hours_r the right digit. Same with minutes.

December 18, 2010
by JackScumm
JackScumm's Avatar

Just a short follow up question. Should the crystal be accurate enough for building an alarm clock?

December 22, 2010
by mrobbins
(NerdKits Staff)

mrobbins's Avatar

Hi Jack,

I've never tried measuring the clock frequency over a long time period like a day. However, an error of 1 minute per day suggests an inaccuracy of 0.07% in clock frequency, or roughly 700 PPM (parts per million). Check out these crystal datasheets (we haven't always been using this specific crystal, but I believe that they have similar specs). It suggests a tolerance of roughly +/- 30 PPM, which is about +/- 2.6 seconds per day.

Now, I haven't tried measuring this, but the solderless breadboard does add some "parasitic" circuit elements like capacitance and inductance which might shift the frequency a bit, although my intuitive guess is that this would make it slower and not faster.

I am assuming that the add_time() function is not called from within an interrupt handler. In this case, there's possibly some strange things happening with this line:

the_time = the_time - 100;

Basically, this gets compiled to a set of instructions which first copy the_time from SRAM into registers, then subtract 100, and then copy the result of the subtraction back into SRAM. In total, I'd guess that's probably 12 to 20 CPU cycles, since the_time is 4 bytes wide. What happens if the realtimeclock timer interrupt (and specifically the_time++) happens during that code? If it happens during the time after it's been copied to registers and before it's completely copied back, then that timer increment is going to get lost. So, just guessing, but there are probably 10 to 15 CPU cycles each iteration of add_time where you're vulnerable to missing a tick.

The solution looks like this:

cli(); // disable global interrupts
the_time = the_time - 100;
sei(); // enable global interrupts

Now, the interupt is not able to fire for those CPU cycles. It's important that the code between the cli and sei is very short so that once sei is fired, the CPU will jump to the timer interrupt that would have happened there.

However, I will admit two things: first, this will happen very rarely or maybe even never. If it were randomly distributed, then you've got maybe 14 vulnerable cycles every second, or a 1 in a million chance of losing a tick each second. (Of course, it probably isn't randomly distributed, and could be happening often.) Second, if anything at all, this would make your alarm clock appear to run slower, not faster as you describe.

Mike

January 23, 2011
by acbp
acbp's Avatar

Hey guys,

Im gonna try to build an A/C thermostat and the first part I need is to set up a timer. Im using the realtimeclock code but I need to display in D/H/M format. I tried to use the codes above but I couldn't make it work so I came out with a simple solution with formulas. Im not an engineer and never programmed in C++ before, Im a business analyst but have some knowledge in electronic.

What I do need now is to reset the timer back to zero after 7 days which is gonna be 604800 seconds. I also need to know how can I set up an event at certain time to activate or deactivate a pin of the processor according with a pre-set time in seconds. Can someone help me with that?

Here is the code I came up with, I just changed the display settings at the end:

while(1) { lcd_home(); lcd_write_string(PSTR("Tony")); lcd_line_two(); fprintf_P(&lcd_stream, PSTR("%.0fsec"), (double) the_time/100.00); lcd_line_four(); fprintf_P(&lcd_stream, PSTR("%.0fd %.0fh %.0fm %.0fs"),(double) floor(the_time/100.0/86400),(double) floor(the_time/100.0/3600)-floor(the_time/100.0/86400)24, (double) floor(the_time/100.0/60)-floor(the_time/100.0/3600)60, (double) the_time/100.0-floor(the_time/100.0/60)*60); }

Thanks,

Tony

April 11, 2011
by JackScumm
JackScumm's Avatar

A few months has passed, but I finally found the cause of my problem. It seems that I need to put capacitors between the crystal legs and ground. With that and Mike's suggestions to disable and enable interrupts I now have a clock that runs very accurately. The info about the capacitors is right there in the data sheet. Maybe I should RTFM next time...

/Jack

Post a Reply

Please log in to post a reply.

Did you know that a NerdKit can be used to build an iPhone-controlled R/C car? Learn more...