Meshtastic-compatible LoRa mesh firmware for Seeed Studio Wio-E5-LE Mini. LoRa mesh only, config via Serial, no BLE/GPS/display.
- MCU: STM32WLE5JC (Cortex-M4 + integrated sub-GHz radio)
- Radio: integrated SX1262-compatible, controlled via STM32WL HAL (SUBGHZSPI)
- Interfaces: UART (Serial) for config and application; no BLE/GPS/display
- RF switch: PA4 (RF_CTRL1), PA5 (RF_CTRL2). Default: RFO_HP (High Power PA)
- arm-none-eabi-gcc
- CMake 3.16+
- Git submodules initialized
git submodule update --init --recursive
./build.sh build # → build/meshtastic_mini.elf
./build.sh flash # Flash via OpenOCD / st-flashmkdir build && cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=../cmake/arm-none-eabi.cmake
cmake --build .| Option | Default | Description |
|---|---|---|
WIO_E5_USE_LP |
OFF | Use RFO_LP PA instead of RFO_HP |
WIO_E5_NO_TCXO |
OFF | Disable TCXO (crystal-only boards) |
USE_STM32WL_RADIO |
ON | SubGHz driver |
USE_NANOPB |
ON | nanopb runtime |
Two boards connected via USB — automatic bidirectional ping-pong:
pip install pyserial
python3 scripts/check_radio_link.pyExpected output:
[ttyUSB0] -> [ttyUSB1]: 'ping'
OK: [ttyUSB1] received 'ping', [ttyUSB0] received 'pong'
[ttyUSB1] -> [ttyUSB0]: 'ping'
OK: [ttyUSB0] received 'ping', [ttyUSB1] received 'pong'
PASS: radio link OK (both directions)
Options: --timeout 15, explicit ports: python3 scripts/check_radio_link.py /dev/ttyUSB0 /dev/ttyUSB1
USART1: PB6 (TX), PB7 (RX), 115200 8N1.
On boot: Meshtastic_mini started, mesh init done, loop.
Any text entered in the terminal is sent as LoRa payload. For example, typing hello + Enter sends the bytes "hello" over LoRa to all nodes. This is not a command — it is data transmitted by radio.
Received packets appear as: RX: <text> RSSI: -XX dBm SNR: X dB. The receiver automatically replies with "pong".
Commands (reserved words):
| Command | Description |
|---|---|
N1 … N9 |
Set node_id (e.g. N1 on first board, N2 on second) |
info |
Show frequency (MHz), SF, NodeId, last RSSI |
help |
List commands |
Default region EU868: 869.525 MHz, BW 250 kHz, SF11.
| Offset | Size | Field | Description |
|---|---|---|---|
| 0x00 | 4 | To | Destination NodeID (0xFFFFFFFF = broadcast) |
| 0x04 | 4 | From | Sender NodeID |
| 0x08 | 4 | Packet ID | Unique packet ID |
| 0x0C | 1 | Flags | HopLimit, WantAck, ViaMQTT, HopStart |
| 0x0D | 1 | Channel | Channel index/hash |
| 0x0E | 1 | Next hop | For relaying |
| 0x0F | 1 | Relay | Relaying node |
On receive: if hop_limit > 0 and packet not seen (by Packet ID + From), decrement hop_limit and rebroadcast.
STM32WLE5 hardware AES. Channel PSK 16 bytes → AES-128. Header is not encrypted; only payload.
To communicate with phones (Meshtastic app), ESP32 nodes, or any Meshtastic device: use the same region, Long Fast (or same preset), and the same channel key. See docs/CONNECTING_TO_MESHTASTIC.md for requirements, default LongFast PSK, step-by-step setup, and limitations.
Meshtastic_mini/
├── CMakeLists.txt
├── cmake/ # Toolchain, HAL/CMSIS/nanopb cmake
├── scripts/ # check_radio_link.py, dual_serial_monitor.py
├── firmware/
│ ├── Core/ # main_loop, serial_io, led, system_clock
│ ├── Radio/ # radio_stm32wl, lora_meshtastic, radio_phy, rf_ctrl
│ ├── Mesh/ # mesh_packet, flood_router
│ ├── Serial/ # serial_framing
│ ├── Crypto/ # aes_meshtastic
│ └── Config/ # config_store
└── third_party/ # STM32CubeWL, nanopb, meshtastic_protobufs
- Meshtastic LoRa Configuration
- Meshtastic Protobufs
- STM32WLE5 Reference Manual
- Wio-E5-LE Mini
- Seeed LoRaWan-E5-Node
To allow flashing: set RDP level to AA, nBOOT0 = 0 via STM32CubeProgrammer.