Your questions, comments, and even corrections are encouraged and very much appreciated! However. I have zero-tolerance for inappropriate or harassing comments. I try to reply to everyone... -James

Leave a comment

12 thoughts on “Blink without delay() explained line-by-line

  1. Hello,
    Great write up – the line by line was very helpful for beginners like myself. I need some further advice on how to do the following:

    1- Always be “looking” for a switch
    2- When the switch is closed sweep a servo (I have this part of the code working nicely)
    3- Wait some amount of time when the sweep is complete to start “looking” for the switch being closed again. So even if the switch is held closed or closed again during this time frame the servo will not sweep.

    It seems I need to somehow use the Millis() command and perhaps some type of flag/states as in your example code in the comments below. I’m just not sure how to tie them together and any help is much appreciated as I mentioned I’m new to the Arduino/coding world.

    Thanks!

  2. Hi! I need to use the Millis() command while reading data from the HX711 ADC. Do you happen to have any tutorial about how to program any ADC (such as the HX711), please? Thank you!

  3. hi
    i am working on a project theft intimation of vehicles using gsm and tracking it by gps.
    here i am getting stuck with the infinite loop used in gps as it is continuously sending the lattitude and longitude. i also have to check 4 ir sensors and a pir sensor continuously.
    please help me urgently for how am i going to use two loops in a program, out of which one is infinite loop.
    the codes i am using are

    (code removed)

    please reply as soon as posible
    thank you

  4. Hi,
    I’m trying to figure out how to print a statement after a certain amount of time after a button is pushed and held down. Millis() starts at the beginning of when the program starts and I want it after the button is pushed. Any suggestions?

    • Just like all of the other millis() examples I have. Record the time at which the event occurs, then compare to the previous time. Use flags to control when the message goes out.

      Something like this:

      //Global Variables
      unsigned long buttonPushedMillis;
      unsigned long delayInterval = 2500; // 2500ms or 2.5 second
      bool messageReady = false; // flag for when button is let go
      
      void setup() {
        Serial.begin(9600);
        pinMode(2, INPUT_PULLUP);
      }
      
      void loop() {
        unsigned long currentMillis = millis(); // record what time it is
        
        // this code will work with a pushbutton using the internal pull-up
        // the variable "buttonPushedMillis" will get updated each iteration of loop, or
        // while the button is held down. when released, buttonPushedMillis has the "last"
        // value of millis
          if (digitalRead(2) == LOW) {
           buttonPushedMillis = currentMillis;
           messageReady = true;
          }
        
        // make sure this code isn't checked until after button has been let go
        if (messageReady) {
          //this is typical millis code here:
          if ((unsigned long)(currentMillis - buttonPushedMillis) >= delayInterval) {
             // okay, enough time has passed since the button was let go.
             Serial.println("Message");
             // wait for next button press
             messageReady = false;
          }
        }
      }
      
  5. Hey James-

    I have been trying to wrap my brain around the millis() concept and i seem to be missing something. I have read your posts roughly 5-6 times each. I just can’t grasp the concept. I have the below code that currently is running and working just fine. I am looking to add a string of Neopixel code to run while the linear actuator is moving both up or down, but only then. Think of it like a warning light while the actuator is moving. I understand the delay() function literally stops the whole void loop() and nothing else can be done, but I just can’t apply the millis() concept. If you have time I would appreciate you taking a look at my code and seeing if you can point me in a direction. I am fairly new to the Arduino world, and while I am enjoying myself I find moments like these frustrating. I appreciate your help in advance.

    The Neopixel code would go where I’ve marked it below:

    //2015 TV Stand and Controller Control
    const int Relay1 = 7;    
    const int Relay2 = 6;
    const int Relay3 = 5;
    const int Relay4 = 4;
    
    int Relay1a = 8;
    int Relay2a = 9;
    int Relay3a = 10;
    int Relay4a = 11;
    
    const int buttonPin0 = 0;
    const int buttonPin1 = 1;
    const int buttonPin2 = 2;
    const int buttonPin3 = 3;
    
    int buttonState0 = 0;
    int buttonState1 = 0;
    int buttonState2 = 0;
    int buttonState3 = 0;
    
    // the setup routine runs once when you press reset:
    void setup()  {
       
      pinMode(buttonPin0, INPUT);
      pinMode(buttonPin1, INPUT);
      pinMode(buttonPin2, INPUT);
      pinMode(buttonPin3, INPUT);  
      
      pinMode(Relay1, OUTPUT);
      pinMode(Relay2, OUTPUT);
      pinMode(Relay3, OUTPUT);
      pinMode(Relay4, OUTPUT);
      pinMode(Relay1a, OUTPUT);
      pinMode(Relay2a, OUTPUT);
      pinMode(Relay3a, OUTPUT);
      pinMode(Relay4a, OUTPUT);
       
    }
    
    void loop ()  { 
      buttonState0 = digitalRead(buttonPin0);//Keyfob D
      buttonState1 = digitalRead(buttonPin1);//Keyfob C
      buttonState2 = digitalRead(buttonPin2);//Keyfob B
      buttonState3 = digitalRead(buttonPin3);//Keyfob A 
    
     if (buttonState3 == HIGH) {
    
    //Neopixel code runs here until the 22 seconds to lift the actuator are up and then they would stop
    
        digitalWrite(Relay1,HIGH);//Actuator up segment
        delay(22000);
        digitalWrite(Relay1,LOW);    
      }
      
      if (buttonState3 == LOW){
      }
      
      if (buttonState2 == HIGH) {
    
    //Neopixel code would run here until the 23 seconds to close the actuator are up and then stop
        
        digitalWrite(Relay2,HIGH);//Actuator down segment
        delay(23000);
        digitalWrite(Relay2,LOW);
      }
        
      if (buttonState2 == LOW);{
      }
      
      if (buttonState1 == HIGH) {
        
        digitalWrite(Relay1a, HIGH);//XBox Controller Tray
        delay(1000);
        digitalWrite(Relay1a, LOW);
        delay(10000);
        digitalWrite(Relay2a, HIGH);
        delay(1000);
        digitalWrite(Relay2a,LOW);
      }
      
      if (buttonState0 == HIGH){
        
        digitalWrite(Relay3a, HIGH);//Remote Control Tray
        delay(1000);
        digitalWrite(Relay3a, LOW);
        delay(10000);
        digitalWrite(Relay4a, HIGH);
        delay(1000);
        digitalWrite(Relay4a, LOW);
      }
    }
    • The changes you need to make aren’t difficult, but will require rethinking the code. Your code can’t have sequential steps. Instead, you need to build “states”. This lets the code decide what the next step will be. For example, once a button is pressed set a flag to high. if that flag is high and relay1’s initial state is 0, then turn it on and “wait.” once that time is over, make relay1’s state be equal to 1 for the off time and “wait.” once that is done set your relay1 state flag back to 0 and start the process with relay2.

      More than I can explain in comments here. I’d suggest you post your code and request on the arduino programming forum [forum.arduino.cc]. Feel free to provide the link once you do, and I’ll try to answer there.

      In the mean time, 3 things I noticed:

      1) based on the code, you need to make sure you are using pull-down resistors with your buttons. Otherwise, you’ll get false reads.

      2) your variable names aren’t very helpful. instead of “button2” make it “red lights” or whatever it controls. It is very easy to get confused between the numbers you make up, the pin numbers on the arduino, and pin numbers on the device when reading through code.

      3) I would avoid using D0 and D1, since those conflict with serial. So if you want to do any debugging, that is going to be very difficult.

  6. Thanks, James, for another excellent post! You might consider, however, revising it to keep the line numbers of the extracted lines consistent with the line numbers of the complete program.