safe way to prevent millis() wrap?

like every 59 49 days or whatever

What's the command to set millis() back to zero?

If you do the math and comparisons in a certain way it isn't necessary to reset millis. Post the code that has you concerned.

When we only care about time intervals, overflow can be used to our advantage as the simple arithmetic difference between two sampled time intervals will remain correct irrespective of overflow.

In the code snippet below, millis() gets truncated to a 16 bit unsigned quantity which will overflow every 65'ish seconds. The calculated time difference however will remain correct as long as LOOP_INTERVAL is less than half the overflow period (32 seconds or so).

// Synchronization loop for short intervals (less than 32 seconds)
#define TimeLap(t1) (int)((word)millis()-(word)t1)
#define LOOP_INTERVAL 1000 // One second

void loop()
{
  static word loop_time;
  
  if (TimeLap(loop_time)>=0) {
    // time synchronized code goes here
    loop_time+=LOOP_INTERVAL; // schedule next run
  }/*if*/
}/*loop*/

Applications that run idle for longer intervals (more than half a minute) should use the full 32 bit millis() value. This version works equally well for short intervals, but consumes more resources than the alternative above.

// Synchronization loop for long intervals (more than 32 seconds)
#define TimeLap(t1) (long)((unsigned long)millis()-(unsigned long)t1)
#define LOOP_INTERVAL 60000 // One minute

void loop()
{
  static unsigned long loop_time;
  
  if (TimeLap(loop_time)>=0) {
    // time synchronized code goes here
    loop_time+=LOOP_INTERVAL; // schedule next run
  }/*if*/
}/*loop*/

The code I'm concerned about is millis() + 1000 exceeding the range of the variable.

I'm doing a one-shot fuse, not looping for pacing code in even intervals.

I do this at the end of setup():

fuse = millis() + 1000;

...

Then, in loop() I have an if statement comparing fuse to current millis(). When millis() exceeds fuse I put the CPU to sleep.

I'm lazy and don't want to do a bunch of conditional logic checking for boundary cases of millis(). I just want to whack millis() to zero in place of setting fuse. Then in my loop() code, I'll just use
if ( millis() > 1000 )...

Anybody know how to whack millis() ?

Anybody know how to whack millis() ?

Yes but "whacking millis" will be implementation dependent. In other words, at any point in the future it may stop working because the folks who work on the Arduino core may change the implmentation. I strongly suggest you do something like this instead...

unsigned long fuseStart;

void setup( void )
{
  fuseStart = millis();
}

void loop( void )
{
  if ( millis() - fuseStart >= 1000 )
  {
    // Sleep here
  }
}

In this code I assume the processor will never wake from sleeping. If that isn't the case it will need a change.

Your code snippet illustrates my point, it breaks when millis is near the top end of it range. You'll end up getting a huge negative number in the comparison and it will never trigger... er ah, well in 49 days it will trigger.

So, given Arduino v0017, what's the commands to whack millis ?
I'm running on a 328P chip.

it breaks when millis is near the top end of it range

If you can prove that you're correct, I'll give you the snippet of code to reset millis for Arduino 15 and I'll download and install Arduino 17 to ensure the snippet is still valid.

The code I'm concerned about is millis() + 1000 exceeding the range of the variable.

.. and that's what you got a solution for.

If you need to time an interval between sleep cycles, the code would read as follows:

// Synchronization loop for short intervals (less than 32 seconds)
#define TimeLap(t1) (int)((word)millis()-(word)t1)
#define LOOP_INTERVAL 1000 // One second

void loop()
{
  // first sleep cycle after 1s
  static word loop_time = LOOP_INTERVAL;
  
  if (TimeLap(loop_time)>=0) {
    // put Arduino to sleep here
    loop_time=(word)millis()+LOOP_INTERVAL; // schedule next sleep
  }/*if*/
}/*loop*/

BenF - aha! With all that type casting I must have missed the fact you are working with the least significant bits of the counter by truncating it.

For what I need to do, I think I have to move the following lines of code you show up to setup() so it only runs once, and get it out of the loop.

// first sleep cycle after 1s
static word loop_time = LOOP_INTERVAL;

What I see happening here is the first interval is not likely going to be a whole interval, but thereafter, I'll get the full 1s. This means a glitch on the first cycle.

My application sleeps mostly. External interrupt button wakes it up, it does something, then stays awake for a short period of time listening for a response which may or may not come, then goes back to sleep again. So it's more of a one-shot timer per run, than a cyclic design. Timing that first cycle, or one-shot, is the most important cycle.

Anyway, I get the message of ignoring millis() boundary conditions if you play in a safe zone of lower bits only. I'll play with this idea.

It would be far easier to whack millis to zero for me, so if that secret is revealed shortly, I'll be in good shape.

For what I need to do, I think I have to move the following lines of code you show up to setup() so it only runs once, and get it out of the loop.

// first sleep cycle after 1s
static word loop_time = LOOP_INTERVAL;

Actually - no. The "static" keyword makes "loop_time" the equivalent of a global variable with a one time initializer. The only difference is that the scope (visibility) of the variable is limited to the loop function. If you need a different first time interval - you just keep the code as is, but change the following:

// first sleep cycle
static word loop_time = FIRST_RUN_INTERVAL;

Even if it's static, won't the next iteration of loop overwrite it?

I think I found my own answer, reading code tells all.
Here is the variable declaration Arduino uses to persist millis:
volatile unsigned long timer0_millis = 0;

So I presume this is how I'd whack it, in my code:
timer0_millis = 0;

So my problem is reduced to this:

setup()
{
// quiesce chip features, change I/O pins, and enable power saves
// setup external interrupt buttons (low level interrupt)
// sleep here (power down mode)
// wakes up here
...
// setup the way I need things
// do my job (transmit information - one shot)

timer0_millis = 0;
}

loop()
{
// listen for echo (if serial.Available() > 0)...
...
if ( millis() >= 1000 ) {
// reset (jump to address zero)
}
}

So what I don't understand is why you want to prevent the wrap in millis() vs the easier solution where you could just accommodate in your logic for the fact that it does wrap.

/quote So what I don't understand is why you want to prevent the wrap in millis() vs the easier solution where you could just accommodate in your logic for the fact that it does wrap. /endquote

Where's the sport in that?

I think you'll agree the code I just posted above is about the easiest thing that can be done here with a one-shot use of a time, that happens to hinge on using millis(), a timer is already built in arduino base.

I'll agree that I'm not using millis() for the purposes it was intended to be used. But so what? I don't need to have running uptime in my application. If arduino provided a general timer library, I'd use that instead. I'd prefer to have a countdown timer and set its value in milliseconds, and then check it for zero.

This is the closest thing to that.

So I presume this is how I'd whack it, in my code:
timer0_millis = 0;

That is NOT correct. Your code suffers from a race condition that will eventually corrupt the value of timer0_millis.

I think you'll agree the code I just posted above is about the easiest thing that can be done here with a one-shot use of a time, that happens to hinge on using millis(), a timer is already built in arduino base.

Except for the fact that the code you posted won't compile because timer0_millis isn't in scope where you're trying to zero it out. And the fact that mucking about with the the state variables used by millis() is a bad idea because it is very likely to break any other library functions which rely on millis() working correctly... And the fact that zeroing a long isn't atomic so even if the code you posted DID compile the results you'd see would be very inconsistent with what you'd expect...

...oh yeah, and just coping with overflow is easy anyways.

Good luck!

No access, scope! Agh. Extern solves that.

But

cli();
timer0_millis = 0;
sei();

makes it a little more atomic, don't you think?

makes it a little more atomic

It does. For what you're trying to do, the code will work.

There's also a flaw that prevents your code from being generally usable. For anyone reading this thread, please take BenF's, Fjornir's, and my advice: don't reset millis. It isn't worth the risks. There's an abundance of ready-to-use one-shot code available in this thread and in the this forum and in the Playground and in the examples and on the internet at-large.

This compiles:

// whack-a-millis

void setup(){
}

void loop() {

extern volatile unsigned long timer0_millis ;
cli();
timer0_millis = 0 ;
sei();

// Groundhog Day

}

If arduino provided a general timer library, I'd use that instead. I'd prefer to have a countdown timer and set its value in milliseconds, and then check it for zero.

C.Badly, "There's an abundance of ready-to-use one-shot code available in this thread and in the this forum and in the Playground and in the examples and on the internet at-large." You're a very elusive poster... holding secrets back... if you know stuff, post stuff / links. Save me from shooting my foot off! Thanks.

I just found MsTimer2 in the playground, this should also work for my case.

#include <MsTimer2.h>

//declare a software reset function, begins execution at address 0
void(* resetFunc) (void) = 0;

setup()
{
// quiesce chip features, change I/O pins, and enable power saves
// setup external interrupt buttons (low level interrupt)
// sleep (power down mode)
// wakes up here
...
// setup the way I need things
// do my job (transmit information - one shot)

MsTimer2::set(1000, resetFunc); // set fuse length 1s on "reset bomb"
MsTimer2::start(); // light the fuse

}

loop()
{
// listen for echo (if serial.Available() > 0) and act on it

// ..when the time is right (as a background process) MsTimer2 calls reset
}

Much cleaner. Pretty much exactly what I want but better! I don't even have to check for zero, that runs as a background task.

using millis method for my program makes it:
Binary sketch size: 3860 bytes (of a 30720 byte maximum)

using MsTimer2 instead makes it:
Binary sketch size: 4214 bytes (of a 30720 byte maximum)

10% bigger! Sure this uses much more code space that twisting millis, but I'm only using around 14% of my 328P, so I'm not needing optimization at this juncture.

It turns out the safest way to prevent millis() from wrapping is not to play that game at all.