A simple WiFi mesh network for ESP32-C3 devices using ESP-IDF.
-
Creates a self-organizing mesh network between ESP32-C3 devices
-
Automatically elects a root node to connect to your WiFi router
-
Sends messages between devices in the mesh## What it does## What it does
-
Works with 2 or more ESP32-C3 boards
- Creates a self-organizing mesh network between ESP32-C3 devices- Creates a self-organizing mesh network between ESP32-C3 devices
-
Install ESP-IDF v5.5.1
-
Edit the WiFi settings in
main/hello_world_main.c:- Automatically elects a root node to connect to your WiFi router- Automatically elects a root node to connect to your WiFi routerstatic const char *ROUTER_SSID = "YourWiFiName";- Sends messages between devices in the mesh- Sends messages between devices in the mesh static const char *ROUTER_PASS = "YourWiFiPassword";
- Works with 2 or more ESP32-C3 boards- Works with 2 or more ESP32-C3 boards
-
Build and flash:
idf.py build idf.py flash monitor
-
Repeat on multiple ESP32-C3 devices
-
First device powered on becomes the root node
-
Other devices automatically join as child nodes
-
All devices can send messages to each other
-
If the root node fails, another device takes over
Root device logs:
I MESH_UNIFIED: MESH_STARTED, layer=1
I MESH_UNIFIED: PARENT_CONNECTED, layer=13. **Build and flash**:3. **Build and flash**:
I MESH_UNIFIED: STATUS: connected=YES, layer=1, routing_table_size=1
Child device logs:
I MESH_UNIFIED: MESH_STARTED, layer=-1 idf.py flash monitor idf.py flash monitor
I MESH_UNIFIED: PARENT_CONNECTED, layer=2
I MESH_UNIFIED: STATUS: connected=YES, layer=2, routing_table_size=1
| Setting | Value | Purpose |
|---|---|---|
| Mesh Password | "meshpassword" |
Inter-node authentication |
| Max Children | 6 |
Connections per parent node |
| Message Buffer | 256 bytes |
RX/TX buffer size |
| Status Interval | 10 seconds |
Health check frequency |
# Install ESP-IDF v5.5.1
git clone --recursive https://github.com/espressif/esp-idf.git
cd esp-idf && git checkout v5.5.1
./install.sh esp32c3
# Activate environment
source export.sh # Linux/macOS
# OR
export.bat # Windows# Clone this repository
git clone https://github.com/heathatgallagher/esp32-mesh-project.git
cd esp32-mesh-project
# Configure for ESP32-C3
idf.py set-target esp32c3
# Build firmware
idf.py build
# Flash to device and monitor
idf.py -p /dev/ttyUSB0 flash monitor # Linux
# OR
idf.py -p COM3 flash monitor # WindowsAutomatically included via main/CMakeLists.txt:
nvs_flashβ Non-volatile storage managementesp_wifiβ WiFi stack and mesh networkingesp_netifβ Network interface abstractionesp_eventβ Event-driven architecture
Perfect for production deployment - zero configuration required!
# 1οΈβ£ Set auto-election on ALL devices
FORCE_ROOT = false
# 2οΈβ£ Flash identical firmware to all ESP32-C3 boards
idf.py flash
# 3οΈβ£ Power on devices in any order
# β¨ First device becomes root automatically
# β¨ Additional devices join as child nodesFor testing or specific topology requirements:
# 1οΈβ£ Designate one device as permanent root
FORCE_ROOT = true # Root device only
# 2οΈβ£ Set all other devices as nodes
FORCE_ROOT = false # Child devices
# 3οΈβ£ Power on root device FIRST, then childrenI MESH_UNIFIED: MESH_STARTED, mesh_id: 11:22:33:44:55:66, layer=1
I MESH_UNIFIED: ROOT_VOTE_STARTED
I MESH_UNIFIED: ROOT_VOTE_STOPPED
I MESH_UNIFIED: PARENT_CONNECTED, layer=1, parent=aa:bb:cc:dd:ee:ff
I MESH_UNIFIED: CHILD_CONNECTED: 12:34:56:78:90:ab
I MESH_UNIFIED: STATUS: connected=YES, layer=1, routing_table_size=2I MESH_UNIFIED: MESH_STARTED, mesh_id: 11:22:33:44:55:66, layer=-1
I MESH_UNIFIED: PARENT_CONNECTED, layer=2, parent=aa:bb:cc:dd:ee:ff
I MESH_UNIFIED: ROOT_ADDRESS: aa:bb:cc:dd:ee:ff
I MESH_UNIFIED: RX from aa:bb:cc:dd:ee:ff (10 bytes): hello-mesh
I MESH_UNIFIED: STATUS: connected=YES, layer=2, routing_table_size=1| Metric | Healthy Range | Warning Signs |
|---|---|---|
| Layer | 1 (root), 2-6 (nodes) | Layer 0 = disconnected |
| Routing Table | 1+ entries | 0 = isolated node |
| Connection | YES |
NO = mesh issues |
| Events/Min | < 100 | > 500 = instability |
Send JSON commands between any mesh nodes:
// π― Command examples
{"cmd":"toggle"} // Toggle GPIO output
{"cmd":"status"} // Request node status
{"cmd":"sensor_read"} // Read sensor data
// π€ Broadcasting to all descendants
mesh_data_t data = {
.data = (uint8_t*)"{\"cmd\":\"toggle\"}",
.size = 17,
.proto = MESH_PROTO_BIN,
.tos = MESH_TOS_P2P
};
mesh_addr_t broadcast = {0};
memset(broadcast.addr, 0xFF, 6); // Broadcast address
esp_mesh_send(&broadcast, &data, MESH_DATA_P2P, NULL, 0);Automatic message handling in dedicated FreeRTOS task:
// Messages processed in rx_task()
if (strstr((char*)data.data, "toggle")) {
gpio_set_level(LED_GPIO, !gpio_get_level(LED_GPIO));
ESP_LOGI(TAG, "LED toggled via mesh command");
}| Problem | Symptoms | Solution |
|---|---|---|
| π No Parent Found | Continuous scanning logs | β
Verify MESH_ID matchesβ Check WiFi router accessibility β Confirm mesh password |
| π« Build Errors | Component not found | β
Check main/CMakeLists.txt dependenciesβ Run idf.py reconfigure |
| πΆ Poor Connection | Frequent disconnections | β
Check signal strength (RSSI) β Reduce distance between nodes β Change WiFi channel |
| π Auth Failures | Router connection fails | β
Verify WiFi credentials β Check router security settings |
# π Monitor real-time logs with filtering
idf.py monitor | grep -E "(MESH_|STATUS:|ERROR)"
# βοΈ Advanced configuration
idf.py menuconfig
βββ Component Config β ESP Wi-Fi Mesh
# π Memory usage analysis
idf.py size-components
# π§Ή Clean rebuild
idf.py fullclean && idf.py build# π’ Healthy mesh formation
β
MESH_STARTED within 30 seconds
β
ROOT_VOTE_STOPPED (election complete)
β
PARENT_CONNECTED (joined hierarchy)
β
STATUS: connected=YES, layer>0
# π΄ Problematic patterns
β Repeated NO_PARENT_FOUND events
β Layer stays at 0 after 60+ seconds
β Routing table size remains 0
β Frequent PARENT_DISCONNECTED eventsβββ .github/
β βββ copilot-instructions.md # AI coding assistant instructions
βββ .vscode/
β βββ settings.json # VS Code ESP-IDF configuration
βββ main/
β βββ CMakeLists.txt # Component dependencies
β βββ hello_world_main.c # Core mesh implementation
βββ CMakeLists.txt # Project configuration
βββ sdkconfig # ESP-IDF build configuration
βββ README.md # This file
- ESP-IDF extension configured for ESP32-C3
- CLANGD integration for IntelliSense
- Serial monitor integration
- Hardware testing requires multiple ESP32-C3 devices
- Python pytest framework available
- Monitor mesh formation and message routing
This project is based on ESP-IDF examples and follows the same licensing terms.
For technical issues:
- Check the comprehensive logging output
- Review mesh event sequences
- Verify network topology in status messages