12 KiB
Architecture Documentation
System Overview
The ESP32 LED Controller is a real-time embedded system designed for model aircraft LED control with the following key components:
┌─────────────────────────────────────────────────────────┐
│ Application Layer │
│ ┌──────────┐ ┌───────────┐ ┌──────────────────────┐ │
│ │ main.c │ │ Web-BLE │ │ Animation Patterns │ │
│ └────┬─────┘ └─────┬─────┘ └──────────┬───────────┘ │
└───────┼──────────────┼────────────────────┼─────────────┘
│ │ │
┌───────┴──────────────┴────────────────────┴─────────────┐
│ Control Layer │
│ ┌──────────────────────────────────────────────────┐ │
│ │ control.c - System Orchestration │ │
│ │ - BLE GATT Server │ │
│ │ - NVS Configuration Storage │ │
│ │ - OTA Firmware Update │ │
│ │ - Subsystem Initialization │ │
│ └──────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
│ │ │
┌───────┼──────────────┼────────────────────┼─────────────┐
│ │ │ │ │
│ ┌────▼────┐ ┌────▼─────┐ ┌────▼─────────┐ │
│ │ LED │ │ RC Signal│ │ Animation │ │
│ │ Driver │ │ Reader │ │ Engine │ │
│ └─────────┘ └──────────┘ └──────────────┘ │
│ │
│ Hardware Layer │
└──────────────────────────────────────────────────────────┘
│ │ │
┌───────┼──────────────┼────────────────────┼─────────────┐
│ ┌────▼────┐ ┌────▼─────┐ │
│ │ RMT │ │ GPIO │ │
│ │ (WS2812)│ │ (PWM) │ │
│ └─────────┘ └──────────┘ │
│ │
│ ESP-IDF HAL & Drivers │
└──────────────────────────────────────────────────────────┘
Module Details
1. main.c - Application Entry Point
Responsibilities:
- System initialization orchestration
- Animation task creation and management
- System health monitoring
- Error handling and recovery
Key Functions:
app_main(): Entry point, initializes control systemanimation_task(): FreeRTOS task for 60 FPS animation updates
Task Priority: Animation task runs at priority 5 (above default)
2. control.c/h - System Control & Orchestration
Responsibilities:
- BLE GATT server implementation
- Configuration management (NVS)
- OTA firmware update handling
- Subsystem initialization and coordination
BLE Service Structure:
Service UUID: 0x00FF
├── Config Characteristic (0xFF01)
│ ├── Read: Get current configuration
│ └── Write: Update and persist configuration
├── Mode Characteristic (0xFF02)
│ ├── Read: Get current animation mode
│ └── Write: Set animation mode
├── PWM Emulation (0xFF03)
│ └── Write: Trigger mode change
└── OTA Characteristic (0xFF04)
└── Write: Stream firmware binary
Configuration Storage:
typedef struct {
int8_t led_pin_strip_a; // -1 = disabled
int8_t led_pin_strip_b; // -1 = disabled
int8_t pwm_pin; // -1 = disabled
ble_timeout_t ble_timeout; // 0, 60, 300 seconds
uint32_t magic; // 0xDEADBEEF validation
} controller_config_t;
NVS Namespace: led_ctrl
NVS Key: config
BLE Timeout Logic:
- Timer starts at boot
- Pauses when device connects
- Resumes when device disconnects
- Disables BLE advertising on timeout
OTA Update Flow:
- Client writes firmware data in 512-byte chunks
- ESP32 writes to inactive OTA partition
- Last chunk (< 512 bytes) triggers completion
- Validates partition, sets boot partition
- Resets configuration and restarts
3. led.c/h - WS2812B LED Driver
Technology: ESP32 RMT (Remote Control) peripheral
Why RMT?
- Hardware timing generation (no CPU overhead)
- Precise WS2812B timing requirements:
- T0H: 350ns ±150ns
- T0L: 900ns ±150ns
- T1H: 900ns ±150ns
- T1L: 350ns ±150ns
- Reset: >280µs
Implementation:
RMT Channel → Custom Encoder → WS2812B Strip
↓ ↓ ↓
80 MHz GRB Encoding Serial Data
Color Management:
- Internal RGB buffer for each strip
- Thread-safe access via mutex
- Hardware converts RGB → GRB for WS2812B
- Support for HSV → RGB conversion
Key Functions:
led_init(): Configure RMT channelsled_set_pixel_a/b(): Set individual LEDled_fill_a/b(): Set all LEDs same colorled_show(): Update physical LEDsled_fade_to_black(): Fade effect for trails
Memory Usage:
- Strip A buffer: num_leds * 3 bytes (RGB)
- Strip B buffer: num_leds * 3 bytes (RGB)
- Default: 44 LEDs * 2 strips * 3 = 264 bytes
4. rcsignal.c/h - PWM Signal Reader
Technology: GPIO interrupt + software edge detection
PWM Signal Specification:
- Standard RC PWM: 1000-2000µs pulse width
- Detection threshold: 1500µs
- Timeout: 100ms (signal loss detection)
Mode Change Logic:
PWM < 1500µs → Set "pull_detected" flag
↓
PWM > 1500µs AND pull_detected → Mode++
↓
pull_detected = false
Implementation:
- ISR captures rising/falling edges
- Calculates pulse width in microseconds
- Monitor task (10ms interval) detects mode changes
- Callback notifies animation system
Thread Safety:
- Volatile variables for ISR communication
- Monitor task runs at priority 5
5. animation.c/h - Animation Engine
Update Rate: 60 FPS (16.67ms per frame)
Global State:
global_hue: Slow color cycling (updates every 3 frames)frame_counter: Frame synchronizationcurrent_mode: Active animation pattern
Animation Techniques:
Fade Effects
// Smooth trails for chase animations
led_fade_to_black(amount);
// Each LED: color = (color * (255 - amount)) / 255
Beat Synchronization
// Sine wave based on BPM and time
beatsin16(bpm, min_val, max_val);
// Returns position oscillating between min and max
HSV Color Space
- Hue: 0-255 (color wheel)
- Saturation: 0-255 (color intensity)
- Value: 0-255 (brightness)
- Automatic RGB conversion
Animation Modes Breakdown:
-
Static Colors (Black, Red, Blue, Green, White)
- Single
led_fill()call - No per-frame updates needed
- Single
-
Rainbow
- HSV hue gradient across strip
- Hue offset per LED:
global_hue + (i * 7) - Global hue increments for animation
-
Rainbow Glitter
- Base rainbow + random white sparkles
- 80/255 chance per frame
- Random LED position
-
Confetti
- Fade to black (10/255 per frame)
- Random position + random hue
- Creates "fireworks" effect
-
Sinelon
- Sweeping dot using sine wave
- Position:
beatsin16(13 BPM) - 20/255 fade creates trails
-
BPM
- Color palette based on party colors
- Beat:
beatsin8(33 BPM) - Brightness modulation per LED
-
Navigation
- Fixed positions for aviation lights
- Red: LEDs 0-2 (left)
- Green: Last 3 LEDs (right)
- White blink: 30 Hz (half frame rate)
-
Chase (Red)
- Red dot with ±2 LED trail
- Position:
beatsin16(40 BPM) - No fade (instant clear)
-
Chase RGB
- Same as Chase but HSV color cycling
- Hue:
global_hue
-
Random
- Random LED, random color each frame
- Rare full clear event
Data Flow
Configuration Update Flow
Web Browser → BLE Write → control.c → NVS Save → Restart (if pins changed)
Animation Update Flow
animation_task (60Hz) → animation_update() → LED buffer → led_show() → RMT → LEDs
PWM Mode Change Flow
RC Signal → GPIO ISR → rcsignal.c → Callback → control.c → animation.c
OTA Update Flow
Web Browser → BLE Write (chunks) → control.c → esp_ota → Flash → Restart
Thread Safety
Mutexes Used
- led_mutex: Protects LED buffer access
- Used by: animation_update(), led_show()
- Type: FreeRTOS mutex
ISR Safety
- rcsignal.c: Volatile variables for ISR communication
- Minimal ISR work: Only timestamp and edge detection
- Deferred processing: Monitor task handles logic
Task Priorities
Priority 5: animation_task, rcsignal_monitor_task
Priority 1: BLE stack tasks (default)
Priority 0: Idle task
Memory Management
Static Allocation
- Configuration structure: 11 bytes (NVS)
- Animation state: ~100 bytes (global variables)
Dynamic Allocation
- LED buffers:
num_leds * 3 * 2bytes (both strips) - RMT encoder: ~200 bytes per strip
- BLE stack: ~30KB (ESP-IDF managed)
Flash Usage
- Code: ~500KB (with BLE stack)
- OTA partitions: 2x 1MB (dual-boot)
- NVS: 24KB
- Factory: 1MB
Heap Usage Estimate
- Total: ~50KB during operation
- Available: ~250KB on ESP32
Power Optimization
Active Mode
- CPU: 240 MHz (animation processing)
- BLE: Active (advertising/connected)
- Power: ~180mA (ESP32 only)
BLE Disabled Mode
- CPU: 240 MHz (animation only)
- BLE: Disabled after timeout
- Power: ~100mA (ESP32 only)
LED Power
- Per LED: ~60mA at full white
- 44 LEDs full white: ~2.6A
- Typical animation: ~500mA average
ESP32 vs ESP32-C3 Differences
ESP32 (Xtensa)
- Dual-core: FreeRTOS symmetric multiprocessing
- BLE + Classic Bluetooth controller
- More GPIO pins available
- Recommended for complex projects
ESP32-C3 (RISC-V)
- Single-core: Simpler task management
- BLE only (no Classic Bluetooth)
- Fewer GPIO pins
- Lower cost option
Compatibility
- Same codebase works on both
- Pin numbers differ (check datasheet)
- RMT peripheral identical
- BLE functionality identical
Performance Characteristics
Latency
- PWM detection: <10ms
- BLE command: <100ms
- Mode change: <20ms (next frame)
- LED update: 16.67ms (60 FPS locked)
Throughput
- LED data: ~13.44 Mbps theoretical (RMT)
- BLE: ~1 Mbps (limited by MTU)
- OTA: ~40 KB/s (BLE transfer)
Timing Precision
- Animation frame: ±0.5ms jitter
- WS2812B timing: ±50ns (RMT hardware)
- PWM measurement: ±1µs (ISR timing)
Future Enhancement Ideas TODO
- Dynamic LED Count: Auto-detect number of LEDs
- Multi-Strip Sync: Synchronized patterns
- Pattern Editor: Visual animation designer
- Scheduler: Time-based mode changes