fix(firmware): replace legacy ESP32 test code with verified ESP32-S3 master firmware & sdkconfig

This commit is contained in:
ertunc-ozbay 2026-10-17 19:20:11 +03:00
parent df7dc140ff
commit d94bd09527
4 changed files with 895 additions and 2855 deletions

View file

@ -7,9 +7,9 @@
[![RTOS](https://img.shields.io/badge/OS-FreeRTOS-008080?style=for-the-badge)](https://www.freertos.org/)
[![Status](https://img.shields.io/badge/Status-Active%20Prototype-success?style=for-the-badge)](#roadmap--milestones)
A custom, high-performance handheld remote controller engineered from scratch for dual-role applications: **long-range, low-latency RC vehicle control** and **USB/Bluetooth HID gaming**.
A custom, high-performance handheld remote controller engineered from scratch for dual-role applications: **long-range, low-latency RC vehicle control** and **USB/Bluetooth HID gaming**.
Built around the **ESP32-S3 (Xtensa® 32-bit LX7 dual-core @ 240 MHz)**, this project bridges hardware and software engineering—combining magnetic Hall-effect sensing, RF telemetry, hardware pulse-counted rotary inputs, hardware PWM audio synthesis, and an SPI graphics pipeline into a unified, battery-powered embedded platform.
Built around the **ESP32-S3-N16R8 (Xtensa® 32-bit LX7 dual-core @ 240 MHz)**, this project bridges hardware and software engineering—combining analog/Hall-effect sensing on `ADC1`, 2.4 GHz nRF24L01+ RF telemetry, hardware pulse-counted (`pulse_cnt`) rotary inputs, and a shared high-speed `SPI2_HOST` (FSPI) bus driving both the 1.3" SH1106 OLED display and radio transceiver without bus collisions.
---
@ -18,64 +18,69 @@ Built around the **ESP32-S3 (Xtensa® 32-bit LX7 dual-core @ 240 MHz)**, this pr
<p align="center">
<img src="images/TOP_VIEW.png" alt="Multi-Functional Controller Top View" width="700">
<br>
<em><b>Figure 1:</b> Top assembly layout — Dual Hall-effect joysticks, rotary encoder, tactile buttons, 1.3" SPI OLED display, NeoPixel telemetry bar, and audio transducers.</em>
<em><b>Figure 1:</b> Top assembly layout — ESP32-S3-N16R8 module, analog joystick, quadrature rotary encoder, 1.3" SH1106 SPI OLED display, and nRF24L01+ RF transceiver.</em>
</p>
<p align="center">
<img src="images/SIDE_VIEW_WITH_ANTENNA.png" alt="Multi-Functional Controller Profile & RF Antenna" width="700">
<br>
<em><b>Figure 2:</b> Ergonomic profile — 2.4 GHz high-gain dipole antenna connected to the NRF24L01+ RF transceiver, rotary dial, and dual USB-C ports.</em>
<em><b>Figure 2:</b> Ergonomic profile — 2.4 GHz external dipole antenna connected to the nRF24L01+ transceiver, rotary dial, and dual USB-C ports.</em>
</p>
<p align="center">
<img src="images/BOTTOM_VIEW.png" alt="Multi-Functional Controller Perfboard Soldering" width="700">
<br>
<em><b>Figure 3:</b> Underbody point-to-point bus routing — 6×9 cm perfboard with dedicated decoupled power rails (100 µF smoothing capacitor) and direct GPIO signal lines.</em>
<em><b>Figure 3:</b> Underbody point-to-point bus routing — 6×9 cm perfboard with dedicated decoupled power rails (100 µF smoothing capacitor across nRF24L01+ VCC/GND) and direct FSPI signal lines.</em>
</p>
---
## Key Hardware & Architectural Features
## Key Hardware & Firmware Architecture
- **Microcontroller Core:** Espressif ESP32-S3-N16R8 (16 MB Quad SPI Flash, 8 MB Octal PSRAM) running FreeRTOS preemptive multitasking.
- **Dual Wireless Pipelines:**
- **2.4 GHz RF (NRF24L01+):** Dedicated SPI radio module with external SMA antenna for low-latency, deterministic RC telemetry.
- **Bluetooth 5.0 LE & Wi-Fi:** Native wireless stacks for PC/gamepad HID modes and wireless telemetry streaming.
- **Precision Analog & Digital Controls:**
- **Dual Hall-Effect Joysticks:** Contactless magnetic sensing for zero stick drift and extended durability.
- **Hardware Pulse-Counted Rotary Encoder:** Quadrature decoding handled in hardware via the ESP32-S3 `pulse_cnt` peripheral to guarantee zero missed ticks during high-load processing loops.
- **Dedicated Navigation Buttons:** Tactile push-buttons configured with internal pull-ups for UI interaction and control toggling.
- **Multi-Sensor Audio & Visual Telemetry:**
- **1.3" SPI OLED Display (SH1106 / SSD1306):** Driven via hardware DMA SPI (`SPI2_HOST`) with custom frame buffering for menus, telemetry, and live status readouts.
- **Polyphonic Melodic Synthesis:** Passive buzzer modulated via hardware LEDC PWM timer (`LEDC_TIMER_0`, 13-bit duty resolution).
- **Percussive Acoustic Alerts:** Dual active buzzers for instant tactile/auditory feedback and warning signals.
- **Visual Beat & Metric Indicators:** Dedicated Kick (GPIO 21) and Hi-Hat (GPIO 22) LEDs alongside an 8-LED WS2812B NeoPixel RGB strip driven via RMT.
- **Microcontroller Core:** Espressif **ESP32-S3-N16R8** (16 MB Quad SPI Flash, 8 MB Octal PSRAM) running FreeRTOS.
- **Collision-Free Shared FSPI (`SPI2_HOST`) Bus:**
- Shares `MOSI` (`GPIO 11`), `MISO` (`GPIO 13`), and `SCK` (`GPIO 12`) between the **1.3" SH1106 OLED** (10 MHz clock) and the **nRF24L01+ 2.4 GHz Transceiver** (1 MHz clock) via independent hardware Chip Select lines (`GPIO 10` and `GPIO 14`).
- **Bare-Metal 5×8 OLED Graphics Engine & Multi-Screen UI State Machine:**
- Direct register-level driver for the 1.3" SH1106 controller (handling the 132×64 internal RAM 2-pixel column offset) with a complete 5×8 bitmap font table (`A–Z`, `0–9`, `<`, `>`, `[`, `]`, `(`, `)`, `/`, `-`, `:`, `.`).
- **4 Interactive Screens:**
1. `DRIVE VEHICLE`: Real-time One-Shot `ADC1` joystick acquisition (`VRx` / `VRy`) and live 2.4 GHz packet broadcasting (`rc_packet_t`).
2. `RADIO CONFIG`: Verifies physical nRF24L01+ SPI link (`SETUP_AW` register `0x03`) and tunes `RF_CH` (register `0x05`) live across channels `0–125` (`2.400–2.525 GHz`) using the rotary dial.
3. `CALIBRATE`: Live raw `ADC1` readout (`0–4095`) with one-click neutral center-point capture.
4. `SYSTEM INFO`: Displays target silicon (`ESP32-S3`) and real-time free RTOS heap memory (`esp_get_free_heap_size()`).
- **Hardware Quadrature Rotary Decoder (`pulse_cnt`):**
- Uses the ESP32-S3 hardware Pulse Counter peripheral on `GPIO 15` (`CLK`) and `GPIO 16` (`DT`) with a `1000 ns` hardware glitch filter and full 4× quadrature edge/level state decoding, paired with a `300 ms` debounced push-switch (`GPIO 17`).
- **Wi-Fi-Safe Analog Joystick Acquisition (`ADC1`):**
- Routes `VRx` (`GPIO 4`, `ADC1_CH3`) and `VRy` (`GPIO 5`, `ADC1_CH4`) with `12 dB` attenuation (`0–3.3V` full-scale) on `ADC_UNIT_1` to avoid `ADC2` Wi-Fi/RF arbitration conflicts.
- **Power Subsystem:**
- Dual parallel 18650 Li-ion cells delivering **4800 mAh** combined capacity.
- Dual USB-C ports: one dedicated for high-efficiency battery charging and one for USB-UART flashing, debugging, and wired HID gamepad control.
- 100 µF low-ESR electrolytic capacitor buffering transient current spikes from RF transmission bursts and buzzer pulses.
- 100 µF low-ESR electrolytic bulk decoupling capacitor suppressing nRF24L01+ TX current spikes.
---
## GPIO Pinout & Peripheral Mapping (ESP32-S3 Hardware Specification)
The physical controller uses a shared high-speed **SPI2_HOST** bus for both the 1.3" OLED and the NRF24L01+ RF transceiver, alongside dedicated ADC1 channels and hardware pulse-counter inputs:
The physical controller uses a shared high-speed **SPI2_HOST** (FSPI) bus for both the 1.3" SH1106 OLED and the nRF24L01+ RF transceiver, alongside dedicated `ADC1` channels and hardware pulse-counter inputs:
| Peripheral / Signal | GPIO | Hardware Interface | Description |
| :--- | :---: | :--- | :--- |
| **SPI Bus: MOSI** | `GPIO 11` | SPI Master Output (`SPI2_HOST`) | Shared data line for NRF24L01+ and OLED (`SDA` / `D1`) |
| **SPI Bus: MISO** | `GPIO 13` | SPI Master Input (`SPI2_HOST`) | Data line from NRF24L01+ radio module |
| **SPI Bus: SCK (Clock)** | `GPIO 12` | SPI Master Clock (`SPI2_HOST`) | Shared clock line for NRF24L01+ and OLED (`CLK` / `D0`) |
| **NRF24L01+ Chip Select (CSN)** | `GPIO 14` | Dedicated SPI Device Select | Radio bus enable / frame delimiter |
| **NRF24L01+ Chip Enable (CE)** | `GPIO 21` | Digital Output | Radio RX/TX state activation and power line |
| **OLED Chip Select (CS)** | `GPIO 10` | Dedicated SPI Device Select | Display bus enable |
| **OLED Data/Command (DC)** | `GPIO 9` | Digital Output | 1.3" OLED command vs. graphic data selection |
| **SPI Bus: MOSI** | `GPIO 11` | SPI Master Output (`SPI2_HOST`) | Shared data line for nRF24L01+ and OLED (`SDA` / `D1`) |
| **SPI Bus: MISO** | `GPIO 13` | SPI Master Input (`SPI2_HOST`) | Data line from nRF24L01+ radio module |
| **SPI Bus: SCK (Clock)** | `GPIO 12` | SPI Master Clock (`SPI2_HOST`) | Shared clock line for nRF24L01+ and OLED (`CLK` / `D0`) |
| **nRF24L01+ Chip Select (CS)** | `GPIO 14` | SPI Device Select | Dedicated radio bus enable |
| **nRF24L01+ Chip Enable (CE)** | `GPIO 21` | Digital Output | Radio TX/RX power state activation line |
| **OLED Chip Select (CS)** | `GPIO 10` | SPI Device Select | Display SPI bus enable |
| **OLED Data/Command (DC)** | `GPIO 9` | Digital Output | 1.3" OLED command vs. data selection |
| **OLED Reset (RES)** | `GPIO 8` | Digital Output | Hardware display reset line |
| **Joystick VRx (X-Axis)** | `GPIO 4` | ADC1 Channel 3 (12 dB Attenuation) | Analog X-axis potentiometer (0–3.3V range, Wi-Fi safe) |
| **Joystick VRy (Y-Axis)** | `GPIO 5` | ADC1 Channel 4 (12 dB Attenuation) | Analog Y-axis potentiometer (0–3.3V range, Wi-Fi safe) |
| **Joystick VRx (X-Axis)** | `GPIO 4` | `ADC1` Channel 3 (`12 dB` Atten) | Analog X-axis potentiometer input (`0–3.3V` safe) |
| **Joystick VRy (Y-Axis)** | `GPIO 5` | `ADC1` Channel 4 (`12 dB` Atten) | Analog Y-axis potentiometer input (`0–3.3V` safe) |
| **Rotary Encoder CLK** | `GPIO 15` | ESP-IDF `pulse_cnt` Unit | Quadrature channel A (hardware edge counter) |
| **Rotary Encoder DT** | `GPIO 16` | ESP-IDF `pulse_cnt` Unit | Quadrature channel B (hardware direction sensing) |
| **Rotary Encoder Switch (SW)**| `GPIO 17` | Digital Input (`PULLUP`) | Rotary push-button (menu select / enter) |
| **Rotary Encoder DT** | `GPIO 16` | ESP-IDF `pulse_cnt` Unit | Quadrature channel B (direction sensing) |
| **Rotary Encoder Switch (SW)**| `GPIO 17` | Digital Input (`PULLUP`) | Push-button (menu enter/select mode) |
### Silicon Multiplexing Notes (ESP32-S3-N16R8 vs. Classic ESP32)
1. **Octal PSRAM & Flash Reservation (`GPIO 26 – GPIO 37`):** On the **ESP32-S3-N16R8** (8 MB Octal PSRAM), `GPIO 26` through `GPIO 37` are wired internally to the Octal SPI Flash/PSRAM bus. Accessing `GPIO 26, 27, 32, 33` triggers an immediate *Guru Meditation Error / Cache Disabled Panic* on boot.
2. **Unbonded Silicon Pins (`GPIO 22 – GPIO 25`):** `GPIO 22, 23, 24, 25` do not exist on the ESP32-S3 pin multiplexing matrix.
3. **FSPI (`SPI2_HOST`) Default Matrix:** Uses native ESP32-S3 FSPI pins (`GPIO 10, 11, 12, 13`) for zero-penalty IOMUX/GPIO matrix routing rather than legacy 2016 ESP32 VSPI defaults (`GPIO 5, 18, 23`).
---
@ -83,13 +88,12 @@ The physical controller uses a shared high-speed **SPI2_HOST** bus for both the
```text
multi-functional-controller/
├── firmware/ # ESP-IDF C99/C++ Firmware Project
├── firmware/ # ESP-IDF C99 Firmware Project (ESP32-S3)
│ ├── CMakeLists.txt # Top-level CMake project configuration
│ ├── sdkconfig # ESP32-S3 configuration (PSRAM, Flash, FreeRTOS)
│ ├── sdkconfig # ESP32-S3 target configuration
│ └── main/
│ ├── CMakeLists.txt # Component registration
│ ├── idf_component.yml # Espressif component dependencies (led_strip)
│ └── mmcontroller.c # Core firmware: FreeRTOS tasks, pulse counter, SPI OLED, LEDC PWM
│ └── mmcontroller.c # Master firmware: Shared SPI2, SH1106 5x8 UI, nRF24L01+, PCNT, ADC1
├── hardware/ # KiCad 10 Electronic Design Automation (EDA)
│ ├── mfc-1.kicad_pro # KiCad project file
│ ├── mfc-1.kicad_sch # Complete schematic design & component symbols
@ -99,6 +103,7 @@ multi-functional-controller/
│ ├── SIDE_VIEW_WITH_ANTENNA.png # RF antenna and profile perspective
│ └── BOTTOM_VIEW.png # Perfboard underside bus wiring
├── .gitignore # Clean repository filter (builds, caches, local configs)
├── LICENSE # MIT License
└── README.md # Master engineering documentation
```
@ -131,9 +136,8 @@ multi-functional-controller/
4. Flash to the controller and open serial monitoring:
```bash
idf.py -p /dev/ttyUSB0 flash monitor
idf.py -p /dev/ttyACM0 flash monitor
```
*(Replace `/dev/ttyUSB0` with your serial device node, e.g. `/dev/ttyACM0`)*.
---
@ -154,15 +158,14 @@ The electronic schematic is developed in **KiCad 10**:
## Roadmap & Milestones
- [x] Initial hardware breadboard and perfboard prototype (6×9 cm assembly).
- [x] Dual-core ESP-IDF firmware setup with FreeRTOS task scheduling.
- [x] Hardware pulse-counter integration for quadrature rotary encoder (`driver/pulse_cnt.h`).
- [x] Hardware LEDC PWM audio synthesis & percussive buzzer drivers.
- [x] High-speed SPI OLED graphics driver with DMA channel support.
- [x] Addressable WS2812B NeoPixel telemetry integration.
- [x] Shared `SPI2_HOST` bus driving both 1.3" SH1106 OLED and nRF24L01+ without bus collisions.
- [x] Full 5×8 bare-metal font renderer (`A–Z`, `0–9`, and UI punctuation/symbols).
- [x] Hardware pulse-counter (`pulse_cnt`) quadrature decoder with 1000 ns glitch filter & 300 ms debounced state machine.
- [x] Live nRF24L01+ SPI register verification (`0x03`) and channel tuning (`0–125`) with `ADC1` joystick packet transmission.
- [ ] Custom multi-layer printed circuit board (PCB) design in KiCad.
- [ ] 3D-printable ergonomic handheld enclosure (PETG / Resin).
- [ ] Low-latency NRF24L01+ bidirectional packet protocol with ACK-payload telemetry.
- [ ] Standard USB Gamepad HID descriptor integration for plug-and-play PC gaming.
- [ ] Bidirectional ACK-payload telemetry from target RC vehicle.
- [ ] Native USB Gamepad HID descriptor integration on ESP32-S3 USB-OTG port.
---

View file

@ -1,2 +0,0 @@
dependencies:
espressif/led_strip: "==2.4.1"

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff