Bench NotesUno handbook

Non-Blocking Timing with millis()

Blink two LEDs at independent rates without delay(), using rollover-safe elapsed-time checks.

IntermediateLEDResistor

Overview

delay() stops everything. millis() returns the milliseconds since start-up, so the sketch can instead check "has enough time passed?" on every pass of the loop and keep doing other work in between.

You will need

  • Arduino Uno R3
  • 2 LEDs
  • 2 × 330 Ω resistors
  • Breadboard

Wiring

Uno pinConnects toNotes
6330 Ω → LED A anode
7330 Ω → LED B anode
GNDBoth LED cathodes
Wiring for Non-Blocking Timing with millis()Arduino Uno D6 to LED A anode through 330 Ω; Arduino Uno GND to LED A cathode; Arduino Uno D7 to LED B anode through 330 Ω; Arduino Uno GND to LED B cathode.Connections (each line is one wire)Arduino UnoLED ALED BD6anode330 ΩGNDcathodeD7anode330 ΩGND cathode
Original wiring diagram. Each line is one jumper wire; boxes on a line are series resistors.

Diagram

Two independent ratesLED A (every 250 ms): on 250 ms, then off 250 ms, then on 250 ms, then off 250 ms, then on 250 ms, then off 250 ms, then on 250 ms, then off 250 ms; LED B (every 700 ms): on 700 ms, then off 700 ms, then on 600 ms.LED A (every 250 ms)ON 250 msoff 250 msON 250 msoff 250 msON 250 msoff 250 msON 250 msoff 250 msLED B (every 700 ms)ON 700 msoff 700 ms0 ms2000 ms
Neither LED waits for the other.

The sketch

two_led_millis.ino
const int LED_A_PIN = 6;
const int LED_B_PIN = 7;
const unsigned long INTERVAL_A_MS = 250;
const unsigned long INTERVAL_B_MS = 700;

unsigned long lastToggleA = 0;
unsigned long lastToggleB = 0;
bool stateA = false;
bool stateB = false;

void setup() {
  pinMode(LED_A_PIN, OUTPUT);
  pinMode(LED_B_PIN, OUTPUT);
}

void loop() {
  unsigned long now = millis();

  if (now - lastToggleA >= INTERVAL_A_MS) {
    lastToggleA = now;
    stateA = !stateA;
    digitalWrite(LED_A_PIN, stateA ? HIGH : LOW);
  }

  if (now - lastToggleB >= INTERVAL_B_MS) {
    lastToggleB = now;
    stateB = !stateB;
    digitalWrite(LED_B_PIN, stateB ? HIGH : LOW);
  }

  // Free to read buttons or sensors here without slowing the LEDs
}

How the code works

Always store times in unsigned long and compare with now - last >= interval. The counter rolls over to 0 after about 49.7 days; unsigned subtraction still gives the right elapsed time across the rollover, while now >= last + interval does not.

What you should observe

  • LED A blinks quickly, LED B slowly, and neither disturbs the other.