# 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 system - `animation_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:** ```c 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:** 1. Client writes firmware data in 512-byte chunks 2. ESP32 writes to inactive OTA partition 3. Last chunk (< 512 bytes) triggers completion 4. Validates partition, sets boot partition 5. 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 channels - `led_set_pixel_a/b()`: Set individual LED - `led_fill_a/b()`: Set all LEDs same color - `led_show()`: Update physical LEDs - `led_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 synchronization - `current_mode`: Active animation pattern **Animation Techniques:** #### Fade Effects ```c // Smooth trails for chase animations led_fade_to_black(amount); // Each LED: color = (color * (255 - amount)) / 255 ``` #### Beat Synchronization ```c // 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:** 1. **Static Colors** (Black, Red, Blue, Green, White) - Single `led_fill()` call - No per-frame updates needed 2. **Rainbow** - HSV hue gradient across strip - Hue offset per LED: `global_hue + (i * 7)` - Global hue increments for animation 3. **Rainbow Glitter** - Base rainbow + random white sparkles - 80/255 chance per frame - Random LED position 4. **Confetti** - Fade to black (10/255 per frame) - Random position + random hue - Creates "fireworks" effect 5. **Sinelon** - Sweeping dot using sine wave - Position: `beatsin16(13 BPM)` - 20/255 fade creates trails 6. **BPM** - Color palette based on party colors - Beat: `beatsin8(33 BPM)` - Brightness modulation per LED 7. **Navigation** - Fixed positions for aviation lights - Red: LEDs 0-2 (left) - Green: Last 3 LEDs (right) - White blink: 30 Hz (half frame rate) 8. **Chase (Red)** - Red dot with ±2 LED trail - Position: `beatsin16(40 BPM)` - No fade (instant clear) 9. **Chase RGB** - Same as Chase but HSV color cycling - Hue: `global_hue` 10. **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 1. **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 * 2` bytes (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 1. **Dynamic LED Count**: Auto-detect number of LEDs 2. **Multi-Strip Sync**: Synchronized patterns 3. **Pattern Editor**: Visual animation designer 4. **Scheduler**: Time-based mode changes