reseting millis()

I am working on a timing function for a light switch and am testing some code to make sure I know how it works. I want to reset the time after a given number of seconds which I thought would be easy but I am still having trouble figuring out how to get it done.
Here is what I have so far.

unsigned long time;
unsigned long last_time;
unsigned long duration;
int reset;

void setup(){
  Serial.begin(9600);
 last_time = 0;
 reset = 0;
}
void loop(){
  
  time = millis();
  
 delay(1000);
 duration = time - last_time;
 last_time = time;
 Serial.print("time ");
 Serial.println(time);
 Serial.print("time between prints ");
 Serial.println(duration);
 if (time > 10000)
 {
 time = reset;
 }
 }

As you can see I am trying to reset time to 0 but when I run it the time just keeps going up.
What am I missing?
Dan

If you're going to cook something on the stove for an hour, you don't set your your time to midnight and wait until 1AM before you take it off the stove, you record the time you started cooking and every so often, subtract it from the current time to determine how long it's been on the stove.

It might be more beneficial to describe, more abstractly, what you are trying to do.

Millis can't be reset. What you need to do is remember when your time period started by storing the value of millis at the time and then working out time elapsed by subtracting current value from the stored value. This is a pretty common technique with timing stuff on computers.

but millis() eventually rolls over to zero again. How do you account for that?

Your clock rolls around to 12 twice a day. How do you compensate for that?

Dodsond:
but millis() eventually rolls over to zero again. How do you account for that?

Very simple, with subtraction:
http://www.cmiyc.com/blog/2012/07/16/arduino-how-do-you-reset-millis/

Unless your desired event timing periods are in excess of 50+ days there is no problem nor concern about the roll-over event. As long as you always subtract (present time - old saved time stamp)then the roll-over will have on effect on your calculation. The subtraction in effects utilizes a 33rd borrow bit to deal with a possible roll-over.

Lefty

I just was not liking the millis() way of turning on my light switch so I went back to my time library. The code seems to be running all right though I havent tested it with the equipment other than the sensors yet (no outputs). My only thing I would like to add is the correct time or at least the correct time of day to the code.
Can't quite figure it out. If there is even a way to manually enter the hour and minute this code would be done.
I would apreciate you glancing at it.

//include the time library, so our garduino can keep track of how long the lights are on
#include <Time.h>

//define analog inputs to which we have connected our sensors
int moistureSensor = 0;
int lightSensor = 1;
int tempSensor = 2;

//define digital outputs to which we have connecte our relays (water and light) and LED (temperature)
int waterPump = 7;
int lightSwitch = 8;
int tempLed = 2;

//define variables to store moisture, light, and temperature values
int moisture_val;
int light_val;
int temp_val;

void setup() {
//open serial port
Serial.begin(9600);
//set the water, light, and temperature pins as outputs that are turned off
pinMode (waterPump, OUTPUT);
pinMode (lightSwitch, OUTPUT);
pinMode (tempLed, OUTPUT);
digitalWrite (waterPump, LOW);
digitalWrite (lightSwitch, LOW);
digitalWrite (tempLed, LOW);


}
void loop() {
// read the value from the moisture-sensing probes, print it to screen, and wait a second
moisture_val = analogRead(moistureSensor);
Serial.print("moisture sensor reads ");
Serial.println( moisture_val );
delay(1000);
// read the value from the photosensor, print it to screen, and wait a second
light_val = analogRead(lightSensor);
Serial.print("light sensor reads ");
Serial.println( light_val );
delay(1000);
// read the value from the temperature sensor, print it to screen, and wait a second
temp_val = analogRead(tempSensor);
Serial.print("temp sensor reads ");
Serial.println( temp_val );
delay(1000);
Serial.print("hour ");
Serial.println(hour());

//turn water on when soil is dry, and delay until soil is wet
if (moisture_val < 850)
{
digitalWrite(waterPump, HIGH);
}

//while (moisture_val < 850)
//{
//delay(10000);
//}

digitalWrite(waterPump, LOW);

//turn on light after 6:00am if room lights are not on
if ((light_val > 400) && (hour() >= 6))
{
digitalWrite(lightSwitch, LOW);
Serial.println("light off after 6 because other lights are on ");
}
else{
  if (hour() >= 6){
  digitalWrite(lightSwitch, HIGH);
  Serial.println("light on after 6a.m.");
  }
  else{
    digitalWrite(lightSwitch, LOW);
    Serial.println("light off not6 yet");
  }
 
}
//turns off light after 8:00 p.m.
if (hour() >= 20)
{
  digitalWrite(lightSwitch, LOW);
  Serial.println("light off after 8 ");
}

//turn on temp alarm light if temp_val is less than 850 (approximately 50 degrees Fahrenheit)
if (temp_val < 850)
{
digitalWrite(tempLed, HIGH);
}

}

Thanks
Dan

My timing would be better if my lights came on at a certain time of day and this program will be running continuously well past 50 days so I'm going to try and go back to the time library again.
Wish me luck and thanks
Dan

Just so reply #7 makes sense I've merged the threads.

Dodsond - is this of any use to you?...

long days=0;
long hours=0;
long mins=0;
long secs=0;
long currentmillis=0;
unsigned long time;
unsigned long last_time;
unsigned long duration;
int reset;

void setup(){
  Serial.begin(9600);
 last_time = 0;
 reset = 0;
}


void loop(){ 
 time = millis();
 
 GetTimeRunning();  
 delay(1000);
if (days>0) // days will displayed only if value is greater than zero
   {
    Serial.print(days);
    Serial.print(" days and: ");
    }
   Serial.print(hours);
   Serial.print(" hours: ");
   Serial.print(mins);
   Serial.print(" minutes: ");
   Serial.print(secs);    
   Serial.println(" Seconds.");
   
}    

void GetTimeRunning()
{
  currentmillis= millis();  
  secs = currentmillis/1000; //convect milliseconds to seconds
  mins=secs/60; //convert seconds to minutes
  hours=mins/60; //convert minutes to hours
  days=hours/24; //convert hours to days
  secs=secs-(mins*60); //subtract the coverted seconds to minutes in order to display 59 secs max
  mins=mins-(hours*60); //subtract the coverted minutes to hours in order to display 59 minutes max
  hours=hours-(days*24); //subtract the coverted hours to days in order to display 23 hours max
  //Display results 
}

Results

0 hours: 0 minutes: 0 Seconds.
0 hours: 0 minutes: 1 Seconds.
0 hours: 0 minutes: 2 Seconds.
0 hours: 0 minutes: 3 Seconds.
0 hours: 0 minutes: 4 Seconds.
0 hours: 0 minutes: 5 Seconds.
0 hours: 0 minutes: 6 Seconds.
0 hours: 0 minutes: 7 Seconds.
0 hours: 0 minutes: 8 Seconds.
0 hours: 0 minutes: 9 Seconds.
0 hours: 0 minutes: 10 Seconds.
0 hours: 0 minutes: 11 Seconds.
0 hours: 0 minutes: 12 Seconds.
0 hours: 0 minutes: 13 Seconds.
0 hours: 0 minutes: 14 Seconds.
0 hours: 0 minutes: 15 Seconds.
0 hours: 0 minutes: 16 Seconds.
0 hours: 0 minutes: 17 Seconds.
0 hours: 0 minutes: 18 Seconds.
0 hours: 0 minutes: 19 Seconds.
0 hours: 0 minutes: 20 Seconds.
0 hours: 0 minutes: 21 Seconds.
0 hours: 0 minutes: 22 Seconds.
0 hours: 0 minutes: 23 Seconds.
0 hours: 0 minutes: 24 Seconds.
0 hours: 0 minutes: 25 Seconds.
0 hours: 0 minutes: 26 Seconds.
..... so on

cjdelphi:

void GetTimeRunning()

{
  currentmillis= millis(); 
  secs = currentmillis/1000; //convect milliseconds to seconds
  mins=secs/60; //convert seconds to minutes
  hours=mins/60; //convert minutes to hours
  days=hours/24; //convert hours to days
 secs=secs-(mins60); //subtract the coverted seconds to minutes in order to display 59 secs max
 mins=mins-(hours
60); //subtract the coverted minutes to hours in order to display 59 minutes max
 hours=hours-(days*24); //subtract the coverted hours to days in order to display 23 hours max
}

Would this not be simpler:

void GetTimeRunning()
{
  currentmillis= millis();  
  secs = currentmillis/1000; //convect milliseconds to seconds
  mins=secs/60; //convert seconds to minutes
  hours=mins/60; //convert minutes to hours
  days=hours/24; //convert hours to days
  secs %= 60; //remainder when divided by 60
  mins %= 60; //remainder when divided by 60
  hours %= 24; //remainder when divided by 24
}

If you're going to cook something on the stove for an hour, you don't set your your time to midnight and wait until 1PM before you take it off the stove

I should hope not. It would be burnt to a crisp 13 hours later... 8)

... because the clock wrapped around.

You should have reset it to 12 when you started. Oh wait, it was at 12.

PaulS:

If you're going to cook something on the stove for an hour, you don't set your your time to midnight and wait until 1PM before you take it off the stove

I should hope not. It would be burnt to a crisp 13 hours later... 8)

Wait, there is another way to cook food? Wish my wife knew that... ]:slight_smile:

marco_c:
Millis can't be reset. What you need to do is remember when your time period started by storing the value of millis at the time and then working out time elapsed by subtracting current value from the stored value. This is a pretty common technique with timing stuff on computers.

Sure it can....

/*
 * Code to Reset the millis() counter value back to 0
 */

void millisReset()
{
extern volatile	unsigned long timer0_millis;
extern volatile	unsigned long timer0_overflow_count;
	noInterrupts();
	timer0_millis = 0;
	timer0_overflow_count = 0;
	interrupts();
}

That said, I think there better approaches to solving the problem.
Also, this routine does not reset the actual hardware so the first millis() value may (will)
increment in less time than normal.

--- bill

TCNT0 = 0;

Or something like that would probably reset the hardware as well.

@OP: that's all very well, but what if you want to time two things? You can't reset millis() twice.

Imagine you are cooking dinner and keeping and eye on how long to cook the meat, the vegies, the gravy, the potatoes, etc. You don't go and get half-a-dozen clocks do you? You use one clock and make a note of when you need to put each thing on, and when it finishes. Without fiddling with the clock to reset the hands back to 12 each time.

Dodsond:
My timing would be better if my lights came on at a certain time of day and this program will be running continuously well past 50 days so I'm going to try and go back to the time library again.
Wish me luck and thanks
Dan

You probably misunderstand. You can't have a delay more than 49.7 days using unsigned long time. That doesn't mean that the code won't work past then, because it will. If the lights turn on and off every day or once a month you should have no problem as long as the start time moves as often.

Morris Dovey here wrote an excellent timing library that uses 64-bit unsigned. Even timing with micros() the longest delay goes well past the next century.

My timing would be better if my lights came on at a certain time of day and this program will be running continuously well past 50 days ...

You are probably better off using a clock chip with a battery backup. Then rather than trying to count milliseconds, you simply look at the time.

What about the time library?
I have that in my code right now as this.

#include <time.h>
//turn on light after 6:00am if room lights are not on
if ((light_val > 400) && (hour() >= 6))
{
digitalWrite(lightSwitch, LOW);
Serial.println("light off after 6 because other lights are on ");
}
else 
{
  if (hour() >= 6)
  {
  digitalWrite(lightSwitch, HIGH);
  Serial.println("light on after 6a.m.");
  }
  else
  {
    //turns off light after 8:00 p.m.
    if (hour() >= 20)
    {
    digitalWrite(lightSwitch, LOW);
    Serial.println("light off after 8 ");
    } 
      else{
      digitalWrite(lightSwitch, LOW);
      Serial.println("light off not6 yet");
  }
  }
}

When I start this routine the hour() =0 and progresses through the 24 hours of the day then goesto the next day. The only problem is that I have to start the program at midnight currently for the time to be right. Looking for a fix from the time library documentation but I am not seeing the easy fix to either input the time manually when I start the problem or for the program to get the time automatically from my machine (if that is even possible). Reading some of the text shows some sort of get time now function that looks like it looks at my computers internal clock but I can't figure out the syntax.
Dan