QMesh: A LoRa-based Voice Mesh Network

Developing a synchronized, flooded mesh network to carry codec2-encoded voice over LoRa

Similar projects worth following
QMesh sets out to provide an alternative to FM voice/APRS data in amateur radio by creating a system where every device serves as a repeater. Such a system will enable rapidly standing up voice networks for EMCOMM and special event communications. Moreover, the large link budget and non-frequency-duplexed design will allow for compact, low-cost, low-power repeater nodes that can operate in remote locations using a battery and solar panel for power.

Enabling this system is a synchronized, flooded mesh network. This network will carry codec2-encoded voice frames between devices. Semtech's Chirp Spread Spectrum-based waveform, LoRa, will enable to the network to resist the considerable self-interference that occurs with a flooded mesh network.

QMesh is a novel mesh networking protocol designed to provide rapid self-healing and streaming capabilities to mesh networks in order to allow for voice communications. QMesh uses synchronized flooding to provide for self-healing as well as the ability to stream data. QMesh applies two techniques to the LoRa Chirp Spread Spectrum (CSS) waveform in order to make QMesh work: Coded Chirp Spread Spectrum (CCSS) and Chirp Offset Multiple Access (COMA).

Synchronized Flooding

A flooded mesh network is a mesh network where every node repeats they packets they receive. Synchronized flooding is a form of flooding where every node repeats the data at the same time. Synchronized flooding allows for self-healing an isochronous data transfer, enabling meshed voice communications. A major drawback of synchronized flooding, however, is the massive self-interference that occurs from multiple nodes retransmitting at the same time. QMesh uses two techniques, Coded Chirp Spectrum (CCSS), and Chirp Offset Multiple Access (COMA), that reduces the self-interference and allows for reliable communcation.

Coded Chirp Spread Spectrum (CCSS)

Forward Error Correction (FEC) is essential to getting reliable communications in the presence of the large amount of self-interference that occurs with synchronized flooding. As a result, QMesh implements a sophisticated form of FEC on top of LoRa, currently Reed-Solomon-Viterbi (RSV). RSV is a combination of convolutional coding concatenated with Reed-Solomon coding. Used in the past in such applications as interplanetary spacecraft, RSV increases communication reliability for both weak signals as well as against interference.

Chirp Offset Multiple Access (COMA)

Chirp Offset Multiple Access (COMA) is a technique that adds randomized, controlled offsets to CSS transmissions in order to reduce interference and allow the receiver to receive one of the transmissions. COMA adds offsets in two ways: by "wobbling" the center frequency of the transmission (up to +/-25%), and by adding a timing offset of up to one half of a symbol period.

LoRa has two potential ways to “spread out” transmissions in order to increase the likelihood of successful capture. The first technique involves spreading out transmit energy at the chip level. Given that LoRa chirps are not continuous frequency sweeps, but rather a series of discrete chirps, slightly shifting the frequencies of the chips should reduce their interference between them. Likewise, by shifting the chirps in frequency and/or time, it should be similarly possible to reduce the amount of interference between colliding packets and increase the likelihood of successful capture. Figures 2 and 3 show how frequency and time shift reduce overlap between transmissions and increase the likelihood of successful capture.

Frequency Hopping Spread Spectrum (FHSS)

QMesh also supports "slow" (i.e., per-packet) frequency-hopping spread spectrum. Spreading out transmissions across multiple channels provides an extra measure of robustness to QMesh communications.

Please see the GitHub Wiki for additional up-to-date information about QMesh.

Adobe Portable Document Format - 37.92 MB - 02/14/2021 at 16:01


RMHR NerdFest 2021 -- QMesh -- Dan Fay KG5VBY.pdf

Slides presented at RMHR NerdFest. Mostly a shortened version of the DCC 2020 deck, but does have a few updates.

Adobe Portable Document Format - 1.24 MB - 02/14/2021 at 15:58


TAPR DCC 2020 Paper.pdf

Slides presented at TAPR's Digital Communications Conference in September 2020. Contains a discussion of the experimental results that show that QMesh's synchronized flooded protocol can actually work.

Adobe Portable Document Format - 1.75 MB - 12/01/2020 at 03:41


TAPR DCC 2020 -- QMesh -- Dan Fay KG5VBY.pdf

Paper submitted to TAPR's Digital Communications Conference in September 2020. Contains a discussion of the experimental results that show that QMesh's synchronized flooded protocol can actually work.

Adobe Portable Document Format - 1.35 MB - 12/01/2020 at 03:39


Portable Network Graphics (PNG) - 7.60 kB - 07/18/2019 at 19:58


View all 15 files

  • 1 × Custom LoRa RF shield
  • 1 × STM32 NUCLEO-144 board
  • 1 × Antenna SMA-male antenna for the right frequency (433MHz, 915MHz, etc.)
  • 1 × USB power supply Need to supply at least 1A
  • 1 × Amateur radio license Technician or higher in the United States to use this semi-custom, experimental RF hardware setup.

View all 7 components

  • UART-Based "Remote" Firmware Update Completed

    Dan Fay4 days ago 0 comments

    The ability to update a QMesh device's firmware over a UART, which will enable remote firmware update, is complete. I can now update the QMesh firmware over a UART, including both a "wired" USB-to-UART adapter as well as over an HC-05 Bluetooth-to-UART module. Next, I'm working on setting up an ESP32 board to provide a Wi-Fi-to-UART bridge that will allow me to communicate with QMesh boards via a sockets interface.

    Some things I learned along the way:

    1. Using gzip to compress firmware updates is fairly straightforward to do, so long as you have a POSIX-y stuff available like malloc() and various file operators. If you have all of this, working on a gzip'ed file isn't much different from working on a regular file. Do note, however, that zlib uses a significant amount of both RAM and ROM. As a result, I only have zlib built into the bootloader.
    2. Mbed OS makes it fairly easy to implement a bootloader. Since I decided to make a bootloader that was just the QMesh app with some functionality removed, it was fairly large, totaling 150-200KB. I have plenty of program flash, so this isn't a big deal, but it might be if I try to fit everything inside of a smaller device.
    3. You can use the watchdog timer to implement a fallback capability for a botched firmware update. Basically, set the watchdog timer to some relatively short time period that's long enough to allow the main firmware to boot up and disable or pet the watchdog. If the firmware update is botched and it doesn't boot, the watchdog timer will reboot the board back into the bootloader, where a golden firmware image can be loaded instead.
    4. Static analyzers are interesting and fairly useful. The easiest one to do is to just enable clang-tidy in Mbed Studio. It definitely forced me to clean up my C++ code. I also set up codechecker (which runs clang-tidy and the Clang Static Analyzer) as well as Facebook Infer. While these are more cumbersome to use, Facebook Infer did some deeper analysis of my code and managed to find some code where I wasn't closing files that I had already opened.

    Hopefully, once I get the remote firmware stuff done, I'll have multiple solar-powered QMesh nodes that I can access and manage over Wi-Fi. This will make testing and improving the protocol much easier!

  • Protobufs Done, KISS Support Added

    Dan Fay05/22/2021 at 03:56 0 comments

    Finished implementing protobufs as the serialization protocol to be used throughout the system, including over the serial port and in the log and configuration files on the NOR flash.

    In the process of implementing protobufs, I realized that I also needed a framing format to "wrap" the protobufs in. I originally considered SLIP's framing, and then realized that the KISS protocol was an easier-to-parse superset of SLIP, with the bonus of being directly supported by many amateur radio applications.

    As a result, my journey through protobufs has made QMesh a KISS-compatible TNC. This means that, using e.g. an HC-05 (HC-05 info/usage) UART-to-Bluetooth bridge, APRSDroid now works with QMesh. Codec2 Walkie Talkie (Github repo here) should also work with it, but I've been focusing on performance tweaks/enhancements to QMesh before giving it a try. Note that I also added in the ability to fragment KISS frames across multiple QMesh frames if the KISS frames are larger than a single QMesh frame.

    After burning up an STM32 board and an HC-05 board trying to update an outdoor QMesh node, I've been working on developing a wireless, ESP32-based remote administration of the outdoor nodes. Basically, the ESP32 would connect to my Wi-Fi network, and allow me a network-based method to access the UART for testing and remotely updating the firmware (I'm also working on a bootloader to update the "main" firmware).

  • Moving to protobufs

    Dan Fay12/27/2020 at 17:40 0 comments

    I'm currently replacing the JSON-based serial communications setup with Google Protobufs. So far, it seems to be a win: simpler coding, more compact representation, and pretty easy to use.

  • Frequency Hopping Added

    Dan Fay12/01/2020 at 03:52 0 comments

    I decided to play around with the CAD feature on the SX126X a bit, and developed a simple scanning-based frequency hopping scheme. As a result, QMesh can now do a hybrid spread-spectrum scheme (CSS+FHSS).

    Some things I learned along the way:

    1. The CAD has a lot of false positives. Doing a "double CAD" helps reduce this issue. Basically, do a CAD, and if it comes back positive, do a CAD+Rx for the final receive.

    2. The CAD starts the oscillator "fresh". This means that, with a TCXO, the CAD will not start until the programmed TCXO stabilization delay completes. I may consider cutting the stabilization time for CADs, as a bunch of correlators just trying to detect some chirps probably doesn't need the TCXO's full accuracy.

  • TAPR DCC Submission and New Results

    Dan Fay08/16/2020 at 14:35 0 comments

    Just submitted a paper about QMesh to TAPR DCC ( 

    As part of this paper, I tested the packet receive rate (PRR) when two and three nodes are retransmitting. When I use Reed-Solomon-Viterbi (RSV) forward error correction, I'm seeing 99% PRR's. I believe that these results are real, since when I turn off FEC, I instead get 93% (for two retransmitting nodes) and 90% (for three retransmitting nodes). Moreover, this setup is a worst-case scenario where the antennas are right next to each other and are separated by a quarter wavelength. Real-world situations should be less challenging than this, so this is a very good sign.

    At this point, *knocks on wood* the underlying protocol is sufficiently reliable that it's ready to handle streaming voice.

  • Testing Results

    Dan Fay03/06/2020 at 03:25 0 comments

    It looks like the basic principle of QMesh -- that a synchronized, flooded mesh network can achieve a decently-high packet receive rate via the capture effect -- is valid.

    If I place two relay nodes right next to each other, I can get a packet receive rate (PRR) of around 80-100% when the received signals are strong. For marginal signal strengths, the collisions seem to effectively raise the noise floor.

  • Testing Capture

    Dan Fay02/19/2020 at 14:50 0 comments

    Basic meshing (i.e., data relaying) is working. Getting receive working was somewhat challenging due to some SPI bus contention issues as well as some CPU usage issues.

    This weekend will hopefully be the time when we determine whether successful capture works!

View all 7 project logs

  • 1

    Once the hardware design stabilizes, I'll have better information here. Right now, however, I'm rapidly changing the design of the RF shield.

View all instructions

Enjoy this project?



ee334 wrote 12/01/2020 at 17:19 point

Why voice? I need only digital. for example NNTP

  Are you sure? yes | no

Dan Fay wrote 12/27/2020 at 17:38 point

QMesh's waveform/protocol design makes it well-suited for latency-sensitive streaming applications like voice. Its rapid self-healing is useful here for similar reasons. It's also what makes QMesh unique vs. all of the other countless LoRa-based mesh networking protocols being developed out there.

When I've done special event communications (mainly distance running races), PTT voice is a lot easier to use than text.

  Are you sure? yes | no

Per-Oskar O wrote 03/21/2020 at 12:08 point

Congratulations to the successful experiment. Do you think it would be possible to use this to make a lora based walkie talkie? I've been looking into the possibility make a cheap and dirty walkie-talkie using a esp32 and ESPnow. But alas, neither my codingskills nor my electronicsskills are good enough for that project. 

  Are you sure? yes | no

Hsingai Tigris Altaica wrote 05/18/2020 at 03:38 point

Oskar you should look into the WiPhone

  Are you sure? yes | no

Dan Fay wrote 12/01/2020 at 03:44 point

The ultimate goal is some sort of walkie-talkie, perhaps based off of the M17 Project's hardware. In the meantime, however, the goal is to make analog "bridge" repeaters so that people can interface with QMesh using existing FM walkie-talkies like Baofengs.

  Are you sure? yes | no

Dan Fay wrote 07/17/2019 at 12:17 point

Yes, there definitely has been! Please see the project's Github page ( for updates.

  Are you sure? yes | no

Dave wrote 05/28/2019 at 21:18 point

Any progress to report on this effort?  Interested.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates