Skip to content

kiazh/Esp32Network

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NRF24 Wireless Link Monitor

End-to-end embedded ML pipeline on ESP32-WROOM-32U + NRF24L01.

The ESP32 receives packets via NRF24L01, extracts real-time wireless link features, and runs a lightweight decision tree to classify the link into one of three states:

State Meaning
NORMAL Stable, low-loss transmission
WEAK High packet loss or long delays
INTERFERENCE Bursty / irregular arrival pattern

This project was built using AEL (AI Embedded Lab) with Claude Code driving the ESP-IDF build/flash/verify loop. See DEVELOPMENT.md for a walkthrough of how the AI iterated on the firmware.


Try it now — no hardware needed

Option A: Python simulation (no ESP32, no NRF24)

pip install numpy scikit-learn
python3 tools/simulate.py

Trains a fresh model on data/synthetic_link_data.csv, simulates all three link conditions, and shows a live ANSI dashboard in your terminal.

Option B: Firmware simulation (ESP32 only, no NRF24 transmitter)

cd firmware
. $IDF_PATH/export.sh
idf.py -DCONFIG_NRF24_SIM_MODE=y -p /dev/cu.usbserial-110 build flash monitor

The ESP32 generates synthetic packets internally — cycles NORMAL → WEAK → INTERFERENCE every 20 s. No second device required.


Running Modes

Mode Hardware needed How to run
Python simulation None python3 tools/simulate.py
Firmware simulation ESP32 only idf.py -DCONFIG_NRF24_SIM_MODE=y build flash monitor
Real hardware ESP32 + NRF24L01 + transmitter idf.py build flash monitor

Hardware (real mode only)

Component Notes
ESP32-WROOM-32U Any ESP32-WROOM variant works
NRF24L01 2.4 GHz transceiver — 3.3 V only
SSD1306 OLED 128×64 I2C display (optional)
Second NRF24L01 On any Arduino/ESP32 as the transmitter

Wiring

NRF24L01 → ESP32

NRF24L01 ESP32 GPIO
VCC 3.3 V
GND GND
CE 4
CSN 5
SCK 18
MOSI 23
MISO 19
IRQ NC

SSD1306 OLED → ESP32 (optional)

OLED ESP32 GPIO
VCC 3.3 V
GND GND
SDA 21
SCL 22

Project Structure

nrf24-link-monitor/
├── firmware/               ESP-IDF project (ESP32 target)
│   ├── CMakeLists.txt
│   ├── sdkconfig.defaults
│   ├── sdkconfig.sim.defaults  SIM_MODE config override
│   ├── partitions.csv
│   ├── components/
│   │   └── board/          Minimal board init (NVS flash)
│   └── main/
│       ├── main.c          App: RX task + feature task + serial CLI
│       ├── Kconfig.projbuild  menuconfig option for SIM_MODE
│       ├── nrf24l01.h/c    SPI driver for NRF24L01 RX mode
│       ├── link_features.h/c  Feature extractor (rate, loss, IAT, burst)
│       ├── link_model.h    Decision tree — generated by training/train.py
│       └── ssd1306.h/c     Minimal I2C OLED driver with 5×7 font
├── training/
│   ├── train.py            Train model → writes firmware/main/link_model.h
│   └── requirements.txt
├── experiments/
│   └── link_monitor_sim_test.py  Offline simulation test script
├── tools/
│   ├── collect.py          Serial CSV harvester for data collection
│   ├── simulate.py         Full pipeline simulation (no hardware needed)
│   └── requirements.txt
└── data/
    └── synthetic_link_data.csv   450-sample dataset (150/class) for offline training

Full Workflow (real hardware)

1. Install ESP-IDF

Follow the ESP-IDF getting started guide. This project requires ESP-IDF v5.x or v6.x.

. $IDF_PATH/export.sh

2. Build and flash

Find your port first:

# macOS
ls /dev/cu.usbserial-* /dev/cu.SLAB_USBtoUART 2>/dev/null
# Linux
ls /dev/ttyUSB*

Then flash:

cd firmware
# macOS:
idf.py -p /dev/cu.usbserial-110 build flash monitor
# Linux:
idf.py -p /dev/ttyUSB0 build flash monitor

3. Collect real training data

You need a second device with NRF24L01 transmitting on channel 76 with an 8-byte payload where byte 0 is a rolling sequence number.

pip install pyserial
python3 tools/collect.py --port /dev/cu.usbserial-110

In the serial monitor, send:

  • c → collect mode
  • 0 → label NORMAL (stable link)
  • 1 → label WEAK (move transmitter far away)
  • 2 → label INTERFERENCE (run a microwave / add BT traffic)

Collect ≥100 samples per class, then Ctrl+C.

4. Train the model

pip install numpy scikit-learn

# On your real collected data:
python3 training/train.py --data data/nrf24_link_data.csv

# Or use the included synthetic dataset to test the pipeline first:
python3 training/train.py --data data/synthetic_link_data.csv

This overwrites firmware/main/link_model.h with a freshly trained decision tree exported as a C static inline function — zero runtime dependencies on the ESP32.

5. Deploy updated model

cd firmware
idf.py -p /dev/cu.usbserial-110 build flash monitor

6. Serial commands

Key Action
i Inference mode (default)
c Collect mode
0 / 1 / 2 Set label (collect mode)
s Print status

The 4 Features

Feature Description
pkt_rate Packets received per second
loss_rate Fraction of expected packets missed (via sequence gaps)
avg_iat_ms Mean inter-arrival time between consecutive packets
burst_score σ/µ of IAT — high = bursty/erratic, low = regular

Features are computed over a 2-second sliding window at 1 Hz.


Model

A scikit-learn DecisionTreeClassifier (max depth 5) is trained on the collected features and exported as a C static inline function — zero runtime dependencies, no library required on the ESP32.

firmware/main/link_model.h is pre-generated from data/synthetic_link_data.csv so the firmware compiles and runs immediately without any extra steps. To retrain on real data, run training/train.py --data <your_csv>.

About

Embedded ML pipeline for NRF24 link quality classification on ESP32, built with AEL

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors