Apologies if this is a FAQ - I have looked on this forum and elsewhere but haven't yet found an answer that isn't bogged down with the details of individual projects.
My need is simple . I want to read a temperature sensor and log the reading alongside a timestamp. So far, in mangled C/Arduino pseudocode:
unsigned long seconds=0;
float t;
loop()
{
led_on();
t=read_temperature();
led_off();
Serial.printf("%lu %.2f\n",seconds,t);
delay(1000); //1 second delay
seconds++ ;
}
Of course it doesn't work because the actual loop() time is the sum of led_on() , read_temperature(), led_off(), Serial.printf() and delay() plus overheads. So a 'second' is more like 1.2 seconds.
I'm wondering if I can improve things by using millis() to make a timestamp, but even after consulting the Arduino doc for millis() I'm not sure - is millis() guaranteed to be accurate within the limits of the processor clock?
No, millis() timing is +/- 1ms without slowing the chip down. It's a speed trick, the low 8 bits never count 6 values including xFF to get 250 steps of 1024 us = 256 us with a non-binary clock -- the second millis() byte is true to the bits, the low byte is 'funny'.
If you want accurate, use micros() but be aware that the micros() return advances 4 every 4 microseconds = 64 MCU cycles. That is still 250 ticks per ms with no +/- except clock source... Uno has a resonator instead of crystal and capacitors, temperature affects the precision of micros(), it's like up to 3 or so minutes a day.
I don't know what you need in the way of time but if your code doesn't block void loop() then an Uno can do a few simple things like sense, process, and react >50 times per ms on average while showing you a loop count once a second.
Your loop() turns the led on then off too fast to see.
Nothing will be done with t, the compiler will ignore it.
The delay(1000) blocks. Speed goes from >50K loops/sec to <1K.
Every ms delayed is 16000 lost clock cycles. Is that worth saving?
Does the datasheet (or a library example) for your DHT state the data is ready to read every one second? Usually DHT data is ready to read every two seconds.
The low byte of millis() return Skips 6 Values including 255 to count 250 instead of 256 noting that 250x1.024=256. Bit 8 will toggle 256 ms +/- 0 ms, it's just the low byte that skips values and makes +/- 1 ms.
If mills() never skips a count, then if you write a tight loop comparing millis() to the last observation, the difference will never be greater than 1. If it ever skips, the difference will be greater than 1.
If you are saying about the drift in the exteranl "ceramic resonator" of UNO R3, then I would say that this is not accurate as accurate the crystal is.
part of the question was is millis() not accurate because it counts 1.024 msec clock tics instead of 1.000 msec clock tics, or because it doesn't have a very accurate time base, a resonator instead of a crystal, or both.
it seems the biggest source of error is the lack of a crystal.
and then the question is how inaccurate is it ... that link said ~1.7 sec /day. is that accurate enough for your application?