Help changing delay() to millis()

I am trying to remove the delay() in this loop of my program by using millis(). Everything thing I try seems to fail one way or another. Either everything turns on and won't turn off at the end, everything turns on then off instantly, or nothing happens at all. This is the loop I am trying to remove the delay() from. It works flawless but I want the delay to actually be 5 minutes. The problem is that during the delay I am locked out of the rest of the program and everything is paused during the delay.

/*********************************** ATO FUNCTION *********************************/
void topOff()
{   
         waitForIt(85, 94, 235, 114);
         myGLCD.setColor(0, 255, 0);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 0, 0, 0, 0, 255, 0);
         myGLCD.print("Topping Off", 118, 98);       
         digitalWrite(autoTopOff, HIGH);             
         digitalWrite(WaveMakerTop, HIGH);           
         digitalWrite(WaveMakerBottom, HIGH);        
         delay(10000);
         t=rtc.getTime();                            
         myGLCD.setColor(153, 0, 102);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 255, 255, 255, 153, 0, 102);
         myGLCD.print("Top-Off Now!", 106, 98);        
         digitalWrite(autoTopOff, LOW);                
}
/******************************* END of ATO FUNCTION ******************************/

I have tried a few ways but it doesn't work. Every version will verify correctly, so I know everything is defined correctly. Once it loads onto my mega 2560, it just won't execute as planned.

{ 
         waitForIt(85, 94, 235, 114);
         myGLCD.setColor(0, 255, 0);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 0, 0, 0, 0, 255, 0);
         myGLCD.print("Topping Off", 118, 98);       
         digitalWrite(autoTopOff, HIGH);             
         digitalWrite(WaveMakerTop, HIGH);           
         digitalWrite(WaveMakerBottom, HIGH);        

        unsigned long currentMillis = millis();

        if(currentMillis - previousMillisATO > 10000) {
         previousMillisATO = currentMillis; 
         
         t=rtc.getTime();                            
         myGLCD.setColor(153, 0, 102);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 255, 255, 255, 153, 0, 102);
         myGLCD.print("Top-Off Now!", 106, 98);        
         digitalWrite(autoTopOff, LOW);                
        }
      }
        { 
         waitForIt(85, 94, 235, 114);
         myGLCD.setColor(0, 255, 0);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 0, 0, 0, 0, 255, 0);
         myGLCD.print("Topping Off", 118, 98);       
         digitalWrite(autoTopOff, HIGH);             
         digitalWrite(WaveMakerTop, HIGH);           
         digitalWrite(WaveMakerBottom, HIGH);      

        if(currentMillis - previousMillisATO > 10000) {
         previousMillisATO = currentMillis;
         
        if (autoTopOffState == LOW)
            autoTopOffState = HIGH;
        else
         autoTopOffState = LOW;
         t=rtc.getTime();                            
         myGLCD.setColor(153, 0, 102);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 255, 255, 255, 153, 0, 102);
         myGLCD.print("Top-Off Now!", 106, 98);       
        digitalWrite(autoTopOff, autoTopOffState);                 
        } 
        }
{ 
        unsigned long currentMillis = millis();

        if(currentMillis - previousMillisATO > 10000) {
         previousMillisATO = currentMillis; 
         
         waitForIt(85, 94, 235, 114);
         myGLCD.setColor(0, 255, 0);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 0, 0, 0, 0, 255, 0);
         myGLCD.print("Topping Off", 118, 98);       
         digitalWrite(autoTopOff, HIGH);             
         digitalWrite(WaveMakerTop, HIGH);           
         digitalWrite(WaveMakerBottom, HIGH);        
        }
       else
       {
         t=rtc.getTime();                            
         myGLCD.setColor(153, 0, 102);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 255, 255, 255, 153, 0, 102);
         myGLCD.print("Top-Off Now!", 106, 98);        
         digitalWrite(autoTopOff, LOW);                
        }
        }
{ 
        unsigned long currentMillis = millis();

        if(currentMillis - previousMillisATO > 10000) {
         previousMillisATO = currentMillis; 
         
         t=rtc.getTime();                            
         myGLCD.setColor(153, 0, 102);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 255, 255, 255, 153, 0, 102);
         myGLCD.print("Top-Off Now!", 106, 98);        
         digitalWrite(autoTopOff, LOW);                
        }
       else
       {
         waitForIt(85, 94, 235, 114);
         myGLCD.setColor(0, 255, 0);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 0, 0, 0, 0, 255, 0);
         myGLCD.print("Topping Off", 118, 98);       
         digitalWrite(autoTopOff, HIGH);             
         digitalWrite(WaveMakerTop, HIGH);           
         digitalWrite(WaveMakerBottom, HIGH);       
        }
        }

Thanks for any help you can offer. Billy

To use timing instead of delay will mean that you have to call that function once per loop(). I see two blocks of stuff being done in that topOff function, one before the delay and one after. Do you want the first part to run every time topOff() is called and the second part only when a certain time has expired? Or once the top portion has executed it shouldn't execute again until the second part has run?

It's probably more helpful if you post all your code.

unsigned long currentMillis = millis();
 LOOP
        if( ( millis() - currentMillis ) < 10000 ) {
             
        do something here....

      }
 ENDLOOP

or 

unsigned long currentMillis = millis();

        while( ( millis() - currentMillis ) < 10000 ) {
             
        do something here....

      }

or, nicer:

unsigned long MyDelay = millis() + 10000;
 LOOP
        if( millis() < MyDelay ) {
             
        do something here....

      }
 ENDLOOP

or

unsigned long MyDelay = millis() + 10000;
 
        while ( millis() < MyDelay ) {
             
        do something here....

      }

Jimmy60:
To use timing instead of delay will mean that you have to call that function once per loop(). I see two blocks of stuff being done in that topOff function, one before the delay and one after. Do you want the first part to run every time topOff() is called and the second part only when a certain time has expired? Or once the top portion has executed it shouldn’t execute again until the second part has run?

It’s probably more helpful if you post all your code.

When the topOff function is called, I was trying to get the top portion to execute once, followed by a delay, and then the second part should run once. Then we should return back to the main loop

I would post the rest of the code but it is over 6000 lines and It’s a code that I purchased and I don’t have the right to post the code in it entirety.

pito:

unsigned long currentMillis = millis();

LOOP
        if( ( millis() - currentMillis ) < 10000 ) {
           
        do something here…

}
ENDLOOP

or

unsigned long currentMillis = millis();

while( ( millis() - currentMillis ) < 10000 ) {
           
        do something here…

}




or, nicer:



unsigned long MyDelay = millis() + 10000;
LOOP
        if( millis() < MyDelay ) {
           
        do something here…

}
ENDLOOP

or

unsigned long MyDelay = millis() + 10000;

while ( millis() < MyDelay ) {
           
        do something here…

}

So I tried both ways and I’m not sure Im doing it right. Cause the only thing that happened is the first part ran followed by the second part instantly.

void topOff()
{
unsigned long MyDelay = millis() + 10000;

         waitForIt(85, 94, 235, 114);
         myGLCD.setColor(0, 255, 0);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 0, 0, 0, 0, 255, 0);
         myGLCD.print("Topping Off", 118, 98);       //Changed from Now Feeding -WGT
         digitalWrite(autoTopOff, HIGH);             //Changed from autoFeeder -WGT
         digitalWrite(WaveMakerTop, HIGH);           //Added to turn pumps on while topping off -WGT
         digitalWrite(WaveMakerBottom, HIGH);        //Added to turn pumps on while topping off -WGT
         
while ( millis() < MyDelay ) {
          
         t=rtc.getTime();                            //Added to reset pumps -WGT
         myGLCD.setColor(153, 0, 102);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 255, 255, 255, 153, 0, 102);
         myGLCD.print("Top-Off Now!", 106, 98);        //Changed from Feed Fish Now -WGT
         digitalWrite(autoTopOff, LOW);                //Changed from autoFeeder -WGT
        }
}
void topOff()
{
unsigned long currentMillis = millis();

         waitForIt(85, 94, 235, 114);
         myGLCD.setColor(0, 255, 0);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 0, 0, 0, 0, 255, 0);
         myGLCD.print("Topping Off", 118, 98);       //Changed from Now Feeding -WGT
         digitalWrite(autoTopOff, HIGH);             //Changed from autoFeeder -WGT
         digitalWrite(WaveMakerTop, HIGH);           //Added to turn pumps on while topping off -WGT
         digitalWrite(WaveMakerBottom, HIGH);        //Added to turn pumps on while topping off -WGT
         
 if( ( millis() - currentMillis ) < 10000 ) {
          
         t=rtc.getTime();                            //Added to reset pumps -WGT
         myGLCD.setColor(153, 0, 102);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 255, 255, 255, 153, 0, 102);
         myGLCD.print("Top-Off Now!", 106, 98);        //Changed from Feed Fish Now -WGT
         digitalWrite(autoTopOff, LOW);                //Changed from autoFeeder -WGT
        }

The case with “if” must be a part of a “loop”, as you have to check millis() against end of your delay there periodically.

The case with “while” shall do what is inside the while(){…} until the millis() are bigger then your delay (it means the dealy is over).

So the second case runs through, the first case above shall do something in a loop for 10seconds (provided the first chunk of your code does not run longer than 10000ms).

Also mind you start your stopwatch (and set the end of the delay) by reading “millis()+10000” (it reads: “from now do a 10000ms delay”), so from that moment the clock ticks, and you have to check whether the delay is over somehow (the more often the better).

If you do:

unsigned long MyDelay = millis() + 10000;  <<< here you start your stopwatch set to 10000ms

blabla code execution takes 10.4seconds here; 

while ( millis() < MyDelay ) {      <<<< here you check whether the 10000ms delay (end time) is over
             
        blabla code execution takes 15 seconds here;

      }

then it will pass through in single shot…

pito:
The case with “if” must be a part of a “loop”, as you have to check millis() against end of your delay there periodically.

The case with “while” shall do what is inside the while(){…} until the millis() are bigger then your delay.

So the second case runs through, the first case above shall do something in a loop for 10seconds (provided the first chunk of your code does not run longer than 10000ms).

Also mind you set the end of the delay by reading “millis()+10000” (it reads: “from now do a 10000ms delay”), so from that moment the clock ticks. If you do:

unsigned long MyDelay = millis() + 10000;  <<< here you start your stopwatch set to 10000ms

blabla takes 10.4seconds;

while ( millis() < MyDelay ) {      <<<< here you check whether the 10000ms time is over
           
       blabla takes 15 seconds

}



then it will pass through in single shot..

Well I got this version to work but … It’s just like the delay. Once the loop start I can no longer use any other function on the controller until the timer has ran out.

/*********************************** ATO TOUCH SCREEN *********************************/
void topOff()
{
unsigned long MyDelay = millis() + 10000;
          
         waitForIt(85, 94, 235, 114);
         myGLCD.setColor(0, 255, 0);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 0, 0, 0, 0, 255, 0);
         myGLCD.print("Topping Off", 118, 98);       //Changed from Now Feeding -WGT
         
        while ( millis() < MyDelay ) 
         {         
         digitalWrite(autoTopOff, HIGH);             //Changed from autoFeeder -WGT
         digitalWrite(WaveMakerTop, HIGH);           //Added to turn pumps on while topping off -WGT
         digitalWrite(WaveMakerBottom, HIGH);        //Added to turn pumps on while topping off -WGT
         }

         t=rtc.getTime();                          
         myGLCD.setColor(153, 0, 102);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 255, 255, 255, 153, 0, 102);
         myGLCD.print("Top-Off Now!", 106, 98);      
         digitalWrite(autoTopOff, LOW);                
}
/******************************* END of ATO TOUCH SCREEN ******************************/

It's just like the delay. Once the loop start I can no longer use any other function on the controller until the timer has ran out.

It is not, as you do something during the delay :) Now it is a matter of your construction how you will proceed with the stuff. The "if" and "while" where just examples.

You can do what you want while the clock ticks. You may have 25 stopwatches running with 25 delays, you have to periodically check all those stopwatches (on any place in your code) and when the particular stopwatch timer is over you may do something.

Try to describe what you want achieve actually.

I have a touch screen on my controller. When I choose the button to top off my aquarium. I want the controller to turn the button a different color and read “Topping Off” instead of the normal “Top-Off Now!” It then turns on both my aquarium wave pumps and turns on the Auto Top-Off pump. Once the timer has run out, the button goes back to it original color and reads “Top-Off Now!”, the Auto-Top Off pump turns off, and it returns to the main loop. I don’t need to turn the wave pumps back off since they will go back to there original configuration once the main loop starts again.

I tried “if” and “if … else” and neither works. The “if” version will just runs right through the loop with no delay. The “if … else” statement gets to the delay and just stays there and doesn’t continue to run the else statement.

/*********************************** ATO TOUCH SCREEN *********************************/
void topOff()
{
unsigned long MyDelay = millis() + 10000;
          
         waitForIt(85, 94, 235, 114);
         myGLCD.setColor(0, 255, 0);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 0, 0, 0, 0, 255, 0);
         myGLCD.print("Topping Off", 118, 98);       //Changed from Now Feeding -WGT
         
         if( millis() < MyDelay ) 
         {        
         digitalWrite(autoTopOff, HIGH);             
         digitalWrite(WaveMakerTop, HIGH);           
         digitalWrite(WaveMakerBottom, HIGH);
        }
         t=rtc.getTime();                            
         myGLCD.setColor(153, 0, 102);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 255, 255, 255, 153, 0, 102);
         myGLCD.print("Top-Off Now!", 106, 98);        
         digitalWrite(autoTopOff, LOW);                
}
/******************************* END of ATO TOUCH SCREEN ******************************/
/*********************************** ATO TOUCH SCREEN *********************************/
void topOff()
{
unsigned long MyDelay = millis() + 10000;
          
         waitForIt(85, 94, 235, 114);
         myGLCD.setColor(0, 255, 0);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 0, 0, 0, 0, 255, 0);
         myGLCD.print("Topping Off", 118, 98);       //Changed from Now Feeding -WGT
         
         if( millis() < MyDelay ) 
         {        
         digitalWrite(autoTopOff, HIGH);             
         digitalWrite(WaveMakerTop, HIGH);           
         digitalWrite(WaveMakerBottom, HIGH);        
         }
         else
        { 
         t=rtc.getTime();                            
         myGLCD.setColor(153, 0, 102);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 255, 255, 255, 153, 0, 102);
         myGLCD.print("Top-Off Now!", 106, 98);        
         digitalWrite(autoTopOff, LOW);                
        }
}
/******************************* END of ATO TOUCH SCREEN ******************************/

So let simplify the stuff:

/*********************************** ATO TOUCH SCREEN *********************************/
void topOff()
{
unsigned long MyDelay = millis() + 10000;
          
         do_topping_off();
         
         if( millis() < MyDelay ) 
         {        
         do_some_digi_write();
         }
         do_auto_top_off_now();              
}
/******************************* END of ATO TOUCH SCREEN ******************************/

So now try to describe the scenario: what shall happen with those 3 functions and when.

pito:
So let simplify the stuff:

/*********************************** ATO TOUCH SCREEN *********************************/

void topOff()
{
unsigned long MyDelay = millis() + 10000;
         
        do_topping_off();
       
        if( millis() < MyDelay )
        {        
        do_some_digi_write();
        }
        do_auto_top_off_now();              
}
/******************************* END of ATO TOUCH SCREEN ******************************/



So now try to describe the scenario: what shall happen with those 3 functions and when.
/*********************************** ATO TOUCH SCREEN *********************************/
void topOff()
{
unsigned long MyDelay = millis() + 10000;
          
         //turn the button a different color and read "Topping Off" instead of the normal "Top-Off Now!"
         
         if( millis() < MyDelay ) 
         {        
          // turns on both my aquarium wave pumps and turns on the Auto Top-Off pump        
         }
         //once time has ran out
         //button goes back to it original color and reads "Top-Off Now!"
         //Auto-Top Off pump turns off
         //returns to the main loop              
}
/******************************* END of ATO TOUCH SCREEN ******************************/

First off, Thanks for taking the time to help me tonight. I do appreciate it. So I ran this code and this is what I got: When I press the button the button changes color and changes to “topping off” and instantly back to “top-off now” and previous color. My pump cycle instantly on and then back to normal.

/*********************************** ATO TOUCH SCREEN *********************************/
void topOff()
{
unsigned long MyDelay = millis() + 10000;
          
         waitForIt(85, 94, 235, 114);
         myGLCD.setColor(0, 255, 0);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 0, 0, 0, 0, 255, 0);
         myGLCD.print("Topping Off", 118, 98);       //Changed from Now Feeding -WGT
         
         if( millis() < MyDelay )
         {        
         digitalWrite(autoTopOff, HIGH);             //Changed from autoFeeder -WGT
         digitalWrite(WaveMakerTop, HIGH);           //Added to turn pumps on while topping off -WGT
         digitalWrite(WaveMakerBottom, HIGH);        //Added to turn pumps on while topping off -WGT
         } 
         t=rtc.getTime();                            //Added to reset pumps -WGT
         myGLCD.setColor(153, 0, 102);
         myGLCD.fillRoundRect(85, 94, 235, 114);
         myGLCD.setColor(255, 255, 255);
         myGLCD.drawRoundRect(85, 94, 235, 114); 
         setFont(SMALL, 255, 255, 255, 153, 0, 102);
         myGLCD.print("Top-Off Now!", 106, 98);        //Changed from Feed Fish Now -WGT
         digitalWrite(autoTopOff, LOW);                //Changed from autoFeeder -WGT
}
/******************************* END of ATO TOUCH SCREEN ******************************/

Here is a little sketch I have been playing with that is the same thing I am trying to do. I am just using the blinkWithOutDelay sketch and adjusting speed of blink.

When the loop starts :

  • LED blinks on/off once a second
  • after 10 seconds, the LED blinks on/off every 1/2 second
  • after another 10 seconds, the LED turns off and stops blinking

With the way the code is written, all it does is some weird LED twinkle then it starts to blink once a second with noting else happening.

const int ledPin =  13;      
int ledState = LOW;             
long previousMillis = 0;        
long interval = 1000; 
long interval2 = 500; 
unsigned long MyDelay = millis() + 10000;

void setup() {
  pinMode(ledPin, OUTPUT);      
}

void loop()
{
  
 /*************** LED blinks once every 1000 milliseconds *****************/
  unsigned long currentMillis = millis(); 

  if(currentMillis - previousMillis > interval) 
  {
    previousMillis = currentMillis;   

    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    digitalWrite(ledPin, ledState);
  }

 /*************** After 10 Seconds, LED starts to blink every 500 millisconds *****************/  
  if( millis() < MyDelay )
  {
    unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval2) 
  {
    previousMillis = currentMillis;   

    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    digitalWrite(ledPin, ledState);
  }
  }
 /*************** LED just turns off after another 10 seconds *****************/  
    if( millis() < MyDelay + 10000 )
    {
    digitalWrite(ledPin, LOW);
    }
  
}

http://gammon.com.au/blink

Great reading. It works great just alone but I don’t know why it won’t work in my code. Code 1 works but Code 2 doesn’t work when I add it to by controller code.

const int ledPin =  13;      
int ledState = LOW;             
long previousMillis = 0;        
long interval = 1000; 
unsigned long MyDelay = millis() + 10000;

void setup() {
  pinMode(ledPin, OUTPUT);      
}

void loop()
{
/*************** LED blinks once every 1000 milliseconds *****************/
  unsigned long currentMillis = millis();

  if( millis() < MyDelay )
  {
    if(currentMillis - previousMillis > interval) 
    {
    previousMillis = currentMillis;   

    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;
   }
    digitalWrite(ledPin, ledState);
  }

/*************** After 10 Seconds, LED turns off *****************/  
 else 
   if( millis() > MyDelay )
    digitalWrite(ledPin, LOW);
  
}
/*********************************** ATO TOUCH SCREEN *********************************/
void topOff()
{
unsigned long MyDelay = millis() + 10000;
         
         if( millis() < MyDelay )
         {        
         digitalWrite(autoTopOff, HIGH);             
         digitalWrite(WaveMakerTop, HIGH);           
         digitalWrite(WaveMakerBottom, HIGH);        
         }
         else
         if( millis() > MyDelay )
         digitalWrite(autoTopOff, LOW);               
         
}
/******************************* END of ATO TOUCH SCREEN ******************************/

There are ways to write code so it works, even if it is wrong. The "wrong" bit is surpressed, except when some circumstances occur. For example to add a value to millis() and then compare will break when millis() overflow. But doing the subtraction as the examples shows means it will work correctly even when the millis() overflow. Also the initialization of myDelay before the code has executed is wrong.

There are 3 small rules when delaying without using the delay function properly:

The data type of storing timer variables is:

unsigned long

Set the timer to start timing now:

timer = millis() ;

Check if the timer has expired:

if ( millis() - timer > delayvalue ) ...

Giving the timer a good name, like LEDBlinkTimer or buttonDebounceTimer, helps in readability.

The above will work with micros() just as well.

The underlying assumption is that the loop with timer code executed often, and is not hampered by waiting on some digitalRead or delay() or large Serial output or uses a (stupid) motor library which blocks while the motor moves.

OK, the magic for code 2 is to add the word ``` static ``` in front of unsigned. That will make it work (for a while), but it is still bad code, for the reasons mentioned above.

(Oh sometime I whish I had the time and tools to write the animation to explain this... )

I’m pretty sure I have figured out the problem, I just can’t fix it. In my main loop, I have an 'if" statement that reads if you push a button then you will go to my “void autoTop()”. While at the “void autoTop()” it should do the follow:

  • set the timer
  • assigns pin number
  • assigns pin as output
  • turns on LED since if statement is true and ignores else statement
  • after 10 seconds the if statement becomes false and the else statement turns off the LED
  • return to main loop

The problem is it only runs through once, leaving out the whole purpose of the “void autoTop()”, then it just returns to the main loop. I need it to continue to run till the if statement has became false, turn off the LED, then return to the main loop.

This is what it does instead of the above:

  • set the timer
  • assigns pin number
  • assigns pin as output
  • turns on LED since if statement is true and ignores else statement
  • return to main loop

Any Thoughts

/*********************************** ATO TOUCH SCREEN *********************************/
void topOff()
{
unsigned long MyDelay = millis() + 10000;     //set timer
const int ledPin =  13;                       //assigns pin number
pinMode(ledPin, OUTPUT);                      //assigns pin as output

/*************** led turns on *****************/
    if( millis() < MyDelay )                  //turns on LED since if statement is true
    digitalWrite(ledPin, HIGH);
    else                                      //ignores else statement since if statement is true
/*************** After 10 Seconds, LED turns off *****************/  
    digitalWrite(ledPin, LOW);
}                                             //returns to main loop
/******************************* END of ATO TOUCH SCREEN ******************************/

You need to separate the "turn off" portion of the function and put it in the main loop. To connect the two, you should set a flag variable in the function, and in the "turn off logic", check if the flag variable is set. Simple example:

int flag = 0;
unsigned long turnOnTime;
unsigned long interval;
void loop()
{
  if (someButtonIsPressed())
  {
    digitalWrite(ledPin, HIGH);
    turnOnTime = millis();
    interval = 1000;
    flag = 1;
  }

 if ( flag && millis() - turnOnTime > interval)
 {
    digitalWrite(ledPin, LOW);
    flag = 0;
  }
}

In this example, when someButtonIsPressed() returns true (presumably on the signal edge of some switch), the led is turned on, an interval is set and a flag is set. Then, outside the someButtonIsPressed() condition, a separate if statement turns it off when its been long enough.

In your statement correct here " if ( flag && millis() - turnOnTime > interval)" or should it read " if ( flag = 1 && millis() - turnOnTime > interval)" or do these both have the same meaning?

Thanks Billy

Wmtasker: In your statement correct here

if ( flag && millis() - turnOnTime > interval)

Correct

if ( flag == 1 && millis() - turnOnTime > interval)

Also correct

if ( flag = 1 && millis() - turnOnTime > interval)

Not correct

Arrch:

Wmtasker: In your statement correct here

if ( flag && millis() - turnOnTime > interval)

Correct

if ( flag == 1 && millis() - turnOnTime > interval)

Also correct

if ( flag = 1 && millis() - turnOnTime > interval)

Not correct

Thank you

Wmtasker: The problem is it only runs through once, leaving out the whole purpose of the "void autoTop()", then it just returns to the main loop. I need it to continue to run till the if statement has became false, turn off the LED, then return to the main loop.

You basically have to stop making functions that take a long time. Imagine if you were cooking and you just put the potatoes on, and decided you couldn't do anything else until they were cooked. That wouldn't be too good would it? So you note the time, and exit the "potato cooking" function and check back from time to time to see if they are ready.