Skip to main content

Overview

The LoRaComV2 module provides simplified LoRa communication with support for point-to-point messaging, multi-node networks, and acknowledged transmissions. It handles packet structuring, addressing, and reliability.

Basic Send/Receive

This example demonstrates bidirectional LoRa communication with callbacks.
1

Enable the module

Include the LoRa communication module:
#define ENABLE_MODULE_LORA_COM_V2
#include "Kinematrix.h"
2

Configure pins and frequency

Define hardware connections and radio frequency:
#define LORA_CS_PIN    10
#define LORA_RESET_PIN 9
#define LORA_IRQ_PIN   2

// Choose frequency for your region:
// 433E6 (Asia), 868E6 (Europe), 915E6 (North America)
#define LORA_FREQUENCY 915E6
3

Create LoRa instance

Initialize the LoRa communication object:
LoRaComV2 lora;
4

Define callbacks

Set up event handlers:
void onInit() {
  Serial.println("LoRa initialized!");
}

void onDataSent(const String &data) {
  Serial.print("Sent: ");
  Serial.println(data);
}

void onDataReceived(const String &data) {
  Serial.print("Received: ");
  Serial.println(data);
  
  // Check signal quality
  Serial.print("RSSI: ");
  Serial.print(lora.packetRssi());
  Serial.print(" dBm, SNR: ");
  Serial.print(lora.packetSnr());
  Serial.println(" dB");
}
5

Initialize in setup()

Configure the LoRa module:
void setup() {
  Serial.begin(115200);
  
  // Initialize LoRa
  if (!lora.init(LORA_CS_PIN, LORA_RESET_PIN, LORA_IRQ_PIN, 
                 LORA_FREQUENCY, onInit)) {
    Serial.println("LoRa init failed!");
    while (1);
  }
  
  // Configure parameters
  lora.configure(8, 125E3, 17);  // SF=8, BW=125kHz, TX=17dBm
  lora.enableCRC();
}
6

Send and receive data

Communicate in the loop:
void loop() {
  // Check for incoming data
  lora.receive(onDataReceived);
  
  // Send data periodically
  if (millis() - lastSendTime > 8000) {
    lastSendTime = millis();
    
    lora.clearData();
    lora.addData("STATUS");
    lora.addData(temperature);
    lora.addData(humidity);
    lora.sendDataCb(onDataSent);
  }
  
  delay(10);
}

Complete Basic Example

#define ENABLE_MODULE_LORA_COM_V2
#include "Kinematrix.h"

#define LORA_CS_PIN    10
#define LORA_RESET_PIN 9
#define LORA_IRQ_PIN   2
#define LORA_FREQUENCY 915E6

LoRaComV2 lora;

float temperature = 21.5;
float humidity = 48.0;
unsigned long lastSendTime = 0;

void onInit() {
  Serial.println("LoRa initialized!");
}

void onDataSent(const String &data) {
  Serial.print("Sent: ");
  Serial.println(data);
}

void onDataReceived(const String &data) {
  Serial.print("Received: ");
  Serial.println(data);
  Serial.print("RSSI: ");
  Serial.print(lora.packetRssi());
  Serial.print(" dBm, SNR: ");
  Serial.print(lora.packetSnr());
  Serial.println(" dB");
  
  // Parse received data
  String command = lora.getStrData(data, 0);
  
  if (command == "DATA_REQUEST") {
    lora.clearData();
    lora.addData("SENSOR_DATA");
    lora.addData(temperature);
    lora.addData(humidity);
    lora.sendData();
  }
}

void setup() {
  Serial.begin(115200);
  
  if (!lora.init(LORA_CS_PIN, LORA_RESET_PIN, LORA_IRQ_PIN, 
                 LORA_FREQUENCY, onInit)) {
    Serial.println("LoRa init failed!");
    while (1);
  }
  
  lora.configure(8, 125E3, 17);
  lora.enableCRC();
}

void loop() {
  lora.receive(onDataReceived);
  
  if (millis() - lastSendTime > 8000) {
    lastSendTime = millis();
    
    temperature = 21.5 + random(-20, 20) / 10.0;
    humidity = 48.0 + random(-50, 50) / 10.0;
    
    lora.clearData();
    lora.addData("STATUS");
    lora.addData(temperature);
    lora.addData(humidity);
    lora.sendDataCb(onDataSent);
  }
  
  delay(10);
}

Acknowledged Transmissions

Reliable message delivery with automatic acknowledgments and retries.

Sender Node

#define NODE_ID 1
#define TARGET_NODE_ID 2
#define MAX_RETRIES 3
#define ACK_TIMEOUT 1000  // milliseconds

void setup() {
  // ... initialize LoRa ...
  
  // Set this node's ID
  lora.setNodeId(NODE_ID);
}

void loop() {
  if (millis() - lastSendTime > 10000) {
    lastSendTime = millis();
    messageCount++;
    
    // Prepare message
    lora.clearData();
    lora.addData("IMPORTANT_DATA");
    lora.addData(NODE_ID);
    lora.addData(messageCount);
    lora.addData(sensorValue);
    
    Serial.print("Sending message #");
    Serial.println(messageCount);
    
    // Send with acknowledgment
    bool sent = lora.sendMessageToNode(TARGET_NODE_ID, 
                                        lora.getDataString().c_str());
    
    if (sent) {
      // Wait for acknowledgment
      String response = lora.sendDataAndWaitResponse(ACK_TIMEOUT, MAX_RETRIES);
      
      if (response.length() > 0) {
        String responseType = lora.getStrData(response, 0);
        
        if (responseType == "ACK") {
          unsigned long ackMsgId = lora.getData(response, 1);
          
          if (ackMsgId == messageCount) {
            Serial.println("ACK received! Success.");
            successCount++;
          }
        }
      } else {
        Serial.println("No ACK received. Failed.");
        failCount++;
      }
    }
    
    // Print statistics
    Serial.print("Success rate: ");
    Serial.print(successCount * 100.0 / messageCount, 1);
    Serial.println("%");
  }
}

Receiver Node

#define NODE_ID 2

void onDataReceived(const String &data) {
  Serial.print("Received: ");
  Serial.println(data);
  
  // Parse message
  String msgType = lora.getStrData(data, 0);
  
  if (msgType == "IMPORTANT_DATA") {
    unsigned long senderId = lora.getData(data, 1);
    unsigned long msgId = lora.getData(data, 2);
    float value = lora.getData(data, 3);
    
    Serial.print("From node ");
    Serial.print(senderId);
    Serial.print(", message #");
    Serial.print(msgId);
    Serial.print(", value: ");
    Serial.println(value);
    
    // Send acknowledgment
    delay(100);  // Small delay before ACK
    
    lora.clearData();
    lora.addData("ACK");
    lora.addData(msgId);
    lora.sendData();
    
    Serial.println("ACK sent");
  }
}

LoRa Configuration

Spreading Factor (SF)

Trade-off between range and data rate:
// Short range, fast (SF7-8)
lora.configure(7, 125E3, 17);  // ~5 km, ~5 kbps

// Medium range (SF9-10)
lora.configure(9, 125E3, 17);  // ~10 km, ~2 kbps

// Long range, slow (SF11-12)
lora.configure(12, 125E3, 17); // ~15+ km, ~250 bps

Bandwidth

Affects sensitivity and data rate:
lora.configure(8, 62.5E3, 17);  // Narrow, better sensitivity
lora.configure(8, 125E3, 17);   // Standard
lora.configure(8, 250E3, 17);   // Wide, faster but less range

Transmit Power

Set output power (2-20 dBm):
lora.configure(8, 125E3, 20);  // Maximum power
lora.configure(8, 125E3, 14);  // Medium power
lora.configure(8, 125E3, 2);   // Minimum power

Range Presets

Pre-configured settings for different scenarios:
// Short range (urban, <2 km)
lora.setShortRange();    // SF7, BW=250kHz

// Medium range (suburban, 2-8 km)
lora.setMediumRange();   // SF9, BW=125kHz

// Long range (rural, 8-20 km)
lora.setLongRange();     // SF12, BW=125kHz
See lora-comv2_lora-range-presets.ino for details.

Data Handling

Adding Data

lora.clearData();                    // Clear buffer
lora.addData("SENSOR");              // String
lora.addData(42);                    // Integer
lora.addData(3.14);                  // Float
lora.addData(true);                  // Boolean

Parsing Received Data

void onDataReceived(const String &data) {
  String cmd = lora.getStrData(data, 0);     // First field as string
  int value1 = lora.getData(data, 1);        // Second field as int
  float value2 = lora.getData(data, 2);      // Third field as float
}

Get Complete Data String

String dataString = lora.getDataString();
Serial.println(dataString);

Signal Quality Monitoring

void onDataReceived(const String &data) {
  int rssi = lora.packetRssi();      // Signal strength (dBm)
  float snr = lora.packetSnr();      // Signal-to-noise ratio (dB)
  
  Serial.print("RSSI: ");
  Serial.print(rssi);
  Serial.print(" dBm, SNR: ");
  Serial.print(snr);
  Serial.println(" dB");
  
  // Evaluate link quality
  if (rssi > -50) {
    Serial.println("Excellent signal");
  } else if (rssi > -100) {
    Serial.println("Good signal");
  } else {
    Serial.println("Weak signal");
  }
}

Multi-Node Networks

Build networks with multiple LoRa nodes:
// Each node has unique ID
lora.setNodeId(NODE_ID);

// Send to specific node
lora.sendMessageToNode(targetId, message);

// Broadcast to all nodes
lora.sendData();  // No specific target
See lora-comv2_mesh-node-example.ino for mesh networking.

Key Methods

MethodDescription
init(cs, reset, irq, freq, callback)Initialize LoRa module
configure(sf, bw, power)Set radio parameters
enableCRC()Enable error checking
setNodeId(id)Set node identifier
clearData()Clear send buffer
addData(value)Add data to buffer
sendData()Transmit data
sendDataCb(callback)Send with callback
receive(callback)Check for incoming data
sendMessageToNode(id, msg)Send to specific node
sendDataAndWaitResponse(timeout, retries)Send with ACK
packetRssi()Get signal strength
packetSnr()Get signal quality
getStrData(data, index)Parse string field
getData(data, index)Parse numeric field

Hardware Requirements

  • LoRa module (SX1276/SX1278)
  • SPI connection to microcontroller
  • Antenna (matched to frequency)

Supported Modules

  • SX1276/SX1278 (Semtech)
  • RFM95/RFM96/RFM98 (HopeRF)
  • EByte E220 (with lora-ebyte-e220 library)

Source Files

Example files located at:
  • Basic: example/modules/communication/wireless/lora/EXAMPLE-lora-comv2/lora-comv2_basic-send-receive-example/
  • Acknowledged: example/modules/communication/wireless/lora/EXAMPLE-lora-comv2/lora-comv2_acknowledged-sender-example/
  • Range presets: example/modules/communication/wireless/lora/EXAMPLE-lora-comv2/lora-comv2_lora-range-presets/

Build docs developers (and LLMs) love