Init fork from Stuart Robinson's repo

This commit is contained in:
2024-10-03 14:30:13 +03:00
commit 9395706524
201 changed files with 45709 additions and 0 deletions

View File

@ -0,0 +1,160 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 25/09/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a basic demonstration of the transmission of a 'Reliable' packet.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. The receiver needs to have the same
NetworkID as configured for the transmitter since the receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended in the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
It is possible to use the 'NetworkID' to direct the packet to specific receivers.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //RFBUSY pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LED1 8 //LED used to indicate transmission
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define TXpower 2 //LoRa transmit power in dBm
#define TXtimeout 5000 //transmit timeout in mS. If 0 return from transmit function after send.
uint8_t buff[] = "Hello World"; //the payload to send
uint16_t PayloadCRC;
uint8_t TXPayloadL; //this is the payload length sent
uint8_t TXPacketL;
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in receiver
void loop()
{
Serial.print(F("Transmit Payload > "));
TXPayloadL = sizeof(buff);
LT.printASCIIArray(buff, TXPayloadL); //print the payload buffer as ASCII
Serial.println();
if (LT.getReliableConfig(NoReliableCRC))
{
Serial.println(F("Payload CRC check disabled"));
}
Serial.flush();
//now transmit the packet
digitalWrite(LED1, HIGH); //LED on to indicate transmit
TXPacketL = LT.transmitReliable(buff, TXPayloadL, NetworkID, TXtimeout, TXpower, WAIT_TX); //will return packet length > 0 if sent OK, otherwise 0 if transmit error
if (TXPacketL > 0)
{
//if transmitReliable() returns > 0 then transmit was OK
PayloadCRC = LT.getTXPayloadCRC(TXPacketL); //read the actual transmitted CRC from the LoRa device buffer
packet_is_OK();
Serial.println();
}
else
{
//if transmitReliable() returns 0 there was an error
packet_is_Error();
Serial.println();
}
digitalWrite(LED1, LOW);
Serial.println();
delay(5000); //have a delay between packets
}
void packet_is_OK()
{
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmittedPayloadCRC,0x")); //print CRC of transmitted payload
Serial.print(PayloadCRC, HEX);
}
void packet_is_Error()
{
Serial.print(F("SendError"));
LT.printIrqStatus(); //prints the text of which IRQs set
LT.printReliableStatus(); //print the reliable status
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
uint16_t index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("201_Basic_Reliable_Transmitter Starting"));
pinMode(LED1, OUTPUT);
led_Flash(2, 125); //two quick LED flashes to indicate program start
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
do
{
digitalWrite(LED1, HIGH);
delay(50);
digitalWrite(LED1, LOW);
delay(50);
} while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF7, LORA_BW_0400, LORA_CR_4_5);
Serial.println();
LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check
Serial.println();
LT.printOperatingSettings(); //reads and prints the configured operating settings, useful check
Serial.println();
Serial.println();
LT.printRegisters(0x900, 0x9FF); //print contents of device registers, normally 0x900 to 0x9FF
Serial.println();
Serial.println(F("Transmitter ready"));
Serial.println();
//enable the following line if you want to disable payload CRC checking
//LT.setReliableConfig(NoReliableCRC); //disable payload CRC check
}

View File

@ -0,0 +1,195 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 25/09/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a simple demonstration of the receipt of a 'Reliable' packet.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. This receiver needs to have the same
NetworkID as configured for the transmitter. The receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. This receiver carries out its own CRC check on the received payload and can then verify
this against the CRC appended to the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
The received payload is copied on receive into the RXBUFFER array. This buffer can be set up to a maximum
size of 251 bytes. A LoRa packet can be up to 255 bytes, but the reliable packet uses 4 bytes to hold the
networkID and payload CRC. As an example if the the transmitted payload array is 16 bytes long, then the
transmit function will increase the packet size by 4 to 20 to accommodate the networkID and payload CRC.
Note that any packets arriving with a length greater than the length defined for RXBUFFER + 4 bytes will
be rejected.
It is possible to use the 'NetworkID' to direct the packet to specific receivers.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //RFBUSY pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LED1 8 //LED used to indicate transmission
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define RXtimeout 10000 //receive timeout in mS.
const uint8_t RXBUFFER_SIZE = 251; //RX buffer size, set to max payload length of 251, or maximum expected payload length
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
uint8_t RXPacketL; //stores length of packet received
uint8_t RXPayloadL; //stores length of payload received
uint8_t PacketOK; //set to > 0 if packetOK
int16_t PacketRSSI; //stores RSSI of received packet
uint16_t LocalPayloadCRC; //locally calculated CRC of payload
uint16_t RXPayloadCRC; //CRC of payload received in packet
uint16_t TransmitterNetworkID; //the NetworkID from the transmitted and received packet
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in transmitter
void loop()
{
PacketOK = LT.receiveReliable(RXBUFFER, RXBUFFER_SIZE, NetworkID, RXtimeout, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
digitalWrite(LED1, HIGH); //LED on to indicate receive
RXPacketL = LT.readRXPacketL(); //get the received packet length
RXPayloadL = RXPacketL - 4; //payload length is always 4 bytes less than packet length
PacketRSSI = LT.readPacketRSSI(); //read the received packets RSSI value
if (PacketOK > 0)
{
//if the LT.receiveReliable() returns a value > 0 for PacketOK then packet was received OK
packet_is_OK();
}
else
{
//if the LT.receiveReliable() function detects an error PacketOK is 0
packet_is_Error();
}
digitalWrite(LED1, LOW);
Serial.println();
}
void packet_is_OK()
{
Serial.print(F("Payload received OK > "));
LT.printASCIIPacket(RXBUFFER, RXPayloadL);
Serial.println();
if (LT.getReliableConfig(NoReliableCRC))
{
Serial.println(F("Payload CRC check disabled"));
}
printPacketDetails();
Serial.println();
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
Serial.print(F("Error "));
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout "));
}
else
{
printPacketDetails();
}
}
void printPacketDetails()
{
LocalPayloadCRC = LT.CRCCCITT(RXBUFFER, RXPayloadL, 0xFFFF); //calculate payload crc from the received RXBUFFER
TransmitterNetworkID = LT.getRXNetworkID(RXPacketL);
RXPayloadCRC = LT.getRXPayloadCRC(RXPacketL);
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmitterNetworkID,0x"));
Serial.print(TransmitterNetworkID, HEX);
Serial.print(F(",LocalPayloadCRC,0x"));
Serial.print(LocalPayloadCRC, HEX);
Serial.print(F(",RXPayloadCRC,0x"));
Serial.print(RXPayloadCRC, HEX);
LT.printReliableStatus();
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
uint16_t index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("202_Basic_Reliable_Receiver Starting"));
pinMode(LED1, OUTPUT);
led_Flash(2, 125); //two quick LED flashes to indicate program start
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
do
{
digitalWrite(LED1, HIGH);
delay(50);
digitalWrite(LED1, LOW);
delay(50);
} while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF7, LORA_BW_0400, LORA_CR_4_5);
Serial.println();
LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check
Serial.println();
LT.printOperatingSettings(); //reads and prints the configured operating settings, useful check
Serial.println();
Serial.println();
LT.printRegisters(0x900, 0x9FF); //print contents of device registers, normally 0x00 to 0x4F
Serial.println();
Serial.println(F("Receiver ready"));
Serial.println();
//enable the following line if you want to disable payload CRC checking
//LT.setReliableConfig(NoReliableCRC); //disable payload CRC check
}

View File

@ -0,0 +1,155 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 21/07/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a basic demonstration of the transmission of a 'Reliable' packet used to
control outputs on a remote receiver.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. This receiver needs to have the same
NetworkID as configured for the transmitter. The receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended is a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended to the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
This example program and the matching receiver, 204_Reliable_Receiver_Controller_Structure, transmits a
data structure that contains variables which when read by the remote receiver flashes an LED attached to
the receiver on and off.
When using these transmit and receive examples the Arduino types should be the same as the structure
formats can be different on some Arduinos.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LED1 8 //LED used to indicate transmission
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define TXpower 2 //LoRa transmit power in dBm
uint8_t TXPacketL;
#define TXtimeout 1000 //transmit timeout in mS. If 0 return from transmit function after send.
struct controllerStructure
{
uint16_t destinationNode;
uint8_t outputNumber;
uint8_t onoroff;
} __attribute__((packed, aligned(1))); //remove structure padding so there is compatibility between 8bit and 32bit Arduinos
struct controllerStructure controller1; //define an instance called controller1 of the structure controllerStructure
uint16_t PayloadCRC;
uint8_t TXPayloadL;
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in receiver
void loop()
{
controller1.destinationNode = 2; //node number we are controlling, 0 to 65535
controller1.outputNumber = 1; //output number on node we are controlling
if (controller1.onoroff == 0) //toggle the on/off status
{
controller1.onoroff = 1;
}
else
{
controller1.onoroff = 0;
}
Serial.print(F("Transmit Structure > "));
TXPayloadL = sizeof(controller1);
LT.printHEXPacket((uint8_t *) &controller1, sizeof(controller1)); //print the sent array as HEX
Serial.println();
Serial.flush();
//now transmit the packet
digitalWrite(LED1, HIGH); //LED on to indicate transmit
TXPacketL = LT.transmitReliable((uint8_t *) &controller1, sizeof(controller1), NetworkID, TXtimeout, TXpower, WAIT_TX); //will return packet length > 0 if sent OK, otherwise 0 if transmit error
if (TXPacketL > 0)
{
//if transmitReliable() returns > 0 then transmit was OK
PayloadCRC = LT.getTXPayloadCRC(TXPacketL); //read the actual transmitted CRC from the LoRa device buffer
packet_is_OK();
Serial.println();
}
else
{
//if transmitReliable() returns 0 there was an error
packet_is_Error();
Serial.println();
}
digitalWrite(LED1, LOW);
Serial.println();
delay(5000); //have a delay between packets
}
void packet_is_OK()
{
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmittedPayloadCRC,0x")); //print CRC of transmitted packet
Serial.print(PayloadCRC, HEX);
}
void packet_is_Error()
{
Serial.print(F("SendError"));
LT.printIrqStatus(); //prints the text of which IRQs set
LT.printReliableStatus(); //print the reliable status
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("203_Reliable_Transmitter_Controller_Structure Starting"));
pinMode(LED1, OUTPUT);
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF7, LORA_BW_0400, LORA_CR_4_5);
Serial.println(F("Transmitter ready"));
Serial.println();
//enable the following line if you want to disable payload CRC checking
//LT.setReliableConfig(NoReliableCRC); //disable payload CRC check
}

View File

@ -0,0 +1,197 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 21/07/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a basic demonstration of the receive of a 'Reliable' packet used to control
outputs on the receiver.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. This receiver needs to have the same
NetworkID as configured for the transmitter. The receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended is a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended to the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
This example program and the matching transmitter, 203_Reliable_Transmitter_Controller_Structure,
receives a reliable packet from the transmitter, reads the variables from the sent data structure which
when read remotly flashes the LED attached to the receiver on and off. Note that for the LED switching
to be actioned the destinationNode and outputNumber received in the structure have to match.
When using these transmit and receive examples the Arduino types should be the same as the structure
formats can be different on some Arduinos.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define LED1 8 //this is output 1
#define RXtimeout 60000 //receive timeout in mS.
uint8_t RXPacketL; //stores length of packet received
uint8_t PacketOK; //set to > 0 if packetOK
int16_t PacketRSSI; //stores RSSI of received packet
uint16_t LocalPayloadCRC; //locally calculated CRC of payload
uint16_t RXPayloadCRC; //CRC of payload received in packet
uint16_t TransmitterNetworkID; //the NetworkID from the transmitted and received packet
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in transmitter
const uint16_t thisNode = 2; //node number for this node
struct controllerStructure
{
uint16_t destinationNode;
uint8_t outputNumber;
uint8_t onoroff;
} __attribute__((packed, aligned(1))); //remove structure padding so there is compatibility between 8bit and 32bit Arduinos
struct controllerStructure controller1; //define an instance called controller1 of the structure controllerStructure
void loop()
{
PacketOK = LT.receiveReliable((uint8_t *) &controller1, sizeof(controller1), NetworkID, RXtimeout, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
RXPacketL = LT.readRXPacketL(); //get the received packet length
PacketRSSI = LT.readPacketRSSI(); //read the received packets RSSI value
if (PacketOK > 0)
{
//if the LT.receiveReliable() returns a value > 0 for PacketOK then packet was received OK
//then only action payload if destinationNode = thisNode
Serial.print(F("Packet received OK > "));
LT.printHEXPacket((uint8_t *) &controller1, sizeof(controller1));
Serial.println();
Serial.print(F("destinationNode "));
Serial.println(controller1.destinationNode);
if (controller1.destinationNode == thisNode)
{
Serial.print(F("outputNumber "));
Serial.println(controller1.outputNumber);
Serial.print(F("onoroff "));
Serial.println(controller1.onoroff);
packet_is_OK();
actionpayload();
}
}
else
{
//if the LT.receiveReliable() function detects an error PacketOK is 0
packet_is_Error();
}
Serial.println();
}
void packet_is_OK()
{
printPacketDetails();
Serial.println();
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
Serial.print(F("Error "));
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout "));
}
else
{
printPacketDetails();
}
}
void actionpayload()
{
Serial.print(F("Action payload > "));
if (controller1.outputNumber == 1)
{
Serial.print(F("outputNumber "));
Serial.print(controller1.outputNumber);
if (controller1.onoroff)
{
Serial.println(F(" High"));
digitalWrite(LED1, HIGH);
}
else
{
Serial.println(F(" Low"));
digitalWrite(LED1, LOW);
}
}
else
{
Serial.println(F("Not valid outputNumber"));
}
}
void printPacketDetails()
{
LocalPayloadCRC = LT.CRCCCITT((uint8_t *) &controller1, sizeof(controller1), 0xFFFF); //calculate payload crc from the received RXBUFFER
TransmitterNetworkID = LT.getRXNetworkID(RXPacketL);
RXPayloadCRC = LT.getRXPayloadCRC(RXPacketL);
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmitterNetworkID,0x"));
Serial.print(TransmitterNetworkID, HEX);
Serial.print(F(",LocalPayloadCRC,0x"));
Serial.print(LocalPayloadCRC, HEX);
Serial.print(F(",RXPayloadCRC,0x"));
Serial.print(RXPayloadCRC, HEX);
LT.printReliableStatus();
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("204_Reliable_Receiver_Controller_Structure Starting"));
pinMode(LED1, OUTPUT); //set high for on
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF7, LORA_BW_0400, LORA_CR_4_5); //configure frequency and LoRa settings
Serial.println(F("Receiver ready"));
Serial.println();
}

View File

@ -0,0 +1,149 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 21/07/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a basic demonstration of the transmission of a 'Reliable' packet used to
control outputs on a remote receiver.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. This receiver needs to have the same
NetworkID as configured for the transmitter. The receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended is a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended to the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
This example program and the matching receiver, 206_Reliable_Receiver_Controller_ArrayRW, transmits a
array that contains variables which when read by the remote receiver flash an LED attached to
the receiver on and off. The variables are writen direct to the array using a library file arrayRW.h.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
#include <arrayRW.h> //routines for reading and writing varaibles to array
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LED1 8 //LED used to indicate transmission
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define TXpower 2 //LoRa transmit power in dBm
#define TXtimeout 1000 //transmit timeout in mS.
uint8_t controlarray[4]; //the array payload to send
uint8_t controlarraysize;
uint16_t PayloadCRC;
uint8_t TXPacketL;
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in receiver
uint16_t destinationNode = 2; //node number we are controlling, 0 to 65535
uint8_t outputNumber = 1; //output number on node we are controlling
uint8_t onoroff = 0; //set to 0 to set remote output off, 1 to set it on
void loop()
{
beginarrayRW(controlarray, 0); //start writing to controlarray array at location 0
arrayWriteUint16(destinationNode);
arrayWriteUint8(outputNumber);
arrayWriteUint8(onoroff); //0 for off, 1 for on
controlarraysize = endarrayRW() + 1; //this function returns the length of the array to send, i.e. the packet payload
Serial.print(F("Transmit Array > "));
LT.printHEXPacket(controlarray, controlarraysize); //print the sent array as HEX
Serial.println();
Serial.flush();
//now transmit the packet
digitalWrite(LED1, HIGH); //LED on to indicate transmit
TXPacketL = LT.transmitReliable(controlarray, controlarraysize, NetworkID, TXtimeout, TXpower, WAIT_TX);
if (TXPacketL)
{
//if transmitReliable() returns > 0 then transmit was OK
PayloadCRC = LT.getTXPayloadCRC(TXPacketL); //read the actual transmitted CRC from the LoRa device
packet_is_OK();
Serial.println();
}
else
{
//if transmitReliable() returns 0 there was an error
packet_is_Error();
Serial.println();
}
digitalWrite(LED1, LOW);
Serial.println();
delay(5000); //have a delay between packets
if (onoroff == 0) //toggle the on/off status
{
onoroff = 1;
}
else
{
onoroff = 0;
}
}
void packet_is_OK()
{
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmittedPayloadCRC,0x")); //print CRC of transmitted packet
Serial.print(PayloadCRC, HEX);
}
void packet_is_Error()
{
Serial.print(F("SendError"));
LT.printIrqStatus(); //prints the text of which IRQs set
LT.printReliableStatus(); //print the reliable status
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("205_Reliable_Transmitter_Controller_ArrayRW Starting"));
pinMode(LED1, OUTPUT);
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF7, LORA_BW_0400, LORA_CR_4_5);
Serial.println(F("Transmitter ready"));
Serial.println();
}

View File

@ -0,0 +1,202 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 21/07/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a basic demonstration of the receive of a 'Reliable' packet used to control
outputs on this receiver.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. This receiver needs to have the same
NetworkID as configured for the transmitter. The receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended is a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended to the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
This example program and the matching transmitter, 205_Reliable_Transmitter_Controller_ArrayRW, receives
an array that contains variables which when read flash an LED attached to the receiver on and off.
The variables are writen direct to the array using a library file arrayRW.h.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
#include <arrayRW.h> //routines for reading and writing varaibles to array
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define LED1 8 //this is output 1
#define RXtimeout 60000 //receive timeout in mS.
const uint8_t RXBUFFER_SIZE = 251; //RX buffer size, set to max payload length of 251, or maximum expected length
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received payloads are copied into
uint8_t RXPacketL; //stores length of packet received
uint8_t RXPayloadL; //stores length of payload received
uint8_t PacketOK; //set to > 0 if packetOK
int16_t PacketRSSI; //stores RSSI of received packet
uint16_t LocalPayloadCRC; //locally calculated CRC of payload
uint16_t RXPayloadCRC; //CRC of payload received in packet
uint16_t TransmitterNetworkID; //the NetworkID from the transmitted and received packet
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in transmitter
uint16_t destinationNode = 2; //node number we are controlling, 0 to 65535
const uint16_t thisNode = 2; //node number for this node
uint8_t outputNumber = 1; //output number on node we are controlling
uint8_t onoroff = 1; //set to 0 to set remote output off, 1 to set it on
void loop()
{
PacketOK = LT.receiveReliable(RXBUFFER, RXBUFFER_SIZE, NetworkID, RXtimeout, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
RXPacketL = LT.readRXPacketL(); //get the received packet length
RXPayloadL = RXPacketL - 4; //payload length is always 4 bytes less than packet length
PacketRSSI = LT.readPacketRSSI(); //read the received packets RSSI value
//now read the received array into variables
beginarrayRW(RXBUFFER, 0); //start reading from array at location 0
destinationNode = arrayReadUint16();
outputNumber = arrayReadUint8();
onoroff = arrayReadUint8(); //0 for off, 1 for on
RXPayloadL = endarrayRW(); //this function returns the length of the array decoded
if (PacketOK > 0)
{
//if the LT.receiveReliable() returns a value > 0 for PacketOK then packet was received OK
//then only action payload if destinationNode = thisNode
Serial.print(F("Payload received OK > "));
LT.printHEXPacket(RXBUFFER, RXPayloadL);
Serial.println();
Serial.print(F("destinationNode "));
Serial.println(destinationNode);
if (destinationNode == thisNode)
{
Serial.print(F("outputNumber "));
Serial.println(outputNumber);
Serial.print(F("onoroff "));
Serial.println(onoroff);
packet_is_OK();
actionpayload();
}
}
else
{
//if the LT.receiveReliable() function detects an error PacketOK is 0
packet_is_Error();
}
Serial.println();
}
void packet_is_OK()
{
printPacketDetails();
Serial.println();
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
Serial.print(F("Error "));
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout "));
}
else
{
printPacketDetails();
}
}
void actionpayload()
{
Serial.print(F("Action payload > "));
if (outputNumber == 1)
{
Serial.print(F("outputNumber "));
Serial.print(outputNumber);
if (onoroff)
{
Serial.println(F(" High"));
digitalWrite(LED1, HIGH);
}
else
{
Serial.println(F(" Low"));
digitalWrite(LED1, LOW);
}
}
else
{
Serial.println(F("Not valid outputNumber"));
}
}
void printPacketDetails()
{
LocalPayloadCRC = LT.CRCCCITT(RXBUFFER, RXPayloadL, 0xFFFF); //calculate payload crc from the received RXBUFFER
TransmitterNetworkID = LT.getRXNetworkID(RXPacketL);
RXPayloadCRC = LT.getRXPayloadCRC(RXPacketL);
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmitterNetworkID,0x"));
Serial.print(TransmitterNetworkID, HEX);
Serial.print(F(",LocalPayloadCRC,0x"));
Serial.print(LocalPayloadCRC, HEX);
Serial.print(F(",RXPayloadCRC,0x"));
Serial.print(RXPayloadCRC, HEX);
LT.printReliableStatus();
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("206_Reliable_Receiver_Controller_ArrayRW Starting"));
pinMode(LED1, OUTPUT); //set high for on
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF7, LORA_BW_0400, LORA_CR_4_5);
Serial.println(F("Receiver ready"));
Serial.println();
}

View File

@ -0,0 +1,150 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 13/09/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a basic demonstration of the transmission of a 'Reliable' packet used to
control outputs on a remote receiver.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. This receiver needs to have the same
NetworkID as configured for the transmitter. The receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended to the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
This example program and the matching receiver, 208_Reliable_SXReceiver_Controller writes a series
of variables direct into the LoRa devices internal buffer, it is not necessary to write variables to a
memory array first. The receiver then reads the matching variables direct from the LoRa devices buffer and
these variables contain the control information to flash a LED attached to the receiver on and off.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LED1 8 //this is output 1
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define TXpower 2 //LoRa transmit power in dBm
#define TXtimeout 1000 //transmit timeout in mS. If 0 return from transmit function after send.
uint8_t TXPacketL;
uint8_t TXPayloadL; //this is the payload length sent
uint16_t PayloadCRC;
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in receiver
uint16_t destinationNode = 2; //node number we are controlling, 0 to 65535
uint8_t outputNumber = 1; //output number on node we are controlling
uint8_t onoroff = 0; //set to 0 to set remote output off, 1 to set it on
uint8_t startaddr = 0; //address in SX buffer to start packet
void loop()
{
LT.startWriteSXBuffer(startaddr); //start the write at SX12XX internal buffer location startaddr
LT.writeUint16(destinationNode); //destination node for packet
LT.writeUint8(outputNumber); //output number on receiver
LT.writeUint8(onoroff); //0 for off, 1 for on
TXPayloadL = LT.endWriteSXBuffer(); //closes packet write and returns the length of the payload to send
Serial.print(F("Transmit SX buffer > "));
LT.printSXBufferHEX(startaddr, TXPayloadL + startaddr - 1); //print the sent SX array as HEX
Serial.println();
Serial.flush();
//now transmit the packet
digitalWrite(LED1, HIGH);
TXPacketL = LT.transmitSXReliable(startaddr, TXPayloadL, NetworkID, TXtimeout, TXpower, WAIT_TX); //will return packet length > 0 if sent OK, otherwise 0 if transmit error
if (TXPacketL > 0)
{
//if transmitReliable() returns > 0 then transmit was OK
PayloadCRC = LT.getTXPayloadCRC(TXPacketL); //read the actual transmitted CRC from the LoRa device buffer
packet_is_OK();
Serial.println();
}
else
{
//if transmitReliable() returns 0 there was an error
packet_is_Error();
Serial.println();
}
digitalWrite(LED1, LOW);
Serial.println();
delay(5000); //have a delay between packets
if (onoroff == 0) //toggle the on/off status
{
onoroff = 1;
}
else
{
onoroff = 0;
}
}
void packet_is_OK()
{
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmittedPayloadCRC,0x")); //print CRC of transmitted packet
Serial.print(PayloadCRC, HEX);
}
void packet_is_Error()
{
Serial.print(F("SendError"));
LT.printIrqStatus(); //prints the text of which IRQs set
LT.printReliableStatus(); //print the reliable status
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("207_Reliable_SXTransmitter_Controller Starting"));
pinMode(LED1, OUTPUT); //set high for on
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF7, LORA_BW_0400, LORA_CR_4_5);
Serial.println(F("Transmitter ready"));
Serial.println();
//enable the following line if you want to disable payload CRC checking
//LT.setReliableConfig(NoReliableCRC); //disable payload CRC check
}

View File

@ -0,0 +1,200 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a simple demonstration of the receipt of a 'Reliable' packet.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. This receiver needs to have the same
NetworkID as configured for the transmitter. The receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended to the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
This example program and the matching transmitter, 207_Reliable_SXTransmitter_Controller reads a
series of variables direct from the packet received in the LoRa devices internal buffer, it is not necessary
to read variables to a memory array first. The receiver then uses these variables as the control information
to flash a LED attached to the receiver on and off.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define LED1 8 //this is output 1
#define RXtimeout 60000 //receive timeout in mS.
uint8_t RXPacketL; //stores length of packet received
uint8_t RXPayloadL; //stores length of payload received
uint8_t PacketOK; //set to > 0 if packetOK
int16_t PacketRSSI; //stores RSSI of received packet
uint16_t LocalPayloadCRC; //locally calculated CRC of payload
uint16_t RXPayloadCRC; //CRC of payload received in packet
uint16_t TransmitterNetworkID; //the NetworkID from the transmitted and received packet
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in transmitter
uint16_t destinationNode; //node number we are controlling, 0 to 65535
const uint16_t thisNode = 2; //node number for this node
uint8_t outputNumber = 1; //output number on node we are controlling
uint8_t onoroff = 1; //set to 0 to set remote output off, 1 to set it on
uint8_t startaddr = 0; //address in SX buffer to start packet
void loop()
{
PacketOK = LT.receiveSXReliable(startaddr, NetworkID, RXtimeout, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
RXPacketL = LT.readRXPacketL(); //get the received packet length, get this before reading packet
RXPayloadL = RXPacketL - 4;
PacketRSSI = LT.readPacketRSSI(); //read the received packets RSSI value
LT.startReadSXBuffer(startaddr); //start buffer read at location 0
destinationNode = LT.readUint16(); //load the destination node
outputNumber = LT.readUint8(); //load the output number
onoroff = LT.readUint8(); //0 for off, 1 for on
RXPayloadL = LT.endReadSXBuffer(); //this function returns the length of the array read
if (PacketOK > 0)
{
//if the LT.receiveReliable() returns a value > 0 for PacketOK then packet was received OK
//then only action payload if destinationNode = thisNode
Serial.print(F("Payload received OK > "));
LT.printSXBufferHEX(startaddr, startaddr + RXPayloadL - 1);
Serial.println();
Serial.print(F("destinationNode "));
Serial.println(destinationNode);
if (destinationNode == thisNode)
{
Serial.print(F("outputNumber "));
Serial.println(outputNumber);
Serial.print(F("onoroff "));
Serial.println(onoroff);
packet_is_OK();
actionpayload();
}
}
else
{
//if the LT.receiveReliable() function detects an error PacketOK is 0
packet_is_Error();
}
Serial.println();
}
void packet_is_OK()
{
printPacketDetails();
Serial.println();
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
Serial.print(F("Error "));
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout "));
}
else
{
printPacketDetails();
}
}
void actionpayload()
{
Serial.print(F("Action payload > "));
if (outputNumber == 1)
{
Serial.print(F("outputNumber "));
Serial.print(outputNumber);
if (onoroff)
{
Serial.println(F(" High"));
digitalWrite(LED1, HIGH);
}
else
{
Serial.println(F(" Low"));
digitalWrite(LED1, LOW);
}
}
else
{
Serial.println(F("Not valid outputNumber"));
}
}
void printPacketDetails()
{
LocalPayloadCRC = LT.CRCCCITTSX(startaddr, startaddr + RXPayloadL - 1, 0xFFFF); //calculate payload crc from the received payload in LoRa device buffer
TransmitterNetworkID = LT.getRXNetworkID(RXPacketL);
RXPayloadCRC = LT.getRXPayloadCRC(RXPacketL); //used the saved packet value to retrieve the payload CRC
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmitterNetworkID,0x"));
Serial.print(TransmitterNetworkID, HEX);
Serial.print(F(",LocalPayloadCRC,0x"));
Serial.print(LocalPayloadCRC, HEX);
Serial.print(F(",RXPayloadCRC,0x"));
Serial.print(RXPayloadCRC, HEX);
LT.printReliableStatus();
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("208_Reliable_SXReceiver_Controller Starting"));
pinMode(LED1, OUTPUT); //set high for on
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF7, LORA_BW_0400, LORA_CR_4_5);
Serial.println(F("Receiver ready"));
Serial.println();
//enable the following line if you want to disable payload CRC checking
//LT.setReliableConfig(NoReliableCRC); //disable payload CRC check
}

View File

@ -0,0 +1,153 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a basic demonstration of the transmission and acknowledgement of a 'Reliable'
packet.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. The receiver needs to have the same
NetworkID as configured for the transmitter since the receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended in the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
If the received packet is valid then the networkID and payload CRC are returned in a 4 byte packet as an
acknowledgement that the transmitter listens for. If the transmitter does not receive the acknowledgement
within the ACKtimeout period, the original packet is re-transmitted until a valid acknowledgement is
received. This program should be used with the matching receiver program, 210_Reliable_Receiver_AutoACK.
The program will attempt to transmit the packet and have it acknowledged by the receiver a number of times
as defined by constant TXattempts. If there is no acknowledge withing this time it will be reported.
It is possible to use the 'NetworkID' to direct the packet to specific receivers.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define TXpower 2 //LoRa transmit power in dBm
#define ACKtimeout 1000 //Acknowledge timeout in mS
#define TXtimeout 1000 //transmit timeout in mS. If 0 return from transmit function after send.
#define TXattempts 10 //number of times to attempt to TX and get an Ack before failing
uint8_t buff[] = "Hello World"; //the payload to send
uint16_t PayloadCRC;
uint8_t TXPacketL;
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in receiver
void loop()
{
//keep transmitting the packet until an ACK is received
uint8_t attempts = TXattempts;
do
{
Serial.print(F("Transmit Payload > "));
LT.printASCIIArray(buff, sizeof(buff)); //print the payload buffer as ASCII
Serial.println();
Serial.flush();
Serial.print(F("Send attempt "));
Serial.println(TXattempts - attempts + 1);
TXPacketL = LT.transmitReliableAutoACK(buff, sizeof(buff), NetworkID, ACKtimeout, TXtimeout, TXpower, WAIT_TX);
attempts--;
if (TXPacketL > 0)
{
//if transmitReliable() returns > 0 then transmit and ack was OK
PayloadCRC = LT.getTXPayloadCRC(TXPacketL); //read the actual transmitted CRC from the LoRa device buffer
packet_is_OK();
Serial.println();
}
else
{
//if transmitReliableAutoACK() returns 0 there was an error, timeout etc
packet_is_Error();
Serial.println();
}
delay(500); //small delay between tranmission attampts
}
while ((TXPacketL == 0) && (attempts != 0));
if (TXPacketL > 0)
{
Serial.println(F("Packet acknowledged"));
}
if (attempts == 0)
{
Serial.print(F("No acknowledge after "));
Serial.print(TXattempts);
Serial.print(F(" attempts"));
}
Serial.println();
delay(5000); //have a delay between packets
}
void packet_is_OK()
{
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmittedPayloadCRC,0x")); //print CRC of transmitted packet
Serial.print(PayloadCRC, HEX);
}
void packet_is_Error()
{
Serial.print(F("No Packet acknowledge"));
LT.printIrqStatus(); //prints the text of which IRQs set
LT.printReliableStatus(); //print the reliable status
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("209_Reliable_Transmitter_AutoACK Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF5, LORA_BW_1600, LORA_CR_4_5);
Serial.println(F("Transmitter ready"));
Serial.println();
}

View File

@ -0,0 +1,153 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a basic demonstration of the transmission and acknowledgement of a 'Reliable'
packet.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. The receiver needs to have the same
NetworkID as configured for the transmitter since the receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended in the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
If the received packet is valid then the networkID and payload CRC are returned in a 4 byte packet as an
acknowledgement that the transmitter listens for. If the transmitter does not receive the acknowledgement
of the networkID and payloadCRC within the ACKtimeout period, the original packet is re-transmitted until
a valid acknowledgement is received. This program should be used with the matching transmitter program,
209_Reliable_Transmitter_AutoACK.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define ACKdelay 100 //delay in mS before sending acknowledge
#define RXtimeout 60000 //receive timeout in mS.
#define TXpower 2 //dBm power to use for ACK
const uint8_t RXBUFFER_SIZE = 251; //RX buffer size, set to max payload length of 251, or maximum expected length
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
uint8_t RXPacketL; //stores length of packet received
uint8_t RXPayloadL; //stores length of payload received
uint8_t PacketOK; //set to > 0 if packetOK
int16_t PacketRSSI; //stores RSSI of received packet
uint16_t LocalPayloadCRC; //locally calculated CRC of payload
uint16_t RXPayloadCRC; //CRC of payload received in packet
uint16_t TransmitterNetworkID; //the NetworkID from the transmitted and received packet
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in transmitter
void loop()
{
PacketOK = LT.receiveReliableAutoACK(RXBUFFER, RXBUFFER_SIZE, NetworkID, ACKdelay, TXpower, RXtimeout, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
RXPacketL = LT.readRXPacketL(); //get the received packet length
RXPayloadL = RXPacketL - 4; //payload length is always 4 bytes less than packet length
PacketRSSI = LT.readPacketRSSI(); //read the received packets RSSI value
if (PacketOK > 0)
{
//if the LT.receiveReliable() returns a value > 0 for PacketOK then packet was received OK
packet_is_OK();
}
else
{
//if the LT.receiveReliable() function detects an error PacketOK is 0
packet_is_Error();
}
Serial.println();
}
void packet_is_OK()
{
Serial.print(F("Payload received OK > "));
LT.printASCIIPacket(RXBUFFER, RXPayloadL);
Serial.println();
printPacketDetails();
Serial.println();
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
Serial.print(F("Error "));
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout "));
}
else
{
printPacketDetails();
}
}
void printPacketDetails()
{
LocalPayloadCRC = LT.CRCCCITT(RXBUFFER, RXPayloadL, 0xFFFF); //calculate payload crc from the received RXBUFFER
TransmitterNetworkID = LT.getRXNetworkID(RXPacketL);
RXPayloadCRC = LT.getRXPayloadCRC(RXPacketL);
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmitterNetworkID,0x"));
Serial.print(TransmitterNetworkID, HEX);
Serial.print(F(",LocalPayloadCRC,0x"));
Serial.print(LocalPayloadCRC, HEX);
Serial.print(F(",RXPayloadCRC,0x"));
Serial.print(RXPayloadCRC, HEX);
LT.printReliableStatus();
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("210_Reliable_Receiver_AutoACK Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF5, LORA_BW_1600, LORA_CR_4_5);
Serial.println(F("Receiver ready"));
Serial.println();
}

View File

@ -0,0 +1,157 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 13/09/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a basic demonstration of the transmission and acknowledgement of a 'Reliable'
packet.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. The receiver needs to have the same
NetworkID as configured for the transmitter since the receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended in the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
If the received packet is valid then the networkID and payload CRC are returned in a 4 byte packet as an
acknowledgement that the transmitter listens for. If the transmitter does not receive the acknowledgement
within the ACKtimeout period, the original packet is re-transmitted until a valid acknowledgement is
received. This program should be used with the matching receiver program, 212_Reliable_SXReceiver_AutoACK.
This example writes the payload direct to the LoRa SX devices internal packet buffer, no intermediate array
or memory is needed. The payload is a simpel remote control packet directed to a specific receiver,
The packet is destined for a specific receiver (destinationNode). A particular output (outputNumber) is turned
on and off.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define TXpower 2 //LoRa transmit power in dBm
#define ACKtimeout 1000 //Acknowledge timeout in mS
#define TXtimeout 1000 //transmit timeout in mS. If 0 return from transmit function after send.
uint16_t PayloadCRC; //CRC of the payload
uint8_t TXPacketL; //length of transmitted packet
uint8_t TXPayloadL; //this is the payload length sent
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in receiver
uint16_t destinationNode = 2; //node number we are controlling, 0 to 65535
uint8_t outputNumber = 1; //output number on node we are controlling
uint8_t onoroff = 0; //set to 0 to set remote output off, 1 to set it on
uint8_t startaddr = 0; //address in SX buffer to start packet
void loop()
{
//keep transmitting the packet until an ACK is received
do
{
LT.startWriteSXBuffer(startaddr); //start the write at SX12XX internal buffer location 0
LT.writeUint16(destinationNode); //destination node for packet
LT.writeUint8(outputNumber); //output number on receiver
LT.writeUint8(onoroff); //0 for off, 1 for on
TXPayloadL = LT.endWriteSXBuffer(); //closes packet write and returns the length of the payload to send
Serial.print(F("Transmit SX buffer > "));
LT.printSXBufferHEX(startaddr, startaddr + TXPayloadL - 1); //print the sent SX array as HEX
Serial.println();
Serial.flush();
TXPacketL = LT.transmitSXReliableAutoACK(startaddr, TXPayloadL, NetworkID, ACKtimeout, TXtimeout, TXpower, WAIT_TX);
if (TXPacketL > 0)
{
//if transmitSXReliableAutoACK() returns > 0 then transmit and ack was OK
PayloadCRC = LT.getTXPayloadCRC(TXPacketL); //read the actual transmitted CRC from the LoRa device buffer
packet_is_OK();
Serial.println();
}
else
{
//if transmitReliable() returns 0 there was an error
packet_is_Error();
Serial.println();
}
delay(500); //small delay between tranmission attampts
}
while (TXPacketL == 0);
Serial.println();
delay(1000); //have a delay between packets
if (onoroff == 0) //toggle the on/off status
{
onoroff = 1;
}
else
{
onoroff = 0;
}
}
void packet_is_OK()
{
Serial.println(F("Packet acknowledged"));
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmittedPayloadCRC,0x")); //print CRC of transmitted packet
Serial.print(PayloadCRC, HEX);
}
void packet_is_Error()
{
Serial.print(F("No Packet acknowledge"));
LT.printIrqStatus(); //prints the text of which IRQs set
LT.printReliableStatus(); //print the reliable status
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("211_Reliable_SXTransmitter_AutoACK Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF5, LORA_BW_1600, LORA_CR_4_5); //configure frequency and LoRa settings
Serial.println(F("Transmitter ready"));
Serial.println();
}

View File

@ -0,0 +1,212 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a basic demonstration of the transmission and acknowledgement of a 'Reliable'
packet.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. The receiver needs to have the same
NetworkID as configured for the transmitter since the receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended in the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
If the received packet is valid then the networkID and payload CRC are returned in a 4 byte packet as an
acknowledgement that the transmitter listens for. If the transmitter does not receive the acknowledgement
of the networkID and payloadCRC within the ACKtimeout period, the original packet is re-transmitted until
a valid acknowledgement is received. This program should be used with the matching transmitter program,
211_Reliable_SXTransmitter_AutoACK.
The packet is destined for a specific receiver (destinationNode). A particular output (outputNumber) is
turned on and off.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define LED1 8 //this is output 1
#define ACKdelay 100 //delay in mS before sending acknowledge
#define RXtimeout 60000 //receive timeout in mS.
#define TXpower 2 //dBm power to use for ACK
uint8_t RXPacketL; //stores length of packet received
uint8_t RXPayloadL; //stores length of payload received
uint8_t PacketOK; //set to > 0 if packetOK
int16_t PacketRSSI; //stores RSSI of received packet
uint16_t LocalPayloadCRC; //locally calculated CRC of payload
uint16_t RXPayloadCRC; //CRC of payload received in packet
uint16_t TransmitterNetworkID; //the NetworkID from the transmitted and received packet
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in transmitter
uint16_t destinationNode; //node number we are controlling, 0 to 65535
const uint16_t thisNode = 2; //node number for this node
uint8_t outputNumber = 1; //output number on node we are controlling
uint8_t onoroff = 1; //set to 0 to set remote output off, 1 to set it on
uint8_t startaddr = 0; //address in SX buffer to start packet
void loop()
{
PacketOK = LT.receiveSXReliableAutoACK(startaddr, NetworkID, ACKdelay, TXpower, RXtimeout, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
RXPacketL = LT.readRXPacketL(); //get the received packet length
RXPayloadL = RXPacketL - 4;
PacketRSSI = LT.readPacketRSSI(); //read the received packets RSSI value
LT.startReadSXBuffer(startaddr); //start buffer read at location addr
destinationNode = LT.readUint16(); //load the destination node
outputNumber = LT.readUint8(); //load the output number
onoroff = LT.readUint8(); //0 for off, 1 for on
RXPayloadL = LT.endReadSXBuffer(); //this function returns the length of the array read
if (PacketOK > 0)
{
//if the LT.receiveReliable() returns a value > 0 for PacketOK then packet and ack was received OK
//then only action payload if destinationNode = thisNode
Serial.print(F("Payload received OK > "));
LT.printSXBufferHEX(startaddr, startaddr + RXPayloadL - 1);
Serial.println();
Serial.print(F("DestinationNode "));
Serial.println(destinationNode);
if (destinationNode == thisNode)
{
Serial.print(F("outputNumber "));
Serial.println(outputNumber);
Serial.print(F("onoroff "));
Serial.println(onoroff);
packet_is_OK();
actionpayload();
}
else
{
Serial.println(F("Not for this node"));
}
}
else
{
//if the LT.receiveReliable() function detects an error PacketOK is 0
packet_is_Error();
}
Serial.println();
}
void packet_is_OK()
{
//Serial.print(F("Payload received OK > "));
//LT.printASCIIPacket(RXBUFFER, RXPayloadL);
//Serial.println();
printPacketDetails();
Serial.println();
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
Serial.print(F("Error "));
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout "));
}
else
{
printPacketDetails();
}
}
void actionpayload()
{
Serial.print(F("Action payload > "));
if (outputNumber == 1)
{
Serial.print(F("outputNumber "));
Serial.print(outputNumber);
if (onoroff)
{
Serial.println(F(" High"));
digitalWrite(LED1, HIGH);
}
else
{
Serial.println(F(" Low"));
digitalWrite(LED1, LOW);
}
}
else
{
Serial.println(F("Not valid outputNumber"));
}
}
void printPacketDetails()
{
LocalPayloadCRC = LT.CRCCCITTReliable(startaddr, (startaddr + RXPayloadL - 1), 0xFFFF); //calculate payload crc from the received RXBUFFER
TransmitterNetworkID = LT.getRXNetworkID(RXPacketL);
RXPayloadCRC = LT.getRXPayloadCRC(RXPacketL);
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmitterNetworkID,0x"));
Serial.print(TransmitterNetworkID, HEX);
Serial.print(F(",LocalPayloadCRC,0x"));
Serial.print(LocalPayloadCRC, HEX);
Serial.print(F(",RXPayloadCRC,0x"));
Serial.print(RXPayloadCRC, HEX);
LT.printReliableStatus();
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("212_Reliable_SXReceiver_AutoACK Starting"));
pinMode(LED1, OUTPUT);
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF5, LORA_BW_1600, LORA_CR_4_5); //configure frequency and LoRa settings
Serial.println(F("Receiver ready"));
Serial.println();
}

View File

@ -0,0 +1,163 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a demonstration of the transmission and acknowledgement of a 'Reliable'
packet.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. The receiver needs to have the same
NetworkID as configured for the transmitter since the receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended in the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
If the received packet is valid then the networkID and payload CRC are returned in a 4 byte packet as an
acknowledgement that the transmitter listens for. If the transmitter does not receive the acknowledgement
within the ACKtimeout period, the original packet is re-transmitted until a valid acknowledgement is
received.
With this example and the matching receiver program, 214_Reliable_Receiver_Controller_ManualACK
the generation of the acknowledge by the receiver is manual. This allows the received packet to be read
and decisions made as to whether to reply with an acknowledge. In this example an acknowledge is only
sent if the destinationNode variable in the transmitted packet matches the number for this node.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define TXpower 2 //LoRa transmit power in dBm
#define ACKtimeout 1000 //Acknowledge timeout in mS, set to 0 if ACK not used.
#define TXtimeout 1000 //transmit timeout in mS. If 0 return from transmit function after send.
uint8_t TXPacketL; //length of transmitted packet
uint8_t TXPayloadL; //this is the payload length sent
uint8_t RXPacketL; //length of received acknowledge
uint16_t PayloadCRC;
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in receiver
uint16_t destinationNode = 2; //node number we are controlling, 0 to 65535
uint8_t outputNumber = 1; //output number on node we are controlling
uint8_t onoroff = 0; //set to 0 to set remote output off, 1 to set it on
uint8_t startaddr = 0; //address in SX buffer to start packet
void loop()
{
//now transmit the packet and keep transmitting until the acknowledge is received
do
{
LT.startWriteSXBuffer(startaddr); //start the write at SX12XX internal buffer location 0
LT.writeUint16(destinationNode); //destination node for packet
LT.writeUint8(outputNumber); //output number on receiver
LT.writeUint8(onoroff); //0 for off, 1 for on
TXPayloadL = LT.endWriteSXBuffer(); //closes packet write and returns the length of the payload to send
Serial.print(F("Transmit payload > "));
LT.printSXBufferHEX(startaddr, startaddr + TXPayloadL - 1); //print the sent SX array as HEX
Serial.println();
Serial.flush();
TXPacketL = LT.transmitSXReliable(startaddr, TXPayloadL, NetworkID, TXtimeout, TXpower, WAIT_TX); //will return packet length > 0 if sent OK, otherwise 0 if transmit error
PayloadCRC = LT.getTXPayloadCRC(TXPacketL); //read the payload CRC sent
RXPacketL = LT.waitReliableACK(NetworkID, PayloadCRC, ACKtimeout);
if (RXPacketL > 0)
{
//if waitReliableACK() returns > 0 then valid ack was received
packet_is_OK();
Serial.println();
Serial.println(F("Ack Received"));
}
else
{
//if transmitReliable() returns 0 there is an error
packet_is_Error();
Serial.println();
Serial.println(F("No Ack Received"));
}
delay(200); //small delay between tranmission attampts
}
while (RXPacketL == 0);
Serial.println();
delay(1000); //have a delay between packets
if (onoroff == 0) //toggle the on/off status
{
onoroff = 1;
}
else
{
onoroff = 0;
}
}
void packet_is_OK()
{
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmittedPayloadCRC,0x")); //print CRC of transmitted packet
Serial.print(PayloadCRC, HEX);
}
void packet_is_Error()
{
Serial.print(F("SendError"));
LT.printIrqStatus(); //prints the text of which IRQs set
LT.printReliableStatus(); //print the reliable status
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("213_Reliable_Transmitter_Controller_ManualACK Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF7, LORA_BW_0400, LORA_CR_4_5); //configure frequency and LoRa settings
Serial.println(F("Transmitter ready"));
Serial.println();
}

View File

@ -0,0 +1,215 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a demonstration of the receiving and acknowledgement of a 'Reliable'
packet.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. The receiver needs to have the same
NetworkID as configured for the transmitter since the receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended in the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
If the received packet is valid then the networkID and payload CRC are returned in a 4 byte packet as an
acknowledgement that the transmitter listens for. If the transmitter does not receive the acknowledgement
within the ACKtimeout period, the original packet is re-transmitted until a valid acknowledgement is
received.
With this example and the matching receiver program, 213_Reliable_Transmitter_Controller_ManualACK
the generation of the acknowledge by the receiver is manual. This allows the received packet to be read
and decisions made as to whether to reply with an acknowledge. In this example an acknowledge is only
sent if the destinationNode variable in the transmitted packet matches the number for this node.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define LED1 8 //this is output 1
#define ACKdelay 100 //delay in mS before sending acknowledge, not used here so set to 0
#define RXtimeout 60000 //receive timeout in mS.
#define TXpower 2 //dBm power to use for ACK
uint8_t RXPacketL; //stores length of packet received
uint8_t RXPayloadL; //stores length of payload received
uint8_t PacketOK; //set to > 0 if packetOK
int16_t PacketRSSI; //stores RSSI of received packet
uint16_t LocalPayloadCRC; //locally calculated CRC of payload
uint16_t RXPayloadCRC; //CRC of payload received in packet
uint16_t TransmitterNetworkID; //the NetworkID from the transmitted and received packet
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in transmitter
uint16_t destinationNode; //node number we are controlling, 0 to 65535
const uint16_t thisNode = 2; //node number for this node
uint8_t outputNumber = 1; //output number on node we are controlling
uint8_t onoroff = 1; //set to 0 to set remote output off, 1 to set it on
uint8_t startaddr = 0; //address in SX buffer to start packet
void loop()
{
PacketOK = LT.receiveSXReliable(startaddr, NetworkID, RXtimeout, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
RXPacketL = LT.readRXPacketL(); //get the received packet length
RXPayloadL = RXPacketL - 4;
PacketRSSI = LT.readPacketRSSI(); //read the received packets RSSI value
LT.startReadSXBuffer(startaddr); //start buffer read at location 0
destinationNode = LT.readUint16(); //load the destination node
outputNumber = LT.readUint8(); //load the output number
onoroff = LT.readUint8(); //0 for off, 1 for on
RXPayloadL = LT.endReadSXBuffer(); //this function returns the length of the array read
if (PacketOK > 0)
{
//if the LT.receiveReliable() returns a value > 0 for PacketOK then packet was received OK
//only action packet if destinationNode = thisNode
Serial.print(F("Payload received OK > "));
LT.printSXBufferHEX(startaddr, startaddr + RXPayloadL - 1); Serial.println();
Serial.print(F("destinationNode "));
Serial.println(destinationNode);
if (destinationNode == thisNode)
{
Serial.print(F("outputNumber "));
Serial.println(outputNumber);
Serial.print(F("onoroff "));
Serial.println(onoroff);
packet_is_OK();
actionpayload();
sendACK();
}
}
else
{
//if the LT.receiveReliable() function detects an error PacketOK is 0
packet_is_Error();
}
Serial.println();
Serial.println();
}
void packet_is_OK()
{
printPacketDetails();
Serial.println();
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
Serial.print(F("Error "));
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout "));
}
else
{
printPacketDetails();
}
}
void actionpayload()
{
Serial.print(F("Action payload > "));
if (outputNumber == 1)
{
Serial.print(F("outputNumber "));
Serial.print(outputNumber);
if (onoroff)
{
Serial.println(F(" High"));
digitalWrite(LED1, HIGH);
}
else
{
Serial.println(F(" Low"));
digitalWrite(LED1, LOW);
}
}
else
{
Serial.println(F("Not valid outputNumber"));
}
}
void printPacketDetails()
{
LocalPayloadCRC = LT.CRCCCITTReliable(0, RXPayloadL - 1, 0xFFFF); //calculate payload crc
TransmitterNetworkID = LT.getRXNetworkID(RXPacketL);
RXPayloadCRC = LT.getRXPayloadCRC(RXPacketL);
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmitterNetworkID,0x"));
Serial.print(TransmitterNetworkID, HEX);
Serial.print(F(",LocalPayloadCRC,0x"));
Serial.print(LocalPayloadCRC, HEX);
Serial.print(F(",RXPayloadCRC,0x"));
Serial.print(RXPayloadCRC, HEX);
LT.printReliableStatus();
}
void sendACK()
{
LocalPayloadCRC = LT.CRCCCITTReliable(0, RXPayloadL - 1, 0xFFFF); //calculate payload crc
delay(ACKdelay);
LT.sendReliableACK(NetworkID, LocalPayloadCRC, TXpower);
Serial.print(F("Ack sent"));
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("214_Reliable_Receiver_Controller_ManualACK Starting"));
pinMode(LED1, OUTPUT); //set high for on
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF7, LORA_BW_0400, LORA_CR_4_5); //configure frequency and LoRa settings
Serial.println(F("Receiver ready"));
Serial.println();
}

View File

@ -0,0 +1,148 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a demonstration of the transmission and acknowledgement of a 'Reliable'
packet.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. The receiver needs to have the same
NetworkID as configured for the transmitter since the receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended in the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
If the received packet is valid then a data payload together with the networkID and payload CRC are
returned in a packet as an acknowledgement that the transmitter listens for. If the transmitter does not
receive the acknowledgement within the ACKtimeout period, the original packet is re-transmitted until a
valid acknowledgement is received.
With this example and the matching receiver program, 216_Reliable_Receiver_ACK_withData, the
generation of the acknowledge by the receiver is manual and also returns data to the transmitter. This
allows the transmitter to send a request to the receiver for it to return data. Since the acknowledge
returns the networkID and payload CRC used in the original transmitted request, when the transmitter
receives the acknowledge it can be very confident the data is geniune.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define TXpower 2 //LoRa transmit power in dBm
#define ACKtimeout 1000 //Acknowledge timeout in mS, set to 0 if ACK not used.
#define TXtimeout 1000 //transmit timeout in mS. If 0 return from transmit function after send.
uint8_t TXPacketL; //length of transmitted packet
uint8_t RXPacketL; //length of received acknowledge
uint16_t PayloadCRC;
const uint8_t RXBUFFER_SIZE = 16; //RX buffer size, set to max payload length of 251, or maximum expected length
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
uint8_t buff[] = "Hello World"; //the payload to send
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in receiver
void loop()
{
do
{
Serial.print(F("Transmit Payload > "));
LT.printASCIIArray(buff, sizeof(buff)); //print the payload buffer as ASCII
Serial.println();
Serial.flush();
PayloadCRC = LT.CRCCCITT(buff, sizeof(buff), 0xFFFF);
//now transmit the packet
TXPacketL = LT.transmitReliable(buff, sizeof(buff), NetworkID, TXtimeout, TXpower, WAIT_TX); //will return packet length > 0 if sent OK, otherwise 0 if transmit error
RXPacketL = LT.waitReliableACK(RXBUFFER, sizeof(RXBUFFER), NetworkID, PayloadCRC, ACKtimeout);
if (RXPacketL > 0)
{
//if waitReliableACK() returns > 0 then ack was received
packet_is_OK();
Serial.println();
Serial.print(F("Ack Received > "));
LT.printASCIIPacket(RXBUFFER, RXPacketL - 5);
Serial.println();
}
else
{
//if transmitReliable() returns 0 there was an error
packet_is_Error();
Serial.println();
Serial.println(F("No Ack Received"));
Serial.println();
}
delay(200); //small delay between tranmission attempts
}
while (RXPacketL == 0);
Serial.println();
delay(5000); //have a delay between packets
}
void packet_is_OK()
{
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmittedPayloadCRC,0x")); //print CRC of transmitted packet
Serial.print(PayloadCRC, HEX);
}
void packet_is_Error()
{
Serial.print(F("SendError"));
LT.printIrqStatus(); //prints the text of which IRQs set
LT.printReliableStatus(); //print the reliable status
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("215_Reliable_Transmitter_ACK_withData Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF5, LORA_BW_1600, LORA_CR_4_5); //configure frequency and LoRa settings
Serial.println(F("Transmitter ready"));
Serial.println();
}

View File

@ -0,0 +1,172 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a demonstration of the transmission and acknowledgement of a 'Reliable'
packet.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. The receiver needs to have the same
NetworkID as configured for the transmitter since the receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended in the packet. The receiver is thus able to check if the payload is valid.
For a packet to be accepted by the receiver, the networkID and payload CRC appended to the packet by the
transmitter need to match those from the receiver which gives a high level of assurance that the packet
is valid.
If the received packet is valid then a data payload together with the networkID and payload CRC are
returned in a packet as an acknowledgement that the transmitter listens for. If the transmitter does not
receive the acknowledgement within the ACKtimeout period, the original packet is re-transmitted until a
valid acknowledgement is received.
With this example and the matching transmitter program, 215_Reliable_Transmitter_ACK_withData, the
generation of the acknowledge by the receiver is manual and also returns data to the transmitter. This
allows the transmitter to send a request to the receiver for it to return data. Since the acknowledge
returns the networkID and payload CRC used in the original transmitted request, when the transmitter
receives the acknowledge it can be very confident the data is geniune.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LT; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define ACKdelay 200 //delay in mS before sending acknowledge, not used here so set to 0
#define RXtimeout 60000 //receive timeout in mS.
#define TXpower 2 //dBm power to use for ACK
const uint8_t RXBUFFER_SIZE = 251; //RX buffer size, set to max payload length of 251, or maximum expected length
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
uint8_t RXPacketL; //stores length of packet received
uint8_t RXPayloadL; //stores length of payload received
uint8_t PacketOK; //set to > 0 if packetOK
int16_t PacketRSSI; //stores RSSI of received packet
uint16_t LocalPayloadCRC; //locally calculated CRC of payload
uint16_t RXPayloadCRC; //CRC of payload received in packet
uint16_t TransmitterNetworkID; //the NetworkID from the transmitted and received packet
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in transmitter
void loop()
{
PacketOK = LT.receiveReliable(RXBUFFER, RXBUFFER_SIZE, NetworkID, RXtimeout, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
RXPacketL = LT.readRXPacketL(); //get the received packet length
RXPayloadL = RXPacketL - 4; //payload length is always 4 bytes less than packet length
PacketRSSI = LT.readPacketRSSI(); //read the received packets RSSI value
if (PacketOK > 0)
{
//if the LT.receiveReliable() returns a value > 0 for PacketOK then packet was received OK
Serial.print(F("Payload received OK > "));
LT.printASCIIPacket(RXBUFFER, RXPayloadL);
Serial.println();
packet_is_OK();
sendACK();
Serial.println();
}
else
{
//if the LT.receiveReliable() function detects an error PacketOK is 0
packet_is_Error();
}
Serial.println();
}
void packet_is_OK()
{
printPacketDetails();
Serial.println();
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
Serial.print(F("Error "));
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout "));
}
else
{
printPacketDetails();
}
}
void printPacketDetails()
{
LocalPayloadCRC = LT.CRCCCITT(RXBUFFER, RXPayloadL, 0xFFFF); //calculate payload crc from the received RXBUFFER
TransmitterNetworkID = LT.getRXNetworkID(RXPacketL);
RXPayloadCRC = LT.getRXPayloadCRC(RXPacketL);
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmitterNetworkID,0x"));
Serial.print(TransmitterNetworkID, HEX);
Serial.print(F(",LocalPayloadCRC,0x"));
Serial.print(LocalPayloadCRC, HEX);
Serial.print(F(",RXPayloadCRC,0x"));
Serial.print(RXPayloadCRC, HEX);
LT.printReliableStatus();
}
void sendACK()
{
uint8_t buff[] = "Goodbye"; //the ack payload to send
LocalPayloadCRC = LT.CRCCCITTReliable(0, RXPayloadL - 1, 0xFFFF); //calculate received payload crc
delay(ACKdelay);
LT.sendReliableACK(buff, sizeof(buff), NetworkID, LocalPayloadCRC, TXpower);
Serial.print(F("Ack sent > "));
LT.printASCIIPacket(buff, sizeof(buff));
}
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println(F("216_Reliable_Receiver_ACK_withData Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1);
}
LT.setupLoRa(2445000000, 0, LORA_SF5, LORA_BW_1600, LORA_CR_4_5); //configure frequency and LoRa settings
Serial.println(F("Receiver ready"));
Serial.println();
}

View File

@ -0,0 +1,238 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 18/04/22
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a demonstration of the transmission and acknowledgement of 'Reliable'
packets to request information or operations from a remote receiver.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. The receiver needs to have the same
NetworkID as configured for the transmitter since the receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended in the packet. The receiver is thus able to check if the payload is valid.
The transmitter sends a request for the receiver which will respond with an acknowledge whach can include
any data requested. The transmitted request is a total of 6 or more bytes, with one byte for the payload
type and another byte for station the request is directed to.
The request is for the receiver to return a set of GPS co-ordinates. This information is included in the
acknowledge the receiver sends if there is a match for request type and station number. The orginal network
ID and payload CRC are also returned with the acknowledge so the transmitter can verify if the packet it
receives in reply is geniune.
The matching receiver program is 218_Reliable_Receiver_Data_Requestor.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
#include "Settings.h"
SX128XLT LT; //create a library class instance called LT
uint8_t TXPacketL; //length of transmitted packet
uint8_t TXPayloadL;
uint8_t RXPayloadL;
uint8_t RXPacketL; //length of received acknowledge
uint16_t PayloadCRC;
uint8_t RXBUFFER[16]; //create the buffer that received packets are copied into
uint8_t RequestType; //type of request to send
uint8_t RequestStation; //station request is aimed at
float Latitude; //variables for GPS location
float Longitude;
float Altitude;
uint8_t TrackerStatus;
//#define DEBUG
void loop()
{
//*****************************************************************************************
//Request GPS location
//*****************************************************************************************
RequestStation = 123;
if (sendRequestGPSLocation(RequestStation, 5))
{
Serial.println(F("Valid ACK received"));
#ifdef DEBUG
packet_is_OK();
#endif
actionRequestGPSLocation();
}
else
{
Serial.println(F("No valid ACK received"));
}
//*****************************************************************************************
Serial.println();
delay(5000);
}
uint8_t sendRequestGPSLocation(uint8_t station, uint8_t sendcount)
{
uint8_t ackrequesttype;
uint8_t ackstation;
uint8_t startcount;
startcount = sendcount;
do
{
Serial.print(startcount - sendcount + 1);
Serial.print(F(" Transmit request"));
printRequestType(RequestGPSLocation);
Serial.print(F(" to station "));
Serial.println(station);
Serial.flush();
//build the request payload
LT.startWriteSXBuffer(0); //initialise SX buffer write at address 0
LT.writeUint8(RequestGPSLocation); //identify type of request
LT.writeUint8(station); //station to reply to request
TXPayloadL = LT.endWriteSXBuffer(); //close SX buffer write
//now transmit the request
digitalWrite(LED1, HIGH);
TXPacketL = LT.transmitSXReliable(0, TXPayloadL, NetworkID, TXtimeout, TXpower, WAIT_TX);
digitalWrite(LED1, LOW);
PayloadCRC = LT.getTXPayloadCRC(TXPacketL);
RXPacketL = LT.waitSXReliableACK(0, NetworkID, PayloadCRC, ACKtimeout);
if (RXPacketL > 0)
{
//if waitSXReliableACK() returns > 0 then valid ack was received
ackrequesttype = LT.getByteSXBuffer(0);
ackstation = LT.getByteSXBuffer(1);
if ((ackrequesttype == RequestGPSLocation) && (ackstation == station))
{
return RXPacketL;
}
delay(200); //small delay between tranmission attampts
}
sendcount--;
}
while ((RXPacketL == 0) && (sendcount > 0));
Serial.println(F("ERROR send request failed"));
return 0;
}
void printRequestType(uint8_t type)
{
switch (type)
{
case 1:
Serial.print(F(" RequestGPSLocation"));
break;
default:
Serial.print(F(" not recognised"));
break;
}
}
void actionRequestGPSLocation()
{
LT.startReadSXBuffer(0); //initialise SX buffer write at address 0
RequestType = LT.readUint8(); //read type of request
RequestStation = LT.readUint8(); //who is the request reply from
Latitude = LT.readFloat(); //read latitude
Longitude = LT.readFloat(); //read longitude
Altitude = LT.readFloat(); //read altitude
TrackerStatus = LT.readUint8(); //read status byte
RXPayloadL = LT.endReadSXBuffer(); //close SX buffer read
Serial.print(F("RequestGPSLocation reply > "));
Serial.print(RequestStation);
Serial.print(F(","));
Serial.print(Latitude, 6);
Serial.print(F(","));
Serial.print(Longitude, 6);
Serial.print(F(","));
Serial.print(Altitude, 1);
Serial.print(F(","));
Serial.print(TrackerStatus);
Serial.println();
}
void packet_is_OK()
{
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmittedPayloadCRC,0x")); //print CRC of transmitted packet
Serial.print(PayloadCRC, HEX);
}
void packet_is_Error()
{
Serial.print(F("SendError"));
LT.printIrqStatus(); //prints the text of which IRQs set
LT.printReliableStatus(); //print the reliable status
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
uint16_t index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.println();
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
}
else
{
Serial.println(F("ERROR No LoRa device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate);
Serial.println(F("Transmitter ready"));
Serial.println();
}

View File

@ -0,0 +1,29 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 18/04/22
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
//******* Setup hardware pin definitions here ! ***************
const uint8_t NSS = 10; //select pin on LoRa device
const uint8_t NRESET = 9; //reset pin on LoRa device
const uint8_t RFBUSY = 7; //busy pin on LoRa device
const uint8_t DIO1 = 3; //DIO1 pin on LoRa device, used for sensing RX and TX done
const uint8_t LORA_DEVICE = DEVICE_SX1280; //we need to define the device we are using
const uint8_t LED1 = 8;
//******* Setup LoRa modem parameters here ! ***************
const uint32_t Frequency = 2445000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const int8_t TXpower = 2; //LoRa transmit power
const uint8_t Bandwidth = LORA_BW_1600; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF5; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in transmitter
const uint8_t RequestGPSLocation = 1; //request type number for GPS location, so receiver knows what information to supply
const uint32_t ACKtimeout = 1000; //Acknowledge timeout in mS, set to 0 if ACK not used.
const uint32_t TXtimeout = 1000; //transmit timeout in mS. If 0 return from transmit function after send.

View File

@ -0,0 +1,249 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 17/04/22
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a demonstration of the transmission and acknowledgement of 'Reliable'
packets to request information or operations from a remote receiver.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. The receiver needs to have the same
NetworkID as configured for the transmitter since the receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended in the packet. The receiver is thus able to check if the payload is valid.
The transmitter sends a request for the receiver which will respond with an acknowledge whach can include
any data requested. The transmitted request is a total of 6 or more bytes, with one byte for the payload
type and another byte for station the request is directed to.
The request is for the receiver to return a set of GPS co-ordinates. This information is included in the
acknowledge the receiver sends if there is a match for request type and station number. The orginal network
ID and payload CRC are also returned with the acknowledge so the transmitter can verify if the packet it
receives in reply is geniune.
The matching transmitter program is 217_Reliable_Transmitter_Data_Requestor.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
#include "Settings.h"
SX128XLT LT; //create a library class instance called LT
uint8_t RXBUFFER[251]; //create the buffer that received packets are copied into
uint8_t RXPacketL; //stores length of packet received
uint8_t RXPayloadL; //stores length of payload received
uint8_t TXPayloadL; //stores length of payload sent
uint16_t TransmitterNetworkID; //the NetworkID from the transmitted and received packet
uint16_t StationNumber;
uint8_t RequestType;
//#define DEBUG
void loop()
{
uint8_t requesttype;
requesttype = waitRequest(ThisStation, 5000); //listen for 5000mS, will return 0 if there is no request
switch (requesttype)
{
case 0:
break;
case RequestGPSLocation:
actionRequestGPSLocation();
break;
default:
Serial.println(F("Request not recognised"));
break;
}
Serial.println();
}
uint8_t waitRequest(uint8_t station, uint32_t timeout)
{
//wait for an incoming request, returns 0 if no request in timeout period
Serial.println(F("Wait request"));
RXPacketL = LT.receiveSXReliable(0, NetworkID, timeout, WAIT_RX);
if (RXPacketL)
{
#ifdef DEBUG
Serial.print(F("Reliable packet received > "));
packet_is_OK();
#endif
RequestType = LT.getByteSXBuffer(0);
StationNumber = LT.getByteSXBuffer(1);
Serial.print(F("Received "));
printRequestType(RequestType);
Serial.print(F(" for station "));
Serial.println(StationNumber);
if (StationNumber == station)
{
return RequestType;
}
else
{
Serial.println(F("ERROR Request not for this station"));
}
}
else
{
if (LT.readIrqStatus() & IRQ_RX_TIMEOUT)
{
Serial.println(F("ERROR Timeout waiting for valid request"));
}
else
{
packet_is_Error();
}
}
return 0;
}
bool actionRequestGPSLocation()
{
uint16_t RXPayloadCRC;
RXPayloadCRC = LT.getRXPayloadCRC(RXPacketL); //fetch received payload crc to return with ack
LT.startWriteSXBuffer(0); //initialise SX buffer write at address 0
LT.writeUint8(RequestGPSLocation); //identify type of request
LT.writeUint8(ThisStation); //who is the request reply from
LT.writeFloat(TestLatitude); //add latitude
LT.writeFloat(TestLongitude); //add longitude
LT.writeFloat(TestAltitude); //add altitude
LT.writeUint8(TrackerStatus); //add status byte
TXPayloadL = LT.endWriteSXBuffer(); //close SX buffer write
delay(ACKdelay);
digitalWrite(LED1, HIGH);
LT.sendSXReliableACK(0, TXPayloadL, NetworkID, RXPayloadCRC, TXpower);
Serial.print(F("RequestGPSLocation Replied > "));
Serial.print(ThisStation);
Serial.print(F(","));
Serial.print(TestLatitude, 6);
Serial.print(F(","));
Serial.print(TestLongitude, 6);
Serial.print(F(","));
Serial.print(TestAltitude, 1);
Serial.print(F(","));
Serial.print(TrackerStatus);
Serial.println();
Serial.flush();
digitalWrite(LED1, LOW);
return true;
}
void printRequestType(uint8_t type)
{
switch (type)
{
case RequestGPSLocation:
Serial.print(F(" RequestGPSLocation"));
break;
default:
Serial.print(F(" Request type not recognised"));
break;
}
}
void packet_is_OK()
{
printPacketDetails();
Serial.println();
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
Serial.print(F("Error "));
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout "));
}
else
{
printPacketDetails();
}
}
void printPacketDetails()
{
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmitterNetworkID,0x"));
Serial.print(LT.getRXNetworkID(RXPacketL), HEX);
Serial.print(F(",RXPayloadCRC,0x"));
Serial.print(LT.getRXPayloadCRC(RXPacketL), HEX);
LT.printReliableStatus();
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
uint16_t index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.println();
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
}
else
{
Serial.println(F("ERROR No LoRa device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate);
Serial.println(F("Receiver ready"));
Serial.println();
}

View File

@ -0,0 +1,37 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 18/04/22
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
//******* Setup hardware pin definitions here ! ***************
const uint8_t NSS = 10; //select pin on LoRa device
const uint8_t NRESET = 9; //reset pin on LoRa device
const uint8_t RFBUSY = 7; //busy pin on LoRa device
const uint8_t DIO1 = 3; //DIO1 pin on LoRa device, used for sensing RX and TX done
const uint8_t LED1 = 8;
const uint8_t LORA_DEVICE = DEVICE_SX1280; //we need to define the device we are using
//******* Setup LoRa modem parameters here ! ***************
const uint32_t Frequency = 2445000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const int8_t TXpower = 10; //LoRa transmit power
const int8_t RangingTXPower = 10; //Transmit power used for ranging
const uint8_t Bandwidth = LORA_BW_1600; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF5; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint32_t ACKdelay = 200; //delay in mS before sending reply
const uint32_t RXtimeout = 10000; //receive timeout in mS.
const uint8_t RequestGPSLocation = 1; //request type for GPS location
//GPS co-ordinates to use for the GPS location request
const float TestLatitude = 51.48230; //GPS co-ordinates to use for test
const float TestLongitude = -3.18136; //Cardiff castle keep, used for testing purposes
const float TestAltitude = 25.5;
const uint8_t TrackerStatus = 1; //set status bit to represent tracker GPS has fix
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in transmitter
const uint8_t ThisStation = 123; //the number of this station for requests and ranging

View File

@ -0,0 +1,240 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 18/04/22
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a demonstration of the transmission and acknowledgement of 'Reliable'
packets to request information or operations from a remote receiver.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. The receiver needs to have the same
NetworkID as configured for the transmitter since the receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended in the packet. The receiver is thus able to check if the payload is valid.
The transmitter sends a request for the receiver which will respond with an acknowledge whach can include
any data requested. The transmitted request is a total of 6 or more bytes, with one byte for the payload
type and another byte for station the request is directed to.
The request is for the receiver to return a set of GPS co-ordinates. This information is included in the
acknowledge the receiver sends if there is a match for request type and station number. The orginal network
ID and payload CRC are also returned with the acknowledge so the transmitter can verify if the packet it
receives in reply is geniune.
No DIO1 pin needs to be connected to the LoRa device for this program.
The matching receiver program is 220_Reliable_Receiver_Data_RequestorIRQ.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
#include "Settings.h"
SX128XLT LT; //create a library class instance called LT
uint8_t TXPacketL; //length of transmitted packet
uint8_t TXPayloadL;
uint8_t RXPayloadL;
uint8_t RXPacketL; //length of received acknowledge
uint16_t PayloadCRC;
uint8_t RXBUFFER[16]; //create the buffer that received packets are copied into
uint8_t RequestType; //type of request to send
uint8_t RequestStation; //station request is aimed at
float Latitude; //variables for GPS location
float Longitude;
float Altitude;
uint8_t TrackerStatus;
//#define DEBUG
void loop()
{
//*****************************************************************************************
//Request GPS location
//*****************************************************************************************
RequestStation = 123;
if (sendRequestGPSLocation(RequestStation, 5))
{
Serial.println(F("Valid ACK received"));
#ifdef DEBUG
packet_is_OK();
#endif
actionRequestGPSLocation();
}
else
{
Serial.println(F("No valid ACK received"));
}
//*****************************************************************************************
Serial.println();
delay(5000);
}
uint8_t sendRequestGPSLocation(uint8_t station, uint8_t sendcount)
{
uint8_t ackrequesttype;
uint8_t ackstation;
uint8_t startcount;
startcount = sendcount;
do
{
Serial.print(startcount - sendcount + 1);
Serial.print(F(" Transmit request"));
printRequestType(RequestGPSLocation);
Serial.print(F(" to station "));
Serial.println(station);
Serial.flush();
//build the request payload
LT.startWriteSXBuffer(0); //initialise SX buffer write at address 0
LT.writeUint8(RequestGPSLocation); //identify type of request
LT.writeUint8(station); //station to reply to request
TXPayloadL = LT.endWriteSXBuffer(); //close SX buffer write
//now transmit the request
digitalWrite(LED1, HIGH);
TXPacketL = LT.transmitSXReliableIRQ(0, TXPayloadL, NetworkID, TXtimeout, TXpower, WAIT_TX);
digitalWrite(LED1, LOW);
PayloadCRC = LT.getTXPayloadCRC(TXPacketL);
RXPacketL = LT.waitSXReliableACKIRQ(0, NetworkID, PayloadCRC, ACKtimeout);
if (RXPacketL > 0)
{
//if waitSXReliableACK() returns > 0 then valid ack was received
ackrequesttype = LT.getByteSXBuffer(0);
ackstation = LT.getByteSXBuffer(1);
if ((ackrequesttype == RequestGPSLocation) && (ackstation == station))
{
return RXPacketL;
}
delay(200); //small delay between tranmission attampts
}
sendcount--;
}
while ((RXPacketL == 0) && (sendcount > 0));
Serial.println(F("ERROR send request failed"));
return 0;
}
void printRequestType(uint8_t type)
{
switch (type)
{
case 1:
Serial.print(F(" RequestGPSLocation"));
break;
default:
Serial.print(F(" not recognised"));
break;
}
}
void actionRequestGPSLocation()
{
LT.startReadSXBuffer(0); //initialise SX buffer write at address 0
RequestType = LT.readUint8(); //read type of request
RequestStation = LT.readUint8(); //who is the request reply from
Latitude = LT.readFloat(); //read latitude
Longitude = LT.readFloat(); //read longitude
Altitude = LT.readFloat(); //read altitude
TrackerStatus = LT.readUint8(); //read status byte
RXPayloadL = LT.endReadSXBuffer(); //close SX buffer read
Serial.print(F("RequestGPSLocation reply > "));
Serial.print(RequestStation);
Serial.print(F(","));
Serial.print(Latitude, 6);
Serial.print(F(","));
Serial.print(Longitude, 6);
Serial.print(F(","));
Serial.print(Altitude, 1);
Serial.print(F(","));
Serial.print(TrackerStatus);
Serial.println();
}
void packet_is_OK()
{
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmittedPayloadCRC,0x")); //print CRC of transmitted packet
Serial.print(PayloadCRC, HEX);
}
void packet_is_Error()
{
Serial.print(F("SendError"));
LT.printIrqStatus(); //prints the text of which IRQs set
LT.printReliableStatus(); //print the reliable status
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
uint16_t index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.println();
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
}
else
{
Serial.println(F("ERROR No LoRa device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate);
Serial.println(F("Transmitter ready"));
Serial.println();
}

View File

@ -0,0 +1,28 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 18/04/22
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
//******* Setup hardware pin definitions here ! ***************
const uint8_t NSS = 10; //select pin on LoRa device
const uint8_t NRESET = 9; //reset pin on LoRa device
const uint8_t RFBUSY = 7; //busy pin on LoRa device
const uint8_t LORA_DEVICE = DEVICE_SX1280; //we need to define the device we are using
const uint8_t LED1 = 8;
//******* Setup LoRa modem parameters here ! ***************
const uint32_t Frequency = 2445000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const int8_t TXpower = 2; //LoRa transmit power
const uint8_t Bandwidth = LORA_BW_1600; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF5; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in transmitter
const uint8_t RequestGPSLocation = 1; //request type number for GPS location, so receiver knows what information to supply
const uint32_t ACKtimeout = 1000; //Acknowledge timeout in mS, set to 0 if ACK not used.
const uint32_t TXtimeout = 1000; //transmit timeout in mS. If 0 return from transmit function after send.

View File

@ -0,0 +1,252 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 17/04/22
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is a demonstration of the transmission and acknowledgement of 'Reliable'
packets to request information or operations from a remote receiver.
A reliable packet has 4 bytes automatically appended to the end of the buffer\array that is the data
payload. The first two bytes appended are a 16bit 'NetworkID'. The receiver needs to have the same
NetworkID as configured for the transmitter since the receiver program uses the NetworkID to check that
the received packet is from a known source. The third and fourth bytes appended are a 16 bit CRC of
the payload. The receiver will carry out its own CRC check on the received payload and can then verify
this against the CRC appended in the packet. The receiver is thus able to check if the payload is valid.
The transmitter sends a request for the receiver which will respond with an acknowledge whach can include
any data requested. The transmitted request is a total of 6 or more bytes, with one byte for the payload
type and another byte for station the request is directed to.
The request is for the receiver to return a set of GPS co-ordinates. This information is included in the
acknowledge the receiver sends if there is a match for request type and station number. The orginal network
ID and payload CRC are also returned with the acknowledge so the transmitter can verify if the packet it
receives in reply is geniune.
No DIO1 pin needs to be connected to the LoRa device for this program.
The matching transmitter program is 219_Reliable_Transmitter_Data_RequestorIRQ.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
#include "Settings.h"
SX128XLT LT; //create a library class instance called LT
uint8_t RXBUFFER[251]; //create the buffer that received packets are copied into
uint8_t RXPacketL; //stores length of packet received
uint8_t RXPayloadL; //stores length of payload received
uint8_t TXPayloadL; //stores length of payload sent
uint16_t TransmitterNetworkID; //the NetworkID from the transmitted and received packet
uint16_t StationNumber;
uint8_t RequestType;
//#define DEBUG
void loop()
{
uint8_t requesttype;
requesttype = waitRequest(ThisStation, 5000); //listen for 5000mS, will return 0 if there is no request
switch (requesttype)
{
case 0:
break;
case RequestGPSLocation:
actionRequestGPSLocation();
break;
default:
Serial.println(F("Request not recognised"));
break;
}
Serial.println();
}
uint8_t waitRequest(uint8_t station, uint32_t timeout)
{
//wait for an incoming request, returns 0 if no request in timeout period
Serial.println(F("Wait request"));
RXPacketL = LT.receiveSXReliableIRQ(0, NetworkID, timeout, WAIT_RX);
if (RXPacketL)
{
#ifdef DEBUG
Serial.print(F("Reliable packet received > "));
packet_is_OK();
#endif
RequestType = LT.getByteSXBuffer(0);
StationNumber = LT.getByteSXBuffer(1);
Serial.print(F("Received "));
printRequestType(RequestType);
Serial.print(F(" for station "));
Serial.println(StationNumber);
if (StationNumber == station)
{
return RequestType;
}
else
{
Serial.println(F("ERROR Request not for this station"));
}
}
else
{
if (LT.readIrqStatus() & IRQ_RX_TIMEOUT)
{
Serial.println(F("ERROR Timeout waiting for valid request"));
}
else
{
packet_is_Error();
}
}
return 0;
}
bool actionRequestGPSLocation()
{
uint16_t RXPayloadCRC;
RXPayloadCRC = LT.getRXPayloadCRC(RXPacketL); //fetch received payload crc to return with ack
LT.startWriteSXBuffer(0); //initialise SX buffer write at address 0
LT.writeUint8(RequestGPSLocation); //identify type of request
LT.writeUint8(ThisStation); //who is the request reply from
LT.writeFloat(TestLatitude); //add latitude
LT.writeFloat(TestLongitude); //add longitude
LT.writeFloat(TestAltitude); //add altitude
LT.writeUint8(TrackerStatus); //add status byte
TXPayloadL = LT.endWriteSXBuffer(); //close SX buffer write
delay(ACKdelay);
digitalWrite(LED1, HIGH);
LT.sendSXReliableACKIRQ(0, TXPayloadL, NetworkID, RXPayloadCRC, TXpower);
Serial.print(F("RequestGPSLocation Replied > "));
Serial.print(ThisStation);
Serial.print(F(","));
Serial.print(TestLatitude, 6);
Serial.print(F(","));
Serial.print(TestLongitude, 6);
Serial.print(F(","));
Serial.print(TestAltitude, 1);
Serial.print(F(","));
Serial.print(TrackerStatus);
Serial.println();
Serial.flush();
digitalWrite(LED1, LOW);
return true;
}
void printRequestType(uint8_t type)
{
switch (type)
{
case RequestGPSLocation:
Serial.print(F(" RequestGPSLocation"));
break;
default:
Serial.print(F(" Request type not recognised"));
break;
}
}
void packet_is_OK()
{
printPacketDetails();
Serial.println();
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
Serial.print(F("Error "));
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout "));
}
else
{
printPacketDetails();
}
}
void printPacketDetails()
{
Serial.print(F("LocalNetworkID,0x"));
Serial.print(NetworkID, HEX);
Serial.print(F(",TransmitterNetworkID,0x"));
Serial.print(LT.getRXNetworkID(RXPacketL), HEX);
Serial.print(F(",RXPayloadCRC,0x"));
Serial.print(LT.getRXPayloadCRC(RXPacketL), HEX);
LT.printReliableStatus();
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
uint16_t index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(115200);
Serial.println();
Serial.println(__FILE__);
Serial.println();
SPI.begin();
if (LT.begin(NSS, NRESET, RFBUSY, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
}
else
{
Serial.println(F("ERROR No LoRa device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate); //need to be in LoRa mode to receive requests
Serial.println(F("Receiver ready"));
Serial.println();
}

View File

@ -0,0 +1,36 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 18/04/22
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
//******* Setup hardware pin definitions here ! ***************
const uint8_t NSS = 10; //select pin on LoRa device
const uint8_t NRESET = 9; //reset pin on LoRa device
const uint8_t RFBUSY = 7; //busy pin on LoRa device
const uint8_t LED1 = 8;
const uint8_t LORA_DEVICE = DEVICE_SX1280; //we need to define the device we are using
//******* Setup LoRa modem parameters here ! ***************
const uint32_t Frequency = 2445000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const int8_t TXpower = 10; //LoRa transmit power
const int8_t RangingTXPower = 10; //Transmit power used for ranging
const uint8_t Bandwidth = LORA_BW_1600; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF5; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint32_t ACKdelay = 200; //delay in mS before sending reply
const uint32_t RXtimeout = 5000; //receive timeout in mS.
const uint8_t RequestGPSLocation = 1; //request type for GPS location
//GPS co-ordinates to use for the GPS location request
const float TestLatitude = 51.48230; //GPS co-ordinates to use for test
const float TestLongitude = -3.18136; //Cardiff castle keep, used for testing purposes
const float TestAltitude = 25.5;
const uint8_t TrackerStatus = 1; //set status bit to represent tracker GPS has fix
const uint16_t NetworkID = 0x3210; //NetworkID identifies this connection, needs to match value in transmitter
const uint8_t ThisStation = 123; //the number of this station for requests and ranging

View File

@ -0,0 +1,157 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 06/11/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - The program listens for incoming packets using the LoRa settings in the 'Settings.h'
file. The pins to access the lora device need to be defined in the 'Settings.h' file also.
There is a printout of the valid packets received in HEX format. Thus the program can be used to receive
and record non-ASCII packets. The LED will flash for each packet received.
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#include <SPI.h>
#include <SX128XLT.h>
#include "Settings.h"
SX128XLT LT;
uint8_t RXPacketL; //stores length of packet received
int16_t PacketRSSI; //stores RSSI of received packet
int8_t PacketSNR; //stores signal to noise ratio of received packet
void loop()
{
RXPacketL = LT.receiveSXBuffer(0, 60000, WAIT_RX); //returns 0 if packet error of some sort, timeout set at 60secs\60000mS
digitalWrite(LED1, HIGH); //something has happened
printSeconds();
PacketRSSI = LT.readPacketRSSI();
PacketSNR = LT.readPacketSNR();
if (RXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
digitalWrite(LED1, LOW);
Serial.println();
}
void packet_is_OK()
{
printReceptionDetails();
Serial.print(RXPacketL);
Serial.print(F(" bytes > "));
LT.printSXBufferHEX(0, (RXPacketL - 1));
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //get the IRQ status
if (IRQStatus & IRQ_RX_TIMEOUT)
{
Serial.print(F(" RXTimeout"));
}
else
{
Serial.print(F(" PacketError"));
printReceptionDetails();
Serial.print(F(" Length,"));
Serial.print(LT.readRXPacketL()); //get the real packet length
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
}
}
void printReceptionDetails()
{
Serial.print(F(" RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB "));
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
uint16_t index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void printSeconds()
{
float secs;
secs = ( (float) millis() / 1000);
Serial.print(secs, 3);
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
Serial.begin(115200);
Serial.println(F("221_LoRa_Packet_Monitor Starting"));
SPI.begin();
//SPI beginTranscation is normally part of library routines, but if it is disabled in library
//a single instance is needed here, so uncomment the program line below
//SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1)
{
led_Flash(50, 50);
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate);
Serial.println();
LT.printModemSettings();
Serial.println();
LT.printOperatingSettings();
Serial.println();
Serial.print(F("Packet monitor ready"));
Serial.println();
}

View File

@ -0,0 +1,29 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 06/11/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
//******* Setup hardware pin definitions here ! ***************
//These are the pin definitions for one of my own boards, the Easy Pro Mini,
//be sure to change the definitions to match your own setup.
#define NSS 10 //select on LoRa device
#define NRESET 9 //reset on LoRa device
#define RFBUSY 7 //RFBUSY pin on LoRa device
#define DIO1 3 //DIO1 on LoRa device, used for RX and TX done
#define LED1 8 //On board LED, high for on
#define LORA_DEVICE DEVICE_SX1280 //this is the device we are using
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 2445000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_0400; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate

View File

@ -0,0 +1,157 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 06/11/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - The program listens for incoming packets using the FLRC settings in the 'Settings.h'
file. The pins to access the lora device need to be defined in the 'Settings.h' file also.
There is a printout of the valid packets received in HEX format. Thus the program can be used to receive
and record non-ASCII packets. The LED will flash for each packet received.
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#include <SPI.h>
#include <SX128XLT.h>
#include "Settings.h"
SX128XLT LT;
uint8_t RXPacketL; //stores length of packet received
int16_t PacketRSSI; //stores RSSI of received packet
int8_t PacketSNR; //stores signal to noise ratio of received packet
void loop()
{
RXPacketL = LT.receiveSXBuffer(0, 60000, WAIT_RX); //returns 0 if packet error of some sort, timeout set at 60secs\60000mS
digitalWrite(LED1, HIGH); //something has happened
printSeconds();
PacketRSSI = LT.readPacketRSSI();
PacketSNR = LT.readPacketSNR();
if (RXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
digitalWrite(LED1, LOW);
Serial.println();
}
void packet_is_OK()
{
printReceptionDetails();
Serial.print(RXPacketL);
Serial.print(F(" bytes > "));
LT.printSXBufferHEX(0, (RXPacketL - 1));
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //get the IRQ status
if (IRQStatus & IRQ_RX_TIMEOUT)
{
Serial.print(F(" RXTimeout"));
}
else
{
Serial.print(F(" PacketError"));
printReceptionDetails();
Serial.print(F(" Length,"));
Serial.print(LT.readRXPacketL()); //get the real packet length
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
}
}
void printReceptionDetails()
{
Serial.print(F(" RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB "));
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
uint16_t index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void printSeconds()
{
float secs;
secs = ( (float) millis() / 1000);
Serial.print(secs, 3);
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
Serial.begin(115200);
Serial.println(F("221_LoRa_Packet_Monitor Starting"));
SPI.begin();
//SPI beginTranscation is normally part of library routines, but if it is disabled in library
//a single instance is needed here, so uncomment the program line below
//SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
while (1)
{
led_Flash(50, 50);
}
}
LT.setupFLRC(Frequency, Offset, BandwidthBitRate, CodingRate, BT, Syncword);
Serial.println();
LT.printModemSettings();
Serial.println();
LT.printOperatingSettings();
Serial.println();
Serial.print(F("Packet monitor ready"));
Serial.println();
}

View File

@ -0,0 +1,31 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 06/11/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
//******* Setup hardware pin definitions here ! ***************
//These are the pin definitions for one of my own boards, the Easy Pro Mini,
//be sure to change the definitions to match your own setup.
#define NSS 10 //select on LoRa device
#define NRESET 9 //reset on LoRa device
#define RFBUSY 7 //RFBUSY pin on LoRa device
#define DIO1 3 //DIO1 on LoRa device, used for RX and TX done
#define LED1 8 //On board LED, high for on
#define LORA_DEVICE DEVICE_SX1280 //this is the device we are using
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 2445000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t BandwidthBitRate = FLRC_BR_1_300_BW_1_2; //FLRC bandwidth and bit rate, 1.3Mbs
//const uint8_t BandwidthBitRate = FLRC_BR_0_260_BW_0_3; //FLRC 260kbps
const uint8_t CodingRate = FLRC_CR_1_0; //FLRC coding rate
const uint8_t BT = RADIO_MOD_SHAPING_BT_1_0; //FLRC BT
const uint32_t Syncword = 0x01234567; //FLRC uses syncword

View File

@ -0,0 +1,389 @@
---
layout: post
title: "Reliable Packets with LoRa"
---
## Reliable Packets
It would be helpful, and in some cases essential, if you could be really sure that a received LoRa packet was actually destined for a particular receiver and that it also contained valid sensor or control data for the application the receiver is running.
It is inevitable that at some stage a LoRa receiver will get a packet from a foreign or unwanted source, so some thought needs to be done to be sure these rogue packets are rejected.
### Sending and receiving reliable packets with cyclic redundancy checks
The examples in this folder use a series of SX12xx library routines that append to the transmitted packets the CRC of the data payload. The receiver can then read this CRC from the packet and then do a local CRC check on the received payload to check there is a match. If there is no match, the packet is automatically rejected.
Additional protection is added to the packet by the use of a 16 bit NetworkID. The NetworkID number (0-65535) is defined for a particular application so the transmitter and receiver need to use the same NetworkID. The receiver will then reject packets that do not match its own defined NetworkID. The NetworkID can also be used to direct packets to particular receivers.
The CRC and NetworkID checking operates within the library transmit and receive functions in the background and although there are library routines to extract the payload CRC and NetworkID, there in no compelling need for the Arduino sketch itself to do so.
The packet structure used for a reliable packet is;
<payload - 0 to 251 bytes> <NetworkID - 2 bytes> <payload CRC - 2 bytes>
The use of the payload CRC and NetworkID adds a high level of certainty that the packet received is valid and safe to act on. If you so wish the CRC checking can be disabled and the NetworkID alone used to check packet validity.
## Reliable packet demonstration examples
There are a number of examples of using reliable packets in this folder. The simplest examples are 201\_Reliable\_Transmitter and 201\_Reliable\_Receiver which transmit and receive a short payload 'Hello World'.
### Examples '201\_Reliable\_Transmitter' and '202\_Reliable\_Receiver'.
The basic reliable transmit function used is;
LT.transmitReliable(buff, sizeof(buff), NetworkID, TXtimeout, TXpower, WAIT\_TX))
The buff defined in the transmit function is the name of a byte array that has been loaded with the payload, this can either be a sequence of characters, numbers or a structure. The receiver function also needs to know the size of this byte array. NetworkID is the ID for a particular application and needs to match the ID in the receiver. TXtimeout is the time in mS to wait for a transmission to finish, its used to stop the LoRa device potentially locking up a sketch\program. TXpower is the transmit power in dBm to be used and WAIT_TX tells the function to wait for the transmit to complete before exiting.
The matching receive function is;
LT.receiveReliable(RXBUFFER, RXBUFFER\_SIZE, NetworkID, RXtimeout, WAIT\_RX);
The receiver fills the defined RXBUFFER with the contents of the received packet if its valid. The size of this buffer\array specified in RXBUFFER\_SIZE needs to be large enough to accommodate the largest payload size intended to be received. Due to the 4 bytes used by the packet for the networkID and payload CRC, the largest payload that can be received is 251 bytes.
The payload is copied on receive into the RXBUFFER array. If the transmitted payload array is say 16 bytes long, and the transmit function increases the packet size by 4 to accommodate the networkID and payload CRC the packet length will be 20 bytes. Note that any packets arriving with a length greater than the size defined for RXBUFFER plus 4 bytes will be rejected.
The NetworkID specified in the receive function has to match that used by the transmitter if the packet is to be accepted.
The RXtimeout parameter is the number of milli seconds the receive function will wait for a packet to be received, if the period is exceeded a time-out will be reported. To not use the time-out function set RXtimeout to 0.
WAIT\_RX makes the receive function wait for the receipt of a packet to complete before exiting.
The transmitter program prints to the Arduino IDE serial monitor the NetworkID and payloadCRC (the payload is "Hello World") and when the receiver picks up the packet this payload should also be printed out. If the networkID of the transmitter does not match the networkID of the receiver the receiver reports the error. If the payload CRC that the transmitter appends to the packet does not match the CRC that the receiver calculates on the payload, this is also reported as an error.
Thus in the receive program '202\_Basic\_Reliable\_Receiver' the code in the 'packet\_is\_OK()' function is only executed it the received packet passes both the networkID and payload CRC checks.
With these example programs if you change the NetworkID either in the transmit or receive program and you should see the receiver rejects them.
The transmitter program output looks like this;
Transmit Payload > Hello World
LocalNetworkID,0x3210,TransmittedPayloadCRC,0xBC69
If the receiver reports a valid packet which passes networkID and CRC checks the output looks like;
Payload received OK > Hello World
LocalNetworkID,0x3210,TransmitterNetworkID,0x3210,LocalPayloadCRC,0xBC69,RXPayloadCRC,0xBC69
If the networkID check fails the output can look like this;
Error LocalNetworkID,0x3210,TransmitterNetworkID,0x55AB,LocalPayloadCRC,0xBC69,RXPayloadCRC,0xBC69
If the payload CRC check fails the output looks like;
Error LocalNetworkID,0x3210,TransmitterNetworkID,0x1234,LocalPayloadCRC,0xBC69,RXPayloadCRC,0xBC69,ReliableIDError
If you don't want to use the CRC checking of the payload it can be turned off with this command;
LT.setReliableConfig(NoReliableCRC); //disable payload CRC check
You need to use the command on both the transmitter and the receiver.
## Using reliable packets to control stuff
Sending Hello World messages is a useful start but a more practical example is to use the payload to control something on the receiver. The reliable examples show how the sent payload can be a structure, writing variables direct to an array and how to write the payload direct into the LoRa devices internal buffer and thus bypassing the need for an memory array.
### Using a structure
The next example 203\_Reliable\_Transmitter\_Controller\_Structure uses a structure as the payload;
struct controllerStructure
{
uint16\_t destinationNode;
uint8\_t outputNumber;
uint8\_t onoroff;
}__attribute__((packed, aligned(1))); //remove structure padding so there is compatibility between 8bit and 32bit Arduinos
The destinationNode is a 16 bit number that the receiver reads to see if the received packet is destined for that receiver. You can set outputNumber to control a range of outputs and onoroff is set to 1 to turn on the output and to 0 to turn it on.
With the 203 transmitter example running load the 204\_Reliable\_Receiver\_Controller\_Structure program onto the receiver Arduino and it should report the packets received and the LED connected to the pin defined by LED1 should flash on and off.
These structure examples would be easy to expand to control more outputs such as servos and similar.
**Note:** Structures on different Arduino types can use different formats. If the transmitter is one Arduino type and the receiver is another type the receiver may not be able to read the transferred structure correctly.
### Writing variables direct to an array
A SX12xx library file, arrayRW.h has routines that allow for variables to be directly written to an array. For example if the name of the array is 'controlarray' and then if you review the transmitter program, 205\_Reliable\_Transmitter\_Controller\_ArrayRW, you will see it fills the array with variables like this;
beginarrayRW(controlarray, 0); //start writing to array at location 0
arrayWriteUint16(destinationNode);
arrayWriteUint8(outputNumber);
arrayWriteUint8(onoroff); //0 for off, 1 for on
controlarraysize = endarrayRW(); //this function returns the length of the array to send
When the 206\_Reliable\_Receive\_Controller\_ArrayRW program receives the packet its loaded into a defined array (RXBUFFER in the example) and the sketch then reads the variables from the the array like this;
beginarrayRW(RXBUFFER, 0); //start reading from array at location 0
destinationNode = arrayReadUint16();
outputNumber = arrayReadUint8();
onoroff = arrayReadUint8(); //0 for off, 1 for on
controlarraysize = endarrayRW(); //this function returns the length of the array to send
As with the previous examples the LED on the receiver should flash on and off.
The full set of write variable functions provided by the arrayRW.h library file is;
arrayWriteUint8(uint8_t buffdata)
arrayWriteInt8(int8_t buffdata)
arrayWriteChar(char buffdata)
arrayWriteUint16(uint16_t buffdata)
arrayWriteInt16(int16_t buffdata)
arrayWriteFloat(float tempf)
arrayWriteUint32(uint32_t tempdata)
arrayWriteInt32(int32_t tempdata)
arrayWriteCharArray(char *buff, uint8_t len)
arrayWriteByteArray(uint8_t *buff, uint8_t len)
And the read functions are;
uint8_t arrayReadUint8()
int8_t arrayReadInt8()
char arrayReadChar()
uint16_t arrayReadUint16()
int16_t arrayReadInt16()
float arrayReadFloat()
uint32_t arrayReadUint32()
int32_t arrayReadInt32()
arrayReadCharArray(char *buff, uint8_t len)
arrayReadByteArray(uint8_t *buff, uint8_t len)
### Low memory controller
Programs 207\_Reliable\_SXTransmitter\_Controller and 208\_Reliable\_SXReceiver\_Controller demonstrate how use the SX12XX library to directly write and read variables to and from the LoRa devices internal buffer directly for transmit and receive functions. There is no memory array required to be defined filled or used by transmitter and receiver programs. If large packets are being sent and received this can save a significant amount of memory.
The 207 and 208 examples follow the same controller example of programs 203 and 204 in that an LED on the receiver should flash on and off.
The transmitter packet is loaded into the LoRa devices buffer like this;
LT.startWriteSXBuffer(0); //start the write at SX12XX internal buffer location 0
LT.writeUint16(destinationNode); //destination node for packet
LT.writeUint8(outputNumber); //output number on receiver
LT.writeUint8(onoroff); //0 for off, 1 for on
TXPayloadL = LT.endWriteSXBuffer(); //closes packet write and returns the length of the payload to send
And the receiver loads the variables from the LoRa devices buffer like this;
LT.startReadSXBuffer(0); //start buffer read at location 0
destinationNode = LT.readUint16(); //load the destination node
outputNumber = LT.readUint8(); //load the output number
onoroff = LT.readUint8(); //0 for off, 1 for on
RXPayloadL = LT.endReadSXBuffer(); //this function returns the length of the array read
Clearly with these direct accesses to the LoRa devices buffer the order and type of variables written has to match the order when read out by the receiver.
The full set of library routines for writing direct to the LoRa devices buffer is;
writeUint8(uint8_t x);
writeInt8(int8_t x);
writeChar(char x);
writeUint16(uint16_t x);
writeInt16(int16_t x);
writeUint32(uint32_t x);
writeInt32(int32_t x);
writeFloat(float x);
writeBuffer(uint8_t *txbuffer, uint8_t size); //uint8_t buffer
writeBufferChar(char *txbuffer, uint8_t size); //char buffer
And for reading direct from the LoRa devices buffer;
uint8_t readUint8();
int8_t readInt8();
char readChar();
uint16_t readUint16();
int16_t readInt16();
uint32_t readUint32();
int32_t readInt32();
float readFloat();
uint8_t readBuffer(uint8_t *rxbuffer); //reads buffer till a null 0x00 is reached
uint8_t readBuffer(uint8_t *rxbuffer, uint8_t size);
uint8_t readBufferChar(char *rxbuffer);
#### Getting the payload CRC into a sketch
The CRC of the transmitted payload, that is appended to the packet and printed out in the examples, can be obtained by the sketch in several ways, first the simplest way is to use a SX12XX library function after the packet has been transmitted or received;
TXpayloadCRC = LT.getTXPayloadCRC(TXPacketL);
RXpayloadCRC = LT.getRXPayloadCRC(RXPacketL);
The payload CRC can be read direct from the end of the packet buffer of the LoRa device like this;
PayloadCRC = LT.readUint16SXBuffer(PayloadL+2);
Where PayloadL is the length in bytes of the payload, this is the method used in the 201 transmitter example.
Or the payload CRC can be calculated locally by accessing the local payload array\buffer directly like this which uses another SX12xx library function;
LocalPayloadCRC = LT.CRCCCITT(buff, sizeof(buff), 0xFFFF);
Where buff is the name of the array containing the payload.
Where 0xFFFF is the CRC check start value, normally 0xFFFF.
And finally there is a SX12xx library function that will return the CRC of an area of the LoRa devices internal buffer like this;
LT.CRCCCITTReliable(0, PayloadL-1, 0xFFFF);
Where PayloadL is the length of the payload array\buffer.
Where 0 is the address in the buffer to start the CRC check.
Where 0xFFFF is the CRC check start value, normally 0xFFFF.
#### Getting the NetworkID into a sketch
The NetworkID used for the transmission or reception of a packet, that is appended to the packet and printed out in the examples, can be obtained by the sketch using an SX12XX library function after the packet has been transmitted or received;
TXNetworkID = LT.getTXNetworkID(TXPacketL);
RXNetworkID = LT.getRXNetworkID(RXPacketL);
## Sending and receiving reliable packets with an acknowledge
Sometimes we may need to be sure the receiver has actually received the packet sent and we may want to keep transmitting the packet until it actually is received. Thus the receiver needs, when it has accepted a valid reliable packet, to send an acknowledge packet back that the transmitter will be listening for.
Clearly we could now have the same problem as for a simple reliable packet, how does the transmitter know the received packet actually is an acknowledge from the specific receiver ?
The simple way to be sure is to turn around the received NetworkID and payloadcrc (i.e. a total of 4 bytes) and send these bytes as an acknowledge. The transmitter program knows the NetworkID and payloadcrc used in the transmit function so can check to a high level of certainty that the received packet is a valid acknowledge, all four bytes of the acknowledge have to be correct.
## Examples using acknowledgements
The previous examples, where there was no acknowledgement used were a very basic transmit and receive, a set of examples using a structure to control an remote output, doing the same with direct array read and write and then a low memory example writing and reading direct to the LoRa devices buffer. There are two types of acknowledgement possible with the library, the first is a simple Auto Acknowledge which is only 4 bytes, consisting of the the NetworkID and payload CRC. The second type of acknowledge allows the receiver to send back data to the transmitter. This form of acknowledge can be used when the transmitter wants to request some data or control information from the receiver. Since the original NetworkID and payload CRC used by the transmitter is sent back with the acknowledge the transmitter can be very confident that the data coming back is genuine.
These two examples; **209\_Reliable\_Transmitter\_AutoACK** and **210\_Reliable\_Receiver\_AutoACK** are the basic 201 and 202 examples modified to use the auto acknowledge.
The transmit function when acknowledge is configured is;
transmitReliable(buff, sizeof(buff), NetworkID, ACKtimeout, TXtimeout, TXpower, WAIT_TX))
If AutoACK is used then a ACKtimeout needs to be specified. ACKtimeout is the milliseconds the transmit function would listen for a valid acknowledge before returning an error. How short this period is rather depends on the LoRa settings in use and the actual Arduinos being used. Remember the sending of the acknowledge will have a on-air time that the transmitter needs to account for. You can in some circumstances have an ACKtimeout as low as 25mS and that is still enough time for the receiver to turn around from receive to transmit and the transmitter to flip to receive mode and pick-up the packet. You need to experiment here, perhaps start at 1000mS and gradually reduce the time (with a working set-up) until the point is reached when the receipt of the acknowledge fails.
With the transmit function if the returned byte is 0 this indicates to the sketch that there has been an error of some type, one such error could be no acknowledge received.
The matching receive function is;
receiveReliable(RXBUFFER, RXBUFFER_SIZE, NetworkID, ACKdelay, TXpower, RXtimeout, WAIT_RX);
The ACKdelay parameter is in miliseconds and it's the time the receiver waits before sending an acknowledge. With some hardware a delay here of 0mS might be OK, but with faster hardware you may need to increase it. Maybe start with an ACKdelay of 50mS and an ACKtimeout of 1000mS in the transmit function and reduce the numbers in steps. You only need to do this if you want or need to maximise response time.
If the returned byte from the receiveReliable() function is 0 then there was a problem during receive.
The 209 transmitter will keep sending the payload until the transmitReliable() function returns a non zero value. The transmitReliable() function will return a zero value if no acknowledge is received within the ACKtimeout period.
Note that in the case of a NetworkID mismatch the receiver will not transmit an acknowledge, so the transmitter reports it as an a NoReliableACK error.
The auto acknowledge is a simple way of making the transmission of packets more reliable, but it might not be appropriate in all circumstances. For instance consider the **207\_Reliable\_Transmitter\_Controller\_LowMemory** and **208\_Reliable\_Receiver\_Controller\_LowMemory** examples where the payload contains the following;
LT.writeUint16(destinationNode); //destination node for packet
LT.writeUint8(outputNumber); //output number on receiver
LT.writeUint8(onoroff); //0 for off, 1 for on
Here the destinationNode number is directed to a particular node number, 2 in that example. If the packet is received by node number 5, then there should be no acknowledge sent. In these circumstances the receiver program needs to intervene directly on the received packet, read the payload and check for a matching destinationNode number. If there is a match then an acknowledge can be sent manually and the transmitter knows the packet has been received.
### Low memory acknowledge
Example programs **211\_Reliable\_SXTransmitter\_AutoACK** and **212\_Reliable\_SXReceiver\_AutoACK** demonstrate how to use the SX12xx library functions to bypass the need to use an intermediate array for the payload. Instead of filling an array with a structure or byte array full of variables, the variables to send are written directly to the LoRa device internal buffer on transmit and read from the buffer on receive.
Filling the SX12XX LoRa devices buffer is done like so;
LT.startWriteSXBuffer(0); //start the write at SX12XX internal buffer location 0
LT.writeUint16(destinationNode); //destination node for packet
LT.writeUint8(outputNumber); //output number on receiver
LT.writeUint8(onoroff); //0 for off, 1 for on
TXPayloadL = LT.endWriteSXBuffer(); //closes packet write and returns the length of the payload to send
And then the appropriate transmit function is used;
TXPacketL = LT.transmitSXReliableAutoACK(0, TXPayloadL, NetworkID, ACKtimeout, TXtimeout, TXpower, WAIT_TX);
On the receive side the receive is setup like so;
PacketOK = LT.receiveSXReliableAutoACK(0, NetworkID, ACKdelay, TXpower, RXtimeout, WAIT_RX);
And if on receive the packet passes the NetworkID and payloadCRC checks (PacketOK returns > 0) it is read like this;
LT.startReadSXBuffer(0); //start buffer read at location 0
destinationNode = LT.readUint16(); //load the destination node
outputNumber = LT.readUint8(); //load the output number
onoroff = LT.readUint8(); //0 for off, 1 for on
RXPayloadL = LT.endReadSXBuffer(); //this function returns the length of the array read
Note that in this example the payload contains a 16 bit destinationNode variable, which can be used to direct the packet to one of many nodes. The sketch checks that the destinationNode matches the number given to that receiver and if there is a match actions the packet.
### Manual acknowledge
The programs **213\_Reliable\_Transmitter\_Controller\_ManualACK** and **214\_Reliable\_Receiver\_Controller\_ManualACK** use a manual acknowledge set-up whereby the receive picks up the transmitted payload and reads the destinationNode parameter to decide if the packet is destined for that node. If it is the acknowledge is sent which contains the networkID and the CRC of the original payload, thus the transmitter knows the sent packet has been received correctly.
The receive sketch can pause at the point the payload is being actioned, perhaps reading an external sensor waiting for conformation that the action as completed, a gate is confirmed opened\closed for instance, before sending the acknowledge.
There is a further enhancement to the manual acknowledge set-up, the acknowledge can contain some data to be returned to the transmitter.
### Manual acknowledge returning data
The standard acknowledge is only 4 bytes, the NetworkID and payload CRC. However the acknowledge can be sent with an array of data included in the acknowledge.
The format of this function is;
transmitReliableACK(uint8\_t *txbuffer, uint8\_t size, uint16\_t networkID, uint16\_t payloadcrc, int8\_t txpower);
Here the receiver sending the acknowledge can include an array txbuffer of a specified size. This returned array could be a structure, as per example 203 and 204 or an array filled directly with the arrayRW.h library file as used in examples 205 and 206.
To demonstrate returning an array in the acknowledge examples 201 and 202 were modified so that the transmitted 'Hello World' example has 'Goodbye' returned from the receiver with the acknowledge and is then printed out on the transmitter. The modified programs are **215\_Reliable\_Transmitter\_ManualACK\_withData** and **216\_Reliable\_Receiver\_ManualACK\_withData**
### Requesting data
We can use the acknowledge functions of reliable packets to send a request to a remote station to transfer data. The returned data will include the networkID and payloadCRC sent with the request and since the returned data\packet is also protected by the internal LoRa packet CRC we can be fairly confident we are getting valid data back.
Take for instance a remote node that has a GPS attached and we want to know the current location of the node. Of course the node could transmit its location on a regular basis but this can be wasteful of power and there will be issues with conflicting transmissions if there are a number of nodes out there.
Examples **217\_Reliable\_Transmitter\_Data\_Requestor** and **218\_Reliable\_Receiver\_Data\_Requestor** demonstrate such a requesting of data.
Assume at the station wanting the remote nodes location we send this payload;
LT.startWriteSXBuffer(0); //initialise SX buffer write at address 0
LT.writeUint8(RequestGPSLocation); //identify type of packet
LT.writeUint8(RequestStation); //station to reply to request
TXPayloadL = LT.endWriteSXBuffer(); //close SX buffer write
RequestGPSLocation is assigned a value of 1;
const uint8_t RequestGPSLocation = 1;
RequestStation is from 0 to 255 and is the station node\number that we want the location from, in this case RequestStation will have a number of 123.
The packet is protected by the NetworkID and payload CRC so station 123 will see the request as valid and loads the location data into the LoRa device like this;
LT.startWriteSXBuffer(0); //initialise SX buffer write at address 0
LT.writeUint8(RequestGPSLocation); //identify type of request
LT.writeUint8(ThisStation); //who is the request reply from
LT.writeFloat(TestLatitude); //add latitude
LT.writeFloat(TestLongitude); //add longitude
LT.writeFloat(TestAltitude); //add altitude
TXPayloadL = LT.endWriteSXBuffer(); //close SX buffer write
In this case the returned values are test values of Latitude, Longitude and Altitude.
The original requesting node sees that the valid reply\Acknowledge is a GPS location request from station 123 and can then act on the data.
Examples **219\_Reliable\_Transmitter\_Data\_RequestorIRQ** and **220\_Reliable\_Receiver\_Data\_RequestorIRQ** are versions of the above 217 and 218 examples that do not require access to the DIO1 pin on the LoRa device to detect RXdone and TXDone. These versions can be useful for situations where there are few microcontroller pins available to drive the LoRa device such as with the ESP32CAM for instance.
### Using program 221\_LoRa\_Packet\_Monitor or 222\_FLRC\_Packet\_Monitor
When debugging what's going on in a send and acknowledge set-up its useful to be able to see what is happening in real time. This packet monitor example will display the bytes received in hexadecimal, in the example printout below you can see two packets. The 16 byte packet contains the text 'Hello World' and then the NetworkID, 0x3210, then the payload CRC, 0xBC69 at the end.
The 4 byte packet that is seen around 130mS later is the acknowledge which contains the NetworkID, 0x3210, then the payload CRC, 0xBC69.
125.103 RSSI,-99dBm,SNR,10dB 16 bytes > 48 65 6C 6C 6F 20 57 6F 72 6C 64 00 10 32 69 BC
125.237 RSSI,-96dBm,SNR,8dB 4 bytes > 10 32 69 BC
<br>
<br>