diff --git a/docs/hardware-setup.md b/docs/hardware-setup.md index 443c05b..fb1f337 100644 --- a/docs/hardware-setup.md +++ b/docs/hardware-setup.md @@ -22,41 +22,13 @@ Any ESP32 board based on the original ESP32 chip should work. Commonly available ## Wiring -### Default: USB only +### USB only (default) -For most development, a single USB cable handles both flashing and protocol communication. The ESP32's built-in USB-to-UART bridge (typically CP2102 or CH340) provides the serial link. +A single USB cable handles both flashing and NDJSON protocol communication. The ESP32 dev board's built-in USB-to-UART bridge (typically CP2102 or CH340) connects to UART0 (TX=GPIO1, RX=GPIO3). -The firmware uses **UART1** (GPIO4/GPIO5) for the NDJSON protocol and keeps **UART0** for ESP-IDF console logging. When using USB only, the USB bridge connects to UART0 by default -- so you will need either: +The firmware uses **UART0** for the NDJSON protocol. The ESP-IDF console is disabled (`CONFIG_ESP_CONSOLE_NONE=y`) so there is no conflict -- the firmware owns UART0 exclusively. No additional wiring or USB-UART adapters are needed. -1. A board that routes UART1 through the USB bridge (uncommon), or -2. A separate USB-UART adapter connected to GPIO4/GPIO5 (described below) - -For quick testing with the firmware's default pin assignment, connect a USB-UART adapter. - -### Dedicated UART (GPIO4/GPIO5) - -Connect a USB-UART adapter (e.g., FTDI FT232R, CP2102, CH340) to the ESP32: - -``` -ESP32 GPIO4 (TX) ----> USB-UART adapter RX -ESP32 GPIO5 (RX) <---- USB-UART adapter TX -ESP32 GND ----> USB-UART adapter GND -``` - -The adapter appears as a second `/dev/ttyUSB*` device on the host. Use this device path for `ESP32_SERIAL_PORT`. - -Do not connect voltage lines (VCC/3V3) between the adapter and the ESP32 if the board is already powered via its own USB port. - -### Pin reassignment - -If GPIO4/GPIO5 conflict with other peripherals on your board, change the pin definitions in `firmware/main/uart_handler.c`: - -```c -#define UART_TX_PIN GPIO_NUM_4 -#define UART_RX_PIN GPIO_NUM_5 -``` - -Rebuild and reflash after changing pins. +The dev board appears as `/dev/ttyUSB*` on the host. Use this device path for `ESP32_SERIAL_PORT`. ## ESP-IDF Setup @@ -115,13 +87,13 @@ make flash SERIAL_PORT=/dev/ttyUSB4 ### 5. Monitor (optional) -Open the ESP-IDF serial monitor to see console logs from UART0: +Open the ESP-IDF serial monitor to watch raw UART traffic. Since the firmware owns UART0 (console is disabled), you will see NDJSON protocol messages rather than ESP-IDF log output: ```bash idf.py -p /dev/ttyUSB4 monitor ``` -Press `Ctrl+]` to exit the monitor. +Press `Ctrl+]` to exit the monitor. Note: while the monitor is open, the MCP server cannot use the same serial port. ### 6. Flash and monitor in one step @@ -184,13 +156,13 @@ The project ships `firmware/sdkconfig.defaults` with the required Bluetooth conf | `CONFIG_BT_BLUEDROID_ENABLED` | y | Use Bluedroid host stack | | `CONFIG_BT_CLASSIC_ENABLED` | y | Enable BR/EDR (Classic BT) | | `CONFIG_BT_BLE_ENABLED` | y | Enable BLE | -| `CONFIG_BT_SSP_ENABLED` | y | Enable Secure Simple Pairing | | `CONFIG_BT_SPP_ENABLED` | y | Enable Serial Port Profile | | `CONFIG_BT_GATTS_ENABLE` | y | Enable GATT Server | | `CONFIG_BTDM_CTRL_MODE_BTDM` | y | Dual-mode controller (Classic + BLE simultaneously) | -| `CONFIG_NVS_ENABLED` | y | Non-volatile storage for bonding data | +| `CONFIG_ESP_CONSOLE_NONE` | y | Disable ESP-IDF console so firmware owns UART0 | +| `CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE` | y | 1.5MB app partition (dual-mode BT stack needs >1MB) | -Do not modify these unless you understand the implications. Disabling `CONFIG_BT_CLASSIC_ENABLED` breaks all Classic BT pairing tests. Disabling `CONFIG_BT_SSP_ENABLED` forces legacy PIN-only pairing. +Do not modify these unless you understand the implications. Disabling `CONFIG_BT_CLASSIC_ENABLED` breaks all Classic BT pairing tests. ## Troubleshooting @@ -232,13 +204,13 @@ If the board has auto-download circuitry (most DevKitC boards do), this should n ### No response over UART -1. **Verify TX/RX pin assignment.** The firmware uses UART1 on GPIO4 (TX) and GPIO5 (RX). If your adapter is connected to different pins, update `uart_handler.c`. +1. **Check baud rate.** Both sides must use 115200. Verify in `screen` or your terminal emulator. -2. **Check baud rate.** Both sides must use 115200. Verify in `screen` or your terminal emulator. +2. **Make sure nothing else is using the port.** The ESP-IDF monitor, `screen`, another MCP server instance, or any other serial tool will lock the device. Only one process can open `/dev/ttyUSB*` at a time. -3. **Check the correct serial device.** If the board has two USB-UART interfaces (one for UART0 console, one for UART1 protocol), make sure you are talking to the right one. +3. **Send valid JSON.** The firmware expects complete JSON objects terminated by `\n`. A bare `ping` won't work -- send `{"type":"cmd","id":"1","cmd":"ping"}\n`. -4. **Look at UART0 console output.** Connect the ESP-IDF monitor to the console port. Boot messages and error logs appear there. If you see `UART1 ready (TX=4 RX=5 @ 115200 baud)` in the log, the firmware started correctly. +4. **Verify the firmware booted.** After flashing, the firmware should emit a `boot` event within ~2 seconds. If you see nothing at all, try pressing the EN (reset) button on the board. ### Build errors about missing Bluetooth headers diff --git a/docs/protocol-spec.md b/docs/protocol-spec.md index 08dcf1c..dd327b6 100644 --- a/docs/protocol-spec.md +++ b/docs/protocol-spec.md @@ -8,7 +8,7 @@ Authoritative reference for the JSON-over-UART protocol used between the Python - **Baud rate:** 115200 - **Frame format:** 8N1 (8 data bits, no parity, 1 stop bit) - **Max line length:** 2048 bytes (lines exceeding this are silently dropped) -- **UART peripheral:** ESP32 UART1 on GPIO4 (TX) and GPIO5 (RX), keeping UART0 free for ESP-IDF console logging +- **UART peripheral:** ESP32 UART0 via the dev board's USB-to-UART bridge (TX=GPIO1, RX=GPIO3). ESP-IDF console is disabled (`CONFIG_ESP_CONSOLE_NONE=y`) so the firmware owns UART0 exclusively. - **Encoding:** UTF-8 - **Newlines:** `\n` only. Carriage returns (`\r`) are stripped by the firmware reader.