Here’s a comprehensive breakdown of all practical methods to blink an LED on an ESP32, categorized by execution model, with framework context, key APIs, and use-case guidance.
Blocking Methods #
| Method | Framework | Key API | Notes |
|---|---|---|---|
| Simple Delay | Arduino / ESP-IDF | delay(500) or vTaskDelay(pdMS_TO_TICKS(500)) | Blocks the CPU. Fine for single-task sketches. |
| Deep Sleep Wake | ESP-IDF / Arduino | esp_sleep_enable_timer_wakeup(), esp_deep_sleep_start() | Not for continuous blinking. Used for ultra-low-power periodic tasks (e.g., sensor + LED indicator). |
Non-Blocking / Polling Methods #
| Method | Framework | Key API | Notes |
|---|---|---|---|
| millis() State Machine | Arduino | if (millis() - lastToggle >= 500) { toggle(); } | Standard non-blocking pattern. Allows concurrent loops (WiFi, sensors, etc.). |
| esp_timer_get_time() | ESP-IDF | uint64_t now = esp_timer_get_time(); | Microsecond-precision version of millis(). Used in same state-machine pattern. |
Hardware Timer & Interrupt Methods #
| Method | Framework | Key API | Notes |
|---|---|---|---|
| Hardware Timer + ISR | ESP-IDF / Arduino | timer_create(), timer_arm(), attachInterrupt() | Uses ESP32’s 4 hardware timers. ISR toggles GPIO. Must be short & marked IRAM_ATTR. |
| LEDC Peripheral (Hardware PWM) | ESP-IDF / Arduino | ledcSetup(), ledcAttachPin(), ledcWriteTone() | Built-in PWM controller. Can generate exact square waves without CPU. Best for precise 1 Hz. |
| RMT Peripheral | ESP-IDF | rmt_init(), rmt_write_sample() | Remote control peripheral. Overkill for blinking but can output arbitrary pulse trains via DMA. |
FreeRTOS Task & Synchronization Methods #
(ESP32 runs FreeRTOS natively in both Arduino & ESP-IDF)









