ESP32-based RC transmitter for the MultiWii ESP32 drone flight controller using ESP-NOW wireless protocol.
- 4-channel control (Throttle, Yaw, Pitch, Roll)
- 2 AUX switches for flight modes
- Bi-directional telemetry from drone
- 16x2 I2C LCD display
- 50Hz update rate
- 500ms failsafe timeout
- Signal strength (RSSI) monitoring
| Component | Quantity | Notes |
|---|---|---|
| ESP32 Dev Board | 1 | Any ESP32 with ADC1 pins |
| Analog Joysticks | 2 | 2-axis with button (optional) |
| Toggle Switches | 2 | For AUX1/AUX2 |
| 16x2 I2C LCD | 1 | Address 0x27 (optional) |
| Battery | 1 | 1S-2S LiPo recommended |
| Function | GPIO | MiniKit Pin | Notes |
|---|---|---|---|
| Throttle | 36 | Pin 3 | Left stick Y-axis (ADC, input-only) |
| Yaw | 39 | Pin 4 | Left stick X-axis (ADC, input-only) |
| Pitch | 34 | Pin 5 | Right stick Y-axis (ADC, input-only) |
| Roll | 35 | Pin 6 | Right stick X-axis (ADC, input-only) |
| AUX1 | 26 | Pin 10 | Flight mode switch |
| AUX2 | 27 | Pin 11 | Secondary function |
| Left JS Btn | 4 | Pin 26 | Left joystick button (optional) |
| Right JS Btn | 16 | Pin 27 | Right joystick button (optional) |
| Battery | 32 | Pin 7 | Voltage divider (optional) |
| LCD SDA | 21 | Pin 9 (right) | I2C data |
| LCD SCL | 22 | Pin 12 (right) | I2C clock |
Notes:
- GPIO 34-39 are input-only (no internal pullups) - perfect for joystick ADC
- GPIO 26, 27 have internal pullups for switches
- Avoid GPIO 0, 2, 5, 12, 15 (strapping pins)
- Avoid GPIO 6-11 (connected to internal flash)
In Arduino IDE:
- File > Preferences
- Add to Additional Board URLs:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - Tools > Board > Boards Manager > Install "ESP32 by Espressif" (version 3.0.7+)
- LiquidCrystal_I2C - For LCD display (install via Library Manager)
Edit ESP_NOW_Transmitter.ino:
// Line 27 - Replace with your drone's MAC address
uint8_t RECEIVER_MAC[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};Get the drone's MAC address from its Serial Monitor output at boot:
ESP32 Receiver MAC Address: AA:BB:CC:DD:EE:FF
- Upload code with Serial Monitor open (115200 baud)
- Move each joystick to min, center, and max positions
- Note the raw ADC values (divided by 4 for 10-bit scale)
- Update calibration arrays:
// Lines 52-55
int throttleCal[] = {13, 524, 1015}; // {min, center, max}
int yawCal[] = {50, 505, 1020};
int pitchCal[] = {12, 544, 1021};
int rollCal[] = {34, 522, 1020};// Lines 58-61
bool throttleReverse = true; // Set false to invert
bool yawReverse = true;
bool pitchReverse = true;
bool rollReverse = true;- Select Tools > Board > ESP32 Dev Module
- Select correct COM port
- Click Upload
- Power on the drone first
- Power on the transmitter
- Transmitter auto-pairs when it receives first packet from drone
- LCD shows "TX OK" then telemetry data when linked
With telemetry:
3.7V 85% ARM
T:127 ANGLE
- Line 1: Drone battery, signal strength, armed status
- Line 2: Throttle value, flight mode
Without telemetry:
TX OK NO LINK
T:127 AUX1:0
Open Serial Monitor at 115200 baud:
TX: T=0 Y=128 P=128 R=128 AUX=0/0 | OK | Drone: 3.7V 85% ARM ANG
- Ensure throttle is at minimum (stick down)
- Move yaw stick fully right and hold for ~1 second
- LCD shows "ARM" when armed
- To disarm: throttle minimum + yaw left
struct struct_message {
uint8_t throttle; // 0-255
uint8_t yaw; // 0-255
uint8_t pitch; // 0-255
uint8_t roll; // 0-255
uint8_t AUX1; // 0 or 1
uint8_t AUX2; // 0 or 1
uint8_t switches; // Reserved
};struct struct_ack {
uint8_t vbat; // Battery (0.1V units, 37 = 3.7V)
uint8_t rssi; // Signal strength (0-100%)
int16_t heading; // Compass heading (degrees)
int16_t pitch; // Pitch angle (0.1 degrees)
int16_t roll; // Roll angle (0.1 degrees)
int16_t alt; // Altitude (cm)
uint8_t flags; // Status flags
};Flag bits:
| Bit | Meaning |
|---|---|
| 0 | Armed |
| 1 | Angle mode |
| 2 | Horizon mode |
| 3 | Baro mode |
- Verify drone is powered and ESP-NOW initialized
- Check MAC address matches exactly
- Ensure both devices on same WiFi channel (default: auto)
- Re-calibrate joystick values
- Check wiring to correct GPIO pins
- Verify using ADC1 pins (32-39)
- Check I2C address (try 0x3F if 0x27 doesn't work)
- Verify SDA/SCL wiring (21/22)
- Run I2C scanner sketch to find address
- Toggle the
*Reverseboolean for that axis - Or swap the wiring on the joystick potentiometer
#define TX_INTERVAL_MS 20 // 50Hz (default)
// Use 10 for 100Hz, 50 for 20HzThe switches byte is reserved for additional channels. Modify both transmitter and ESP_NOW_RX.cpp to use individual bits.
Comment out LCD code and remove the library include if not using a display.
GPL (inherited from MultiWii project)
- Original nRF24 transmitter: ELECTRONOOBS
- ESP-NOW conversion: Claude Code
- MultiWii flight controller: Alexandre Dubus