Time one minute: Need some Math help -- please

Hi, I am struggling with this. Just too old I guess, but can’t seem to get my head around it.

I have the following code waiting for one minute a lot of times. I have just run it with “adj = 0;” and after 172 minutes (2h:52m:0s) I timed it as 2h:52m:15s. Not a lot but this could be running for twenty hours or more and that’s about two-minutes of error.

How do I calculate “adj” to to minimize that error? I can live with a few seconds error after twenty-hours, but not two or three minutes. The functions that call waitOne… take differing times to complete their inner tasks so I need to time say a thousand cycles or so to find that time, then adjust “adj” in the waitOne call, to give me almost perfect minutes.

If one call is supposed to take 17h:34m:0s and I time it with a stopwatch as 17h:36m:43s, or 17h:31m:12s etc. How do I calculate what “adj” should be to do that?

``````// It's called in several places but never i uses by more than one function at a time.
void loop() {
for (uint8_t i = 0; i < 2300; i++) {
waitOneMinute(false,0);
//  Do something
}
// Other stuff here
for (uint8_t i = 0; i < 900; i++) {
waitOneMinute(true,0);
//  Do something
}
...
}

void waitOneMinute(bool doTemp, uint16_t adj) {
uint32_t aMilli = 0;
uint32_t aMin = millis() + (60 * (1000UL + adj));
do {
aMilli = millis();
if (aMilli % 1000 == 0) {
lcdTicker();  // Flashes "*" every second on LCD
}
if (doTemp) {  // will turn on/off to maintain temp
if (aMilli % 5000 == 0) { // Had to use "aMilli" as "millis() % 5000 == 0"
tempCheck();                 // didn't work reliably
lcdUpdate(-1);               // Shows Countdown on LCD
}
}
} while (millis() < aMin);
}
``````

Thanks

The error is 172.25/172 = 1.0015, or about 0.15%, which is expected for the lousy resonator on the Arduino.

Since the clock is running a bit slow, instead of 1000UL you could try using 999UL as “1 second”, but such adjustments are pretty coarse.

Two options are to buy an Arduino with an accurate crystal, rather than a resonator, or use an external Real Time Clock module (RTC).

Thanks for the detail. The Arduino is currently embedded in a bread-machine, but will look for something with a crystal if it has the same pin-set as the Nano.

I doubt I can use an RTC as very short of spare pins and memory, currently 79% and just holding.

On an Arduino with I2C, an RTC will use only those two pins (and if it's already using them, you can still add another I2C device, as long as it has a unique address. I have recently made an hourglass device, and I define "one second" as 1000000 microseconds. Then by varying this number, the time rate is adjusted. Right now it's accurate to within 20ppm, with no RTC.

I have the following code waiting for one minute a lot of times.

Never wait never delay!

Just let loop go round and round and check if it is time to do something. After all what the fick else has the CPU got to do!

Mark

ChrisTenone:
On an Arduino with I2C, an RTC will use only those two pins

Thank for the info, will try the "second" thing you mention. As to adding the RTC, I'd have to disassemble a lot of the machine to solder it in. The waitOneMinute seemed to work on the breadboard for longish (6-hours+) delays, but it wasn't until it was in the machine and waiting 20-hours the problem arose.

holmes4:
After all what the fick else has the CPU got to do!

Well, looking at my code for waitOneMinute you will see the CPU has a lot to do for each iteration.

flash a ticker on/off every second
checkTemp
update LCD etc

they all take finite time each time they are called.

If you have a better way then please offer some code, as flippant comments are of no help.

If you have a better way then please offer some code, as flippant comments are of no help.

We recommend careful study of the "Blink without delay" example provided with the Arduino IDE.

Then move on to the "How to do several things at once" examples linked here.