A fork of the RNode Firmware CE (Community Edition) with added NeoPixel status indicator support for ESP32-based boards like the LilyGO LoRa32 v2.1.
The NeoPixel lights up on boot and on every data transfer (RX/TX), giving you an at-a-glance visual indicator that your node is alive and actively relaying traffic.
When the device powers on, the NeoPixel lights up purple and stays lit while the firmware initializes. The OLED display cycles through hardware init, device checks, and version info — all while the NeoPixel confirms the node is alive.
Once checks pass, the device is ready and the NeoPixel remains lit for 60 seconds before turning off. Any RX or TX activity re-triggers it.
The upstream firmware already has NeoPixel support for some boards (e.g. NRF52-based RAK4631). This fork extends it to ESP32-based boards (specifically the LilyGO LoRa32 v2.1) and adds a timed activity indicator so the LED stays lit for a configurable duration after each event:
| Event | Default Color | Default Duration |
|---|---|---|
| Boot | Purple (128, 0, 128) | 60 seconds |
| RX (receive) | White (255, 255, 255) | 30 seconds |
| TX (transmit) | Blue (0, 0, 255) | 30 seconds |
After the timeout, the LED turns off automatically. Any new activity resets the timer.
Mark Qvist's original build guide suggests wiring the NeoPixel data line to GPIO 12. We found that GPIO 12 does not work — it's a strapping pin on the ESP32 that controls the flash voltage regulator at boot. If it's pulled high by the NeoPixel data line during reset, the board can fail to boot entirely or behave erratically.
This fork defaults to GPIO 13 instead, which works reliably. If you've already built your RNode following the original guide, you'll need to move the data wire from GPIO 12 to GPIO 13 (they're right next to each other on most ESP32 boards).
You can override the pin at compile time if you've wired to a different GPIO:
#define PIN_NEOPIXEL 13All NeoPixel parameters can be overridden with #define before including Config.h (or passed as build flags):
// Timeouts (milliseconds)
#define NP_BOOT_TIMEOUT_MS 60000
#define NP_RX_TIMEOUT_MS 30000
#define NP_TX_TIMEOUT_MS 30000
// Boot color (RGB 0-255)
#define NP_BOOT_R 128
#define NP_BOOT_G 0
#define NP_BOOT_B 128
// Receive color
#define NP_RX_R 255
#define NP_RX_G 255
#define NP_RX_B 255
// Transmit color
#define NP_TX_R 0
#define NP_TX_G 0
#define NP_TX_B 255A known-good pre-built binary for the LilyGO LoRa32 v2.1 is included in the Release/ directory. You can flash it directly without compiling anything.
- arduino-cli installed
- ESP32 core installed (
make prep-esp32, orarduino-cli core install esp32:esp32@2.0.17 --config-file arduino-cli.yaml) - Your RNode connected via USB
# macOS
ls /dev/cu.usb*
# Linux
ls /dev/ttyACM* /dev/ttyUSB*arduino-cli upload -p /dev/cu.usbserial-XXXX \
--fqbn esp32:esp32:ttgo-lora32 \
--input-file Release/rnode_firmware_lora32v21_neopixel.binReplace /dev/cu.usbserial-XXXX with your actual serial port.
After flashing, set the firmware hash so rnodeconf recognizes the device:
rnodeconf /dev/cu.usbserial-XXXX --firmware-hash $(./partition_hashes Release/rnode_firmware_lora32v21_neopixel.bin)The RNode Bootstrap Console is stored in a separate SPIFFS partition. To flash it:
python3 Release/esptool/esptool.py \
--port /dev/cu.usbserial-XXXX \
--chip esp32 --baud 921600 \
--before default_reset --after hard_reset \
write_flash -z --flash_mode dio --flash_freq 80m --flash_size 4MB \
0x210000 Release/console_image.binTo compile the firmware yourself, you need arduino-cli installed.
# Install dependencies (ESP32 core, libraries, etc.)
make prep-esp32
# Build for LilyGO LoRa32 v2.1
make firmware-lora32_v21
# Upload to device (defaults to /dev/ttyACM0, override with port=)
make upload-lora32_v21 port=/dev/cu.usbserial-XXXXThe upload-lora32_v21 target handles flashing the firmware, setting the firmware hash, and writing the console image in one step.
See the upstream build documentation for full details on all supported targets.
This fork is tested on the LilyGO LoRa32 v2.1 with an external NeoPixel on GPIO 13. It should work on any ESP32-based RNode board with a WS2812/NeoPixel connected to the configured pin.
For the full list of boards supported by the base firmware, see the upstream RNode Firmware CE.
This project builds on the work of others. Big thanks to:
-
Mark Qvist — Creator of the Reticulum network stack, the original RNode Firmware, and the RNode ecosystem. His handheld RNode build guide is what got us started, and the NeoPixel wiring in this fork follows his design (with the GPIO 12 to 13 fix). His blog and documentation are invaluable resources for anyone working with RNodes.
-
Jacob Eva / Liberated Embedded Systems — Maintainer of the RNode Firmware CE (Community Edition), which this repo is forked from. The CE fork added NeoPixel support for the LilyGO LoRa32 (contributed by @0x62 in PR #71) and continues to expand board support.
-
Reticulum — The cryptography-based networking stack that RNodes are designed to work with. None of this would exist without it.
GNU General Public License v3.0 — see LICENSE for details.
The upstream RNode Firmware is Copyright 2024 Mark Qvist / unsigned.io. The RNode Firmware CE is Copyright Jacob Eva / Liberated Embedded Systems. The SX1276 driver is released under MIT License, Copyright 2018 Sandeep Mistry / Mark Qvist.



