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.

Basic Electronics » Clock Accuracy

January 09, 2010
by carlhako
carlhako's Avatar

Hi

I have been playing around with the nerdkit for a couple of weeks now. My first project im building an alarm clock. Im starting with basic functionality displaying the time! I have some 7 segment led displays im using to show the time. Ive used the code from the "Crystal Real Time Clock" tutorial to output seconds to the display as a starter. Ive got this working ok. Now to my question how accurate is this clock? My code that updates the display has a 5ms delay in it because the microprocessor was updating faster than the mosfets could switch the circuit. Will this put my time out by 5ms every loop? using "#include "../libnerdkits/delay.h" and delay_ms(5); or will the clock counter inside the cpu count every cycle regardless of what the code is doing?

the basics to be circuit design is currently using 2 displays. 2 n mosfets turn each display on 1 at a time, using 7 more mosfets for each segment, updating 1 then the other inside a loop. this allows me to add on more displays by using 1 pin each. I did try using a n and a p type mosfet together to use 1 pin to control 2 displays but i had problems where the different type of mosfet has a different resistance causing the displays to be different brightness.

couple of pics 1 2

Thanks

January 09, 2010
by Rick_S
Rick_S's Avatar

From my experience, you may see a bit of lost accuracy, not from the program so much as much as from the crystal oscillator itself. It has been explained to me that crystals of the type used for cpu clocking are not as accurate as those for time keeping. If programmed correctly you can expect to see anywhere from an ultra precise clock to one that is off a few seconds here and there.

On another note, when multiplexing led displays, you don't need to put a mosfet at each of the segments. In your case, (two displays), all you need is two mosfets. One to control each of your common anodes. (some would debate even the need for those two) As in the case of the ledarray, there are no resistors or mosfets controlling the display. (Personally for this type of application, I normally use both... but that's just me and I'm definitely NOT and expert :) )

If you are looking for examples, HERE is a link to a kit to build a clock using an ATmega168 with 4 segment LED display. They have links to their schematic and C code. That may get you pointed in the right direction.

Rick

January 09, 2010
by carlhako
carlhako's Avatar

Thanks Rick

Ill continue with my project and see how accurate it is at the end before worrying about it any more. I had a look at that link and the schematic link basically they are driving the leds right off the MCU and inside the display i guess it has mosfets on the common grounds to switch the individual displays.

Im not sure that that will work for me as my display units share a common positive and have separate earths. I will have a fiddle with the wiring see what i can do.

January 09, 2010
by BobaMosfet
BobaMosfet's Avatar

Actually crystals are generally more accurate than tank circuits or other oscillating means. Particularly full-swing crystals operating at or near their fundamental frequency.

The NK staff has actually provided surprisingly high-quality clock crystals, meeting the above description. I have tested several of these on an oscillosocope and found the following:

Frequency: 14.75MHz (steady) Amplitude: 4.663V RiseTime: 19.1ns.

You can probably create a relatively accurate realtime, interrupt-driven (and I do mean really good), software clock on this MCU with a base resolution of 5us. Any smaller than that isn't really feasible due to how the MCU works, instruction timing, algorithm overhead, interrrupt overhead, etc.

It's something I'm toying with now.

January 09, 2010
by BobaMosfet
BobaMosfet's Avatar

I need to clarify a couple of points on my last post.

The crystals that the NK staff provided are clocking at 14.745Mhz (steady)... the "14.75MHz" was a typo I didn't see until now.

Using the prescaler, you can actually get a resolution 500ns. However, that leaves only 7 free clock-cycles between such events-- so it is somewhat impractical. I have figured out a way to have an accurate 1us clock, but it means everything must be written with 'real-time' in mind (ie. interrupt driven), keeping in mind the ISR limitations the chip has.

If you clock it at 20MHz, there are more cycles available, but you also have to make changes to the nerdkits library to do your application upload/downloading due to the 115,200bps design discussed elsewhere on the board.

January 09, 2010
by Rick_S
Rick_S's Avatar

Thanks Boba, I was basing that on my experience with a 12mhz crystal and a mega8 I had. I'm glad to know the cyrstals provided are pretty accurate. My experience may have been me, but the info I gave was based on some that was given to me in another forum at that time. Maybe I'll have to give a clock another go...

Rick

January 10, 2010
by mrobbins
(NerdKits Staff)

mrobbins's Avatar

As to carlhako's original question: the delay_us and delay_ms functions are not particularly accurate, especially if they are interrutped by any running interrupts. However, take a look at our Crystal Real Time Clock video for a interrupt-based, accurate 0.01s resolution clock. This will probably be useful in the construction of your alarm clock!

Mike

January 11, 2010
by carlhako
carlhako's Avatar

Thanks Guys I used the Crystal Real Time Clock code as a basis i have it just counting up from 0 to 99 in an endless loop. I am currently assembling the led array kit this is teaching me some better ways of lighting multiple leds rather than using all these mosfets.

http://pastebin.com/f5a641ec5 <-- thats the code im using sorry not many comments in the bits ive changed.

January 11, 2010
by carlhako
carlhako's Avatar

Just to clarify my original question when using the internal clock and an interupt that fires every 100ms does this always happen regardless of what the cpu is doing e.g. processing some math or stuck in a loop or something. To answer my own question it doesnt matter what your code is doing the interupt takes priority and will execute straight away.

January 12, 2010
by Keith726
Keith726's Avatar

carlhako;

I also was concerned about the accuracy of the completed clock - the MCU has to run the software as well as keep time. I added a separate realtime clock chip, a Maxim DS1302, which uses a serial interface (uses less pins than a parallel interface, but requires more code to communicate with the chip). I am happy with the accuracy of my completed clock (made it for my girlfriend's birthday in October - time is still accurate to the minute (no seconds display) now in mid-January).

January 12, 2010
by Keith726
Keith726's Avatar

Addition to my previous post: The Maxim DS1302 Real Time Clock (RTC) uses a its own crystal, a standard 32.768 kHz clock crystal. I'm a n00b, but from what I've read from application notes by Maxim and Atmega, the main problem with crystal accuracy is temperature - the output frequency varies with temperature. Maxim has a chip that combines the 32.768 kHz crystal with a thermometer, and does temperature compensation to give accurate frequency. I intend to use that chip as the input to my Atmega's counter, instead of using the main MCU's crystal as the time base. My problem is that our data sheet says that you can't prescale the asyncronous counter, so I guess I'll have to find another way to use this crystal as the base frequency for the clock.

Atmel application note DOC1259 shows how to do this using an Atmel AVR 134, which (I guess) has a RTC module in it.

Does anyone know how to use an external frequency source on the Atmega 168, to generate a 1-second interrupt? Again, I want to keep the crystal-counting separate from the MCU processing so that the resulting clock is more accurate.

January 12, 2010
by Keith726
Keith726's Avatar

carlhako,

One more thing - I don't think you need all of those transistors. The MCU can drive LEDs directly - you can wire each of the 7 segments to a pin on the MCU, as long as your 7-segment display can use 5 volts. You will need the current-limiting resistors on each segment to prevent drawing too much current to each segment's LEDs.

You can use the transistors to switch on and off each 7-segment display in a multiplex mode, displaying the first numeral on the first display, then the next numeral on the next display, etc.

Your small 7-segment LEDs should operate on 5 volts (check its data sheet), and you should be able to drive them directly from the MCU, which is what I do on my clock. I intend to build a larger clock - I bought 2-1/2" LED displays, and that requires more than 5 volts to operate each segment. For that, I will use 12 volts to the display, switching the segments on and off by using transistors: 5 volts signal from the MCU switching 12 volts through the transistors.

January 12, 2010
by Rick_S
Rick_S's Avatar

For the 12volt display, you might try a darlington array like a ULN2803. These are capable of sinking up to 500ma and make for a nice simple connection with multiple LED's. Just a little food for thought...

Rick

January 12, 2010
by BobaMosfet
BobaMosfet's Avatar

Here are some nifty gacts about the crystals in the NerdKits.

The crystal supplied with my NerdKit is an FS1474P. It's tolerance from center frequency (14.7456MHz) is +/-20PPM * 10^-6 at 25C degrees. It's working temperature range is -10C to +60C. It ages, as do all crystals-- so with constant use it will gain or slow down by +/-5 * 10^-6 MHz/year.

January 14, 2010
by carlhako
carlhako's Avatar

Thanks all for the very helpful info, ill first put it together using just the atmega168 with the nerdkits crystal. My other crystals are +/-50ppm accuracy so ill go with nk one. but now im working my way through the led array pdf ive just finished assembly and have the test pattern working first go. Ill post some pics on my clock when i have it displaying the time.

I checked the datasheet on the displays im using they are SA56-11YWA rated at max 2.5v 30ma.

January 16, 2010
by carlhako
carlhako's Avatar

update: I have rebuilt using no mosfets, powering the leds directly off the mcu which is working fine. My problem is actually the accuracy. The code i have written is just a simple counter, displaying seconds and minutes. After 40min it is out by a full second, i am using my wrist watch to compare. Using the stock crystal supplied with as short as legs as possable and as close to the mcu as i can get it.

Here is my code pastebin link

Could somebody please point me to where my time loss is coming from?

January 16, 2010
by BobaMosfet
BobaMosfet's Avatar

Are you losing or gaining time?

January 16, 2010
by carlhako
carlhako's Avatar

Gaining, tested with another crystal rated at +/- 20ppm with same result.

January 17, 2010
by BobaMosfet
BobaMosfet's Avatar

carlhako--

It isn't the crystal. You can realistically stop looking in that direction. "+/-20ppm" is x10^-6 power. Infinitesimally small.

If you are gaining time it is because something else in the program is affecting interrupts. Remember, unless you immediately reenable interrupts in your interrupt routine (as the first instruction) it is possible it might drift. You also need to make sure you don't have any rounding errors in your calculations.

You're going to have to calculate out all your instruction timing, and really dig into exactly what is going on at the clock-pulse level, how long things take, when interrupts are enabled/disabled, etc. Extreme accuracy isn't a trivial endeavor.

January 17, 2010
by Rick_S
Rick_S's Avatar

That's where having a real-time clock chip do the time keeping comes in handy. That way all you have to do is poll the RTC chip and you don't have to worry about timing issues in your program nearly as much.

January 17, 2010
by carlhako
carlhako's Avatar

Thanks for the info Ill hand the time keeping to a separate chip. There are tonns of alarm clock projects out there with source code i should be able to find something to work out how to use the chip.

Keith726 do you mind posting the code you used on your alarm clock? would be very helpful thanks

January 24, 2010
by carlhako
carlhako's Avatar

I thought i would post an update,

I have the clock running now with a ds1302, modifying code I found from a few google searches. I left it run overnight, in the morning the time was spot on. I am currently working on adding some buttons to set the time and change settings as soon as I have them working ill post some new pics and current code. I am planing to have it display temperature as well maybe alternate every second between time and temp, also want to add a humidity sensor but i only have 3 pins left (11-13), not including pin 14. I also have to run a piezo somehow for an alarm, ill learn how to do that from the music from the piezo project.

To free pins ive looked into led drivers you can control them via serial just like the ds1302, im thinking ill have to go into that direction to free up pins. They are also cheap about $5 AU per chip with 40 pins and provide a constant current so brighter, evenly lit leds.

January 24, 2010
by bretm
bretm's Avatar

20ppm isn't negligible. If the crystal is only off by 20ppm that's 1.7 seconds per day. That's fine for a lot of applications and not fine for others. But my own experience with the Nerdkit crystal, at my house temperature, is that it's off by more like 8-10 seconds per day. In my opinion you really have to use something like a DS1302 to make a real clock.

Another approach is to use something like a CMMR-6P which decodes the time signal from the WWVB radio station (for North America users). That's what I did for a New Years countdown clock project, which is counting down from around 29,000,000 right now. The radio signal is often too weak during the day so what I did to compensate for the 14.74MHz xtal inaccuracy was to measure how fast the crystal was actually oscillating during the periods where the WWVB signal is available, and compensating for the inaccuracy with software during the day when the xtal is on its own.

I'm using a 400Hz interrupt and measuring the number of interrupts over 100-second periods. I would expect 40,000 interrupts, but if I measure 40,005, for example, the software will ignore 5 interrupts per 100 seconds during the day. I use an average over all of the good 100-second sample periods I can get during the night while there's a good signal. Note that 40,005 represents an error of more than 10 seconds per day, and it's pretty typical of what I've seen from the 14.74MHz crystal.

The only problem with this approach is that the temperature is higher during the day, so it's not an ideal solution, but so far so good.

The other advantage, and main reason for using WWVB, of course, is that you don't have to set the clock at all--just tell it the time zone.

One tip for using the CMMR-6P is keep the antenna loop away from the LED-switching transistors, and use power-filtering capacitors liberally. The USB/RS232 adapter for in-circuit programming is also very noisy--keep it a good 30cm away from the antenna.

January 27, 2010
by Keith726
Keith726's Avatar

carlhako,

sorry, I've been offline for a while. Glad you found the code for the DS1302 on the Web, and glad you got it up and running.

January 27, 2010
by Keith726
Keith726's Avatar

bretm,

Do you have more info on using CMMR-6P and WWVB?

January 28, 2010
by bretm
bretm's Avatar

Sure. Is there any specific aspect you want more info on? Start with CMMR-6P datasheet and WWVB time code format.

CMMR has one bit per second output, so you just need one AVR pin for it. I set up a pin change interrupt on it, and a separate 400Hz timer-based interrupt. I did 400Hz instead of 100Hz because I'm also strobing eight 7-segment displays 50 times per second each.

When the WWVB signal rises it means we're in the middle of a second, so I just make a note of the duration of the low pulse. When it falls again it means we're at the start of a new second. I look at the duration of the low and high parts of the pulse, and if they don't total close to 1 second I ignore the pulse. You have to allow some wiggle room because of WWVB signal noise, plus timing delays introduced by the CMMR module itself.

If the low and high signal durations add up to a second, I check to see if the low portion was 200ms, 500ms, or 800ms. Once again you have to allow for wiggle room. I've seen short low's that go up to 250ms occasionally. If it's not near one of those values I throw away the pulse.

If the low and high add up to a second and it was low for near 200ms, 500ms, or 800ms, then I count it as a good pulse. If I get two long pulses in a row, I know it's the start of a new minute, and then I start tracking the shorts/mediums/longs according to the WWVB time code format and calculate how many seconds have elapsed so far in the year. I subtract that from the total number of seconds in the year (WWVB provides a leap-year bit) and use that as the current countdown. If I get any bad pulses I throw away the minute and start over.

Every 400 cycles of the 400Hz interrupt, I decrement the countdown by one and update the display.

Actually what I do is call a separate routine that does the actual work. That routine is usually called 400 times per second, but every once I while I skip it, or I call it twice, depending on whether the 400Hz clock is running fast or slow.

Because the duration of an individual second reported by the CMMR is a bit dodgy, I wait for 100 of them to get an average duration and I measure how many 400Hz interrupts I got during that period. It should be 40,000. I keep track of the difference. Then, during each 400Hz interrupt, I accumulate that difference, and once the difference totals 40,000 I skip the update. If I hit -40,000, I perform the update twice.

For example, if I see 40,007 interrupts in 100 seconds, I start adding 7's to a total at each timer interrupt. When the 7's add up to 40,000, which will happen 14.29 seconds or so, I skip one of the 400Hz updates. (If it's -7 then I essentially start at 40,000 and count down to zero, and then do the update twice.) That way I average out to 400 updates per second instead of 400.07.

If that's not already too complicated, I don't actually just use the result from a single 100-second period. For every good 100-second period (100 good pulses in a row) I update a moving average of the differences. I combine 80% of the old value with 20% of the new value, and use that as the actual offset. For example, if the old value was +5.0 and a new 100-second period indicates I should use +7, I update it to +5.4. During the timer interrupt I only use integer math so I also store the rounded value for the real-time calculations.

During the night, while it's getting a strong WWVB signal, the counter is updating itself every minute and it stays in lock-step with the radio signal. During the day when the signal can't be separated from the noise, it's just the 400Hz timer that updates the counter once per second.

I compare the result against this New Year's Countdown web site.

January 31, 2010
by BobaMosfet
BobaMosfet's Avatar

Worst case, with the FS1474P crystal drifting off center tolerance due to temperature as far as it can go: 0.117 (approx) seconds in a 24 hour period. No more. Any other time you are losing, is due solely to your code and your MCU implementation or incorrect tuning of the crystal.

It will only drift from center frequency by about 1.728Hz at 25C, and it's working temperature is -10C to +60C, in which case it will only drift by about +/-20Hz (maximum). Due to aging, it may lose up to 5Hz per year). Above, there was a mention that '20PPM' is equivalent to a loss of 1.7secs per day-- that was incorrect. It isn't 20PPM- that is only PART of the reference equation. Maximum drift at any operating temperature will be less than +/- 22Hz, at any given second.

If you want to regulate the temperature of the crystal, find an LED/bulb/resistor, and measure it's temperature at a given current using some reliable means over an hour in still air. If that falls within the crystal's working range, affix the LED to the crystal case, so that it will maintain the crystal's temperature, then use an oscilloscope to measure the crystal's frequency. Update your calculations to reflect.

If you code carefully, working with the caveats of the way interrupts work with the ATMEGA, you can create a substantially accurate clock that will not lose time over any appreciable period. Certainly not a second or more per day. There are a lot of means you can 'correct' any discrepencies using various circuits or I/Cs if you need more accuracy.

Using the suggestion I've provided for maintaining the crystal at a temperature, you can be able to lose/gain not more than about 1/100th of a second in a 24-hour period. Which means you shouldn't lose/gain more than about 3-4 seconds per year.

And remember, don't drop or shock your crystals, they are delicate.

February 21, 2010
by peabo
peabo's Avatar

There is another solution.

Jacob Rabinow (google him) is the inventor of the self-adjusting spring-wound clock.

In his invention, he imagines that an adjustment of many hours is simply to fix the time.

But an adjustment of only a few minutes must be to compensate for the clock running too fast or too slow, so he arranged that repeated small adjustments would change the rate of the clock. After a while, the adjustments dwindle to zero because the clock is keeping accurate time.

March 23, 2010
by carlhako
carlhako's Avatar

Thanks paebo thats an excellent idea.

I haven't been spending that much time lately on my alarm clock but this is where im at as of last night. It shows the time, you can set the time and i have a menu type system working. I am using a ds1302 for keeping the time and a max7219 for powering the led 4seg display, i used this chip to free up pins on the mcu.

Here is PIC and code

MAIN

MAX7219 Code

DS1302 Code

Hopefully this code can help someone else trying to use a ds1302/max7219.

May 14, 2012
by HexManiac
HexManiac's Avatar

I also had difficulty getting my NerdKit real time clock to keep accurate time, even after trying different crystals, and adding 22pf caps between crystal legs and ground as the ATMega datasheet reccomends, I was still losing about .5s per hour.

I needed to achieve an accuracy better than +- 500ms per day so I came up with this quick and dirty modification to realtimeclock1.c:

SIGNAL(SIG_OUTPUT_COMPARE0A) 
{
    // when Timer0 gets to its Output Compare value,
    // one one-hundredth of a second has elapsed (0.01 seconds).
    the_time++;

    // adjust for inaccuracy
    if(the_time%1000UL==0) // every 10 seconds
    {
        // Change compare value to adjust accuracy:
        // make this < 143 if your clock runs fast,
        // or make it > 143 if your clock runs slow.
        OCR0A = 139; 
        // this value works well for me, been running
        // for more than 34 hours with no significant
        // loss or gain.
    }
    else
    {
        OCR0A = 143; // restore normal compare value
    }
}

My NerdKit RTC has been running for nearly 36 hours now, with no noticeable loss or gain. Close enough to proceed with my project...

HexManiac

Post a Reply

Please log in to post a reply.

Did you know that reading a double floating point variable with scanf requires "%lf" for "long float"? Learn more...