A precise source of "1 hz" ? - alternative to RTC

I have a project where the microcontroller (leonardo) I would like it to be correct to calculate very precise mAh. (having very precisely calibrated voltage and current sensing at high resolution)

I could use a RTC, but it's a huge overkill as I do not require actual time - only good definition of "1s" - which could be picked up by an interrupt.

Till now I've corrected it a bit by increasing "second" at less than 1000 millis()

Hi AndreK,

I assume that since you don't want to use an RTC, then using a GPS 1PPS would be over-overkill.

What accuracy are you looking for? You may be able to use an external crystal to control the Leonardo clock, or a crystal circuit to drive an interrupt-sensing input.

Pat.

Till now I've corrected it a bit by increasing "second" at less than 1000 millis()

What?

How much accuracy do you need? Unless something is badly-wrong, millis() should be far-far more accurate than your voltage (or current) measurement. The built-in 10-bit ADC has a resolution of about 1/1000, whereas the clock frequency error should be in the parts-per-million range.

Just make sure that you are calculating elapsed time by taking the direct millis() (from the time your processor was reset) or by subtracting Ending millis() from Starting millis() so that errors don't accumulate.

Or use micros() for more stable 1s.

first I used to wait for millis to be 996 - that resulted in +5 sec after about 7.5 minutes. - so I did the math , and reduced it to 985 , then it was about 4 sec ahead after 7 minutes.

I tried to reduce that as some of the battery tests are >4 hours (for realistic discharge rate)

As for the voltage and current, I get it from an 16bit ADC calibrated against calibration source (like 2.5000 and 10.0000 volts) DA step size is 0.000025234V/bit
the load is controlled by a 12bit ADC (for linear operation - not PWM) - so that's why I currently think of clock as the next thing to improve .

Hi,
What is the application that requires that sort of precision and accuracy to calculate mAh?

If you are trying for such tight resolution and accuracy I cannot see the reasoning behind not using a RTC module.
It seems like a lot of work to do what a less than $1.00US item can do, no overkill about it.

Tom... :slight_smile:

AndreK:
As for the voltage and current, I get it from an 16bit ADC calibrated against calibration source (like 2.5000 and 10.0000 volts) DA step size is 0.000025234V/bit

On a completly static\stable voltage, how much does the 16bit AD reading vary ?

srnet:
On a completly static\stable voltage, how much does the 16bit AD reading vary ?

connected to the calibration source, it's actually no variation, sometimes it may change +/-1 on the ADC value, but is usually steady >10seconds a time. - guess it depends how borderline it is to switch.

I did not observe it that closely with a battery - the display&logging is only volts+two decimals.

Hi,
Have you tried to measure a battery capacitiy yet, even with dogey 1Hz period, to see if any noise problems with such high resolution?

Tom.... :slight_smile:

TomGeorge:
What is the application that requires that sort of precision and accuracy to calculate mAh?

It's to measure actual mAh / Wh of batteries, such accuracy is not really needed, but when I do something, I often overdo it a bit. :slight_smile:
The only reason avoiding RTC is not cost, but rather the small housing I printed for the Leonardo+PCB+4x20 display (load modules and balancing connector is outside.) I can jam in a RTC,(removing battery connector) it would just be nicer with something smaller :slight_smile:

consider problem solved :slight_smile:

noise it's not a problem. - and the arduino does not run from the same power it's testing.
the tested source is only loaded by a transitor and resistor - not using PWM, but 12bit DAC to drive it.

Hi,

Reprint your housing, as you say you overdo things, so reprint to get perfection.

Tom.... :slight_smile:

If you're in the UK, over time, 50Hz mains is extremely stable

I've used a 4060 CMOS oscillator/divider, together with a 32.768 kHz crystal to generate a 1Hz signal.

However by the time you have built the circuit it is not going to be any smaller or cost efficient than buying an RTC module

AndreK:
first I used to wait for millis to be 996 - that resulted in +5 sec after about 7.5 minutes. - so I did the math , and reduced it to 985 , then it was about 4 sec ahead after 7 minutes.

Without seeing your code, I'm guessing you have a coding issue that is causing timing errors to accumulate. The proper way to implement this is discussed in the thread Demonstration code for several things at the same time. It's really unlikely that a crystal controlled oscillator is off by 1.5% over a period of minutes. If you had a board with a ceramic resonator, that would be plausible.

AndreK:
Till now I've corrected it a bit by increasing "second" at less than 1000 millis()

Do you make a difference between an "UNO R3" and a "LEONARDO?

While "UNO R3" boards provide a very inaccurate internal clocking, because they usean relatively inaccurate "ceramic resonator"for clocking the controller, the internal clocking of LEONARDO boards are much more accurate!

LEONARDO boards use a "crystal oscillator" instead a "ceramic resonator", because they need it for their USB driving capabilities.
So LEONARDO clocking might be 80 times more accurate tthan UNO R3 clocking.

This is not accurate enough?

So please tell: How accurate do you need the one-second-timing, actually?

MrMark:
Without seeing your code, I'm guessing you have a coding issue that is causing timing errors to accumulate

Yes, I do quite a few of those:

 if (millis() - millisSEC >= 989)  {
    millisSEC = millis();

will need to fine-read the thread you mentioned to try to understand exactly why that might be bad - I see no obvious reason beside the few cycles lost between comparsion & copy but I assumed it is too few to be noticible)
(I did not see how the assembly look and count the cycles per operation) - but that should be easily offset by using a lower number, like a do.

Leonardo with 16MHz crystal oscillator (shown in documentation, KX-7, ±50ppm)
Should be able to use a timer and interrupt to get 0.005% timing accuracy for mAh measurements.

Example 1mAh:

0.99995 mAh (-50ppm error)
1.00000 mAh (0.0ppm error)
1.00005 mAh (+50ppm error)

Need better than this for error due to timing? What accuracy and precision do you need?

AndreK:
Yes, I do quite a few of those:

 if (millis() - millisSEC >= 989)  {

millisSEC = millis();





will need to fine-read the thread you mentioned to try to understand exactly why that might be bad - I see no obvious reason beside the few cycles lost between comparsion & copy but I assumed it is too few to be noticible) 
(I did not see how the assembly look and count the cycles per operation) - but that should be easily offset by using a lower number, like a do.

Well there's your problem!

Do this instead:

 if (millis() - millisSEC >= 989)  {
    millisSEC += 989;

millis() does not always increment by 1. Because it actually ticks slightly slow (1.024 ms, 976.6 Hz), the millis algorithm keeps track of the cumulative error and will increment by 2 when the error reaches a certain threshold. This happens every 41-42 ticks.

Incrementing by the interval size will keep your task on the correct average interval rate, even if there will be some jitter. Assigning the new millis value like you were doing will slow down the average rate of the interval.

I am a little late to this thread, but how would you know if you had exactly 1 HZ?

Paul

Use micros() for timing, it doesn't skip like millis().