🛠 Multitâche non bloquant : heartbeat + bouton avec debounce
Objectives
Move away from sequential delay: execute two independent tasks in loop using millis — a 500 ms LED blink and a button with 30 ms software debouncing. This is the skill that separates beginners from intermediates on bare-metal microcontrollers (no OS on the UNO, just a bootloader).
Hardware
- 1 Arduino UNO R3 + USB-B cable
- 1 push button between pin 2 and GND (internal pull-up)
- 1 LED + 330 Ω resistor on pin 13 (or the built-in "L" LED)
Complete code
// Deux tâches sans delay : heartbeat 500 ms + toggle par bouton (debounce 30 ms).
const uint8_t LED = 13;
const uint8_t BTN = 2;
bool ledOn = false;
bool dernierEtatBtn = HIGH;
uint32_t dernierBlink = 0, dernierChangementBtn = 0;
void setup {
pinMode(LED, OUTPUT);
pinMode(BTN, INPUT_PULLUP);
Serial.begin(9600);
}
void loop {
uint32_t maintenant = millis;
// Tâche 1 : heartbeat non bloquant.
if (maintenant - dernierBlink >= 500) {
dernierBlink = maintenant;
digitalWrite(LED, !digitalRead(LED));
}
// Tâche 2 : bouton avec anti-rebond de 30 ms, front d'appui.
bool btn = digitalRead(BTN);
if (btn != dernierEtatBtn && maintenant - dernierChangementBtn >= 30) {
dernierChangementBtn = maintenant;
dernierEtatBtn = btn;
if (btn == LOW) { // appuyé (actif-bas)
ledOn = !ledOn;
Serial.print(F("toggle -> ")); Serial.println(ledOn);
}
}
digitalWrite(LED, ledOn ? HIGH : LOW);
}
Expected verification
The LED pulses continuously; each press (a single one, even if the button clicks) toggles the state displayed in the Serial Monitor. Test the difference: without the 30 ms window, a single press triggers 3 to 10 visible toggles in the Monitor — mechanical bouncing is real.
Common errors
- Comparing
millis < previous:millisoverflow occurs after ~50 days; unsigned subtraction (now - previous >= X) is the only correct form. - Updating the timestamp only when the state is stable: the debounce window never closes.
- Mixing the
ledOnflag and the heartbeat on the same LED without understanding who writes last (here, the finaldigitalWritewins). - Wanting "real" multitasking: beyond a few tasks, look at the official FreeRTOS AVR port rather than stacking
if millischecks. - Forgetting that
loopmust remain short: no long calculations (1-Wire sensor, I²C wait) should block the heartbeat.
Other tutorials for this board
Code examples for this board
clignotante.inoArduinobouton-poussoir.inoArduinopwm-fade.inoArduinocapteur-lumiere-ldr.inoArduinoservo-balayage.inoArduinoruban-neopixel.inoArduino