I intend to use power-down sleep mode. When sleeping, the current value of millis is frozen. Therefore, if we know exactly how much time passed during sleep mode, we can adjust millis() as desired.
The proposed function is a good approach but I still need to change many existing programs that are migrating from non-sleep to sleep mode. Probably, I will go in this way if there is no way to direct change the variable used by millis().
Inspired by your question I wrote a simple StopWatch Class based upon millis(), See - Arduino Playground - StopWatchClass . It will not work for your question but nevertheless I thought you might be interested.
If you have a look at wiring.c, you'll see that millis() reads variable timer0_millis. If you take the right precautions you can update this variable. I've amended my SleepDelay library to do this and I'm currently testing it out. So far, it seems ok but I'm going to test it for a few days first.
If you have a look at wiring.c, you'll see that millis() reads variable timer0_millis
timer0_millis is only part of the value. The other part is the timer itself. It is extremely difficult to change the millis value without introducing an offset.
Kind of off thread, but it's funny how frequently people ask or want to be able to preset a value for millis(), seems to be a very popular request. And while I'm certainly not a guru software type, none of the reasons given for needing this seem to not be better handled in a different and better matter?
@Lefty
One of my CS teachers told me that software is made from the same the stuff dreams are made of, if you can dream it you can make it
The "problem" is often that people don't have a formal training in algorithmic - OO or realtime design which often leads to "if the only tool is a hammer, every problem is a nail" thinking. A very common pattern. People have a timing problem, they know millis() is about time, so millis() can/should solve it, and often it just can solve it, but sometimes not. Even knowing this pattern I find myself doing it too
If you change timer0_millis without also considering TCNT0 and the hidden / unreachable value within the timer, your change introduces an error into the millis value (an offset from the correct value).
...
#include <Wire.h>
...
// timer0_millis can change inside the ISR process for timer0
// 2 options: disable interrupts OR make 2 consecutive readings and
// compare. I am using the second option here:
unsigned long reading1;
unsigned long reading2;
boolean readingOK = false;
int k=0;
while (k<1000 && !readingOK) {
reading1 = timer0_millis;
reading2 = timer0_millis;
if (reading1 == reading2) { readingOK = true; }
k++;
}
timer0_millis = 2000 + reading1; // e.g. 2000: time elapsed while sleep
nint++;
Serial.print("Going to sleep. Count # " );
Serial.println(nint );
Serial.print("Time: millis() " );
Serial.println(millis() );
delay(2); // wait until the last serial character is send
It completely solved my problem. There is a small error in the process. However, if the process is always the same after returning from sleeping, we can determine its value with great accuracy and adjust.
may you help me to understand better the issues you mentioned? I tried to run the code for hours, and it continue working.
Sometimes, the comparison returns false and it is probably caused my the "on going" modification of the variable. But, I only realize the mentioned operation just after the "true", that is after the modification if this is the case.