Skip to content

Communication LoRa

pschatzmann edited this page Oct 22, 2026 · 2 revisions

LoRa is a long range, low power radio (433/868/915 MHz) that reaches several kilometers - but with a very small bandwidth of a few kbit/s up to some tens of kbit/s. This is enough for low quality voice or short sound clips, not for music. See Communication for the general considerations.

The AudioLoRa class

AudioLoRa (AudioTools/Communication/AudioLoRa.h) uses the arduino-LoRa library (install it) for SX127x based modules (e.g. RFM95, the Heltec and TTGO LoRa boards) and makes it an audio stream: what you write is collected into packets of max_size bytes and sent; received packets can be read.

If process_audio_info is true (the default), begin() first sends a small packet with the AudioInfo (sample rate, channels, bits), so that the receiver learns the audio format.

Field (AudioLoRaConfig) Default Description
frequency 868E6 the frequency band permitted in your region: 433E6, 868E6 (Europe) or 915E6 (America)
spreading_factor 6 6..12: higher = more range, but much slower
signal_bandwidth 500E3 higher = faster, but less range
tx_power 20 transmit power in dB
sync_word 0xF3 only devices with the same sync word talk to each other
max_size 200 the bytes in one packet
pin_ss, pin_rst, pin_dio0 board specific the pins of the LoRa module
spi_speed the SPI speed
process_audio_info true send/receive the AudioInfo header

The defaults are already set for the highest possible speed.

Sending and receiving

From the lora examples. The sender:

#include "AudioTools.h"
#include "AudioTools/Communication/AudioLoRa.h"

AudioInfo info(8000, 1, 16);
SineGenerator<int16_t> sineWave(32000);
GeneratedSoundStream<int16_t> sound(sineWave);
AudioLoRa lora;
StreamCopy copier(lora, sound);

void setup() {
  SPI.begin(SCK, MISO, MOSI, SS);
  auto cfg = lora.defaultConfig();
  cfg.copyFrom(info);
  if (!lora.begin(cfg)) stop();
  sineWave.begin(info, N_B4);
}

void loop() { copier.copy(); }

The receiver (the example measures the throughput with a MeasuringStream - replace it with your output):

AudioLoRa lora;
MeasuringStream out;
StreamCopy copier(out, lora);

void setup() {
  auto cfg = lora.defaultConfig();
  lora.begin(cfg);
  out.begin();
}

void loop() { copier.copy(); }

Things to consider

  • Bandwidth: 8000 Hz 16 bit mono PCM needs 128 kbit/s - far more than LoRa can transmit. Measure what you get and reduce the data: 8 bit (EncoderL8), a low sample rate and a speech codec (e.g. Codec2 at 0.7 - 3.2 kbit/s or GSM). Without such a codec, record the audio first and send it as a file instead of streaming it.
  • Duty cycle: in many regions (e.g. 868 MHz in Europe) a device may only transmit for 1% of the time - continuous streaming is not allowed.
  • Startup order: the AudioInfo header is sent only once in begin(). Start the receiver first, or set process_audio_info = false and configure the same format on both sides.
  • Lost packets are not repeated: use a codec that can resync (or a container, see Serial).
  • RadioHeadStream (AudioTools/Communication/RadioHeadStream.h) is an alternative based on the RadioHead drivers (e.g. RH_RF95), so other LoRa and radio modules can be used too: RadioHeadStream radio(driver, TX_MODE); sends the written data in messages of the driver's maximum message length (call flush() to send the rest), and in RX_MODE the received messages can be read like any other stream. It does not send an AudioInfo header, and there is no example yet.

Clone this wiki locally