I'm trying to make a project using NodeMCU that show pictures in small OLED screen and also controlling WS2812 LED Ring.

I manage to do each of them separately but I'm not sure how to mix them together. The problem lies in the fact that most code examples for both the screen and the LED use sleep and that will of course only work for one of the other but not both.

This is the first project I've looked at to display bitmaps with SSD1306 screen and nodemcu.

This is the second project I've looked at to control NeoPixel WS2812 ring.

The main project was that both of them use delay as a way to wait for some amount of time to "progress". But, I couldn't just wait because then it will mess up both the screen and the NeoPixel.

One more thing is I have to also take reading input into account. I still not 100% sure about the input but it will probably be potentiometer and maybe a button.

I think I have found the solution which is to break the large "tasks" of reading input, controlling screen and controlling leds into smaller parts and do the waiting in a cooperative way.

I've found this instructable which both explain how to do it and also provide code example.

I'll be glad to know if people how other ways to implement this.

  • 1
    I'm not sure how to mix them together ... how do you drink some water while eating dinner?
    – jsotola
    Jun 23, 2023 at 23:36
  • 2
    Why don't you post your code? We can take a look at it and probably suggest something to get you started.
    – Fahad
    Jun 25, 2023 at 9:43
  • 1
    There is an example called BlinkWithoutDelay (you can find that in the Arduino IDE by going to Files->Examples->02.Digital). That gives you an idea of how you can do your things without using delay(). The third link you added uses that concept.
    – Fahad
    Jul 5, 2023 at 7:49

1 Answer 1


You need to stop using delay and instead keep track of elapsed time. One of the comments under your question suggests looking at the BlinkWithoutDelay example, which is part of the Arduino IDE.

The jocular comment "how do you drink some water while eating dinner" suggests the solution. You do one thing for a moment, and then do another thing. When eating dinner you don't wait for the entire meal to be consumed before you can drink a glass of water.

Here's some example code that blinks two LEDs at different rates:

// Which pins are connected to which LED
const byte greenLED = 12;
const byte redLED = 13;

// Time periods of blinks in milliseconds (1000 to a second).
const unsigned long greenLEDinterval = 500;
const unsigned long redLEDinterval = 1000;

// Variable holding the timer value so far. One for each "Timer"
unsigned long greenLEDtimer;
unsigned long redLEDtimer;

void setup () 
  pinMode (greenLED, OUTPUT);
  pinMode (redLED, OUTPUT);
  greenLEDtimer = millis ();
  redLEDtimer = millis ();
  }  // end of setup

void toggleGreenLED ()
   if (digitalRead (greenLED) == LOW)
      digitalWrite (greenLED, HIGH);
      digitalWrite (greenLED, LOW);

  // remember when we toggled it
  greenLEDtimer = millis ();  
  }  // end of toggleGreenLED

void toggleRedLED ()
   if (digitalRead (redLED) == LOW)
      digitalWrite (redLED, HIGH);
      digitalWrite (redLED, LOW);

  // remember when we toggled it
  redLEDtimer = millis ();  
  }  // end of toggleRedLED

void loop ()

  // Handling the blink of one LED.
  if ( (millis () - greenLEDtimer) >= greenLEDinterval)
     toggleGreenLED ();

  // The other LED is controlled the same way. Repeat for more LEDs
  if ( (millis () - redLEDtimer) >= redLEDinterval) 
    toggleRedLED ();

/* Other code that needs to execute goes here.
   It will be called many thousand times per second because the above code
   does not wait for the LED blink interval to finish. */

}  // end of loop

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.