Firmware
Complete guide for building, flashing, configuring, and debugging the ESP32-S3 firmware.
Prerequisites
Section titled “Prerequisites”ESP-IDF Installation
Section titled “ESP-IDF Installation”Install ESP-IDF v5.x following the official guide:
mkdir -p ~/espcd ~/espgit clone -b v5.2 --recursive https://github.com/espressif/esp-idf.gitcd esp-idf./install.sh esp32s3source export.shmicro-ROS Component
Section titled “micro-ROS Component”The firmware depends on micro-ROS for ESP32. It will be fetched automatically by the ESP-IDF component manager on first build.
USB Driver
Section titled “USB Driver”- Linux: No driver needed (CP2102 supported by kernel)
- macOS: Install Silicon Labs CP210x driver
- Windows: Install CP210x Universal Driver from Silicon Labs
# Source ESP-IDF environment. $HOME/esp/esp-idf/export.sh
cd firmware/esp32
# Set target chipidf.py set-target esp32s3
# (Optional) Configure optionsidf.py menuconfig
# Build (default SKU: standard)idf.py buildSKU Variants
Section titled “SKU Variants”Available: basic, standard, industrial
# Build specific SKU variant (from firmware/esp32/ directory)cp sdkconfig.defaults.industrial sdkconfig.defaultsidf.py fullclean && idf.py buildHost-Side Unit Tests (no hardware needed)
Section titled “Host-Side Unit Tests (no hardware needed)”cd firmware/testsmake clean && make./test_runnerConnection
Section titled “Connection”Connect USB-C cable between your computer and the ESP32-S3 programming port.
If using UART header instead:
- TX -> USB-UART adapter RX
- RX -> USB-UART adapter TX
- GND -> GND
- Hold BOOT button during reset to enter download mode
Flash Command
Section titled “Flash Command”idf.py -p /dev/ttyUSB0 flashPort names by platform:
- Linux:
/dev/ttyUSB0or/dev/ttyACM0 - macOS:
/dev/cu.usbserial-*or/dev/cu.SLAB_USBtoUART - Windows:
COM3(check Device Manager)
Monitor
Section titled “Monitor”idf.py -p /dev/ttyUSB0 monitorExpected boot messages:
I (325) boot: ESP-IDF v5.2I (330) boot: compile time May 15 2026I (380) 3we_fw: Firmware version: 0.2.0 (standard)I (385) 3we_fw: Motor PID initialized (Kp=1.0, Ki=0.5, Kd=0.01)I (390) 3we_fw: IMU BNO055 detected at 0x28I (395) 3we_fw: micro-ROS transport: USB-CDC @ 921600 baudI (400) 3we_fw: Watchdog timeout: 200msI (405) 3we_fw: Ready. Waiting for micro-ROS agent...micro-ROS Agent (Pi Side)
Section titled “micro-ROS Agent (Pi Side)”After flashing, start the micro-ROS agent on the Raspberry Pi to bridge serial data to ROS 2 topics:
ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyACM0 --baud 921600Or use the built-in launcher:
threewe hw start-agentPublished Topics
Section titled “Published Topics”Once running, the ESP32 publishes:
| Topic | Type | Rate | Description |
|---|---|---|---|
/wheel_encoders | sensor_msgs/JointState | 50 Hz | Encoder ticks for 4 wheels (FL, FR, BL, BR) |
/imu/raw | sensor_msgs/Imu | 100 Hz | Raw IMU data from BNO055 |
/battery_voltage | std_msgs/Float32 | 1 Hz | Battery voltage reading |
Subscribed Topics
Section titled “Subscribed Topics”| Topic | Type | Description |
|---|---|---|
/cmd_vel | geometry_msgs/Twist | Velocity commands (converted to wheel speeds) |
/motor_enable | std_msgs/Bool | Enable/disable motor drivers |
Configuration
Section titled “Configuration”Edit firmware/esp32/main/config.h to adjust:
#define WHEEL_RADIUS_M 0.0325f // 65mm diameter wheels#define WHEEL_BASE_M 0.10f // distance from center to wheel#define ENCODER_CPR 11 // counts per revolution#define PID_KP 1.0f#define PID_KI 0.5f#define PID_KD 0.01f#define IMU_I2C_ADDR 0x28#define MOTOR_PWM_FREQ 20000 // 20 kHz PWM#define WATCHDOG_TIMEOUT_MS 200 // Stop motors if no cmd for 200ms#define MICROROS_BAUD 921600OTA Updates
Section titled “OTA Updates”For field-deployed robots, the firmware supports OTA updates:
# Build OTA imageidf.py build# Upload via network (requires OTA partition scheme)python scripts/ota_upload.py --ip 192.168.1.100 --file build/3we_firmware.binPre-flight checks before OTA:
- Battery voltage > 7.0V (3S LiPo)
- Robot is stationary (motors stopped)
- WiFi signal strength > -70 dBm
Troubleshooting
Section titled “Troubleshooting”| Symptom | Solution |
|---|---|
| ESP32 not detected on USB | Hold BOOT button while pressing RESET to enter download mode. |
| Agent connects but no topics | Check baud rate matches (921600 on both sides). |
| IMU reports zeros | Verify I2C wiring (SDA to GPIO8, SCL to GPIO9 on default config). |
| Motors jitter at low speed | Increase PID_KI or reduce MOTOR_PWM_FREQ. |
| Encoder counts drift | Confirm encoder CPR matches your specific motor model. |
| Build fails with “component not found” | Run idf.py reconfigure to fetch micro-ROS component. |