Building a Multi-Device RC Controller with ESP-NOW
Prerequisites: This is part of our IoT Firmware series. If you’re new to ESP32 development, make sure to check out our first blog post in the series where we cover the basics of ESP32 programming and MicroPython setup. Basic soldering skills will be helpful for this project, especially when connecting the joysticks and buttons to the ESP32-C6 board.
⚡ Check out the project repository for the complete source code, detailed setup instructions, and to contribute to the project! Feel free to star the repo if you find it helpful. 🌟
Ever wanted to control multiple devices wirelessly with a single controller? In this project, we’ll explore how to build a powerful RC controller using the ESP32-C6 microcontroller and ESP-NOW protocol. This isn’t just another RC project - it’s a versatile system that can control up to three different devices simultaneously, perfect for robotics, drones, or any IoT project that needs wireless control.
Why ESP-NOW?
ESP-NOW is a powerful wireless communication protocol developed by Espressif Systems. It offers several advantages over traditional wireless protocols:
- Low Latency: Perfect for real-time control applications
- Long Range: Up to 200 meters in open space
- Simple Implementation: No need for complex network setup
- Low Power Consumption: Ideal for battery-powered projects
- Peer-to-Peer Communication: Direct device-to-device communication without a router
Hardware Components
Here’s what you’ll need to build this project:
| Component | Quantity | Purpose | Notes |
|---|---|---|---|
| ESP32-C6 | 1 | Main microcontroller | Latest ESP32 variant with improved wireless capabilities |
| Analog Joysticks | 2 | Dual-axis control | 10K potentiometer type recommended |
| Push Buttons | 4 | Additional controls | Tactile switches with pull-up/down resistors |
| NeoPixel LED | 1 | Visual feedback | WS2812B compatible |
| Power Supply | 1 | Battery or USB power | 3.3V regulated power supply |
I recommend using a board with integrated WS2812B LEDs, such as the ESP boards from Waveshare.
Pin Configuration
Here’s the detailed pin mapping for connecting all components:
| Component | Pin | Function | Configuration |
|---|---|---|---|
| Joystick 1 X-Axis | GPIO 2 | Left/Right control | ADC, 11DB attenuation |
| Joystick 1 Y-Axis | GPIO 3 | Up/Down control | ADC, 11DB attenuation |
| Joystick 2 X-Axis | GPIO 0 | Secondary X control | ADC, 11DB attenuation |
| Joystick 2 Y-Axis | GPIO 1 | Secondary Y control | ADC, 11DB attenuation |
| Joystick 1 Button | GPIO 4 | Joystick 1 press | Pull-up input |
| Joystick 2 Button | GPIO 5 | Joystick 2 press | Pull-up input |
| Device Switch | GPIO 15 | Device selection | Pull-down input |
| Button 2 | GPIO 21 | Additional control | Pull-down input |
| Button 3 | GPIO 22 | Additional control | Pull-down input |
| Button 4 | GPIO 19 | Additional control | Pull-down input |
| NeoPixel LED | GPIO 8 | Status indicator | Digital output |
Software Architecture
The controller uses a simple but effective architecture:
Initialization
- ESP-NOW setup
- ADC configuration
- GPIO pin setup
- NeoPixel initialization
Main Loop
- Device selection handling
- Input reading
- Data packaging
- Wireless transmission
Data Communication
The controller sends data in a structured JSON format every 70ms (configurable):
{
"Joystick1-X": value, // 0-4095 (12-bit ADC)
"Joystick1-Y": value, // 0-4095 (12-bit ADC)
"Joystick2-X": value, // 0-4095 (12-bit ADC)
"Joystick2-Y": value, // 0-4095 (12-bit ADC)
"Joystick1-Button": value, // 0 or 1
"Joystick2-Button": value, // 0 or 1
"Button1": value, // 0 or 1
"Button2": value, // 0 or 1
"Button3": value, // 0 or 1
"Button4": value, // 0 or 1
"Device": active_device_index // 0, 1, or 2
}
Visual Feedback System
The NeoPixel LED provides intuitive feedback for device selection:
- 🟢 Green (10,0,0): Device 1 selected
- 🔴 Red (0,10,0): Device 2 selected
- 🔵 Blue (0,0,10): Device 3 selected
Common Challenges and Solutions
1. Connection Issues
If you’re experiencing connection problems:
- Verify MAC addresses are correctly configured in
device_macslist - Ensure devices are within range (up to 200m in open space)
- Check power supply stability (3.3V required)
- Verify ESP-NOW initialization sequence
2. Joystick Calibration
For optimal joystick performance:
- Use proper ADC attenuation settings (11DB for full 3.3V range)
- Implement deadzone handling (center point ±5%)
- Calibrate center points on startup
- Use 12-bit ADC resolution (0-4095 range)
3. Power Management
To ensure stable operation:
- Use a stable 3.3V power supply
- Add 100μF decoupling capacitors near power pins
- Consider separate power for NeoPixels (5V)
- Monitor power consumption (ESP32-C6 can draw up to 500mA)
Getting Started
Hardware Setup
- Connect components according to the pin configuration
- Ensure proper power supply
- Add decoupling capacitors
- Test continuity of all connections
Software Setup
- Flash MicroPython to ESP32-C6
- Upload the controller code
- Configure target device MAC addresses
- Test basic functionality
Testing
- Power on the controller
- Test each input
- Verify LED feedback
- Check wireless communication
- Monitor serial output for debugging
Future Enhancements
The project can be extended in several ways:
- Add more control channels
- Implement battery monitoring
- Create a custom enclosure
- Add OLED display for status
- Implement failsafe mechanisms
- Add OTA updates
- Implement power saving modes
Conclusion
This ESP-NOW RC controller project demonstrates the power and flexibility of ESP32 microcontrollers in wireless control applications. Whether you’re building a robot, drone, or any other IoT project, this controller provides a solid foundation for wireless control systems.
The combination of ESP-NOW protocol, MicroPython, and the ESP32-C6’s capabilities makes this project both powerful and accessible to makers of all skill levels.
Check Out the Project
Want to build this project yourself? Head over to our GitHub repository where you’ll find:
- Complete source code
- Detailed wiring diagrams
- Troubleshooting guide
- Example receiver code
- Community support
Happy building! 🚀