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
Parameter Value Notes Range Up to 10-15 km Line of sight, depends on environment Frequency 433 MHz, 868 MHz, 915 MHz Region-dependent Data Rate 0.3 - 50 kbps Configurable spreading factor Power Consumption 10-120 mA TX, <1 mA sleep Very low for IoT Spreading Factor SF7 - SF12 Higher SF = longer range, lower speed Bandwidth 125 kHz, 250 kHz, 500 kHz Configurable TX Power 2-20 dBm Typically 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 8 E 6
#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 ( 915 E 6 )) {
Serial . println ( "LoRa init failed!" );
while ( 1 );
}
// Configure LoRa parameters
LoRa . setTxPower ( 17 ); // 17 dBm
LoRa . setSpreadingFactor ( 8 ); // SF8
LoRa . setSignalBandwidth ( 125 E 3 ); // 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 ( 915 E 6 )) {
Serial . println ( "LoRa init failed!" );
while ( 1 );
}
LoRa . setSpreadingFactor ( 8 );
LoRa . setSignalBandwidth ( 125 E 3 );
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 ( 915 E 6 );
// 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 ());
}
}
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 915 E 6
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
125 E 3 , // 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 , 125 E 3 , 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 ( 0x 00 , 0x 01 ); // Address high/low
lora . setChannel ( 23 ); // Channel
lora . setTransmissionPower ( 22 ); // Max power
lora . setAirDataRate ( 0b 010 ); // 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 );
}
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 (
0x 00 , // Address high
0x 02 , // 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 ( 0b 011 ); // WOR period
Serial . println ( "WOR mode enabled" );
}
LoRa Configuration Guide
Spreading Factor vs Range/Speed
SF Data Rate Range Use Case 7 ~5.5 kbps Shortest High-speed, short range 8 ~3.1 kbps Medium Balanced 9 ~1.8 kbps Good General purpose 10 ~980 bps Better Long range 11 ~440 bps Excellent Very long range 12 ~250 bps Maximum Maximum range, slowest
Bandwidth Selection
// Wider bandwidth = faster data rate, shorter range
lora . setSignalBandwidth ( 500 E 3 ); // Fast, short range
lora . setSignalBandwidth ( 250 E 3 ); // Medium
lora . setSignalBandwidth ( 125 E 3 ); // 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
Maximum Range Configuration
// Optimize for maximum range
lora . setSpreadingFactor ( 12 ); // Slowest, longest range
lora . setSignalBandwidth ( 125 E 3 ); // 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 ( 125 E 3 );
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 ( 500 E 3 );
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