Skip to content

Repository files navigation

ESP32 Alarm Clock with NeoPixels, Wi-Fi, and NVS Persistence

This project is an ESP-IDF–based firmware for ESP32 that combines:

  • Wi-Fi Manager with captive portal for first-time setup
  • Time Manager using NTP + local timezone rules
  • Alarm Manager with NVS persistence and one-shot timers
  • NeoPixel Driver with RMT hardware for smooth LED output
  • LED Animations including breathing, pulsing, rainbow, and cross-fade to solid
  • Button Manager for latching or momentary button events
  • Potentiometer Manager to control maximum LED brightness in real time

The system can trigger LED animations at configured alarms or timers, with brightness capped by a physical potentiometer.


Features

  • Wi-Fi Manager

    • Connects to stored credentials in NVS
    • If connection fails, starts an AP (ESP32_Config) with a captive portal for entering credentials
  • Time Manager

    • Syncs via NTP
    • Handles daylight savings through POSIX TZ rules
    • Provides callbacks when time is synced
  • Alarm Manager

    • Supports daily alarms at specified times
    • Per-alarm enabled/disabled state
    • Alarms persist across reboots via NVS
    • One-shot timers (e.g., “run in 15 minutes”) supported
    • Alarms trigger LED animations or user callbacks
  • NeoPixel Driver

    • Uses ESP32’s RMT peripheral for precise WS2812/SK6812 timing
    • Supports both GRB (WS2812B) and GRBW (SK6812) strips
    • Global brightness cap applied at transmit
  • Animations

    • Breathing (sinusoidal brightness)
    • Pulsing (on/off cycles)
    • Rainbow (continuous cycling colors)
    • Fade-to-solid (cross-fade from current frame to a new solid color)
  • Button Manager

    • GPIO interrupt–driven, debounced edge detection
    • Fires callback on any state change (works for latching switches)
    • Example: toggle a 15-minute timer with each press
  • Potentiometer Manager

    • Reads an analog input (ADC1, e.g. GPIO34)
    • Smooths readings with IIR filter
    • Maps value to 0–255 brightness cap
    • Auto-refreshes LEDs so brightness changes apply immediately

Hardware

  • ESP32-WROOM or similar
  • NeoPixel strip (WS2812B or SK6812)
    • Data pin: GPIO 15
  • Button
    • Wired to GPIO 18
    • Configure internal pull-up if tied to GND
  • Potentiometer
    • Wired to ADC1 channel (default: GPIO34)
    • 10kΩ recommended, wiper to GPIO34, ends to 3V3 and GND

Getting Started

Prerequisites

  • ESP-IDF v4.4+ (recommended v5.1 or later)
  • Python environment for ESP-IDF (idf.py)

Build & Flash

idf.py set-target esp32
idf.py build flash monitor

Build Embedded Web UI (SPIFFS)

The firmware serves the SPA from a spiffs partition when connected to Wi-Fi.

  1. Build frontend assets:
cd web_frontend
npm install
npm run build
  1. Build + flash firmware (includes SPIFFS image via CMake):
cd ..
idf.py build flash monitor

Quick Copy-Paste Flow (Frontend + Firmware)

From the project root, run:

cd web_frontend && npm install && npm run build && cd .. && . $IDF_PATH/export.sh && idf.py build flash monitor

This does all of the following:

  • builds web_frontend/dist
  • packages it into build/spiffs.bin
  • flashes bootloader/partition table/app/SPIFFS image

On first boot, if no Wi-Fi credentials are found:

  • The ESP32 starts an AP called ESP32_Config
  • Connect and visit http://192.168.4.1 to enter SSID & password

Alarm settings are now loaded from flash storage, not hard-coded at boot.


Example Behavior

  • Boot:
    • LEDs show a connecting animation
    • Device connects to Wi-Fi and syncs time
  • Alarm:
    • At configured and enabled time (e.g., 12:00:00), LEDs cross-fade into a chosen animation
  • Button:
    • Each press triggers a callback (e.g., start a 15-minute one-shot timer)
  • Potentiometer:
    • Adjusting it immediately changes the maximum LED brightness

Project Structure

components/
  ├── wifi_manager/        # Wi-Fi + captive portal
  ├── time_manager/        # NTP sync + TZ
  ├── storage_manager/     # NVS wrapper
  ├── alarm_manager/       # Persistent alarms + one-shot timers
  ├── neopixel_driver/     # RMT-based LED driver
  ├── neopixel_animations/ # Breathing, rainbow, fade-to-solid, etc.
  ├── button_manager/      # Edge-triggered debounced button events
  └── pot_manager/         # ADC potentiometer → brightness cap
main/
  └── main.c               # Application wiring everything together
web_frontend/
  ├── src/                 # Mithril SPA
  └── mock-server/         # Local mock REST API for frontend testing

Alarm REST API

The device exposes a REST API on port 80:

  • GET /api/alarms
  • POST /api/alarms
  • PUT /api/alarms/:id
  • DELETE /api/alarms/:id
  • GET /api/vacation-mode
  • PUT /api/vacation-mode

Alarm payload:

{
  "id": "weekday",
  "day": 1,
  "hour": 6,
  "minute": 45,
  "second": 0,
  "enabled": true
}

The HTTP server is implemented in components/wifi_manager/wifi_manager.c. It serves:

  • Wi-Fi setup page on / when not connected
  • SPA static files from SPIFFS on / and /* when connected
  • REST API on /api/*

License

CC0 1.0 Universal


About

Set Adafruit Neopixel LEDs to a certain color at a certain time. This is designed to let my 4-year-old know when he can get out of bed in the morning so he does not wake us up too early.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages