2025 C LVGL Raspberry Pi Zero 2W Meshtastic LoRa SX1262 SPI Protobuf GPS

BugQuest LoRa

A homemade Meshtastic node on RPi Zero 2W — because a phone can do it, but a proper appliance does it better.

View on GitHub
BugQuest LoRa

LoRa and Meshtastic: the concept

LoRa (Long Range) is a low-power radio technology that allows sending small messages over several kilometers — without WiFi, without 4G, without conventional infrastructure. In practice, very simple messages traveling over the air on the 868 MHz band in Europe.

Meshtastic builds a network layer on top of that: each device becomes a node capable of relaying messages from others. There's no central server, no subscription, no single control point. If a path exists in the network, the message eventually arrives, even if the internet is offline.

What makes this kind of system interesting goes beyond the purely technical. It's another way to think about communication: distributed, resilient, independent from platforms. A network that continues to exist even when conventional infrastructure disappears — or simply when you choose to do without it.

Why not just a phone app?

The Meshtastic Android app exists, works very well and does exactly what you expect from it.

But a phone is still a phone: shared battery, unpredictable operating system, apps killed in the background, updates arriving whenever they want. And above all, hard to make a real permanent relay without sacrificing a device.

The goal here was different: a dedicated machine. An object that boots fast, consumes little (~3W), and does just one thing properly.

The final setup: Raspberry Pi Zero 2W, 3.5" SPI touchscreen, SX1262 LoRa 868 MHz radio, all in an... improvised enclosure! An appliance, not a compromise.

The node — RPi Zero 2W + touchscreen + LoRa SX1262 radio
The node — RPi Zero 2W + touchscreen + LoRa SX1262 radio

A GUI without a graphical environment

On a Raspberry Pi Zero 2W, launching X11 or Wayland just to display a UI doesn't make much sense. That's a lot of abstraction for little value.

The system therefore runs on Raspberry Pi OS Lite, without a desktop. The application is written in C and draws directly into the framebuffer (/dev/fb0).

For the interface, I use LVGL, an embedded graphics library designed for constrained systems, but perfectly suited here.

The real bottleneck is the screen's SPI bus. Refreshing a full framebuffer every frame is too costly. So dirty rectangles are used: only modified areas are redrawn.

For the offline map, one additional step was taken: tiles are pre-converted to RGB565, the screen's native format, which avoids any on-the-fly decoding.

Talking to Meshtastic from C

Meshtastic uses Protocol Buffers to encode its messages. On the Pi, the meshtasticd daemon exposes a local interface via TCP (127.0.0.1:4403).

I could have gone through Python or Node.js, but that would have added unnecessary layers for an application written entirely in C.

So I implemented a native protobuf client in C to communicate directly with the daemon and decode messages.

Fewer dependencies, minimal latency, and above all a more direct understanding of the protocol. More verbose, but much more stable over time.

Real-time node list — SNR, RSSI, battery and network status
Real-time node list — SNR, RSSI, battery and network status

"Unplanned" features

A LoRa node doesn't need to scan WiFi QR codes. Nor simulate a USB keyboard. Nor display a photo gallery. Nor update itself from its own interface.

But once the hardware is there — touchscreen, CSI camera, USB gadget enabled — possibilities chain together naturally.

The WiFi QR scanner allows configuring a network without a keyboard or complex interface, via standard WPA QR codes (libzbar).

USB HID mode lets the Pi present itself as a keyboard and automatically send key sequences to a connected computer.

The photo gallery exists simply because the camera was already there.

The OTA update is, on the other hand, genuinely useful: git pull, rebuild, reboot, with visual feedback in the interface.

Offline map — RGB565 tiles, nodes and real-time GPS position
Offline map — RGB565 tiles, nodes and real-time GPS position

In practice

The node is operational on the LoRa EU_868 network (869.525 MHz).

From the outside, it appears like any other Meshtastic node on the public map.

From the inside, it's a fully controlled system: a machine that does exactly what it was designed for, without depending on a phone, a third-party application or an external service.

And above all, an object that keeps working even when everything else becomes uncertain.

realitynauts@bugquest:~
×
Realitynauts
RN

$ cat auteur.txt

Realitynauts — Dev PHP / Python / Hardware
Autistic. Intensely focused. Always in prod.

$ cat opportunites.txt

Does this project resonate? Got a similar
or complementary project? Let's talk.

$ ./contact.sh