user-1: I have two questions want to ask 

I'm using Arduino Uno with 16*2 LCD Blue ( also I have temp. sensor and two motors also 3 limit switches) ,, my code is working good, but sometimes my lcd stop printing the values of Temperature and time [print nothing i.e. print all the leds on] \\ then when I reboot it everything works good .... why this problem happened ? 
Is there any way to save the value of millis function when the arduino was rebooted ?

thanks for your help
regards 

My code is for an egg incubator , it consists of 

Dht22 sensor [humidity + Temp]
three limit sw.
one motor
16*2 lcd
lamp [acting as  heaters]

As I said previously,  millis function  that I'm using is for controlling the motor movement every 3 hours and stop the movement after 18 days of working 
The main problem I faced is POINT 1 that I mentioned previously (I don't need to lose the time when I reboot the LCD)
If any one can help by giving me a short code as an example who to deal with EEPROM or any other idea.
Here is my code 
#include "DHT.h"  //includes lib for the temperature-humdity sensor
#include <LiquidCrystal.h> //lcd lib

#define DHTPIN 13 //pin that DHT is connected to 
#define DHTTYPE DHT22 //Sensor we are using

DHT dht(DHTPIN, DHTTYPE); //defines location for DHT

int sw1,sw2,sw3;
const int LM1=0;
const int LM2=1;
const int LM3=6;
const int LAMP=8;
const int CW=10;
const int CCW= 9;
const int Buzzer=7;
long previousMillis = 0;        // will store last time LED was updated
unsigned long RealTime = 0;  
float MOTORTime =0;// This is the real time that present on LCD now.
unsigned long MOTORSTOP = 0;// store the valve after 18 days of ranning ,, 

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 10800000;           // interval at which to blink (milliseconds)(3 hours waiting)

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {

  lcd.begin(16, 2);   // set up the LCD's number of rows and columns: [LCD that we have (Colomn,Row)]
  pinMode(LAMP,OUTPUT);
  pinMode(LM1,INPUT);
  pinMode(LM2,INPUT);
  pinMode(LM3,INPUT);
  pinMode(CW,OUTPUT);
  pinMode(CCW,OUTPUT);

 }
void loop() {
  sw3=digitalRead(LM3);
      unsigned long currentMillis = millis();
MOTORSTOP = currentMillis;
if (MOTORSTOP < 1555200000){ // 18 days
  float h = dht.readHumidity(); //defines the variable for humidity
  float t = dht.readTemperature(); //defines the variable for temperature
  // set the cursor to column 0, line 0
  lcd.setCursor(0,0);
  // print the humidity 
  lcd.print("H ");
  lcd.print(h);
  lcd.print("% ");
  //move line down
  lcd.setCursor(0,1);
  lcd.print("T ");
  lcd.print(t);
  lcd.print("C ");

  lcd.setCursor(10,0);
  lcd.print("MOTOR"); // to print motor working time


if (t==37.65)digitalWrite(LAMP,LOW);// Lamp OFF
else if (t>37.65)digitalWrite (LAMP,LOW); // Lamp OFF
else { digitalWrite(LAMP,HIGH);}// Lamp ON


  delay(2000); //wait two sec. before taking another reading.
  ///////////////stepper motor control and delay time 2.45 hours. 
 sw1= digitalRead(LM1);
  sw2= digitalRead(LM2);


  RealTime = currentMillis - previousMillis;
  MOTORTime=((RealTime/(1000))/60); //////////////////////////////////////////// 
  MOTORTime = 180 - MOTORTime;

  if (MOTORTime >= 1){
   lcd.setCursor(10,1);
  lcd.print(MOTORTime); }// this will print the ACTUAL Time Remaining on LCD
  else {
    lcd.setCursor(10,1);
   lcd.print("<1 MIN");}


  if(RealTime > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

  if (sw1==LOW && sw2==HIGH){
    digitalWrite (CW,LOW);
    digitalWrite (CCW,LOW);
    do {
      digitalWrite(Buzzer,HIGH);
      digitalWrite (CW,HIGH);// change the direction of rotation (DOWN Movement)
      digitalWrite (CCW,LOW);

      sw2= digitalRead(LM2);}
      while(sw2==HIGH);}

      else if (sw1==HIGH && sw2==LOW){

      digitalWrite(CW,LOW);
      digitalWrite(CCW,LOW);

        do {
          digitalWrite(Buzzer,HIGH);
          digitalWrite(CW,LOW);// change the direction of rotation (UP Movement)
          digitalWrite(CCW,HIGH);

          sw1= digitalRead(LM1);}
          while(sw1 == HIGH);}}
}
//----------------------------------------------------------------------------------------------------------------------
else if (((MOTORSTOP/10800000)>= 144 )&& (LM3== LOW)&&(MOTORSTOP >= 1555200000)){
  digitalWrite (CW,LOW);
    digitalWrite (CCW,LOW);

   float h = dht.readHumidity(); //defines the variable for humidity
  float t = dht.readTemperature(); //defines the variable for temperature
  // set the cursor to column 0, line 0
  lcd.setCursor(0,0);
  // print the humidity 
  lcd.print("H ");
  lcd.print(h);
  lcd.print("% ");
  //move line down
  lcd.setCursor(0,1);
  lcd.print("T ");
  lcd.print(t);
  lcd.print("C ");

  lcd.setCursor(10,0);
  lcd.print("MOTOR"); // to print motor working time
  lcd.setCursor(10,1);
  lcd.print("OFF");

if (t==36.70)digitalWrite(LAMP,LOW);// Lamp OFF
else if (t>36.70)digitalWrite (LAMP,LOW); // Lamp OFF
else { digitalWrite(LAMP,HIGH);}// Lamp ON


  delay(2000); //wait two sec. before taking another reading.

}
}


user6959: Summary: 
You have an incorrect variable type assignment for previousMillis ('long' instead of 'unsigned long') resulting in illegal mixing of types in a subtraction. 
It is not certain that this is causing your problems but, if not, it will cause problems at some stage if millis() is never reset  - if only when millis() passes its halfway point.  
It is not possible to prove with certainty that the mixing of types is not causing a problem without examining the compiled code as the action is 'illegal' and so no assurance is possible.
(We hope that the compiler writer 'got it right' :-) ). 

Details:
Where you now use  

long previousMillis = 0;  

You should use   

unsigned long previousMillis = 0;  

Both 'long' and 'unsigned long' are 32 bit data types but long is signed and effectively "wraps around" at half value.
Apart from having funny things happen after about 25 days, if you mix data types in a calculation as you do in  

RealTime = currentMillis - previousMillis;
  where


RealTime = unsigned long  
currentMillis = unsigned long , but  
previousMillis = long

then there is no certainty as to what the code will do when subtracting a long' from an 'unsigned long'.   
We know what we would like it to do, and we hope that the compiler writer made the same assumptions as we do, but there is no guarantee. 
Interestingly, while it does no harm for RealTime to be of type 'unsigned long', this is usually not essential, as we know that  

up to about 25 days the result will fit in the lower 31 bits of a 'long' and
  up to 65.535 seconds the result will fit in the 16 bits of an unsigned int and
  up to 32.767 seconds the result will fit in the lower 15 bits of an int.  

So, if your period between millis() tests is guaranteed to fit in the above ranges then the lower range variables may be used. 
While the mixing of types in the actual subtraction produces a technically undefined result, the use of a different type for the result than is used in the calculation is acceptable as the calculation result is well defined as long as the subtraction is performed correctly.

millis() wrap-around - NOT a problem:
People have expressed concern about incorrect results when millis() overflows after about 50 days, but this need not be a concern if correct data typing is used.   When two variables or 'counters' (in this case eg millis() and previousMillis), both of type 'unsigned long' are subtracted or compared, the result is arithmetically valid, even if the "upper" variable ( millis() ) has reached the top of its range and 'wrapped around'. This result is true for any two unsigned integer counters which are both of the same length.
ie the result of eg

delay = millis() - previousMillis 

will ALWAYS be valid if millis() and previousMillis are both 'unsigned long's.
This result is not intuitively obvious to most people and there are many "solutions" to this "problem" on web which seek to correct a problem that does not exist. If you are interested in making use of this fact in other situations it is worth taking pencil and paper (or your favoured equivalent) and using eg 3 or 4 bit variables, working through how this works and why. What happens is that the overflowing / wrapping around higher counter (millis() in this case) "looks like" a longer unsigned variable with additional bits above its MSb. When the subtraction is carried out an MSb "bowwow" may occur  - this is being "borrowed" from data bits that do not exist but this matters not when only the lower N bits (32 in this case) are of importance. 

Variable (including the state of millis() ) can be saved in EEROM memory prior to a reboot. IF the data has to be validly written when a power outage occurs the system must detect the outage and continue to run long enough to validly write to EEROM. This requires proper design of power supply holdup time - without which EEROM corruption may occur due to power loss while writing to memory. As well as internal EEROM, it is possible to use low cost I^2C EEROM memory if non volatile storage requirements exceed uC EEROM capacity. 

More detail on any of the above available if required. 

user7508: It has been suggested to you to save the millis value in the EEPROM.
Although this can work, there is a big issue with the frequency at which
you save it. If you save too often, you will burn your EEPROM, as it is
only rated to 105 writes. If you do not save often enough,
you will have most of the time a very outdated value in EEPROM. The
problem can be mitigated by adopting a wear-leveling strategy, but this
adds significant complexity.
There is a simpler solution to this problem: instead of using the
EEPROM, save the value in RAM. Actually, the millis value already lives
in RAM, and since the RAM is not initialized by hardware on reset, you
will find, when your program starts, that the last millis is right where
you left it! It is then cleared by your program, in a function called
__do_clear_bss that belongs to the C runtime and runs before
setup().
In order to preserve millis across a reset, you can do the following:

Write a function that copies the millis value into some other global
variable. This function must run early in the startup sequence, before
__do_clear_bss clears millis. This can be achieved by putting
the function in the .init3 section of the program, as explained in
the avr-libc documentation on memory
sections.
And the global variable must be in the .noinit section in order for
the C runtime not to mess with it.
In setup(), restore the millis value from that global variable.

This way you will have a continuous millis across resets, with one
caveat: on a cold boot, it will start with an unpredictable value. This
should be no issue if you take care to never rely on absolute time but
only on time differences, which is a good practice if only to avoid
issues when millis rolls over. If you nevertheless want to reset millis
on a cold boot, you have several options:

Connect a "reset time" button to your Arduino and hold the button
pressed when you power it up. setup() would then know it should not
restore the millis value.
Write some magic
number
in RAM. If you find this number at startup, it is extremely likely
that the program is starting from a warm reset.
If your Arduino has a fairly recent version of optiboot, you
will find the reset flags in the CPU register r2 when your program
starts. These flags tell you whether you come from a cold boot or a
warm reset.

The program below is an example that implements strategy 2. It prints
the millis value on the serial port roughly every second. On reset, it
prints “-- starting --” and continues from where it left.
// If this is in RAM at startup, we come from a warm reset.
volatile const unsigned long magic = 0x12345678;

// This is where Arduino core keeps the millis() value.
extern volatile unsigned long timer0_millis;

// Here we will save a copy of timer0_millis.
unsigned long __attribute__((section(".noinit"))) savedMillis;

// Save the millis value at startup.
void __attribute__((section(".init3"),naked)) saveMillis()
{
    if (magic == 0x12345678)  // very likely a reset
        savedMillis = timer0_millis;
    else                      // cold boot
        savedMillis = 0;
}

void setup()
{
    // DO THIS FIRST: Restore the saved value of millis.
    noInterrupts();
    timer0_millis = savedMillis;
    interrupts();

    // Other initializations can be done now.
    Serial.begin(9600);
    Serial.println("-- starting --");
}

void loop()
{
    Serial.println(millis());
    delay(1000);
}


user313: You might try a real-time clock module instead of the millis() function. They keep time in external hardware and are battery backed so continue through a power down, you get calendar date and clock time instead of milliseconds since restart, and they don't overflow every 50 days.

-1: <p>I have two questions want to ask </p>

<ol>
<li><p>I'm using Arduino Uno with 16*2 LCD Blue ( also I have temp. sensor and two motors also 3 limit switches) ,, my code is working good, but sometimes my lcd stop printing the values of Temperature and time [print nothing i.e. print all the leds on] \\ then when I reboot it everything works good .... why this problem happened ? </p></li>
<li><p>Is there any way to save the value of millis function when the arduino was rebooted ?</p></li>
</ol>

<p>thanks for your help
regards </p>

<hr>

<p>My code is for an egg incubator , it consists of </p>

<ol>
<li>Dht22 sensor [humidity + Temp]</li>
<li>three limit sw.</li>
<li>one motor</li>
<li>16*2 lcd</li>
<li>lamp [acting as  heaters]</li>
</ol>

<p>As I said previously,  millis function  that I'm using is for controlling the motor movement every 3 hours and stop the movement after 18 days of working </p>

<p>The main problem I faced is POINT 1 that I mentioned previously (I don't need to lose the time when I reboot the LCD)</p>

<p>If any one can help by giving me a short code as an example who to deal with EEPROM or any other idea.</p>

<p>Here is my code </p>

<pre><code>#include "DHT.h"  //includes lib for the temperature-humdity sensor
#include &lt;LiquidCrystal.h&gt; //lcd lib

#define DHTPIN 13 //pin that DHT is connected to 
#define DHTTYPE DHT22 //Sensor we are using

DHT dht(DHTPIN, DHTTYPE); //defines location for DHT

int sw1,sw2,sw3;
const int LM1=0;
const int LM2=1;
const int LM3=6;
const int LAMP=8;
const int CW=10;
const int CCW= 9;
const int Buzzer=7;
long previousMillis = 0;        // will store last time LED was updated
unsigned long RealTime = 0;  
float MOTORTime =0;// This is the real time that present on LCD now.
unsigned long MOTORSTOP = 0;// store the valve after 18 days of ranning ,, 

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 10800000;           // interval at which to blink (milliseconds)(3 hours waiting)

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {

  lcd.begin(16, 2);   // set up the LCD's number of rows and columns: [LCD that we have (Colomn,Row)]
  pinMode(LAMP,OUTPUT);
  pinMode(LM1,INPUT);
  pinMode(LM2,INPUT);
  pinMode(LM3,INPUT);
  pinMode(CW,OUTPUT);
  pinMode(CCW,OUTPUT);

 }
void loop() {
  sw3=digitalRead(LM3);
      unsigned long currentMillis = millis();
MOTORSTOP = currentMillis;
if (MOTORSTOP &lt; 1555200000){ // 18 days
  float h = dht.readHumidity(); //defines the variable for humidity
  float t = dht.readTemperature(); //defines the variable for temperature
  // set the cursor to column 0, line 0
  lcd.setCursor(0,0);
  // print the humidity 
  lcd.print("H ");
  lcd.print(h);
  lcd.print("% ");
  //move line down
  lcd.setCursor(0,1);
  lcd.print("T ");
  lcd.print(t);
  lcd.print("C ");

  lcd.setCursor(10,0);
  lcd.print("MOTOR"); // to print motor working time


if (t==37.65)digitalWrite(LAMP,LOW);// Lamp OFF
else if (t&gt;37.65)digitalWrite (LAMP,LOW); // Lamp OFF
else { digitalWrite(LAMP,HIGH);}// Lamp ON


  delay(2000); //wait two sec. before taking another reading.
  ///////////////stepper motor control and delay time 2.45 hours. 
 sw1= digitalRead(LM1);
  sw2= digitalRead(LM2);


  RealTime = currentMillis - previousMillis;
  MOTORTime=((RealTime/(1000))/60); //////////////////////////////////////////// 
  MOTORTime = 180 - MOTORTime;

  if (MOTORTime &gt;= 1){
   lcd.setCursor(10,1);
  lcd.print(MOTORTime); }// this will print the ACTUAL Time Remaining on LCD
  else {
    lcd.setCursor(10,1);
   lcd.print("&lt;1 MIN");}


  if(RealTime &gt; interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

  if (sw1==LOW &amp;&amp; sw2==HIGH){
    digitalWrite (CW,LOW);
    digitalWrite (CCW,LOW);
    do {
      digitalWrite(Buzzer,HIGH);
      digitalWrite (CW,HIGH);// change the direction of rotation (DOWN Movement)
      digitalWrite (CCW,LOW);

      sw2= digitalRead(LM2);}
      while(sw2==HIGH);}

      else if (sw1==HIGH &amp;&amp; sw2==LOW){

      digitalWrite(CW,LOW);
      digitalWrite(CCW,LOW);

        do {
          digitalWrite(Buzzer,HIGH);
          digitalWrite(CW,LOW);// change the direction of rotation (UP Movement)
          digitalWrite(CCW,HIGH);

          sw1= digitalRead(LM1);}
          while(sw1 == HIGH);}}
}
//----------------------------------------------------------------------------------------------------------------------
else if (((MOTORSTOP/10800000)&gt;= 144 )&amp;&amp; (LM3== LOW)&amp;&amp;(MOTORSTOP &gt;= 1555200000)){
  digitalWrite (CW,LOW);
    digitalWrite (CCW,LOW);

   float h = dht.readHumidity(); //defines the variable for humidity
  float t = dht.readTemperature(); //defines the variable for temperature
  // set the cursor to column 0, line 0
  lcd.setCursor(0,0);
  // print the humidity 
  lcd.print("H ");
  lcd.print(h);
  lcd.print("% ");
  //move line down
  lcd.setCursor(0,1);
  lcd.print("T ");
  lcd.print(t);
  lcd.print("C ");

  lcd.setCursor(10,0);
  lcd.print("MOTOR"); // to print motor working time
  lcd.setCursor(10,1);
  lcd.print("OFF");

if (t==36.70)digitalWrite(LAMP,LOW);// Lamp OFF
else if (t&gt;36.70)digitalWrite (LAMP,LOW); // Lamp OFF
else { digitalWrite(LAMP,HIGH);}// Lamp ON


  delay(2000); //wait two sec. before taking another reading.

}
}
</code></pre>
 6959: <p><strong>Summary:</strong>  </p>

<p>You have an incorrect variable type assignment for previousMillis ('long' instead of 'unsigned long') resulting in illegal mixing of types in a subtraction. </p>

<p>It is not certain that this is causing your problems but, if not, it will cause problems at some stage if millis() is never reset  - if only when millis() passes its halfway point.  </p>

<p>It is not possible to prove with certainty that the mixing of types is not causing a problem without examining the compiled code as the action is 'illegal' and so no assurance is possible.<br>
(We <strong>hope</strong> that the compiler writer 'got it right' :-) ). </p>

<hr>

<p><strong>Details:</strong></p>

<p>Where you now use  </p>

<blockquote>
  <p>long previousMillis = 0;  </p>
</blockquote>

<p>You should use   </p>

<blockquote>
  <p>unsigned long previousMillis = 0;  </p>
</blockquote>

<p>Both 'long' and 'unsigned long' are 32 bit data types but long is signed and effectively "wraps around" at half value.</p>

<p>Apart from having funny things happen after about 25 days, if you mix data types in a calculation as you do in  </p>

<blockquote>
  <p>RealTime = currentMillis - previousMillis;<br>
  where</p>
</blockquote>

<ul>
<li>RealTime = unsigned long  </li>
<li>currentMillis = unsigned long , but  </li>
<li>previousMillis = long</li>
</ul>

<p>then there is no certainty as to what the code will do when subtracting a long' from an 'unsigned long'.   </p>

<p>We know what we would like it to do, and we hope that the compiler writer made the same assumptions as we do, but there is no guarantee. </p>

<p>Interestingly, while it does no harm for RealTime to be of type 'unsigned long', this is usually not essential, as we know that  </p>

<blockquote>
  <p>up to about 25 days the result will fit in the lower 31 bits of a 'long' and<br>
  up to 65.535 seconds the result will fit in the 16 bits of an unsigned int and<br>
  up to 32.767 seconds the result will fit in the lower 15 bits of an int.  </p>
</blockquote>

<p>So, if your period between millis() tests is guaranteed to fit in the above ranges then the lower range variables may be used. </p>

<p>While the mixing of types in the actual subtraction produces a technically undefined result, the use of a different type for the result than is used in the calculation is acceptable as the calculation result is well defined as long as the subtraction is performed correctly.</p>

<hr>

<p>millis() wrap-around - <strong>NOT</strong> a problem:</p>

<p>People have expressed concern about incorrect results when millis() overflows after about 50 days, but this need not be a concern if correct data typing is used.   When two variables or 'counters' (in this case eg millis() and previousMillis), both of type 'unsigned long' are subtracted or compared, the result is arithmetically valid, even if the "upper" variable ( millis() ) has reached the top of its range and 'wrapped around'. This result is true for any two unsigned integer counters which are both of the same length.<br>
ie the result of eg</p>

<blockquote>
  <p>delay = millis() - previousMillis </p>
</blockquote>

<p>will ALWAYS be valid if millis() and previousMillis are both 'unsigned long's.<br>
This result is not intuitively obvious to most people and there are many "solutions" to this "problem" on web which seek to correct a problem that does not exist. If you are interested in making use of this fact in other situations it is worth taking pencil and paper (or your favoured equivalent) and using eg 3 or 4 bit variables, working through how this works and why. What happens is that the overflowing / wrapping around higher counter (millis() in this case) "looks like" a longer unsigned variable with additional bits above its MSb. When the subtraction is carried out an MSb "bowwow" may occur  - this is being "borrowed" from data bits that do not exist but this matters not when only the lower N bits (32 in this case) are of importance. </p>

<hr>

<p>Variable (including the state of millis() ) can be saved in EEROM memory prior to a reboot. IF the data has to be validly written when a power outage occurs the system must detect the outage and continue to run long enough to validly write to EEROM. This requires proper design of power supply holdup time - without which EEROM corruption may occur due to power loss while writing to memory. As well as internal EEROM, it is possible to use low cost I^2C EEROM memory if non volatile storage requirements exceed uC EEROM capacity. </p>

<hr>

<p>More detail on any of the above available if required. </p>
 7508: <p>It has been suggested to you to save the millis value in the EEPROM.
Although this can work, there is a big issue with the frequency at which
you save it. If you save too often, you will burn your EEPROM, as it is
only rated to 10<sup>5</sup> writes. If you do not save often enough,
you will have most of the time a very outdated value in EEPROM. The
problem can be mitigated by adopting a wear-leveling strategy, but this
adds significant complexity.</p>

<p>There is a simpler solution to this problem: instead of using the
EEPROM, save the value in RAM. Actually, the millis value already lives
in RAM, and since the RAM is not initialized by hardware on reset, you
will find, when your program starts, that the last millis is right where
you left it! It is then cleared by your program, in a function called
<code>__do_clear_bss</code> that belongs to the C runtime and runs before
<code>setup()</code>.</p>

<p>In order to preserve millis across a reset, you can do the following:</p>

<ul>
<li>Write a function that copies the millis value into some other global
variable. This function must run early in the startup sequence, before
<code>__do_clear_bss</code> clears millis. This can be achieved by putting
the function in the <em>.init3</em> section of the program, as explained in
<a href="http://www.nongnu.org/avr-libc/user-manual/mem_sections.html" rel="nofollow">the avr-libc documentation on memory
sections</a>.
And the global variable must be in the <em>.noinit</em> section in order for
the C runtime not to mess with it.</li>
<li>In <code>setup()</code>, restore the millis value from that global variable.</li>
</ul>

<p>This way you will have a continuous millis across resets, with one
caveat: on a cold boot, it will start with an unpredictable value. This
should be no issue if you take care to never rely on absolute time but
only on time differences, which is a good practice if only to avoid
issues when millis rolls over. If you nevertheless want to reset millis
on a cold boot, you have several options:</p>

<ol>
<li>Connect a "reset time" button to your Arduino and hold the button
pressed when you power it up. <code>setup()</code> would then know it should not
restore the millis value.</li>
<li>Write some <a href="https://en.wikipedia.org/wiki/Magic_number_%28programming%29" rel="nofollow">magic
number</a>
in RAM. If you find this number at startup, it is extremely likely
that the program is starting from a warm reset.</li>
<li>If your Arduino has a fairly recent version of optiboot, you
will find the reset flags in the CPU register r2 when your program
starts. These flags tell you whether you come from a cold boot or a
warm reset.</li>
</ol>

<p>The program below is an example that implements strategy 2. It prints
the millis value on the serial port roughly every second. On reset, it
prints “-- starting --” and continues from where it left.</p>

<pre class="lang-cpp prettyprint-override"><code>// If this is in RAM at startup, we come from a warm reset.
volatile const unsigned long magic = 0x12345678;

// This is where Arduino core keeps the millis() value.
extern volatile unsigned long timer0_millis;

// Here we will save a copy of timer0_millis.
unsigned long __attribute__((section(".noinit"))) savedMillis;

// Save the millis value at startup.
void __attribute__((section(".init3"),naked)) saveMillis()
{
    if (magic == 0x12345678)  // very likely a reset
        savedMillis = timer0_millis;
    else                      // cold boot
        savedMillis = 0;
}

void setup()
{
    // DO THIS FIRST: Restore the saved value of millis.
    noInterrupts();
    timer0_millis = savedMillis;
    interrupts();

    // Other initializations can be done now.
    Serial.begin(9600);
    Serial.println("-- starting --");
}

void loop()
{
    Serial.println(millis());
    delay(1000);
}
</code></pre>
 313: <p>You might try a real-time clock module instead of the <code>millis()</code> function. They keep time in external hardware and are battery backed so continue through a power down, you get calendar date and clock time instead of milliseconds since restart, and they don't overflow every 50 days.</p>
