Skip to main content
Kinematrix provides multiple LoRa implementations for long-range, low-power wireless communication supporting distances up to 10+ kilometers.

LoRa Modules Overview

LoRa Base

Foundation LoRa library (Sandeep Mistry)

LoRa Com V2

Enhanced communication with mesh and half-duplex modes

LoRa EByte E220

EByte E220 module-specific implementation

LoRa Specifications

ParameterValueNotes
RangeUp to 10-15 kmLine of sight, depends on environment
Frequency433 MHz, 868 MHz, 915 MHzRegion-dependent
Data Rate0.3 - 50 kbpsConfigurable spreading factor
Power Consumption10-120 mA TX, <1 mA sleepVery low for IoT
Spreading FactorSF7 - SF12Higher SF = longer range, lower speed
Bandwidth125 kHz, 250 kHz, 500 kHzConfigurable
TX Power2-20 dBmTypically 17-20 dBm

LoRa Base

Foundation LoRa library based on Sandeep Mistry’s implementation, providing core SPI-based LoRa functionality.

Hardware Configuration

lib/modules/communication/wireless/lora/lora-base.h
// Default pins (Arduino)
#define LORA_DEFAULT_SPI           SPI
#define LORA_DEFAULT_SPI_FREQUENCY 8E6
#define LORA_DEFAULT_SS_PIN        10  // Chip select
#define LORA_DEFAULT_RESET_PIN     9   // Reset
#define LORA_DEFAULT_DIO0_PIN      2   // Interrupt

Basic Transmitter

#define ENABLE_MODULE_LORA_BASE
#include "Kinematrix.h"

void setup() {
  Serial.begin(115200);
  
  // Initialize LoRa at 915 MHz
  if (!LoRa.begin(915E6)) {
    Serial.println("LoRa init failed!");
    while (1);
  }
  
  // Configure LoRa parameters
  LoRa.setTxPower(17);              // 17 dBm
  LoRa.setSpreadingFactor(8);       // SF8
  LoRa.setSignalBandwidth(125E3);   // 125 kHz
  LoRa.setCodingRate4(5);           // 4/5 coding rate
  LoRa.enableCrc();                 // Enable CRC
  
  Serial.println("LoRa initialized");
}

void loop() {
  Serial.println("Sending packet...");
  
  // Send packet
  LoRa.beginPacket();
  LoRa.print("Temperature: ");
  LoRa.print(25.5);
  LoRa.endPacket();
  
  delay(5000);
}

Basic Receiver

void setup() {
  Serial.begin(115200);
  
  if (!LoRa.begin(915E6)) {
    Serial.println("LoRa init failed!");
    while (1);
  }
  
  LoRa.setSpreadingFactor(8);
  LoRa.setSignalBandwidth(125E3);
  LoRa.enableCrc();
  
  Serial.println("LoRa receiver ready");
}

void loop() {
  int packetSize = LoRa.parsePacket();
  
  if (packetSize) {
    Serial.print("Received packet: ");
    
    // Read packet
    while (LoRa.available()) {
      Serial.write(LoRa.read());
    }
    
    // Print RSSI
    Serial.print(" RSSI: ");
    Serial.print(LoRa.packetRssi());
    Serial.print(" SNR: ");
    Serial.println(LoRa.packetSnr());
  }
}

Interrupt-Driven Reception

volatile bool packetReceived = false;

void onReceive(int packetSize) {
  packetReceived = true;
}

void setup() {
  Serial.begin(115200);
  LoRa.begin(915E6);
  
  // Register interrupt callback
  LoRa.onReceive(onReceive);
  
  // Put radio in receive mode
  LoRa.receive();
  
  Serial.println("LoRa receiver (interrupt mode)");
}

void loop() {
  if (packetReceived) {
    packetReceived = false;
    
    String message = "";
    while (LoRa.available()) {
      message += (char)LoRa.read();
    }
    
    Serial.print("Received: ");
    Serial.println(message);
    Serial.print("RSSI: ");
    Serial.println(LoRa.packetRssi());
  }
}

LoRa Com V2

Enhanced LoRa communication module with advanced features including mesh networking, half-duplex operation, and structured messaging.

Key Features

  • Multiple Operation Modes: Normal, half-duplex, and mesh
  • Structured Messages: Source/destination routing with message IDs
  • ACK System: Optional acknowledgment for reliable delivery
  • Node Discovery: Automatic mesh network discovery
  • Signal Quality: RSSI, SNR, and frequency error reporting
  • Buffering: 256-byte TX/RX buffers

Message Structure

lib/modules/communication/wireless/lora/lora-comv2.h
typedef struct {
    uint8_t msgType;      // MSG_DATA, MSG_ACK, MSG_COMMAND, MSG_BROADCAST, MSG_PING, MSG_PONG
    uint16_t sourceId;    // Source node ID
    uint16_t destId;      // Destination node ID
    uint16_t msgId;       // Message ID for tracking
    uint8_t ttl;          // Time to live (mesh hops)
    uint16_t payloadLen;  // Payload length
    char payload[240];    // Actual data
} LoRaMessage;

Configuration Structure

typedef struct {
    uint8_t cs;              // Chip select pin
    uint8_t rst;             // Reset pin
    uint8_t irq;             // Interrupt pin
    uint16_t nodeId;         // This node's ID
    long frequency;          // Operating frequency
    uint8_t spreadFactor;    // Spreading factor (7-12)
    long bandwidth;          // Bandwidth (125E3, 250E3, 500E3)
    uint8_t txPower;         // TX power (2-20 dBm)
    uint8_t syncWord;        // Sync word (default 0x12)
    uint16_t preambleLen;    // Preamble length
} LoRaConfig;

Basic Point-to-Point

#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;

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

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 initialization failed!");
    while (1);
  }
  
  // Configure parameters
  lora.configure(
    8,       // Spreading factor
    125E3,   // Bandwidth
    17       // TX power (dBm)
  );
  
  lora.enableCRC();
  lora.setPreambleLength(8);
  
  Serial.println("LoRa ready");
}

void loop() {
  // Send data
  lora.clearData();
  lora.addData("TEMP");
  lora.addData(25.67);
  lora.addData("HUM");
  lora.addData(60.2);
  
  if (lora.sendData()) {
    Serial.println("Data sent");
  }
  
  delay(5000);
}

Bi-Directional Communication

example/modules/communication/wireless/lora/EXAMPLE-lora-comv2/lora-comv2_basic-send-receive-example/lora-comv2_basic-send-receive-example.ino
LoRaComV2 lora;
float temperature = 0.0;
float humidity = 0.0;

void onDataReceived(const String &data) {
  Serial.print("Data received: ");
  Serial.println(data);
  
  // Get signal quality
  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") {
    // Send sensor data
    lora.clearData();
    lora.addData("SENSOR_DATA");
    lora.addData(temperature);
    lora.addData(humidity);
    delay(100);
    lora.sendData();
  }
  else if (command == "PING") {
    // Respond to ping
    lora.clearData();
    lora.addData("PONG");
    lora.addData(millis() / 1000);
    delay(50);
    lora.sendData();
  }
}

void loop() {
  // Check for incoming data
  lora.receive(onDataReceived);
  
  // Send periodic status updates
  static unsigned long lastSend = 0;
  if (millis() - lastSend > 8000) {
    lastSend = millis();
    
    lora.clearData();
    lora.addData("STATUS");
    lora.addData(temperature);
    lora.addData(humidity);
    lora.sendData();
  }
  
  delay(10);
}

Acknowledged Transmission

void loop() {
  lora.clearData();
  lora.addData("CRITICAL");
  lora.addData("Alert message");
  
  // Send with acknowledgment and retries
  if (lora.sendDataWithAck(1000, 3)) {
    Serial.println("Message acknowledged");
  } else {
    Serial.println("No acknowledgment received");
  }
  
  delay(10000);
}

Request-Response Pattern

void loop() {
  lora.clearData();
  lora.addData("GET_SENSOR");
  
  // Send request and wait for response
  String response = lora.sendDataAndWaitResponse(
    2000,  // 2-second timeout
    3      // Max 3 retries
  );
  
  if (response.length() > 0) {
    Serial.print("Response: ");
    Serial.println(response);
    
    float temp = lora.getData(response, 0);
    float humidity = lora.getData(response, 1);
  }
  
  delay(5000);
}

Half-Duplex Mode

Alternate between transmit and receive modes to avoid collisions:
void setup() {
  // ... initialization ...
  
  // Enable half-duplex mode with 1-second intervals
  lora.setMode(MODE_HALF_DUPLEX, 1000);
}

void onDataReceived(const String &data) {
  Serial.println("RX: " + data);
}

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

void loop() {
  // Automatically switches between TX and RX
  lora.runHalfDuplexCycle(onDataReceived, onDataSent);
  
  // Queue data to send when in TX mode
  if (lora.isInTransmitState()) {
    lora.clearData();
    lora.addData("Sensor");
    lora.addData(analogRead(A0));
  }
}

Mesh Networking

void setup() {
  lora.init(LORA_CS_PIN, LORA_RESET_PIN, LORA_IRQ_PIN, LORA_FREQUENCY);
  lora.configure(8, 125E3, 17);
  
  // Enable mesh mode with node ID
  lora.enableMeshMode(101);  // This node is ID 101
  
  // Discover other nodes
  lora.discoverNodes(2);  // TTL=2 hops
}

void loop() {
  // Send to specific node in mesh
  lora.sendToMesh(
    102,                    // Destination node ID
    "Temperature: 25.5",   // Data
    3                       // TTL (max hops)
  );
  
  // Check known nodes
  uint8_t nodeCount = lora.getKnownNodeCount();
  Serial.print("Known nodes: ");
  Serial.println(nodeCount);
  
  for (uint8_t i = 0; i < nodeCount; i++) {
    Serial.print("  Node ID: ");
    Serial.println(lora.getKnownNodeId(i));
  }
  
  delay(10000);
}

Broadcast Messages

void loop() {
  // Broadcast to all nodes
  lora.broadcastMessage(
    "ALERT: System update",
    3  // TTL for mesh relay
  );
  
  delay(60000);  // Broadcast every minute
}

LoRa EByte E220

Specialized implementation for the EByte E220 LoRa module with advanced configuration capabilities.

Module Features

  • UART Interface: Serial communication with the module
  • Configuration Modes: Normal, WOR (Wake on Radio), sleep
  • Fixed/Broadcast: Address-based routing
  • RSSI Support: Signal strength monitoring
  • Structure Transmission: Send/receive C structs directly

Basic Configuration

#define ENABLE_MODULE_LORA_EBYTE_E220
#include "Kinematrix.h"

LoRaModuleEByteE220 lora(&Serial2, UART_BPS_RATE_9600);

void setup() {
  Serial.begin(115200);
  
  if (!lora.begin()) {
    Serial.println("E220 init failed!");
    while (1);
  }
  
  // Configure module
  lora.setAddress(0x00, 0x01);      // Address high/low
  lora.setChannel(23);               // Channel
  lora.setTransmissionPower(22);     // Max power
  lora.setAirDataRate(0b010);       // 2.4k bps
  lora.enableRSSI(true);             // Enable RSSI
  
  Serial.println("E220 ready");
}

Simple Message Transmission

void loop() {
  String message = "Temperature: " + String(25.5);
  
  if (lora.sendMessage(message)) {
    Serial.println("Message sent");
  } else {
    Serial.print("Error: ");
    Serial.println(lora.getLastError());
  }
  
  delay(5000);
}

Receive with RSSI

void loop() {
  if (lora.available()) {
    String message;
    int rssi;
    
    if (lora.receiveMessage(&message, &rssi)) {
      Serial.print("Received: ");
      Serial.println(message);
      Serial.print("RSSI: ");
      Serial.print(rssi);
      Serial.println(" dBm");
    }
  }
  
  delay(10);
}

Fixed Address Transmission

void loop() {
  // Send to specific address and channel
  lora.sendFixedMessage(
    0x00,              // Address high
    0x02,              // Address low
    23,                // Channel
    "Hello Node 2"    // Message
  );
  
  delay(5000);
}

Broadcast Transmission

void loop() {
  // Broadcast on channel 23
  lora.sendBroadcastMessage(23, "Broadcast message");
  delay(10000);
}

Structure Transmission

struct SensorData {
  float temperature;
  float humidity;
  uint32_t timestamp;
  uint8_t batteryLevel;
};

void loop() {
  SensorData data;
  data.temperature = 25.5;
  data.humidity = 60.2;
  data.timestamp = millis();
  data.batteryLevel = 85;
  
  // Send structure
  if (lora.sendStructure(data)) {
    Serial.println("Structure sent");
  }
  
  delay(5000);
}

// Receiver
void receiveStructure() {
  if (lora.available()) {
    SensorData data;
    int rssi;
    
    if (lora.receiveStructure(&data, &rssi)) {
      Serial.print("Temp: ");
      Serial.println(data.temperature);
      Serial.print("Humidity: ");
      Serial.println(data.humidity);
      Serial.print("RSSI: ");
      Serial.println(rssi);
    }
  }
}

WOR (Wake on Radio) Mode

void setup() {
  lora.begin();
  
  // Configure WOR for low power
  lora.configureWOR(0b011);  // WOR period
  
  Serial.println("WOR mode enabled");
}

LoRa Configuration Guide

Spreading Factor vs Range/Speed

SFData RateRangeUse Case
7~5.5 kbpsShortestHigh-speed, short range
8~3.1 kbpsMediumBalanced
9~1.8 kbpsGoodGeneral purpose
10~980 bpsBetterLong range
11~440 bpsExcellentVery long range
12~250 bpsMaximumMaximum range, slowest

Bandwidth Selection

// Wider bandwidth = faster data rate, shorter range
lora.setSignalBandwidth(500E3);  // Fast, short range
lora.setSignalBandwidth(250E3);  // Medium
lora.setSignalBandwidth(125E3);  // Slow, long range (default)

TX Power Configuration

// Higher power = longer range, more power consumption
lora.setTxPower(20);  // Maximum (100mW)
lora.setTxPower(17);  // High (50mW) - recommended
lora.setTxPower(14);  // Medium (25mW)
lora.setTxPower(10);  // Low (10mW) - for short range

Coding Rate

// Higher coding rate = more error correction, slower
lora.setCodingRate4(5);  // 4/5 (default)
lora.setCodingRate4(6);  // 4/6
lora.setCodingRate4(7);  // 4/7
lora.setCodingRate4(8);  // 4/8 - maximum error correction

Range Optimization

// Optimize for maximum range
lora.setSpreadingFactor(12);      // Slowest, longest range
lora.setSignalBandwidth(125E3);   // Narrowest bandwidth
lora.setTxPower(20);               // Maximum power
lora.setCodingRate4(8);            // Maximum error correction
lora.setPreambleLength(12);        // Longer preamble
lora.enableCrc();                  // Enable error detection
Expected range: 10-15 km (line of sight) Data rate: ~250 bps
// Balance between range and speed
lora.setSpreadingFactor(8);
lora.setSignalBandwidth(125E3);
lora.setTxPower(17);
lora.setCodingRate4(5);
lora.enableCrc();
Expected range: 2-5 km Data rate: ~3.1 kbps
// Optimize for speed (short range)
lora.setSpreadingFactor(7);
lora.setSignalBandwidth(500E3);
lora.setTxPower(14);
lora.setCodingRate4(5);
Expected range: 500m - 2km Data rate: ~21.9 kbps

Troubleshooting

Frequency Regulations: Ensure you’re using the correct frequency for your region:
  • US/Canada/South America: 915 MHz
  • Europe: 868 MHz
  • Asia: 433 MHz or 923 MHz
Check:
  • Matching frequency on both devices
  • Matching spreading factor and bandwidth
  • Matching sync word
  • Antenna connected properly
  • Power supply adequate (3.3V, stable)
Debug:
Serial.print("Frequency: ");
Serial.println(lora.getSignalBandwidth());
Serial.print("SF: ");
Serial.println(lora.getSpreadingFactor());
Possible causes:
  • Antenna issue (impedance mismatch, damaged)
  • Low TX power
  • High spreading factor not used
  • Obstacles blocking signal
Solutions:
  • Check antenna (50Ω impedance)
  • Increase TX power to 17-20 dBm
  • Increase spreading factor
  • Ensure line of sight
Enable CRC and check signal quality:
lora.enableCrc();

// Check signal quality on receive
int rssi = lora.packetRssi();
float snr = lora.packetSnr();

if (rssi < -120) {
  Serial.println("Signal too weak");
}
if (snr < 0) {
  Serial.println("Noisy environment");
}

Best Practices

Duty Cycle: In Europe (868 MHz), adhere to 1% duty cycle regulations. For US (915 MHz), no duty cycle restrictions but be considerate.
Power Management: Use sleep mode between transmissions to conserve battery:
lora.sleep();  // Sleep mode
// ... wait ...
lora.idle();   // Wake up

Application Examples

Environmental Monitoring

Deploy sensor nodes across large areas (farms, forests)

Smart Agriculture

Soil moisture, weather stations, irrigation control

Asset Tracking

Long-range location tracking for vehicles or equipment

Disaster Communication

Emergency mesh networks when infrastructure fails

ESP-NOW

Alternative for shorter-range mesh networks

Modbus

Wired industrial communication protocol

Build docs developers (and LLMs) love