first commit

This commit is contained in:
2021-05-11 20:43:42 +03:00
commit 9f3ffaba30
381 changed files with 69596 additions and 0 deletions

View File

@@ -0,0 +1,183 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/03/20
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 program that demonstrates the detailed setup of a LoRa test transmitter.
A packet containing ASCII text is sent according to the frequency and LoRa settings specified in the
'Settings.h' file. The pins to access the lora device need to be defined in the 'Settings.h' file also.
The details of the packet sent and any errors are shown on the Arduino IDE Serial Monitor, together with
the transmit power used, the packet length and the CRC of the packet. The matching receive program,
'104_LoRa_Receiver' can be used to check the packets are being sent correctly, the frequency and LoRa
settings (in Settings.h) must be the same for the transmitter and receiver programs. Sample Serial
Monitor output;
10dBm Packet> Hello World 1234567890* BytesSent,23 CRC,DAAB TransmitTime,64mS PacketsSent,2
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
uint8_t TXPacketL;
uint32_t TXPacketCount, startmS, endmS;
uint8_t buff[] = "Hello World 1234567890";
void loop()
{
Serial.print(TXpower); //print the transmit power defined
Serial.print(F("dBm "));
Serial.print(F("Packet> "));
Serial.flush();
TXPacketL = sizeof(buff); //set TXPacketL to length of array
buff[TXPacketL - 1] = '*'; //replace null character at buffer end so its visible on reciver
LT.printASCIIPacket(buff, TXPacketL); //print the buffer (the sent packet) as ASCII
digitalWrite(LED1, HIGH);
startmS = millis(); //start transmit timer
if (LT.transmit(buff, TXPacketL, 10000, TXpower, WAIT_TX)) //will return packet length sent if OK, otherwise 0 if transmit error
{
endmS = millis(); //packet sent, note end time
TXPacketCount++;
packet_is_OK();
}
else
{
packet_is_Error(); //transmit packet returned 0, there was an error
}
digitalWrite(LED1, LOW);
Serial.println();
delay(packet_delay); //have a delay between packets
}
void packet_is_OK()
{
//if here packet has been sent OK
uint16_t localCRC;
Serial.print(F(" BytesSent,"));
Serial.print(TXPacketL); //print transmitted packet length
localCRC = LT.CRCCCITT(buff, TXPacketL, 0xFFFF);
Serial.print(F(" CRC,"));
Serial.print(localCRC, HEX); //print CRC of transmitted packet
Serial.print(F(" TransmitTime,"));
Serial.print(endmS - startmS); //print transmit time of packet
Serial.print(F("mS"));
Serial.print(F(" PacketsSent,"));
Serial.print(TXPacketCount); //print total of packets sent OK
}
void packet_is_Error()
{
//if here there was an error transmitting packet
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the the interrupt register
Serial.print(F(" SendError,"));
Serial.print(F("Length,"));
Serial.print(TXPacketL); //print transmitted packet length
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX); //print IRQ status
LT.printIrqStatus(); //prints the text of which IRQs set
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("103_LoRa_Transmitter_Detailed_Setup 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));
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
//The function call list below shows the complete setup for the LoRa device using the information defined in the
//Settings.h file.
//The 'Setup LoRa device' list below can be replaced with a single function call;
//LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
//***************************************************************************************************
//Setup LoRa device
//***************************************************************************************************
LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device
LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions
LT.setRfFrequency(Frequency, Offset); //set the operating frequency
LT.calibrateImage(0); //run calibration after setting frequency
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters
LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX
LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34
LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current
LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on RX done
//***************************************************************************************************
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(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F
Serial.println();
Serial.println();
Serial.print(F("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,39 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/03/20
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. Some pins such as DIO1,
//DIO2, BUZZER are not used by this sketch so they do not need to be connected and
//should be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup LoRa Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const int8_t TXpower = 10; //LoRa transmit power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets

View File

@@ -0,0 +1,250 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/03/20
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 program that demonstrates the detailed setup of a LoRa test receiver.
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 on the Arduino IDE Serial Monitor of the valid packets received, the packet is
assumed to be in ASCII printable text, if it's not ASCII text characters from 0x20 to 0x7F, expect
weird things to happen on the Serial Monitor. The LED will flash for each packet received and the
buzzer will sound, if fitted.
Sample serial monitor output;
7s Hello World 1234567890*,CRC,DAAB,RSSI,-52dBm,SNR,9dB,Length,23,Packets,5,Errors,0,IRQreg,50
If there is a packet error it might look like this, which is showing a CRC error,
968s PacketError,RSSI,-87dBm,SNR,-11dB,Length,23,Packets,613,Errors,2,IRQreg,70,IRQ_HEADER_VALID,IRQ_CRC_ERROR,IRQ_RX_DONE
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
uint32_t RXpacketCount;
uint32_t errors;
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
uint8_t RXPacketL; //stores length of packet received
int16_t PacketRSSI; //stores RSSI of received packet
int8_t PacketSNR; //stores signal to noise ratio (SNR) of received packet
void loop()
{
RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 60000, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
digitalWrite(LED1, HIGH); //something has happened
if (BUZZER > 0) //turn buzzer on
{
digitalWrite(BUZZER, HIGH);
}
PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value
PacketSNR = LT.readPacketSNR(); //read the received SNR value
if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL is 0
{
packet_is_Error();
}
else
{
packet_is_OK();
}
if (BUZZER > 0)
{
digitalWrite(BUZZER, LOW); //buzzer off
}
delay(10); //so we can see LED flash more easily on fast processors
digitalWrite(LED1, LOW); //LED off
Serial.println();
}
void packet_is_OK()
{
uint16_t IRQStatus, localCRC;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
RXpacketCount++;
printElapsedTime(); //print elapsed time to Serial Monitor
Serial.print(F(" "));
LT.printASCIIPacket(RXBUFFER, RXPacketL); //print the packet as ASCII characters
localCRC = LT.CRCCCITT(RXBUFFER, RXPacketL, 0xFFFF); //calculate the CRC, this is the external CRC calculation of the RXBUFFER
Serial.print(F(",CRC,")); //contents, not the LoRa device internal CRC
Serial.print(localCRC, HEX);
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(RXPacketL);
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
printElapsedTime(); //print elapsed time to Serial Monitor
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout"));
}
else
{
errors++;
Serial.print(F(" PacketError"));
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL()); //get the device packet length
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus(); //print the names of the IRQ registers set
}
delay(250); //gives a longer buzzer and LED flash for error
}
void printElapsedTime()
{
float seconds;
seconds = millis() / 1000;
Serial.print(seconds, 0);
Serial.print(F("s"));
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("104_Lora_Receiver_Detailed_Setup Starting"));
Serial.println();
if (BUZZER > 0)
{
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
SPI.begin();
//SPI beginTranscation is normally part of library routines, but if it is disabled in the library
//a single instance is needed here, so uncomment the program line below
//SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("Lora Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
//The function call list below shows the complete setup for the LoRa device using the information defined in the
//Settings.h file.
//The 'Setup Lora device' list below can be replaced with a single function call;
//LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
//***************************************************************************************************
//Setup Lora device
//***************************************************************************************************
LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device
LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions
LT.setRfFrequency(Frequency, Offset); //set the operating frequency
LT.calibrateImage(0); //run calibration after setting frequency
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters
LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX
LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34
LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current
LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_RX_DONE, 0, 0); //set for IRQ on RX done
//***************************************************************************************************
Serial.println();
LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check
Serial.println();
LT.printOperatingSettings(); //reads and prints the configured operting settings, useful check
Serial.println();
Serial.println();
LT.printRegisters(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F
Serial.println();
Serial.println();
Serial.print(F("Receiver ready - RXBUFFER_SIZE "));
Serial.println(RXBUFFER_SIZE);
Serial.println();
}

View File

@@ -0,0 +1,44 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/03/20
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. Some pins such as DIO1,
//DIO2, BUZZER may not be in used by this sketch so they do not need to be
//connected and should be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define BUZZER 4 //pin for buzzer, on when logic high
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup LoRa Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const int8_t TXpower = 2; //LoRa transmit power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets
#define RXBUFFER_SIZE 32 //RX buffer size

View File

@@ -0,0 +1,145 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 program demonstrates the transmitting of a structure as a LoRa packet. The
contents of the structure are the same as in the '8_LoRa_LowMemory_TX' program. The packet sent is
typical of what might be sent from a GPS tracker.
The structure type is defined as trackerPacket and an instance called location1 is created. The struture
which includes a character array (text) is filled with values and transmitted.
The matching receiving program '15_LoRa_RX_Structure' can be used to receive and display the packet,
though the program '9_LoRa_LowMemory_RX' should receive it as well, since the contents are the same.
Note that the structure definition and variable order (including the buffer size) used in the transmitter
need to match those used in the receiver.
The contents of the packet transmitted should be;
"tracker1" (buffer) - trackerID
1+ (uint32_t) - packet count
51.23456 (float) - latitude
-3.12345 (float) - longitude
199 (uint16_t) - altitude
8 (uint8_t) - number of satellites
3999 (uint16_t) - battery voltage
-9 (int8_t) - temperature
Good luck.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
SX127XLT LT;
uint32_t TXpacketCount = 1;
uint32_t startmS, endmS;
struct trackerPacket
{
uint8_t trackerID[13];
uint32_t txcount;
float latitude;
float longitude;
uint16_t altitude;
uint8_t satellites;
uint16_t voltage;
int8_t temperature;
};
struct trackerPacket location1; //define an instance called location1 of the structure trackerPacket
void loop()
{
//fill the defined structure with values
uint8_t buff[] = "tracker1"; //create the contents to be of location1.trackerID
memcpy (&location1.trackerID, &buff, sizeof(buff)); //copy the contents of buff[] into the structure
location1.txcount = TXpacketCount;
location1.latitude = 51.23456;
location1.longitude = -3.12345;
location1.altitude = 199;
location1.satellites = 8;
location1.voltage = 3999;
location1.temperature = -9;
digitalWrite(LED1, HIGH);
startmS = millis();
if (LT.transmit((uint8_t *) &location1, sizeof(location1), 0, TXpower, WAIT_TX)) //will return packet length sent if OK, otherwise 0
{
endmS = millis();
digitalWrite(LED1, LOW);
TXpacketCount++;
Serial.print(TXpacketCount);
Serial.print(F(" "));
Serial.print(sizeof(location1));
Serial.print(F(" Bytes Sent"));
Serial.print(F(" "));
Serial.print(endmS - startmS);
Serial.print(F("mS"));
}
else
{
Serial.print(F("Send Error - IRQreg,"));
Serial.print(LT.readIrqStatus(), HEX);
}
digitalWrite(LED1, LOW);
Serial.println();
delay(packet_delay);
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
led_Flash(2, 125);
}
else
{
Serial.println(F("Device error"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println(F("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,39 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 definitiosn to match your own setup. Some pins such as DIO1,
//DIO2, may not be in used by this sketch so they do not need to be connected and
//should be set to -1.
#define NSS 10 //select on LoRa device
#define NRESET 9 //reset on LoRa device
#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1
#define LED1 8 //On board LED, high for on
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 10; //LoRa TX power
#define packet_delay 1000 //mS delay between packets

View File

@@ -0,0 +1,194 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 17/12/19
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 program demonstrates the receiving of a structure as a LoRa packet. The packet
sent is typical of what might be sent from a GPS tracker.
The structure type is defined as trackerPacket and an instance called location1 is created. The structure
includes a character array (text).
The matching receiving program is '15_LoRa_RX_Structure' can be used to receive and display the packet,
though the program '9_LoRa_LowMemory_RX' should receive it as well, since the packet contents are the same.
Not that the structure definition and variable order (including the buffer size) used in the transmitter
need to match those used in the receiver. Good luck.
The contents of the packet received, and printed to serial monitor, should be;
"tracker1" (buffer) - trackerID
1+ (uint32_t) - packet count
51.23456 (float) - latitude
-3.12345 (float) - longitude
199 (uint16_t) - altitude
8 (uint8_t) - number of satellites
3999 (uint16_t) - battery voltage
-9 (int8_t) - temperature
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
SX127XLT LT;
uint8_t RXPacketL; //stores length of packet received
uint32_t RXpacketCount; //count of received packets
int16_t PacketRSSI; //RSSI of received packet
int8_t PacketSNR; //signal to noise ratio of received packet
uint32_t errors; //count of packet errors
struct trackerPacket
{
uint8_t trackerID[13];
uint32_t txcount;
float latitude;
float longitude;
uint16_t altitude;
uint8_t satellites;
uint16_t voltage;
int8_t temperature;
};
struct trackerPacket location1; //define an instance called location1 of the structure trackerPacket
void loop()
{
RXPacketL = LT.receive( (uint8_t *) &location1, sizeof(location1), 0, WAIT_RX); //wait for a packet to arrive with no timeout
digitalWrite(LED1, HIGH); //something has happened, what I wonder ?
PacketRSSI = LT.readPacketRSSI();
PacketSNR = LT.readPacketSNR();
if (RXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
digitalWrite(LED1, LOW);
Serial.println();
}
void printlocation1()
{
uint8_t buff[13]; //define a buffer to receive a copy from the structure
memcpy (&buff, &location1.trackerID, sizeof(buff)); //copy the contents of buffer in struture to buff[]
//now print the contents of the structure
Serial.print((char*) buff); //cast to a char type for printing
Serial.print(F(","));
Serial.print(location1.txcount);
Serial.print(F(","));
Serial.print(location1.latitude, 5);
Serial.print(F(","));
Serial.print(location1.longitude, 5);
Serial.print(F(","));
Serial.print(location1.altitude);
Serial.print(F("m,"));
Serial.print(location1.satellites);
Serial.print(F("sats,"));
Serial.print(location1.voltage);
Serial.print(F("mV,"));
Serial.print(location1.temperature);
Serial.print(F("c "));
}
void packet_is_OK()
{
RXpacketCount++;
Serial.print(RXpacketCount);
Serial.print(F(" "));
printlocation1();
printpacketDetails();
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus();
if (IRQStatus & IRQ_RX_TIMEOUT)
{
Serial.print(F("RXTimeout"));
}
else
{
errors++;
Serial.print(F("PacketError"));
printpacketDetails();
Serial.print(F("IRQreg,"));
Serial.print(IRQStatus, HEX);
}
}
void printpacketDetails()
{
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 setup(void)
{
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("Device error"));
while (1)
{
led_Flash(50, 50);
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.print(F("Receiver ready"));
Serial.println();
Serial.println();
}

View File

@@ -0,0 +1,39 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 17/12/19
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 definitiosn to match your own setup. Some pins such as DIO1,
//DIO2, may not be in used by this sketch so they do not need to be connected and
//should be set to -1.
#define NSS 10 //select on LoRa device
#define NRESET 9 //reset on LoRa device
#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1
#define LED1 8 //On board LED, high for on
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 10; //LoRa TX power in dBm
#define packet_delay 1000 //mS delay between packets

View File

@@ -0,0 +1,72 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
This programs is supplied as is, it is up to the user of the program to decide if the programs are
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This program blinks an LED connected the pin number defined below. The pin 13 LED,
fitted to some Arduinos is blinked as well. The blinks should be close to one per second. messages are
sent to the Serial Monitor also.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define LED1 8 //pin number for LED, set logic level high for on
#define Program_Version "V1.0"
uint16_t seconds; //used to display time elapsed on Serial Monitor
void loop()
{
Serial.print(seconds);
Serial.println(F(" Seconds")); //this message should print on console at close to once per second
seconds++;
digitalWrite(LED1, HIGH);
digitalWrite(13, HIGH);
delay(100);
digitalWrite(LED1, LOW);
digitalWrite(13, LOW);
delay(890); //should give approx 1 second flash
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
//general purpose routine for flashing LED as indicator
uint16_t index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH); //LED on
digitalWrite(13, HIGH); //Arduino board LED on
delay(delaymS);
digitalWrite(LED1, LOW); //LED off
digitalWrite(13, LOW); //Arduino board LED off
delay(delaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
pinMode(13, OUTPUT); //setup pin as output for some Arduino boards that include an LED on pin 13
digitalWrite(LED1, HIGH);
digitalWrite(13, HIGH);
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("1_LED_Blink Starting"));
}

View File

@@ -0,0 +1,266 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 18/03/20
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 program is stand alone, it is not necessary to install the SX12XX-LoRa library
to use it. This test program is for the SX127X LoRa devices.
The program checks that a lora device can be accessed by doing a test register write and read.
If there is no device found a message is printed on the serial monitor. The contents of the registers
from 0x00 to 0x7F are printed and the program then changes the frequency between two values and prints
out the registers. This is to prove that the device registers are being read and written correctly.
There is a copy of the typical printout below. Note that the read back changed frequency may be slightly
different to the programmed frequency, there is a rounding error due to the use of floats to calculate
the frequency. Although the program sets the frequency in the 434Mhz band, it will work on 868Mhz and
915Mhz devices and there is no attempt to confugure the device for transmission or reception.
The Arduino pin number that NSS on the LoRa device is connected to must be specified in #define NSS
line below. Leave the NRESET and DIOx pins not connected.
Typical printout;
2_Register_Test Starting
LoRa Device found
Device version 0x12
Frequency at Start 434000000
Registers at Start
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00 00 09 1A 0B 00 52 6C 80 00 4F 09 2B 20 08 02 0A
0x10 FF 70 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40
0x20 00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55
0x30 90 40 40 00 00 0F 00 00 00 F5 20 82 FD 02 80 40
0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B
0x50 14 00 00 10 00 00 00 0F E0 00 0C FD 06 00 5C 78
0x60 00 19 0C 4B CC 0D FD 20 04 47 AF 3F F6 3F DB 0B
0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00
Change Frequency to 434100000
Changed Frequency 434099968
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00 00 09 1A 0B 00 52 6C 86 66 4F 09 2B 20 08 02 0A
0x10 FF 70 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40
0x20 00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55
0x30 90 40 40 00 00 0F 00 00 00 F5 20 82 FD 02 80 40
0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B
0x50 14 00 00 10 00 00 00 0F E0 00 0C FD 06 00 5C 78
0x60 00 19 0C 4B CC 0D FD 20 04 47 AF 3F F6 3F DB 0B
0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00
Change Frequency to 434200000
Changed Frequency 434199936
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00 00 09 1A 0B 00 52 6C 8C CC 4F 09 2B 20 08 02 0A
0x10 FF 70 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40
0x20 00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55
0x30 90 40 40 00 00 0F 00 00 00 F5 20 82 FD 02 80 40
0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B
0x50 14 00 00 10 00 00 00 0F E0 00 0C FD 06 00 5C 78
0x60 00 19 0C 4B CC 0D FD 20 04 47 AF 3F F6 3F DB 0B
0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00
Note: An SX1272 will report as version 0x22 and the frequency at power up is 915000000hz.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
const uint8_t REG_FRMSB = 0x06; //register number for setting and reading frequency, high byte
const uint8_t REG_FRMID = 0x07; //register number for setting and reading frequency, mid byte
const uint8_t REG_FRLSB = 0x08; //register number for setting and reading frequency, low byte
const uint8_t REG_VERSION = 0x42; //register containg version number of device
//********* Setup hardware pin definition here ! **************
#define NSS 10 //lora device select
//**************************************************************/
#include <SPI.h>
uint32_t frequency;
void setup()
{
Serial.begin(9600);
Serial.println(F("2_Register_Test Starting"));
SPI.begin();
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
//The begin function setups the hardware pins used by device and then checks if device is found
if (begin(NSS))
{
Serial.println(F("LoRa Device found"));
}
else
{
Serial.println(F("No device responding"));
}
Serial.print(F("Device version 0x"));
uint8_t deviceversion = readRegister(REG_VERSION);
if (deviceversion < 0x10)
{
Serial.print(F("0"));
}
Serial.println(deviceversion, HEX);
frequency = getFreqInt(); //read the set frequency following a reset
Serial.print(F("Frequency at Start "));
Serial.println(frequency);
Serial.println(F("Registers at Start ")); //show the all registers following a power up
printRegisters(0x00, 0x7F);
}
void loop()
{
Serial.println();
Serial.println();
Serial.println(F("Change Frequency to 434100000"));
setRfFrequency(434100000, 0); //change the frequency at reset, in hertz
frequency = getFreqInt(); //read back the changed frequency
Serial.print(F("Changed Frequency "));
Serial.println(frequency); //print the changed frequency, did the write work (allow for rounding errors) ?
printRegisters(0x00, 0x7F); //show the registers after frequency change
Serial.println();
Serial.println(F("Change Frequency to 434200000"));
setRfFrequency(434200000, 0); //change the frequency at reset, in hertz
frequency = getFreqInt(); //read back the changed frequency
Serial.print(F("Changed Frequency "));
Serial.println(frequency); //print the changed frequency, did the write work (allow for rounding errors) ?
printRegisters(0x00, 0x7F); //show the registers after frequency change
Serial.println();
delay(5000);
}
uint8_t readRegister(uint8_t address)
{
uint8_t regdata;
digitalWrite(NSS, LOW); //set NSS low
SPI.transfer(address & 0x7F); //mask address for read
regdata = SPI.transfer(0); //read the byte
digitalWrite(NSS, HIGH); //set NSS high
return regdata;
}
void writeRegister(uint8_t address, uint8_t value)
{
digitalWrite(NSS, LOW); //set NSS low
SPI.transfer(address | 0x80); //mask address for write
SPI.transfer(value); //write the byte
digitalWrite(NSS, HIGH); //set NSS high
}
uint32_t getFreqInt()
{
//get the current set LoRa device frequency, return as long integer
uint8_t Msb, Mid, Lsb;
uint32_t uinttemp;
float floattemp;
Msb = readRegister(REG_FRMSB);
Mid = readRegister(REG_FRMID);
Lsb = readRegister(REG_FRLSB);
floattemp = ((Msb * 0x10000ul) + (Mid * 0x100ul) + Lsb);
floattemp = ((floattemp * 61.03515625) / 1000000ul);
uinttemp = (uint32_t)(floattemp * 1000000);
return uinttemp;
}
void printRegisters(uint16_t Start, uint16_t End)
{
//prints the contents of lora device registers to serial monitor
uint16_t Loopv1, Loopv2, RegData;
Serial.print(F("Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F"));
Serial.println();
for (Loopv1 = Start; Loopv1 <= End;)
{
Serial.print(F("0x"));
if (Loopv1 < 0x10)
{
Serial.print(F("0"));
}
Serial.print((Loopv1), HEX);
Serial.print(F(" "));
for (Loopv2 = 0; Loopv2 <= 15; Loopv2++)
{
RegData = readRegister(Loopv1);
if (RegData < 0x10)
{
Serial.print(F("0"));
}
Serial.print(RegData, HEX);
Serial.print(F(" "));
Loopv1++;
}
Serial.println();
}
}
void setRfFrequency(uint64_t freq64, int32_t offset)
{
freq64 = freq64 + offset;
freq64 = ((uint64_t)freq64 << 19) / 32000000;
writeRegister(REG_FRMSB, (uint8_t)(freq64 >> 16));
writeRegister(REG_FRMID, (uint8_t)(freq64 >> 8));
writeRegister(REG_FRLSB, (uint8_t)(freq64 >> 0));
}
bool begin(int8_t pinNSS)
{
pinMode(pinNSS, OUTPUT);
digitalWrite(pinNSS, HIGH);
if (checkDevice())
{
return true;
}
return false;
}
bool checkDevice()
{
//check there is a device out there, writes a register and reads back
uint8_t Regdata1, Regdata2;
Regdata1 = readRegister(REG_FRMID); //low byte of frequency setting
writeRegister(REG_FRMID, (Regdata1 + 1));
Regdata2 = readRegister(REG_FRMID); //read changed value back
writeRegister(REG_FRMID, Regdata1); //restore register to original value
if (Regdata2 == (Regdata1 + 1))
{
return true;
}
else
{
return false;
}
}

View File

@@ -0,0 +1,121 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/03/20
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 minimum setup LoRa test transmitter. A packet containing the ASCII text
"Hello World 1234567890" is sent using the frequency and LoRa settings specified in the LT.setupLoRa()
command. The pins to access the lora device need to be defined at the top of the program also.
The details of the packet sent and any errors are shown on the Arduino IDE Serial Monitor, together with
the transmit power used and the packet length. The matching receiver program, '4_LoRa_Receiver' can be used
to check the packets are being sent correctly, the frequency and LoRa settings (in the LT.setupLoRa()
commands) must be the same for the transmitter and receiver programs. Sample Serial Monitor output;
10dBm Packet> Hello World 1234567890* BytesSent,23 PacketsSent,6
For an example of a more detailed configuration for a transmitter, see program 103_LoRa_Transmitter.
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
SX127XLT 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 DIO0 3 //DIO0 pin on LoRa device, used for sensing RX and TX done
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
#define TXpower 10 //LoRa transmit power in dBm
uint8_t TXPacketL;
uint32_t TXPacketCount;
uint8_t buff[] = "Hello World 1234567890"; //the message to send
void setup()
{
Serial.begin(9600);
Serial.println();
Serial.println(F("3_LoRa_Transmitter Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1);
}
LT.setupLoRa(434000000, 0, LORA_SF7, LORA_BW_125, LORA_CR_4_5, LDRO_AUTO); //configure frequency and LoRa settings
Serial.print(F("Transmitter ready"));
Serial.println();
}
void loop()
{
Serial.print(TXpower); //print the transmit power defined
Serial.print(F("dBm "));
Serial.print(F("Packet> "));
Serial.flush();
TXPacketL = sizeof(buff); //set TXPacketL to length of array
buff[TXPacketL - 1] = '*'; //replace null character at buffer end so its visible on receiver
LT.printASCIIPacket(buff, TXPacketL); //print the buffer (the sent packet) as ASCII
if (LT.transmit(buff, TXPacketL, 10000, TXpower, WAIT_TX)) //will return packet length sent if OK, otherwise 0 if transmit error
{
TXPacketCount++;
packet_is_OK();
}
else
{
packet_is_Error(); //transmit packet returned 0, there was an error
}
Serial.println();
delay(1000); //have a delay between packets
}
void packet_is_OK()
{
//if here packet has been sent OK
Serial.print(F(" BytesSent,"));
Serial.print(TXPacketL); //print transmitted packet length
Serial.print(F(" PacketsSent,"));
Serial.print(TXPacketCount); //print total of packets sent OK
}
void packet_is_Error()
{
//if here there was an error transmitting packet
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the the interrupt register
Serial.print(F(" SendError,"));
Serial.print(F("Length,"));
Serial.print(TXPacketL); //print transmitted packet length
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX); //print IRQ status
LT.printIrqStatus(); //prints the text of which IRQs set
}

View File

@@ -0,0 +1,168 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/03/20
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 minimum setup LoRa test receiver. The program listens for incoming packets
using the frequency and LoRa settings in the LT.setupLoRa() command. The pins to access the lora device
need to be defined at the top of the program also.
There is a printout on the Arduino IDE serial monitor of the valid packets received, the packet is assumed
to be in ASCII printable text, if it's not ASCII text characters from 0x20 to 0x7F, expect weird things to
happen on the Serial Monitor. Sample serial monitor output;
8s Hello World 1234567890*,RSSI,-44dBm,SNR,9dB,Length,23,Packets,7,Errors,0,IRQreg,50
If there is a packet error it might look like this, which is showing a CRC error;
137s PacketError,RSSI,-89dBm,SNR,-8dB,Length,23,Packets,37,Errors,2,IRQreg,70,IRQ_HEADER_VALID,IRQ_CRC_ERROR,IRQ_RX_DONE
If there are no packets received in a 10 second period then you should see a message like this;
112s RXTimeout
For an example of a more detailed configuration for a receiver, see program 104_LoRa_Receiver.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
SX127XLT 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 DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
#define RXBUFFER_SIZE 255 //RX buffer size
uint32_t RXpacketCount;
uint32_t errors;
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
uint8_t RXPacketL; //stores length of packet received
int16_t PacketRSSI; //stores RSSI of received packet
int8_t PacketSNR; //stores signal to noise ratio (SNR) of received packet
void setup()
{
Serial.begin(9600);
Serial.println();
Serial.println(F("4_LoRa_Receiver Starting"));
Serial.println();
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1);
}
LT.setupLoRa(434000000, 0, LORA_SF7, LORA_BW_125, LORA_CR_4_5, LDRO_AUTO); //configure frequency and LoRa settings
Serial.print(F("Receiver ready - RXBUFFER_SIZE "));
Serial.println(RXBUFFER_SIZE);
Serial.println();
}
void loop()
{
RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 60000, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
PacketRSSI = LT.readPacketRSSI(); //read the received packets RSSI value
PacketSNR = LT.readPacketSNR(); //read the received packets SNR value
if (RXPacketL == 0) //if the LT.receive() function detects an error RXpacketL is 0
{
packet_is_Error();
}
else
{
packet_is_OK();
}
Serial.println();
}
void packet_is_OK()
{
uint16_t IRQStatus;
RXpacketCount++;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
printElapsedTime(); //print elapsed time to Serial Monitor
Serial.print(F(" "));
LT.printASCIIPacket(RXBUFFER, RXPacketL); //print the packet as ASCII characters
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(RXPacketL);
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
printElapsedTime(); //print elapsed time to Serial Monitor
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout"));
}
else
{
errors++;
Serial.print(F(" PacketError"));
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL()); //get the real packet length
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus(); //print the names of the IRQ registers set
}
}
void printElapsedTime()
{
float seconds;
seconds = millis() / 1000;
Serial.print(seconds, 0);
Serial.print(F("s"));
}

View File

@@ -0,0 +1,93 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 23/02/20
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 - Transmits a FM tone using the LoRa device that can be picked up on an FM UHF
handheld receiver. The tones are not true FM but the UHF receiver does not know that.
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
void loop()
{
Serial.print(TXpower); //print the transmit power defined
Serial.print(F("dBm "));
Serial.println(F("PlayTone> "));
Serial.println();
digitalWrite(LED1, HIGH);
LT.toneFM(1000, 1000, deviation, adjustfreq, TXpower);
digitalWrite(LED1, LOW);
delay(1000);
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("58_FM_Tone 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));
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
LT.setupDirect(Frequency, Offset);
Serial.print(F("Tone Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,32 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 23/02/20
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. Some pins such as DIO1,
//DIO2 are not used by this particular sketch so they are set to -1 and not connected.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup Direct Modem Parameters Here ! ***************
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint16_t deviation = 10000; //deviation, total frequency shift low to high
const float adjustfreq = 0.9; //adjustment to tone frequency
const int8_t TXpower = 10; //LoRa transmit power in dBm

View File

@@ -0,0 +1,200 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 10/06/20
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 demonstration of using automatic frequency adjustments (AFC) on a receiver
to keep the frequency difference between transmitter and receiver as low as possible. The LoRa settings
used are defined in the Settings.h file.
If a packet is received OK, then all that is needed is a call to the LT.doAFC() function, that reads the
last frequency error, calculates the new offset and changes the set frequency accordingly.
When the receiver starts the frequency error may be as large as 4000hz, when the AFC operates the error
should reduce to 100hz or so. The first AFC correction to run is doAFCPPM(); which based on the frequency
error also adjusts the PPM setting. If doAFC(); were only used then as the frequency error is reduced then
the PPM adjustment would reduce.
Note that the maximum permitted frequency error between transmitter and receiver is 25% of the bandwidth
in use. So at 125000hz bandwidth the maximum frequency error is 31500hz, if the bandwidth is 7800hz the
maximum frequency error is 1950hz. Whilst the AFC functionality can keep transmitter and receiver close
together when reception is working if the transmitter and receiver are to far apart in frequency for
reception to work in the first place then AFC cannot operate to correct for the frequency differences.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h"
SX127XLT LT; //create a library class instance called LT
uint32_t RXpacketCount;
uint32_t errors;
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
uint8_t RXPacketL; //stores length of packet received
int16_t PacketRSSI; //stores RSSI of received packet
int8_t PacketSNR; //stores signal to noise ratio (SNR) of received packet
int32_t frequencyerror; //frequency error of receved packet
bool FirstAFC = true; //used to note that AFC has been called more than once
void loop()
{
Serial.print(F("SetFrequency,"));
Serial.print(Frequency);
Serial.print(F("hz,Offset,"));
Serial.print(LT.getOffset());
Serial.print(F("hz "));
RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 60000, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
PacketRSSI = LT.readPacketRSSI(); //read the received packets RSSI value
PacketSNR = LT.readPacketSNR(); //read the received packets SNR value
if (RXPacketL == 0) //if the LT.receive() function detects an error RXpacketL is 0
{
packet_is_Error();
}
else
{
packet_is_OK();
if (FirstAFC)
{
LT.doAFCPPM(); //the first time AFC is called do the PPM adjust also
FirstAFC = false;
}
else
{
LT.doAFC(); //PPM adjust has been done so now just adjust frequency
}
}
Serial.println();
}
void packet_is_OK()
{
uint16_t IRQStatus;
RXpacketCount++;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
frequencyerror = LT.getFrequencyErrorHz();
printElapsedTime(); //print elapsed time to Serial Monitor
Serial.print(F(" "));
LT.printASCIIPacket(RXBUFFER, RXPacketL); //print the packet as ASCII characters
Serial.print(F(","));
Serial.print(LT.readRegister(REG_FEIMSB),HEX);
Serial.print(F(","));
Serial.print(LT.readRegister(REG_FEIMID),HEX);
Serial.print(F(","));
Serial.print(LT.readRegister(REG_FEILSB),HEX);
Serial.print(F(",Regval,"));
Serial.print(LT.getFrequencyErrorRegValue(),HEX);
Serial.print(F(",FreqErrror,"));
Serial.print(frequencyerror);
Serial.print(F("hz,PpmCorrection,"));
Serial.print(LT.readRegister(REG_PPMCORRECTION));
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(RXPacketL);
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
printElapsedTime(); //print elapsed time to Serial Monitor
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout"));
}
else
{
errors++;
Serial.print(F(" PacketError"));
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL()); //get the real packet length
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus(); //print the names of the IRQ registers set
}
}
void printElapsedTime()
{
float seconds;
seconds = millis() / 1000;
Serial.print(seconds, 0);
Serial.print(F("s"));
}
void setup()
{
Serial.begin(9600);
Serial.println();
Serial.println(F("73_LoRa_Receiver_AFC starting"));
Serial.println();
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1);
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
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.print(F("Receiver ready - RXBUFFER_SIZE "));
Serial.println(RXBUFFER_SIZE);
Serial.println();
}

View File

@@ -0,0 +1,41 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 10/06/20
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. Some pins such as DIO1,
//DIO2, BUZZER may not be in used by this sketch so they do not need to be
//connected and should be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup LoRa Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const int8_t TXpower = 2; //LoRa transmit power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets
#define RXBUFFER_SIZE 128 //RX buffer size

View File

@@ -0,0 +1,106 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 23/02/20
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 - Transmits a FM tone using the LoRa device that can be picked up on an FM UHF
handheld receiver. The tones are generated in direct mode by applying a pulse using the Arduino tone()
function (not supported by all Arduinos) to the DIO2 pin.
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LoRa; //create a library class instance called LoRa
void loop()
{
Serial.print(TXpower); //print the transmit power defined
Serial.print(F("dBm "));
Serial.println(F("PlayTones> "));
Serial.println();
LoRa.setupDirect(Frequency, Offset);
LoRa.setTXDirect(); //turn on transmit
LoRa.setTxParams(TXpower, RADIO_RAMP_DEFAULT); //set TX power
LoRa.writeRegister(REG_FDEVLSB, deviation); //set the deviation
LoRa.writeRegister(REG_PLLHOP, 0xAD); //set fast hop mode, needed for fast changes of frequency
while(1) //repeat forever
{
digitalWrite(LED1, HIGH);
tone(DIO2, 1000); //pin, frequency, durationmS
delay(1000);
digitalWrite(LED1, LOW);
noTone(DIO2);
delay(1000);
};
}
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); //setup pin as output for indicator LED
pinMode(6, OUTPUT);
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("80_Direct_DIO2_Tone 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));
//setup hardware pins used by device, then check if device is found
if (LoRa.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
Serial.print(F("Tone Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,31 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 23/02/20
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. Some pins such as DIO1,
//DIO2 are not used by this particular sketch so they are set to -1 and not connected.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 6 //DIO2 pin on LoRa device can be used for tone
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup Direct Modem Parameters Here ! ***************
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t deviation = 0x52; //set approx 5khz deviation
const int8_t TXpower = 10; //LoRa transmit power in dBm

View File

@@ -0,0 +1,266 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 program that can be used to test the effectiveness of a LoRa link or its
attached antennas. Simulations of antenna performance are no substitute for real world tests and this
simple program allows both long distance link performance to be evaluated and antenna performance to be
compared.
The program sends short test packets that reduce in power by 1dBm at a time. The start power is defined
by start_power and the end power is defined by end_power (see Settings.h file). Once the end_power point
is reached, the program pauses a short while and starts the transmit sequence again at start_power.
The packet sent contains the power used to send the packet. By listening for the packets with the basic
LoRa receive program (4_LoRa_Receiver) you can see the reception results, which should look something
like this;
11s 1*T+05,CRC,80B8,RSSI,-73dBm,SNR,9dB,Length,6,Packets,9,Errors,0,IRQreg,50
12s 1*T+04,CRC,9099,RSSI,-74dBm,SNR,9dB,Length,6,Packets,10,Errors,0,IRQreg,50
14s 1*T+03,CRC,E07E,RSSI,-75dBm,SNR,9dB,Length,6,Packets,11,Errors,0,IRQreg,50
Above shows 3 packets received, the first at +05dBm (+05 in printout), the second at 4dBm (+04 in
printout) and the third at 3dBm (+03) in printout.
If it is arranged so that reception of packets fails halfway through the sequence by attenuating either the
transmitter (with an SMA attenuator for instance) or the receiver (by placing it in a tin perhaps) then
if you swap transmitter antennas you can see the dBm difference in reception, which will be the dBm difference
(gain) of the antenna.
To start the sequence a packet is sent with the number 999, when received it looks like this;
T*1999
This received packet could be used for the RX program to be able to print totals etc.
LoRa settings to use for the link test are specified in the 'Settings.h' file.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h>
#include <SX127XLT.h>
#include <ProgramLT_Definitions.h>
#include "Settings.h"
SX127XLT LT;
int8_t TestPower;
uint8_t TXPacketL;
void loop()
{
Serial.println(F("Start Test Sequence"));
Serial.print(TXpower);
Serial.print(F("dBm "));
Serial.print(F("Start Packet> "));
SendTest1ModePacket();
Serial.println();
for (TestPower = start_power; TestPower >= end_power; TestPower--)
{
Serial.print(TestPower);
Serial.print(F("dBm "));
Serial.print(F("Test Packet> "));
Serial.flush();
SendTestPacket(TestPower);
Serial.println();
delay(packet_delay);
}
Serial.println(F("Finished Test Sequence"));
Serial.println();
}
void SendTestPacket(int8_t lpower)
{
//build and send the test packet in addressed form, 3 bytes will be added to begining of packet
int8_t temppower;
uint8_t buff[3]; //the packet is built in this buffer
TXPacketL = sizeof(buff);
if (lpower < 0)
{
buff[0] = '-';
}
else
{
buff[0] = '+';
}
if (TestPower == 0)
{
buff[0] = ' ';
}
temppower = TestPower;
if (temppower < 0)
{
temppower = -temppower;
}
if (temppower > 19)
{
buff[1] = '2';
buff[2] = ((temppower - 20) + 0x30);
}
else if (temppower > 9)
{
buff[1] = '1';
buff[2] = ((temppower - 10) + 0x30);
}
else
{
buff[1] = '0';
buff[2] = (temppower + 0x30);
}
LT.printASCIIPacket(buff, sizeof(buff));
digitalWrite(LED1, HIGH);
TXPacketL = LT.transmitAddressed(buff, sizeof(buff), TestPacket, Broadcast, ThisNode, 5000, lpower, WAIT_TX);
digitalWrite(LED1, LOW);
if (TXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
}
void SendTest1ModePacket()
{
//used to allow an RX to recognise the start off the sequence and possibly print totals
uint8_t buff[3]; //the packet is built in this buffer
buff[0] = '9';
buff[1] = '9';
buff[2] = '9';
TXPacketL = sizeof(buff);
LT.printASCIIPacket(buff, sizeof(buff));
digitalWrite(LED1, HIGH);
TXPacketL = LT.transmitAddressed(buff, sizeof(buff), TestMode1, Broadcast, ThisNode, 5000, start_power, WAIT_TX);
delay(mode_delaymS); //longer delay, so that the start test sequence is obvious
digitalWrite(LED1, LOW);
if (TXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
}
void packet_is_OK()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //get the IRQ status
Serial.print(F(" "));
Serial.print(TXPacketL);
Serial.print(F(" Bytes SentOK"));
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus();
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //get the IRQ status
Serial.print(F(" SendError,"));
Serial.print(F("Length,"));
Serial.print(TXPacketL);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus();
delay(packet_delay); //change LED flash so packet error visible
delay(packet_delay);
digitalWrite(LED1, HIGH);
delay(packet_delay);
delay(packet_delay);
digitalWrite(LED1, LOW);
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("10_LoRa_Link_Test_Transmitter Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println();
LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check
Serial.println();
LT.printOperatingSettings(); //reads and prints the configured operting settings, useful check
Serial.println();
Serial.println();
LT.printRegisters(0x00, 0x4F); //print contents of device registers
Serial.println();
Serial.println();
Serial.print(F("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,46 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 definitiosn to match your own setup. Some pins such as DIO1,
//DIO2 may not be in used by this sketch so they do not need to be connected and should
//be set to -1.
#define NSS 10 //select on LoRa device
#define NRESET 9 //reset on LoRa device
#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1
#define LED1 8 //On board LED, high for on
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 17; //Transmit power used when sending packet starting test sequence
const int8_t start_power = 17; //link test starts at this transmit power
const int8_t end_power = 2; //and ends at this power
const uint8_t ThisNode = 'T'; //this identifies the node in transmissions
#define packet_delay 1000 //mS delay between packets
#define mode_delaymS 2000 //mS delay after sending start test sequence

View File

@@ -0,0 +1,223 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 and the buzzer will sound,
if fitted. The measured frequency difference between the frequency used by the transmitter and the
frequency used by the receiver is shown. If this frequency difference gets to 25% of the set LoRa
bandwidth, packet reception will fail. The displayed error can be reduced by using the 'offset'
setting in the 'Settings.h' file.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
#include <TimeLib.h> //get the library here; https://github.com/PaulStoffregen/Time
time_t recordtime; //used to record the current time, preventing displayed rollover on printing
SX127XLT LT;
uint32_t RXpacketCount;
uint32_t errors;
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
recordtime = now(); //stop the time to be displayed rolling over
printtime();
PacketRSSI = LT.readPacketRSSI();
PacketSNR = LT.readPacketSNR();
if (RXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
digitalWrite(LED1, LOW);
if (BUZZER > 0)
{
delay(50); //lets have a slightly longer beep
digitalWrite(BUZZER, LOW);
}
Serial.println();
}
void packet_is_OK()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus();
RXpacketCount++;
if (BUZZER > 0)
{
digitalWrite(BUZZER, HIGH);
}
Serial.print(F(" FreqErrror,"));
Serial.print(LT.getFrequencyErrorHz());
Serial.print(F("hz "));
LT.printSXBufferHEX(0, (RXPacketL - 1));
Serial.print(F(" RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(RXPacketL);
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //get the IRQ status
if (IRQStatus & IRQ_RX_TIMEOUT)
{
Serial.print(F(" RXTimeout"));
}
else
{
errors++;
Serial.print(F(" PacketError"));
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL()); //get the real packet length
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
}
}
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 printDigits(int8_t digits)
{
//utility function for digital clock display: prints preceding colon and leading 0
Serial.print(F(":"));
if (digits < 10)
Serial.print('0');
Serial.print(digits);
}
void printtime()
{
Serial.print(hour(recordtime));
printDigits(minute(recordtime));
printDigits(second(recordtime));
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("11_Packet_Logger_Receiver Starting"));
Serial.println();
if (BUZZER > 0)
{
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
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, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("Radio Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50);
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println();
LT.printModemSettings();
Serial.println();
LT.printOperatingSettings();
Serial.println();
Serial.println();
printtime();
Serial.print(F(" Receiver ready"));
Serial.println();
}

View File

@@ -0,0 +1,39 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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. Some pins such as DIO1,
//DIO2, BUZZER may not be in used by this sketch so they do not need to be connected
//and should be set to -1.
#define NSS 10 //select on LoRa device
#define NRESET 9 //reset on LoRa device
#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1
#define LED1 8 //On board LED, high for on
#define BUZZER 4 //Buzzer if fitted, high for on. Set to -1 if not used
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 2; //LoRa TX power
#define packet_delay 1000 //mS delay between packets

View File

@@ -0,0 +1,138 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 program that transmits a long LoRa packets lasting about 5 seconds that
can be used to measure the frequency and power of the transmission using external equipment. The bandwidth
of the transmission is only 10khz, so a frequency counter should give reasonable average result.
The LoRa settings to use, including transmit powwer, are specified in the 'Settings.h' file.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
SX127XLT LT;
uint8_t TXPacketL;
uint32_t TXPacketCount;
void loop()
{
Serial.print(F("Sending "));
Serial.print(TXpower);
Serial.print(F("dBm Packet > "));
Serial.flush();
uint8_t buff[] = "Hello World!1234Hello World!1234"; //use a longish packet to measure
TXPacketL = sizeof(buff);
LT.printASCIIPacket(buff, TXPacketL); //print the packet
digitalWrite(LED1, HIGH);
if (LT.transmit(buff, TXPacketL, 10000, TXpower, WAIT_TX)) //will return packet length sent if OK, otherwise 0
{
TXPacketCount++;
packet_is_OK();
digitalWrite(LED1, LOW);
}
else
{
packet_is_Error();
digitalWrite(LED1, LOW);
}
Serial.println();
delay(packet_delay);
}
void packet_is_OK()
{
Serial.print(F(" "));
Serial.print(TXPacketL);
Serial.print(F(" Bytes SentOK"));
Serial.print(F(" PacketsSent "));
Serial.print(TXPacketCount);
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //get the IRQ status
Serial.print(F("SendError,"));
Serial.print(F("Length,"));
Serial.print(TXPacketL);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus();
digitalWrite(LED1, LOW); //this leaves the LED on slightly longer for a packet send error
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("13_Frequency_and_Power_Check_TX Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.print(F("Transmitter ready - TXBUFFER_SIZE "));
Serial.println(TXBUFFER_SIZE);
LT.printModemSettings();
Serial.println();
Serial.println();
}

View File

@@ -0,0 +1,41 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 definitiosn to match your own setup. Some pins such as DIO1,
//DIO2, BUZZER SWITCH1 may not be in used by this sketch so they do not need to be
//connected and should be set to -1.
#define NSS 10 //select on LoRa device
#define NRESET 9 //reset on LoRa device
#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1
#define LED1 8 //On board LED, high for on
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_010; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF8; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_8; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 10; //LoRa TX power in dBm, 10dBm = 10mW
#define packet_delay 2500 //mS delay between transmissions
#define TXBUFFER_SIZE 64 //TX buffer size

View File

@@ -0,0 +1,183 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 program can be used to check the frequency error between a pair of LoRa
devices, a transmitter and receiver. This receiver measures the frequecy error between the receivers
centre frequency and the centre frequency of the transmitted packet. The frequency difference is shown
for each packet and an average over 10 received packets reported. Any transmitter program can be used
to give this program something to listen to, including example program '3_LoRa_Transmit'.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
SX127XLT LT;
uint32_t RXpacketCount;
uint32_t errors;
uint8_t RXBUFFER[RXBUFFER_SIZE]; //a buffer is needed to receive packets
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
int32_t totalHzError = 0; //used to keep a running total of hZ error for averaging
void loop()
{
RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 0, WAIT_RX); //wait for a packet to arrive
digitalWrite(LED1, HIGH); //something has happened
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()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus();
RXpacketCount++;
Serial.print(F("PacketOK > "));
Serial.print(F(" RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(RXPacketL);
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
Serial.println();
printFrequencyError();
}
void printFrequencyError()
{
int32_t hertzerror, regdata;
regdata = LT.getFrequencyErrorRegValue();
hertzerror = LT.getFrequencyErrorHz();
Serial.print(F("ErrorRegValue,"));
Serial.print(regdata, HEX);
Serial.print(F(" PacketHertzError,"));
Serial.print(hertzerror);
Serial.println(F("hz"));
totalHzError = totalHzError + hertzerror;
if (RXpacketCount == 10)
{
Serial.print(F("******** AverageHertzerror "));
Serial.print((totalHzError / 10));
Serial.println(F("hz"));
RXpacketCount = 0;
totalHzError = 0;
delay(5000);
}
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //get the IRQ status
errors++;
Serial.print(F("PacketError,RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL()); //get the real packet length
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus();
digitalWrite(LED1, LOW);
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("16_LoRa_RX_Frequency_Error_Check Starting"));
Serial.println();
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println(F("Receiver ready"));
Serial.println();
}

View File

@@ -0,0 +1,43 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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. Some pins such as DIO1,
//DIO2, BUZZER SWITCH1 may not be in used by this sketch so they do not need to be
//connected and should be set to -1.
#define NSS 10 //select on LoRa device
#define NRESET 9 //reset on LoRa device
#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1
#define LED1 8 //On board LED, high for on
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 10; //LoRa TX power
#define packet_delay 1000 //mS delay between packets
#define RXBUFFER_SIZE 32 //RX buffer size

View File

@@ -0,0 +1,298 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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.
The program is a matching receiver program for the '10_LoRa_Link_Test_Transmitter'. The packets received
are displayed on the serial monitor and analysed to extract the packet data which indicates the power
used to send the packet. A count is kept of the numbers of each power setting received. When the transmitter
sends the test mode packet at the beginning of the sequence (displayed as 999) the running totals of the
powers received are printed. Thus you can quickly see at what transmit power levels the reception fails.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
#include <ProgramLT_Definitions.h>
SX127XLT LT; //create a library class instance called LT
uint32_t RXpacketCount;
uint32_t errors;
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
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
uint32_t Test1Count[21]; //buffer where counts of received packets are stored, +2dbm to +20dBm
uint32_t Mode1_Cycles = 0; //count the number of cyles received
bool updateCounts = false; //update counts set to tru when first TestMode1 received, at sequence start
void loop()
{
RXPacketL = LT.receiveAddressed(RXBUFFER, RXBUFFER_SIZE, 15000, WAIT_RX); //wait for a packet to arrive with 15seconds (15000mS) timeout
digitalWrite(LED1, HIGH); //something has happened
PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value
PacketSNR = LT.readPacketSNR(); //read the received SNR value
if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL == 0
{
packet_is_Error();
}
else
{
packet_is_OK();
}
if (BUZZER > 0)
{
delay(25); //gives a slightly longer beep
digitalWrite(BUZZER, LOW); //buzzer off
}
digitalWrite(LED1, LOW); //LED off
Serial.println();
}
void packet_is_OK()
{
uint16_t IRQStatus;
if (BUZZER > 0) //turn buzzer on for a valid packet
{
digitalWrite(BUZZER, HIGH);
}
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
RXpacketCount++;
printElapsedTime(); //print elapsed time to Serial Monitor
Serial.print(F(" "));
LT.printASCIIPacket(RXBUFFER, RXPacketL - 3); //print the packet as ASCII characters
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(RXPacketL);
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
processPacket();
}
void processPacket()
{
int8_t lTXpower;
uint8_t packettype;
uint32_t temp;
packettype = LT.readRXPacketType(); //need to know the packet type so we can decide what to do
if (packettype == TestPacket)
{
lTXpower = ((RXBUFFER[1] - 48) * 10) + (RXBUFFER[2] - 48); //convert packet text to power
Serial.print(F(" ("));
Serial.print(lTXpower);
Serial.print(F("dBm)"));
if (updateCounts)
{
temp = (Test1Count[lTXpower]);
Test1Count[lTXpower] = temp + 1;
}
}
if (packettype == TestMode1)
{
//this is a command to switch to TestMode1 also updates totals and logs
updateCounts = true;
Serial.println();
Serial.println(F("End test sequence"));
if (Mode1_Cycles > 0)
{
print_Test1Count();
}
Serial.println();
Mode1_Cycles++;
}
}
void print_Test1Count()
{
//prints running totals of the powers of received packets
int8_t index;
uint32_t j;
Serial.print(F("Test Packets "));
Serial.println(RXpacketCount);
Serial.print(F("Test Cycles "));
Serial.println(Mode1_Cycles);
Serial.println();
for (index = 20; index >= 2; index--)
{
Serial.print(index);
Serial.print(F("dBm,"));
j = Test1Count[index];
Serial.print(j);
Serial.print(F(" "));
}
Serial.println();
Serial.print(F("CSV"));
for (index = 20; index >= 2; index--)
{
Serial.print(F(","));
j = Test1Count[index];
Serial.print(j);
}
Serial.println();
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
printElapsedTime(); //print elapsed time to Serial Monitor
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout"));
}
else
{
errors++;
Serial.print(F(" PacketError"));
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL()); //get the real packet length
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus(); //print the names of the IRQ registers set
}
}
void printElapsedTime()
{
float seconds;
seconds = millis() / 1000;
Serial.print(seconds, 0);
Serial.print(F("s"));
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("20_LoRa_Link_Test_Receiver Starting"));
Serial.println();
if (BUZZER > 0)
{
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
//setup SPI, its external to library on purpose, so settings can be mixed and matched with other SPI devices
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));
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
//this function call sets up the device for LoRa using the settings from settings.h
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println();
LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check
Serial.println();
LT.printOperatingSettings(); //reads and prints the configured operting settings, useful check
Serial.println();
Serial.println();
Serial.print(F("Receiver ready - RXBUFFER_SIZE "));
Serial.println(RXBUFFER_SIZE);
Serial.println();
}

View File

@@ -0,0 +1,44 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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. Some pins such as DIO1,
//DIO2, BUZZER may not be in used by this sketch so they do not need to be
//connected and should be included and be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define BUZZER 4 //pin for buzzer, on when logic high
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup LoRa Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const int8_t TXpower = 10; //LoRa transmit power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets
#define RXBUFFER_SIZE 32 //RX buffer size

View File

@@ -0,0 +1,283 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 21/12/19
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, the packet is assumed to be in ASCII printable text,
if its not ASCII text characters from 0x20 to 0x7F, expect weird things to happen on the Serial Monitor.
The LED will flash for each packet received and the buzzer will sound, if fitted.
Sample serial monitor output;
1109s {packet contents} CRC,3882,RSSI,-69dBm,SNR,10dB,Length,19,Packets,1026,Errors,0,IRQreg,50
If there is a packet error it might look like this, which is showing a CRC error,
1189s PacketError,RSSI,-111dBm,SNR,-12dB,Length,0,Packets,1126,Errors,1,IRQreg,70,IRQ_HEADER_VALID,IRQ_CRC_ERROR,IRQ_RX_DONE
A summary of the packet reception is sent to the OLED display as well, useful for portable applications.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
#include <U8x8lib.h> //get library here > https://github.com/olikraus/u8g2
U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for standard 0.96" SSD1306
//U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for 1.3" OLED often sold as 1.3" SSD1306
#define DEFAULTFONT u8x8_font_chroma48medium8_r //font for U8X8 Library
uint32_t RXpacketCount;
uint32_t RXpacketErrors;
uint16_t IRQStatus;
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
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.receive(RXBUFFER, RXBUFFER_SIZE, 0, WAIT_RX); //wait for a packet to arrive with no timeout
digitalWrite(LED1, HIGH); //something has happened
if (BUZZER > 0)
{
digitalWrite(BUZZER, HIGH); //buzzer on
}
PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value
PacketSNR = LT.readPacketSNR(); //read the received SNR value
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL == 0
{
packet_is_Error();
}
else
{
packet_is_OK();
}
if (BUZZER > 0)
{
digitalWrite(BUZZER, LOW); //buzzer off
}
digitalWrite(LED1, LOW); //LED off
Serial.println();
}
void packet_is_OK()
{
uint16_t localCRC;
RXpacketCount++;
printElapsedTime(); //print elapsed time to Serial Monitor
Serial.print(F(" "));
LT.printASCIIPacket(RXBUFFER, RXPacketL); //print the packet as ASCII characters
localCRC = LT.CRCCCITT(RXBUFFER, RXPacketL, 0xFFFF); //calculate the CRC, this is the external CRC calculation of the RXBUFFER
Serial.print(F(",CRC,")); //contents, not the LoRa device internal CRC
Serial.print(localCRC, HEX);
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(RXPacketL);
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(RXpacketErrors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
disp.clearLine(0);
disp.setCursor(0, 0);
disp.print(F("OK"));
dispscreen1();
}
void packet_is_Error()
{
printElapsedTime(); //print elapsed time to Serial Monitor
RXpacketErrors++;
Serial.print(F(" PacketError"));
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL()); //get the real packet length
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(RXpacketErrors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus(); //print the names of the IRQ registers set
disp.clearLine(0);
disp.setCursor(0, 0);
disp.print(F("Packet Error"));
dispscreen1();
delay(500); //gives longer buzzer and LED falsh for error
}
void printElapsedTime()
{
float seconds;
seconds = millis() / 1000;
Serial.print(seconds, 0);
Serial.print(F("s"));
}
void dispscreen1()
{
disp.clearLine(1);
disp.setCursor(0, 1);
disp.print(F("RSSI "));
disp.print(PacketRSSI);
disp.print(F("dBm"));
disp.clearLine(2);
disp.setCursor(0, 2);
disp.print(F("SNR "));
if (PacketSNR > 0)
{
disp.print(F("+"));
}
disp.print(PacketSNR);
disp.print(F("dB"));
disp.clearLine(3);
disp.setCursor(0, 3);
disp.print(F("Length "));
disp.print(LT.readRXPacketL());
disp.clearLine(4);
disp.setCursor(0, 4);
disp.print(F("Packets "));
disp.print(RXpacketCount);
disp.clearLine(5);
disp.setCursor(0, 5);
disp.print(F("Errors "));
disp.print(RXpacketErrors);
disp.clearLine(6);
disp.setCursor(0, 6);
disp.print(F("IRQreg "));
disp.print(IRQStatus, HEX);
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("33_LoRa_RSSI_Checker_With_Display Starting"));
Serial.println();
if (BUZZER > 0)
{
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
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));
disp.begin();
disp.setFont(DEFAULTFONT);
disp.clear();
disp.setCursor(0, 0);
disp.print(F("Check LoRa"));
disp.setCursor(0, 1);
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
disp.print(F("LoRa OK"));
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
disp.print(F("Device error"));
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
//this function call sets up the device for LoRa using the settings from settings.h
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println();
LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check
Serial.println();
LT.printOperatingSettings(); //reads and prints the configured operting settings, useful check
Serial.println();
Serial.println();
LT.printRegisters(0x00, 0x4F); //print contents of device registers
Serial.println();
Serial.println();
Serial.print(F("Receiver ready - RXBUFFER_SIZE "));
Serial.println(RXBUFFER_SIZE);
Serial.println();
}

View File

@@ -0,0 +1,44 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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. Some pins such as DIO1,
//DIO2, BUZZER may not be in used by this sketch so they do not need to be
//connected and should be included and be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define BUZZER 4 //pin for buzzer, on when logic high
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup LoRa Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const int8_t TXpower = 2; //LoRa transmit power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets
#define RXBUFFER_SIZE 255 //RX buffer size

View File

@@ -0,0 +1,282 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 26/03/20
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 program that can be used to test the throughput of a LoRa transmitter.
Whilst the various LoRa calculators tell you the on air data rate, in practice the achievable data
rate will be less than that due to the overhead of the software routines to load and send a packet
and internal delays in the LoRa device itself.
A buffer is filled with characters and that buffer is then transmitted. The total time for a number of
transmissions is recorded and the bit rate calculated. The packet size (1 - 255 bytes) and the number of
packets to send in the test are specified in the 'Settings.h' file, see the 'Setup packet parameters Here !'
section. The setting file also has the lora settings to use. A lower spreading factors and higher
bandwidths will result in higher bitrates.
There is the option of turning on an a requirement for an acknowledgement from a remote receiver, before
the transmitter sends the next packet, set this; 'const bool waitforACK = true;' definition in the
settings file. The matching receiver program '43_LoRa_Data_Throughput_Acknowledge_Receiver' does then need
to be configured with same lora settings as this transmitter. When this option is set, the program will
keep running until the number of transmissions and acknowledgements has completed without any timeouts
in order to produce a valid average.
The results of the test are printed out thus;
SX1278,434000000hz,SF7,BW500000,CR4:5,LDRO_Off,SyncWord_0x12,IQNormal,Preamble_8
Total transmit time 100 packets = 1382mS
Average 16 byte packet transmit time = 13.82mS
Packets per second 72.36
Bits per packet sent = 128
Data rate = 9262bps
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include <ProgramLT_Definitions.h>
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
uint32_t startmS, endmS, sendtimemS, bitspersecond, bitsPerpacket;
uint32_t TXPacketCount;
float averagePacketTime;
uint8_t packetNumber;
uint8_t RXPacketL; //length of received packet
uint8_t PacketType; //for packet addressing, identifies packet type received
uint32_t packetCheck;
bool loopFail = false;
void loop()
{
uint16_t index, index2;
uint8_t TXBUFFER[TXPacketL + 1]; //create buffer for transmitted packet
loopFail = false;
Serial.println(F("Start transmit test"));
startmS = millis(); //start transmit timer
for (index = 0; index < numberPackets; index++)
{
//fill the buffer
for (index2 = 0; index2 < TXPacketL; index2++)
{
TXBUFFER[index2] = index2;
}
TXBUFFER[0] = TestPacket; //set first byte to identify this test packet
TXBUFFER[1] = index; //put the index as packet number in second byte of packet
Serial.print(index); //print number of packet sent
if (waitforACK)
{
packetCheck = ( (uint32_t) TXBUFFER[4] << 24) + ( (uint32_t) TXBUFFER[3] << 16) + ( (uint32_t) TXBUFFER[2] << 8) + (uint32_t) TXBUFFER[1];
Serial.print(F(",Checkvalue,"));
Serial.print(packetCheck, HEX);
Serial.print(F(","));
}
digitalWrite(LED1, HIGH);
if (LT.transmit(TXBUFFER, TXPacketL, 10000, TXpower, WAIT_TX)) //will return 0 if transmit error
{
digitalWrite(LED1, LOW);
if (waitforACK)
{
if (!waitAck(packetCheck))
{
Serial.print(F("NoACKreceived,"));
loopFail = true;
break;
}
}
}
else
{
packet_is_Error(); //transmit packet returned 0, there was an error
loopFail = true;
}
Serial.println();
}
if (!loopFail)
{
endmS = millis(); //all packets sent, note end time
digitalWrite(LED1, LOW);
Serial.println();
LT.printModemSettings();
sendtimemS = endmS - startmS;
Serial.println();
Serial.print(F("Total transmit time "));
Serial.print(numberPackets);
Serial.print(F(" packets = "));
Serial.print(sendtimemS);
Serial.println(F("mS"));
averagePacketTime = (float) ((endmS - startmS) / numberPackets);
if (waitforACK)
{
Serial.print(F("Average "));
Serial.print(TXPacketL);
Serial.print(F(" byte packet transmit and acknowledge time = "));
}
else
{
Serial.print(F("Average "));
Serial.print(TXPacketL);
Serial.print(F(" byte packet transmit time = "));
}
Serial.print(averagePacketTime, 2);
Serial.println(F("mS"));
Serial.print(F("Packets per second "));
Serial.println((float) (1000/averagePacketTime));
bitsPerpacket = (uint32_t) (TXPacketL * 8);
Serial.print(F("Bits per packet sent = "));
Serial.println(bitsPerpacket);
Serial.print(F("Data rate = "));
Serial.print((bitsPerpacket / (averagePacketTime / 1000)), 0);
Serial.print(F("bps"));
Serial.println();
Serial.println();
delay(10000); //have a delay between loops so we can see result
}
else
{
Serial.println(F("Transmit test failed, trying again"));
Serial.println();
delay(1000);
}
}
bool waitAck(uint32_t TXnum)
{
uint32_t RXnum;
uint16_t IRQStatus;
RXPacketL = LT.receiveSXBuffer(0, 1000, WAIT_RX); //returns 0 if packet error of some sort
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F("RXTimeout,"));
return false;
}
else
{
Serial.print(F("ACKRX,"));
}
LT.startReadSXBuffer(0);
PacketType = LT.readUint8();
RXnum = LT.readUint32();
RXPacketL = LT.endReadSXBuffer();
if ( (PacketType != ACK) || (RXnum != TXnum))
{
Serial.print(F("NotValidACK,"));
return false;
}
else
{
Serial.print(RXnum, HEX);
Serial.print(F(",OK"));
return true;
}
}
void packet_is_Error()
{
//if here there was an error transmitting packet
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the the interrupt register
Serial.print(F(" SendError,"));
Serial.print(F("Length,"));
Serial.print(TXPacketL); //print transmitted packet length
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX); //print IRQ status
LT.printIrqStatus(); //prints the text of which IRQs set
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("42_LoRa_Data_Throughput_Test_Transmitter Starting"));
SPI.begin();
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
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();
Serial.print(F("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,42 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 26/03/20
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. Some pins such as DIO1,
//DIO2, BUZZER are not used by this sketch so they do not need to be connected and
//should be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup LoRa Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_500; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const int8_t TXpower = 10; //LoRa transmit power in dBm
//******* Setup packet parameters Here ! ***************
const uint8_t numberPackets = 50; //number of packets to send in transmit loop
const uint8_t TXPacketL = 16; //length of packet to send
const bool waitforACK = true; //set to true to have transmit wait for ack before continuing

View File

@@ -0,0 +1,174 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 25/03/20
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 receiver program that can be used to test the throughput of a LoRa
transmitter. The matching program '42_LoRa_Data_Throughput_Test_Transmitter' is setup to send packets
that require an acknowledgement before sending the next packet. This will slow down the effective
throughput. Make sure the lora settings in the 'Settings.h' file match those used in the transmitter.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include <ProgramLT_Definitions.h>
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
uint32_t RXpacketCount;
uint32_t errors;
uint8_t RXBUFFER[255]; //create the buffer that received packets are copied into
uint8_t RXPacketL; //stores length of packet received
uint8_t TXPacketL; //stores length of packet sent
int16_t PacketRSSI; //stores RSSI of received packet
int8_t PacketSNR; //stores signal to noise ratio (SNR) of received packet
uint8_t PacketType; //for packet addressing, identifies packet type
uint32_t packetCheck;
void loop()
{
RXPacketL = LT.receive(RXBUFFER, 255, 60000, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
digitalWrite(LED1, HIGH); //something has happened
if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL is 0
{
packet_is_Error();
}
else
{
packet_is_OK();
}
digitalWrite(LED1, LOW); //LED off
Serial.println();
}
void packet_is_OK()
{
RXpacketCount++;
Serial.print(RXBUFFER[1]);
Serial.print(F(" RX"));
packetCheck = ( (uint32_t) RXBUFFER[4] << 24) + ( (uint32_t) RXBUFFER[3] << 16) + ( (uint32_t) RXBUFFER[2] << 8 ) + (uint32_t) RXBUFFER[1];
Serial.print(F(",SendACK"));
sendAck(packetCheck);
}
void sendAck(uint32_t num)
{
//acknowledge the packet received
uint8_t len;
LT.startWriteSXBuffer(0); //initialise buffer write at address 0
LT.writeUint8(ACK); //identify type of packet
LT.writeUint32(num); //send the packet check, bytes 1 to 5 of packet
len = LT.endWriteSXBuffer(); //close buffer write
digitalWrite(LED1, HIGH);
TXPacketL = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX);
digitalWrite(LED1, LOW);
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(",RXTimeout"));
}
else
{
errors++;
PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value
Serial.print(F("Error"));
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,Len,"));
Serial.print(LT.readRXPacketL()); //get the device packet length
}
}
void printElapsedTime()
{
float seconds;
seconds = millis() / 1000;
Serial.print(seconds, 0);
Serial.print(F("s"));
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("43_LoRa_Data_Throughput_Acknowledge_Receiver Starting"));
Serial.println();
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println();
LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check
Serial.println();
Serial.println();
Serial.print(F("Receiver ready"));
Serial.println();
}

View File

@@ -0,0 +1,39 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 25/03/20
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. Some pins such as DIO1,
//DIO2, BUZZER may not be in used by this sketch so they do not need to be
//connected and should be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup LoRa Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_500; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const int8_t TXpower = 10; //LoRa transmit power in dBm

View File

@@ -0,0 +1,252 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/04/20
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 and save to SD card 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 and
the buzzer will sound, if fitted. The measured frequency difference between the frequency used by the
transmitter and the frequency used by the receiver is shown. If this frequency difference gets to 25%
of the set LoRa bandwidth, packet reception will fail. The displayed error can be reduced by using the
'offset' setting in the 'Settings.h' file.
There will be a limit to how fast the logger can receive packets, mainly caused by the delay in writing
to SD card, so at high packet rates, packets will be lost.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h>
#include <SdFat.h> //https://github.com/greiman/SdFat
SdFat SD;
File logFile;
char filename[] = "Log000.txt";
bool SD_Found = false; //set if SD card found at program startup
uint8_t lognumber;
#include <SX127XLT.h>
SX127XLT LT;
#include "Settings.h"
#include <TimeLib.h> //get the library here; https://github.com/PaulStoffregen/Time
uint32_t RXpacketCount; //count of good packets
uint32_t errors; //count of packet errors
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
uint16_t IRQStatus; //used to read the IRQ status
int32_t FreqErrror; //frequency error of received packet, in hz
time_t recordtime; //used to record the current time, preventing displayed rollover on printing
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
#include "SD_Logger_Library.h"
void loop()
{
RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 60000, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
digitalWrite(LED1, HIGH); //something has happened
recordtime = now(); //stop the time to be displayed rolling over
printtime();
printtimeSD();
PacketRSSI = LT.readPacketRSSI();
PacketSNR = LT.readPacketSNR();
FreqErrror = LT.getFrequencyErrorHz();
IRQStatus = LT.readIrqStatus();
if (RXPacketL == 0)
{
packet_is_Error();
packet_is_ErrorSD();
}
else
{
packet_is_OK();
packet_is_OKSD();
}
digitalWrite(LED1, LOW);
if (BUZZER > 0)
{
delay(50); //lets have a slightly longer beep
digitalWrite(BUZZER, LOW);
}
Serial.println();
}
void packet_is_OK()
{
RXpacketCount++;
if (BUZZER > 0)
{
digitalWrite(BUZZER, HIGH);
}
Serial.print(F(" FreqErrror,"));
Serial.print(FreqErrror);
Serial.print(F("hz "));
LT.printHEXPacket(RXBUFFER, RXPacketL);
Serial.print(F(" RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(RXPacketL);
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
}
void packet_is_Error()
{
RXPacketL = LT.readRXPacketL(); //get the real packet length
if (IRQStatus & IRQ_RX_TIMEOUT)
{
Serial.print(F(" RXTimeout"));
}
else
{
errors++;
Serial.print(F(" PacketError"));
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(RXPacketL);
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
}
}
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 printDigits(int8_t digits)
{
//utility function for digital clock display: prints preceding colon and leading 0
Serial.print(F(":"));
if (digits < 10)
Serial.print('0');
Serial.print(digits);
}
void printtime()
{
Serial.print(hour(recordtime));
printDigits(minute(recordtime));
printDigits(second(recordtime));
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("60_LoRa_Packet_Logger_Receiver_SD Starting"));
Serial.println();
if (BUZZER > 0)
{
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
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, DIO0, LORA_DEVICE))
{
Serial.println(F("lora device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50);
}
}
lognumber = setup_SDLOG() ; //setup SD card
Serial.print(F("Lognumber "));
Serial.println(lognumber);
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println();
LT.printModemSettings();
Serial.println();
printModemSettingsSD();
logFile.println();
LT.printOperatingSettings();
Serial.println();
printOperatingSettingsSD();
logFile.println();
printtime();
Serial.print(F("Receiver ready"));
Serial.println();
}

View File

@@ -0,0 +1,410 @@
//SD_Logger_Library.h
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/04/20
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.
*******************************************************************************************************/
void printModemSettingsSD();
void printOperatingSettingsSD();
void printOperatingModeSD(uint8_t opmode);
uint8_t setup_SDLOG();
void printDeviceSD();
void printSXBufferHEXSD(uint8_t start, uint8_t end);
void printHEXByteSD(uint8_t temp);
void packet_is_OKSD();
void packet_is_ErrorSD();
void printDigitsSD(int8_t digits);
void printtimeSD();
void printModemSettingsSD()
{
uint8_t regdata;
uint8_t sf;
uint32_t bandwidth;
uint8_t cr;
uint8_t opt;
uint16_t syncword;
uint8_t invertIQ;
uint16_t preamble;
uint32_t freqint;
if (LORA_DEVICE == DEVICE_SX1272)
{
regdata = (LT.readRegister(REG_MODEMCONFIG1) & READ_BW_AND_2);
}
else
{
regdata = (LT.readRegister(REG_MODEMCONFIG1) & READ_BW_AND_X);
}
//get al the data frome the lora device in one go to avoid swapping
//devices on the SPI bus all the time
if (LORA_DEVICE == DEVICE_SX1272)
{
regdata = (LT.readRegister(REG_MODEMCONFIG1) & READ_BW_AND_2);
}
else
{
regdata = (LT.readRegister(REG_MODEMCONFIG1) & READ_BW_AND_X);
}
bandwidth = LT.returnBandwidth(regdata);
freqint = LT.getFreqInt();
sf = LT.getLoRaSF();
cr = LT.getLoRaCodingRate();
opt = LT.getOptimisation();
syncword = LT.getSyncWord();
invertIQ = LT.getInvertIQ();
preamble = LT.getPreamble();
printDeviceSD();
logFile.print(F(","));
logFile.print(freqint);
logFile.print(F("hz,SF"));
logFile.print(sf);
logFile.print(F(",BW"));
logFile.print(bandwidth);
logFile.print(F(",CR4:"));
logFile.print(cr);
logFile.print(F(",LDRO_"));
if (opt)
{
logFile.print(F("On"));
}
else
{
logFile.print(F("Off"));
}
logFile.print(F(",SyncWord_0x"));
logFile.print(syncword, HEX);
if (invertIQ == LORA_IQ_INVERTED)
{
logFile.print(F(",IQInverted"));
}
else
{
logFile.print(F(",IQNormal"));
}
logFile.print(F(",Preamble_"));
logFile.print(preamble);
logFile.flush();
}
void printOperatingSettingsSD()
{
//get al the data frome the lora device in one go to avoid swapping
//devices on the SPI bus all the time
uint8_t ver = LT.getVersion();
uint8_t pm = LT.getPacketMode();
uint8_t hm = LT.getHeaderMode();
uint8_t crcm = LT.getCRCMode();
uint8_t agc = LT.getAGC();
uint8_t lnag = LT.getLNAgain();
uint8_t boosthf = LT.getLNAboostHF();
uint8_t boostlf = LT.getLNAboostLF();
uint8_t opmode = LT.getOpmode();
printDeviceSD();
logFile.print(F(","));
printOperatingModeSD(opmode);
logFile.print(F(",Version_"));
logFile.print(ver, HEX);
logFile.print(F(",PacketMode_"));
if (pm)
{
logFile.print(F("LoRa"));
}
else
{
logFile.print(F("FSK"));
}
if (hm)
{
logFile.print(F(",Implicit"));
}
else
{
logFile.print(F(",Explicit"));
}
logFile.print(F(",CRC_"));
if (crcm)
{
logFile.print(F("On"));
}
else
{
logFile.print(F("Off"));
}
logFile.print(F(",AGCauto_"));
if (agc)
{
logFile.print(F("On"));
}
else
{
logFile.print(F("Off"));
}
logFile.print(F(",LNAgain_"));
logFile.print(lnag);
logFile.print(F(",LNAboostHF_"));
if (boosthf)
{
logFile.print(F("On"));
}
else
{
logFile.print(F("Off"));
}
logFile.print(F(",LNAboostLF_"));
if (boostlf)
{
logFile.print(F("On"));
}
else
{
logFile.print(F("Off"));
}
logFile.flush();
}
void printOperatingModeSD(uint8_t opmode)
{
switch (opmode)
{
case 0:
logFile.print(F("SLEEP"));
break;
case 1:
logFile.print(F("STDBY"));
break;
case 2:
logFile.print(F("FSTX"));
break;
case 3:
logFile.print(F("TX"));
break;
case 4:
logFile.print(F("FSRX"));
break;
case 5:
logFile.print(F("RXCONTINUOUS"));
break;
case 6:
logFile.print(F("RXSINGLE"));
break;
case 7:
logFile.print(F("CAD"));
break;
default:
logFile.print(F("NOIDEA"));
break;
}
}
uint8_t setup_SDLOG()
{
//checks if the SD card is present and can be initialised
//returns log number, 1-99, if OK, 0 if not
uint8_t i;
Serial.print(F("SD card..."));
if (!SD.begin(SDCS))
{
Serial.println(F("ERROR SD card fail"));
Serial.println();
SD_Found = false;
return 0;
}
Serial.print(F("Initialized OK - "));
SD_Found = true;
for (i = 1; i < 100; i++) {
filename[4] = i / 10 + '0';
filename[5] = i % 10 + '0';
if (! SD.exists(filename)) {
// only open a new file if it doesn't exist
logFile = SD.open(filename, FILE_WRITE);
break;
}
}
Serial.print(F("Writing to "));
Serial.println(filename);
return i;
}
void printDeviceSD()
{
switch (LORA_DEVICE)
{
case DEVICE_SX1272:
logFile.print(F("SX1272"));
break;
case DEVICE_SX1276:
logFile.print(F("SX1276"));
break;
case DEVICE_SX1277:
logFile.print(F("SX1277"));
break;
case DEVICE_SX1278:
logFile.print(F("SX1278"));
break;
case DEVICE_SX1279:
logFile.print(F("SX1279"));
break;
default:
logFile.print(F("Unknown Device"));
}
}
void printHEXPacketSD(uint8_t *buffer, uint8_t size)
{
uint8_t index;
for (index = 0; index < size; index++)
{
printHEXByteSD(buffer[index]);
logFile.print(F(" "));
}
}
void printHEXByteSD(uint8_t temp)
{
if (temp < 0x10)
{
logFile.print(F("0"));
}
logFile.print(temp, HEX);
}
void packet_is_OKSD()
{
//uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus();
if (BUZZER > 0)
{
digitalWrite(BUZZER, HIGH);
}
logFile.print(F(" FreqErrror,"));
logFile.print(LT.getFrequencyErrorHz());
logFile.print(F("hz "));
printHEXPacketSD(RXBUFFER, RXPacketL);
logFile.print(F(" RSSI,"));
logFile.print(PacketRSSI);
logFile.print(F("dBm,SNR,"));
logFile.print(PacketSNR);
logFile.print(F("dB,Length,"));
logFile.print(RXPacketL);
logFile.print(F(",Packets,"));
logFile.print(RXpacketCount);
logFile.print(F(",Errors,"));
logFile.print(errors);
logFile.print(F(",IRQreg,"));
logFile.println(IRQStatus, HEX);
logFile.flush();
}
void packet_is_ErrorSD()
{
//uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //get the IRQ status
RXPacketL = LT.readRXPacketL(); //get the real packet length
if (IRQStatus & IRQ_RX_TIMEOUT)
{
logFile.print(F(" RXTimeout"));
}
else
{
logFile.print(F(" PacketError"));
logFile.print(F(",RSSI,"));
logFile.print(PacketRSSI);
logFile.print(F("dBm,SNR,"));
logFile.print(PacketSNR);
logFile.print(F("dB,Length,"));
logFile.print(RXPacketL);
logFile.print(F(",Packets,"));
logFile.print(RXpacketCount);
logFile.print(F(",Errors,"));
logFile.print(errors);
logFile.print(F(",IRQreg,"));
logFile.println(IRQStatus, HEX);
}
logFile.flush();
}
void printDigitsSD(int8_t digits)
{
//utility function for digital clock display: prints preceding colon and leading 0
logFile.print(F(":"));
if (digits < 10)
logFile.print('0');
logFile.print(digits);
}
void printtimeSD()
{
logFile.print(hour(recordtime));
printDigitsSD(minute(recordtime));
printDigitsSD(second(recordtime));
}

View File

@@ -0,0 +1,41 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/04/20
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, An ATmeag1284P base for my BBF modules.
//Be sure to change the definitions to match your own setup. Some pins such as DIO1, DIO210 BUZZER may not
//be in used by this sketch so they do not need to be connected and should be included and be set to -1.
#define NSS 10 //select on LoRa device
#define NRESET 9 //reset on LoRa device
#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1
#define LED1 8 //On board LED, high for on
#define BUZZER 4 //Buzzer if fitted, high for on. Set to -1 if not used
#define SDCS 30 //CS pin for SD card
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 10; //LoRa TX power
#define packet_delay 1000 //mS delay between packets
#define RXBUFFER_SIZE 255 //RX buffer size

View File

@@ -0,0 +1,98 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 23/02/20
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 - Transmits an FSK carrier on a single frequency. Useful for checking the output
of a LoRa device. View the output level on a low cost SDR or spectrum analyser.
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
void loop()
{
Serial.print(TXpower); //print the transmit power defined
Serial.print(F("dBm "));
digitalWrite(LED1, HIGH);
Serial.print(F("Transmit Carrier > On "));
LT.setupDirect(Frequency, Offset);
LT.fskCarrierOn(TXpower);
delay(2000);
LT.fskCarrierOff();
digitalWrite(LED1, LOW);
Serial.println(F("off"));
delay(1000);
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("66_FSK_Carrier_Generator 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));
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
//LT.setupDirect(Frequency, Offset);
//Serial.print(F("Transmitter ready"));
//Serial.println();
}

View File

@@ -0,0 +1,28 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 23/02/20
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. Some pins such as DIO1,
//DIO2 are not used by this particular sketch so they are set to -1 and not connected.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup Direct Modem Parameters Here ! ***************
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const int8_t TXpower = 2; //LoRa transmit power in dBm

View File

@@ -0,0 +1,63 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 20/01/19
This programs is supplied as is, it is up to the user of the program to decide if the programs are
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This program blinks an LED connected the pin number defined below. The blinks
should be close to one per second. messages are sent to the Serial Monitor also.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define LED1 2 //pin number for LED, set logic level high for on
#define Program_Version "V1.0"
uint16_t seconds; //used to display time elapsed on Serial Monitor
void loop()
{
Serial.print(seconds);
Serial.println(F(" Seconds")); //this message should print on console at close to once per second
seconds++;
digitalWrite(LED1, HIGH);
delay(100);
digitalWrite(LED1, LOW);
delay(890); //should give approx 1 second flash
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
//general purpose routine for flashing LED as indicator
uint16_t index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH); //LED on
delay(delaymS);
digitalWrite(LED1, LOW); //LED off
delay(delaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("1_LED_Blink_ESP32 Starting"));
}

View File

@@ -0,0 +1,300 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 20/01/20
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 program is stand alone, it is not necessary to install the SX12XX-LoRa library
to use it.
The program checks that a SX127X LoRa device can be accessed by doing a test register write and read.
If there is no device found a message is printed on the serial monitor. The contents of the registers
from 0x00 to 0x7F are printed, there is a copy of a typical printout below. Note that the read back
changed frequency may be slightly different to the programmed frequency, there is a rounding error due
to the use of floats to calculate the frequency.
The Arduino pin numbers that the NSS and NRESET pins on the LoRa device are connected to must be
specified in the hardware definitions section below. The LoRa device type in use, SX1272, SX1276,
SX1277, SX1278 or SX1279 must be specified also.
Typical printout;
2_Register_Test Starting
SX1276-79 Selected
LoRa Device found
Device version 0x12
Frequency at reset 434000000
Registers at reset
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00 00 09 1A 0B 00 52 6C 80 00 4F 09 2B 20 08 02 0A
0x10 FF 6F 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40
0x20 00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55
0x30 90 40 40 00 00 0F 00 00 00 F5 20 82 00 02 80 40
0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B
0x50 14 00 00 12 00 00 00 0F E0 00 0C 00 08 00 5C 78
0x60 00 19 0C 4B CC 0F 01 20 04 47 AF 3F CF 00 53 0B
0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00
Changed Frequency 434099968
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00 00 09 1A 0B 00 52 6C 86 66 4F 09 2B 20 08 02 0A
0x10 FF 6F 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40
0x20 00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55
0x30 90 40 40 00 00 0F 00 00 00 F5 20 82 00 02 80 40
0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B
0x50 14 00 00 12 00 00 00 0F E0 00 0C 00 08 00 5C 78
0x60 00 19 0C 4B CC 0F 01 20 04 47 AF 3F CF 00 53 0B
0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
const uint8_t REG_FRMSB = 0x06; //register number for setting setting and reading frequency, high byte
const uint8_t REG_FRMID = 0x07; //register number for setting setting and reading frequency, mid byte
const uint8_t REG_FRLSB = 0x08; //register number for setting setting and reading frequency, low byte
const uint8_t REG_VERSION = 0x42; //register containg version number of device
const uint8_t DEVICE_SX1272 = 0x10; //SX1272
const uint8_t DEVICE_SX1276 = 0x11; //SX1276
const uint8_t DEVICE_SX1277 = 0x12; //SX1277
const uint8_t DEVICE_SX1278 = 0x13; //SX1278
const uint8_t DEVICE_SX1279 = 0x14; //SX1279
//********* Setup hardware definitions here ! *****************
//These are the pin definitions for one of the Tracker boards, the ESP32_Micro_Node, be sure to change
//them to match your own setup. You will also need to connect up the pins for the SPI bus, which on the
//ESP32_Micro_Node are SCK on pin 18, MISO on pin 19 and MOSI on pin 23.
#define NSS 5 //SX127X device select
#define NRESET 27 //SX127X reset pin
#define DIO0 -1 //DIO0 pin on LoRa device, not used here so set to -1
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define LORA_DEVICE DEVICE_SX1278 //defines the type of LoRa device used, needed for correct program operation
//**************************************************************/
#include <SPI.h>
void setup()
{
Serial.begin(9600);
Serial.println(F("2_Register_Test_ESP32 Starting"));
SPI.begin();
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
//The begin function setups the hardware pins used by device and then checks if device is found
//the DIO0, DIO1 and DIO2 pins are not used in this example so are set to -1
//the LT.begin fuction can define the pins and device type directly in this way (for SX1278);
//LT.begin(10, 9, -1, -1, -1, DEVICE_SX1278)
if (begin(NSS, NRESET, -1, -1, -1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
}
else
{
Serial.println(F("No device responding"));
}
Serial.print(F("Device version 0x"));
uint8_t deviceversion = readRegister(REG_VERSION);
if (deviceversion < 0x10)
{
Serial.print(F("0"));
}
Serial.println(deviceversion, HEX);
}
void loop()
{
uint32_t frequency;
frequency = getFreqInt(); //read the set frequency following a reset
Serial.print(F("Frequency at reset "));
Serial.println(frequency);
Serial.println(F("Registers at reset")); //show the all registers following a reset
printRegisters(0x00, 0x7F);
Serial.println();
Serial.println();
setRfFrequency(434100000, 0); //change the frequency at reset, in hertz
frequency = getFreqInt(); //read back the changed frequency
Serial.print(F("Changed Frequency "));
Serial.println(frequency); //print the changed frequency, did the write work (allow for rounding errors) ?
printRegisters(0x00, 0x7F); //show the registers after frequency change
Serial.println();
delay(5000);
resetDevice(LORA_DEVICE); //reset the device and start again
}
uint8_t readRegister(uint8_t address)
{
uint8_t regdata;
digitalWrite(NSS, LOW); //set NSS low
SPI.transfer(address & 0x7F); //mask address for read
regdata = SPI.transfer(0); //read the byte
digitalWrite(NSS, HIGH); //set NSS high
return regdata;
}
void writeRegister(uint8_t address, uint8_t value)
{
digitalWrite(NSS, LOW); //set NSS low
SPI.transfer(address | 0x80); //mask address for write
SPI.transfer(value); //write the byte
digitalWrite(NSS, HIGH); //set NSS high
}
uint32_t getFreqInt()
{
//get the current set LoRa device frequency, return as long integer
uint8_t Msb, Mid, Lsb;
uint32_t uinttemp;
float floattemp;
Msb = readRegister(REG_FRMSB);
Mid = readRegister(REG_FRMID);
Lsb = readRegister(REG_FRLSB);
floattemp = ((Msb * 0x10000ul) + (Mid * 0x100ul) + Lsb);
floattemp = ((floattemp * 61.03515625) / 1000000ul);
uinttemp = (uint32_t)(floattemp * 1000000);
return uinttemp;
}
void printRegisters(uint16_t Start, uint16_t End)
{
//prints the contents of SX127x registers to serial monitor
uint16_t Loopv1, Loopv2, RegData;
Serial.print(F("Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F"));
Serial.println();
for (Loopv1 = Start; Loopv1 <= End;)
{
Serial.print(F("0x"));
if (Loopv1 < 0x10)
{
Serial.print(F("0"));
}
Serial.print((Loopv1), HEX);
Serial.print(F(" "));
for (Loopv2 = 0; Loopv2 <= 15; Loopv2++)
{
RegData = readRegister(Loopv1);
if (RegData < 0x10)
{
Serial.print(F("0"));
}
Serial.print(RegData, HEX);
Serial.print(F(" "));
Loopv1++;
}
Serial.println();
}
}
void setRfFrequency(uint64_t freq64, int32_t offset)
{
freq64 = freq64 + offset;
freq64 = ((uint64_t)freq64 << 19) / 32000000;
writeRegister(REG_FRMSB, (uint8_t)(freq64 >> 16));
writeRegister(REG_FRMID, (uint8_t)(freq64 >> 8));
writeRegister(REG_FRLSB, (uint8_t)(freq64 >> 0));
}
void resetDevice(uint8_t device)
{
if (device == DEVICE_SX1272)
{
digitalWrite(NRESET, HIGH);
delay(2);
digitalWrite(NRESET, LOW);
delay(20);
Serial.println(F("SX1272 Selected"));
}
else
{
digitalWrite(NRESET, LOW);
delay(2);
digitalWrite(NRESET, HIGH);
delay(20);
Serial.println(F("SX1276-79 Selected"));
}
}
bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinDIO0, int8_t pinDIO1, int8_t pinDIO2, uint8_t device)
{
pinMode(pinNSS, OUTPUT);
digitalWrite(pinNSS, HIGH);
pinMode(pinNRESET, OUTPUT);
digitalWrite(pinNRESET, LOW);
if (pinDIO0 >= 0)
{
pinMode( pinDIO0, INPUT);
}
if (pinDIO1 >= 0)
{
pinMode( pinDIO1, INPUT);
}
if (pinDIO2 >= 0)
{
pinMode( pinDIO2, INPUT);
}
resetDevice(device);
if (checkDevice())
{
return true;
}
return false;
}
bool checkDevice()
{
//check there is a device out there, writes a register and reads back
uint8_t Regdata1, Regdata2;
Regdata1 = readRegister(REG_FRMID); //low byte of frequency setting
writeRegister(REG_FRMID, (Regdata1 + 1));
Regdata2 = readRegister(REG_FRMID); //read changed value back
writeRegister(REG_FRMID, Regdata1); //restore register to original value
if (Regdata2 == (Regdata1 + 1))
{
return true;
}
else
{
return false;
}
}

View File

@@ -0,0 +1,193 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 20/01/20
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 LoRa test transmitter for an ESP32 device. A packet containing
ASCII text is sent according to the frequency and LoRa settings specified in the 'Settings.h' file.
The pins to access the SX127X need to be defined in the 'Settings.h' file also.
The program also has the option of using a logic pin to control the power to the lora and SD card
devices, which can save power in sleep mode. If the hardware is fitted to your board these devices are
powered on by setting the VCCPOWER pin low. If your board does not have this feature set VCCPOWER to -1.
The details of the packet sent and any errors are shown on the Serial Monitor, together with the transmit
power used, the packet length and the CRC of the packet. The matching receive program, '4_LoRa_Receive'
can be used to check the packets are being sent correctly, the frequency and LoRa settings (in Settings.h)
must be the same for the Transmit and Receive program. Sample Serial Monitor output;
10dBm Packet> {packet contents*} BytesSent,23 CRC,DAAB TransmitTime,54mS PacketsSent,1
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the SX127X device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
uint8_t TXPacketL;
uint32_t TXPacketCount, startmS, endmS;
uint8_t buff[] = "Hello World 1234567890";
void loop()
{
Serial.print(TXpower); //print the transmit power defined
Serial.print(F("dBm "));
Serial.print(F("Packet> "));
Serial.flush();
TXPacketL = sizeof(buff); //set TXPacketL to length of array
buff[TXPacketL - 1] = '*'; //replace null character at buffer end so its visible on reciver
LT.printASCIIPacket(buff, TXPacketL); //print the buffer (the sent packet) as ASCII
digitalWrite(LED1, HIGH);
startmS = millis(); //start transmit timer
if (LT.transmit(buff, TXPacketL, 5000, TXpower, WAIT_TX)) //will return packet length sent if OK, otherwise 0 if transmit error
{
endmS = millis(); //packet sent, note end time
TXPacketCount++;
packet_is_OK();
}
else
{
packet_is_Error(); //transmit packet returned 0, there was an error
}
digitalWrite(LED1, LOW);
Serial.println();
delay(packet_delay); //have a delay between packets
}
void packet_is_OK()
{
//if here packet has been sent OK
uint16_t localCRC;
Serial.print(F(" BytesSent,"));
Serial.print(TXPacketL); //print transmitted packet length
localCRC = LT.CRCCCITT(buff, TXPacketL, 0xFFFF);
Serial.print(F(" CRC,"));
Serial.print(localCRC, HEX); //print CRC of sent packet
Serial.print(F(" TransmitTime,"));
Serial.print(endmS - startmS); //print transmit time of packet
Serial.print(F("mS"));
Serial.print(F(" PacketsSent,"));
Serial.print(TXPacketCount); //print total of packets sent OK
}
void packet_is_Error()
{
//if here there was an error transmitting packet
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the the interrupt register
Serial.print(F(" SendError,"));
Serial.print(F("Length,"));
Serial.print(TXPacketL); //print transmitted packet length
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX); //print IRQ status
LT.printIrqStatus(); //prints the text of which IRQs set
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
if (VCCPOWER >= 0)
{
pinMode(VCCPOWER, OUTPUT); //For controlling power to external devices
digitalWrite(VCCPOWER, LOW); //VCCOUT on. lora device on
}
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("3_LoRa_Transmitter_ESP32 Starting"));
//SPI.begin(); //default setup can be used be used
SPI.begin(SCK, MISO, MOSI, NSS); //alternative format for SPI3, VSPI; SPI.begin(SCK,MISO,MOSI,SS)
//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));
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
//The function call list below shows the complete setup for the LoRa device using the information defined in the
//Settings.h file.
//The 'Setup LoRa device' list below can be replaced with a single function call;
//LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
//***************************************************************************************************
//Setup LoRa device
//***************************************************************************************************
LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device
LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions
LT.setRfFrequency(Frequency, Offset); //set the operating frequency
LT.calibrateImage(0); //run calibration after setting frequency
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters
LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX
LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34
LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current
LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on RX done
//***************************************************************************************************
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(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F
Serial.println();
Serial.println();
Serial.print(F("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,44 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 20/01/20
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 the Tracker boards, the ESP32_Micro_Node, be sure to change
//them to match your own setup. You will also need to connect up the pins for the SPI bus, which on the
//ESP32_Micro_Node are SCK on pin 18, MISO on pin 19 and MOSI on pin 23. Some pins such as DIO1, DIO2 and
//BUZZER may not be in used by this sketch so they do not need to be connected and should be set to -1.
#define NSS 5 //select pin on LoRa device
#define SCK 18 //SCK on SPI3
#define MISO 19 //MISO on SPI3
#define MOSI 23 //MOSI on SPI3
#define NRESET 27 //reset pin on LoRa device
#define LED1 2 //on board LED, high for on
#define DIO0 35 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define VCCPOWER 14 //pin controls power to external devices
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup LoRa Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const int8_t TXpower = 10; //LoRa transmit power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets

View File

@@ -0,0 +1,258 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 20/02/20
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 SX127X need to be defined in the 'Settings.h' file also.
The program also has the option of using a logic pin to control the power to the lora and SD card
devices, which can save power in sleep mode. If the hardware is fitted to your board these devices are
powered on by setting the VCCPOWER pin low. If your board does not have this feature set VCCPOWER to -1.
There is a printout of the valid packets received, the packet is assumed to be in ASCII printable text,
if its not ASCII text characters from 0x20 to 0x7F, expect weird things to happen on the Serial Monitor.
The LED will flash for each packet received and the buzzer will sound, if fitted.
Sample serial monitor output;
1109s Hello World 1234567890*,CRC,DAAB,RSSI,-61dBm,SNR,9dB,Length,23,Packets,1026,Errors,0,IRQreg,50
If there is a packet error it might look like this, which is showing a CRC error,
1189s PacketError,RSSI,-111dBm,SNR,-12dB,Length,0,Packets,1126,Errors,1,IRQreg,70,IRQ_HEADER_VALID,IRQ_CRC_ERROR,IRQ_RX_DONE
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the SX127X device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
uint32_t RXpacketCount;
uint32_t errors;
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
uint8_t RXPacketL; //stores length of packet received
int8_t PacketRSSI; //stores RSSI of received packet
int8_t PacketSNR; //stores signal to noise ratio of received packet
void loop()
{
RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 60000, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
digitalWrite(LED1, HIGH); //something has happened
if (BUZZER > 0) //turn buzzer on
{
digitalWrite(BUZZER, HIGH);
}
PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value
PacketSNR = LT.readPacketSNR(); //read the received SNR value
if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL == 0
{
packet_is_Error();
}
else
{
packet_is_OK();
}
if (BUZZER > 0)
{
digitalWrite(BUZZER, LOW); //buzzer off
}
digitalWrite(LED1, LOW); //LED off
Serial.println();
}
void packet_is_OK()
{
uint16_t IRQStatus, localCRC;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
RXpacketCount++;
printElapsedTime(); //print elapsed time to Serial Monitor
Serial.print(F(" "));
LT.printASCIIPacket(RXBUFFER, RXPacketL); //print the packet as ASCII characters
localCRC = LT.CRCCCITT(RXBUFFER, RXPacketL, 0xFFFF); //calculate the CRC, this is the external CRC calculation of the RXBUFFER
Serial.print(F(",CRC,")); //contents, not the LoRa device internal CRC
Serial.print(localCRC, HEX);
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(RXPacketL);
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
printElapsedTime(); //print elapsed time to Serial Monitor
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout"));
}
else
{
errors++;
Serial.print(F(" PacketError"));
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL()); //get the real packet length
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus(); //print the names of the IRQ registers set
}
delay(250); //gives a longer buzzer and LED flash for error
}
void printElapsedTime()
{
float seconds;
seconds = millis() / 1000;
Serial.print(seconds, 0);
Serial.print(F("s"));
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
if (VCCPOWER >= 0)
{
pinMode(VCCPOWER, OUTPUT); //For controlling power to external devices
digitalWrite(VCCPOWER, LOW); //VCCOUT on. lora device on
}
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("4_LoRa_Receiver_ESP32 Starting"));
Serial.println();
if (BUZZER > 0)
{
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
//SPI.begin(); //default setup can be used be used
SPI.begin(SCK, MISO, MOSI, NSS); //alternative format for SPI3, VSPI; SPI.begin(SCK,MISO,MOSI,SS)
//SPI beginTranscation is normally part of library routines, but if it is disabled in the library
//a single instance is needed here, so uncomment the program line below
//SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
//The function call list below shows the complete setup for the LoRa device using the information defined in the
//Settings.h file.
//The 'Setup LoRa device' list below can be replaced with a single function call;
//LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
//***************************************************************************************************
//Setup LoRa device
//***************************************************************************************************
LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device
LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions
LT.setRfFrequency(Frequency, Offset); //set the operating frequency
LT.calibrateImage(0); //run calibration after setting frequency
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters
LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX
LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34
LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current
LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_RX_DONE, 0, 0); //set for IRQ on RX done
//***************************************************************************************************
Serial.println();
LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check
Serial.println();
LT.printOperatingSettings(); //reads and prints the configured operting settings, useful check
Serial.println();
Serial.println();
LT.printRegisters(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F
Serial.println();
Serial.println();
Serial.print(F("Receiver ready - RXBUFFER_SIZE "));
Serial.println(RXBUFFER_SIZE);
Serial.println();
}

View File

@@ -0,0 +1,49 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 15/01/20
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 the Tracker boards, the ESP32_Micro_Node, be sure to change
//them to match your own setup. You will also need to connect up the pins for the SPI bus, which on the
//ESP32_Micro_Node are SCK on pin 18, MISO on pin 19 and MOSI on pin 23. Some pins such as DIO1, DIO2 and
//BUZZER may not be in used by this sketch so they do not need to be connected and should be set to -1.
#define NSS 5 //select pin on LoRa device
#define SCK 18 //SCK on SPI3
#define MISO 19 //MISO on SPI3
#define MOSI 23 //MOSI on SPI3
#define NRESET 27 //reset pin on LoRa device
#define RFBUSY 25 //busy line
#define LED1 2 //on board LED, high for on
#define DIO0 35 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define BUZZER -1 //pin for buzzer, set to -1 if not used
#define VCCPOWER 14 //pin controls power to external devices
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup LoRa Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const int8_t TXpower = 10; //LoRa transmit power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets
#define RXBUFFER_SIZE 32 //RX buffer size

View File

@@ -0,0 +1,277 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 26/03/20
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 program that can be used to test the throughput of a LoRa transmitter.
Whilst the various LoRa calculators tell you the on air data rate, in practice the achievable data
rate will be less than that due to the overhead of the software routines to load and send a packet
and internal delays in the LoRa device itself.
A buffer is filled with characters and that buffer is then transmitted. The total time for a number of
transmissions is recorded and the bit rate calculated. The packet size (1 - 255 bytes) and the number of
packets to send in the test are specified in the 'Settings.h' file, see the 'Setup packet parameters Here !'
section. The setting file also has the lora settings to use. A lower spreading factors and higher
bandwidths will result in higher bitrates.
There is the option of turning on an a requirement for an acknowledgement from a remote receiver, before
the transmitter sends the next packet, set this; 'const bool waitforACK = true;' definition in the
settings file.
The results of the test are printed out thus;
SX1278,434000000hz,SF7,BW500000,CR4:5,LDRO_Off,SyncWord_0x12,IQNormal,Preamble_8
Total Transmit time 50 packets = 567mS
Average 10 byte packet transmit time = 11.34mS
Bits per packet sent = 80
Data rate = 7055bps
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include <ProgramLT_Definitions.h>
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
uint32_t startmS, endmS, sendtimemS, bitspersecond, bitsPerpacket;
uint32_t TXPacketCount;
float averagePacketTime;
uint8_t packetNumber;
uint8_t RXPacketL; //length of received packet
uint8_t PacketType; //for packet addressing, identifies packet type received
uint32_t packetCheck;
bool loopFail = false;
void loop()
{
uint16_t index, index2;
uint8_t TXBUFFER[TXPacketL + 1]; //create buffer for transmitted packet
loopFail = false;
Serial.println(F("Start transmit test"));
startmS = millis(); //start transmit timer
for (index = 0; index < numberPackets; index++)
{
//fill the buffer
for (index2 = 0; index2 < TXPacketL; index2++)
{
TXBUFFER[index2] = index2;
}
TXBUFFER[0] = TestPacket; //set first byte to identify this test packet
TXBUFFER[1] = index; //put the index as packet number in second byte of packet
Serial.print(index); //print number of packet sent
if (waitforACK)
{
packetCheck = ( (uint32_t) TXBUFFER[4] << 24) + ( (uint32_t) TXBUFFER[3] << 16) + ( (uint32_t) TXBUFFER[2] << 8) + (uint32_t) TXBUFFER[1];
Serial.print(F(",Checkvalue,"));
Serial.print(packetCheck, HEX);
Serial.print(F(","));
}
digitalWrite(LED1, HIGH);
if (LT.transmit(TXBUFFER, TXPacketL, 2000, TXpower, WAIT_TX)) //will return 0 if transmit error
{
digitalWrite(LED1, LOW);
if (waitforACK)
{
if (!waitAck(packetCheck))
{
Serial.print(F("NoACKreceived,"));
loopFail = true;
break;
}
}
}
else
{
packet_is_Error(); //transmit packet returned 0, there was an error
loopFail = true;
}
Serial.println();
}
if (!loopFail)
{
endmS = millis(); //all packets sent, note end time
digitalWrite(LED1, LOW);
Serial.println();
LT.printModemSettings();
sendtimemS = endmS - startmS;
Serial.println();
Serial.print(F("Total transmit time "));
Serial.print(numberPackets);
Serial.print(F(" packets = "));
Serial.print(sendtimemS);
Serial.println(F("mS"));
averagePacketTime = (float) (endmS - startmS) / numberPackets;
if (waitforACK)
{
Serial.print(F("Average "));
Serial.print(TXPacketL);
Serial.print(F(" byte packet transmit and acknowledge time = "));
}
else
{
Serial.print(F("Average "));
Serial.print(TXPacketL);
Serial.print(F(" byte packet transmit time = "));
}
Serial.print(averagePacketTime, 2);
Serial.println(F("mS"));
bitsPerpacket = (uint32_t) (TXPacketL * 8);
Serial.print(F("Bits per packet sent = "));
Serial.println(bitsPerpacket);
Serial.print(F("Data rate = "));
Serial.print((bitsPerpacket / (averagePacketTime / 1000)), 0);
Serial.print(F("bps"));
Serial.println();
Serial.println();
delay(10000); //have a delay between loops so we can see result
}
else
{
Serial.println(F("Transmit test failed, trying again"));
Serial.println();
delay(1000);
}
}
bool waitAck(uint32_t TXnum)
{
uint32_t RXnum;
uint16_t IRQStatus;
RXPacketL = LT.receiveSXBuffer(0, 1000, WAIT_RX); //returns 0 if packet error of some sort
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F("RXTimeout,"));
return false;
}
else
{
Serial.print(F("ACKRX,"));
}
LT.startReadSXBuffer(0);
PacketType = LT.readUint8();
RXnum = LT.readUint32();
RXPacketL = LT.endReadSXBuffer();
if ( (PacketType != ACK) || (RXnum != TXnum))
{
Serial.print(F("NotValidACK,"));
return false;
}
else
{
Serial.print(RXnum, HEX);
Serial.print(F(",OK"));
return true;
}
}
void packet_is_Error()
{
//if here there was an error transmitting packet
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the the interrupt register
Serial.print(F(" SendError,"));
Serial.print(F("Length,"));
Serial.print(TXPacketL); //print transmitted packet length
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX); //print IRQ status
LT.printIrqStatus(); //prints the text of which IRQs set
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("42_LoRa_Data_Throughput_Transmitter_Test_ESP32 Starting"));
SPI.begin();
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
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();
Serial.print(F("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,46 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 26/03/20
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 an ESP32 shield base.
#define SCK 18 //SCK on SPI3
#define MISO 19 //MISO on SPI3
#define MOSI 23 //MOSI on SPI3
#define NSS 5 //select pin on LoRa device
#define NRESET 27 //reset pin on LoRa device
#define RFBUSY 25 //busy line
#define DIO1 35 //DIO1 pin on LoRa device, used for RX and TX done
#define LED1 2 //on board LED, high for on
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup LoRa Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_500; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const int8_t TXpower = 14; //LoRa transmit power in dBm
//******* Setup packet parameters Here ! ***************
const uint8_t numberPackets = 100; //number of packets to send in transmit loop
const uint8_t TXPacketL = 255; //length of packet to send
const bool waitforACK = false; //set to true to have transmit wait for ack before continuing

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

View File

@@ -0,0 +1,111 @@
## ESP32 - SX12XX Library Example Programs
Having originally tested the SX127X part of the library on a ATMega328P based micro controller I decided to check that the library was code compatible with another popular processor that can be programmed in the Arduino IDE, the ESP32.
Unfortunately there is frequently a misunderstanding about what an 'ESP32' is. The ESP32 is a single surface mountable module to which you need to add various components to make a usable board. However the many different types of 'ESP32' boards may use different types of components and connections which could conflict with the pins used in the library examples here. It is not practical to test the examples on all possible permutations of 'ESP32' assembled boards, there are over 60 different boards supported by the Arduino IDE and I would go poor buying them all.
Thus the ESP32 examples presented here have been tested against a known standard which is an actual ESP32 Wroom module with no additional hardware, apart from the components shown in the schematic below. It is possible that the examples will not work against your particular 'ESP32' assembled board. If the example programs do not work for you, it is not an issue with the library but a difference between the reference hardware and your particular setup. I am not in a position to assist in resolving issues with particular ESP32 board versions.
![Picture 1](/pictures/ESP32_Bare_Bones_Schematic.jpg)
As well as testing against the bare bones ESP32 schematic shown above, some of the examples will have been tested on a small portable unit I built which follows the same principles of the bare bones schematic. This PCB was developed to create a PCB that could be used for a small ESP32 based GPS tracker node, initially for use on The Things Network. The board has a GPS, I2C SSD1306 OLED and RFM98 lora device. There are options for a micro SD card, DS18B20 temperature sensor and a I2C FRAM. With it all assembled, the node consumes around 31uA in deep sleep with all devices connected. The 'Micro\_Node' contains additional circuitry to power off devices such as the lora module and GPS. Its highly unlikely that a standard ESP32 board will achieve a sleep current anywhere near the 'Micro_Node', this unit is pictured below;
![Picture 1](/pictures/ESP32_Micro_Node.jpg)
### ESP32 Deep Sleep
The ESP32 does some things with I\O pins when going into deep sleep that you might not expect. There are functions in this SX12XX library for putting the LoRa device into deep sleep, whilst still preserving register settings. The current then taken by the lora device is circa 0.5uA. However these functions will likely not work directly with most ESP32 boards due to the way the ESP32 handles the I\O pins in deep sleep mode.
When designing a board where a very low deep sleep current it is important, you need to build the design in stages, checking the deep sleep current after adding each component. Debugging a high deep sleep current on a fully assembled board can be from extremely difficult to impossible. Achieving a low deep sleep current for particular ESP32 boards is well outside the scope of this SX12xx library.
<br>
**3\_LoRa\_Transmitter and 4\_LoRa\_Receiver example programs**
These example programs work when used with the ESP32 'bare bones' schematic shown earlier and the 'ESP32 Dev Module' board type selected in the Arduino IDE.
The pins used for SPI were;
SCK 18
MISO 19
MOSI 23
NSS 5
NRESET 27
RFBUSY 25 (SX126X and SX128X devices only)
DIOX 35 (DIOX is DIO0 on the SX127X devices and DIO1 on SX126X and SX128X devices)
In the example programs for ESP32, you can start the SPI with;
SPI.begin();
And the default SPI pin outs for the ESP32 module shown above will be used.
Alternatively you can uses this format to start SPI;
SPI.begin(SCK, MISO, MOSI, NSS);
And the pin definitions will be taken from those specified in the 'Settings.h' file. If you change these pin allocations from the defaults given you will need to be sure they are valid for your particular ESP32 board.
The SX12XX example programs are specifically written for and and tested on ATmega processors such as 328,1284 and 2560. However most will work, with minor modification, on the ESP32.
This is a run through of the changes that were needed to have the tracker receiver examples; **25\_GPS\_Tracker\_Receiver\_With\_Display\_and\_GPS**, written for the ATmega328P run on the ESP32 bare bones type boards described above.
The original SX12XX tracker program uses the SPI interface to talk to the lora device, I2C to talk to the OLED display and software serial to talk to the GPS.
The pins used for SPI were;
SCK 18
MISO 19
MOSI 23
NSS 5
NRESET 27
RFBUSY 25 (SX126X and SX128X devices only)
DIOX 35 (DIOX is DIO0 on the SX127X devices and DIO1 on SX126X and SX128X devices)
The ESP32 I2C pin connections were;
SDA 21
SCL 22
There is no need for software serial on the ESP32 as it has an available hardware serial port. These are the pin connections used;
GPSTX 16 //this is data out from the GPS into the ESP32
GPSRX 17 //this is data out from the ESP32 into the GPS
The other pins used were;
LED1 2 //On board indicator LED, logic high for on
GPSPOWER 26 //Pin that controls power to GPS, set to -1 if not used
The only software changes required were to change the lines in the Settings.h file from;
#define USE_SOFTSERIAL_GPS
#define HardwareSerialPort Serial2
to;
//#define USE_SOFTSERIAL_GPS
#define HardwareSerialPort Serial2
This removes the definition USE\_SOFTSERIAL\_GPS from the sketch and the effect of this change is then to remove these two lines from the Sketch;
#include <SoftwareSerial.h>
SoftwareSerial GPSserial(RXpin, Txpin);
And include this one;
#define GPSserial HardwareSerialPort
Which sets the commands to read data from the GPS such as GPSserial.read() to be in effect Serial2.read(), which is the ESP32 hardware serial port used.
**Note:** The provided lora settings (in the Settings.h file) may not be optimised for long distance. See the 'What is LoRa' document for information on how LoRa settings affect range.
### Stuart Robinson
### April 2020

View File

@@ -0,0 +1,308 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 03/02/20
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 transmits a LoRa packet without using a processor buffer, the LoRa
devices internal buffer is filled directly with variables.
The sensor used is a BME280. The pressure, humidity, and temperature are read and transmitted. There
is also a 16bit value of battery mV (simulated) and and a 8 bit status value at the packet end.
Although the LoRa packet transmitted and received has its own internal CRC error checking, you could
still receive packets of the same length from another source. If this valid packet were to be used
to recover the sensor values, you could be reading rubbish. To reduce the risk of this, when the packet
is transmitted the CRC value of the actual sensor data is calculated and sent out with the packet.
This CRC value is read by the receiver and used to check that the received CRC matches the supposed
sensor data in the packet. As an additional check there is some addressing information at the beginning
of the packet which is also checked for validity. Thus we can be relatively confident when reading the
received packet that its genuine and from this transmitter. The packet is built and sent in the
sendSensorPacket() function, there is a 'highlighted section' where the actual sensor data is added to
the packet.
Between readings the LoRa device, BME280 sensor, and Atmel microcontroller are put to sleep in units of
8 seconds using the Atmel processor internal watchdog.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file.
The program also has the option of using a logic pin to control the power to the lora and SD card
devices, which can save power in sleep mode. If the hardware is fitted to your board these devices are
powered on by setting the VCCPOWER pin low. If your board does not have this feature set VCCPOWER to -1.
There is also an option of using a logic pin to turn the resistor divider used to read battery voltage on
and off. This reduces current used in sleep mode. To use the feature set the define for pin BATVREADON
in 'Settings.h' to the pin used. If not using the feature set the pin number to -1.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
#include <ProgramLT_Definitions.h>
SX127XLT LT;
#include <Seeed_BME280.h> //get library here; https://github.com/Seeed-Studio/Grove_BME280
BME280 bme280; //create an instance of the BME280 senosor
#include <Wire.h>
uint32_t TXpacketCount;
uint8_t TXPacketL;
float temperature; //the BME280 temperature value
float pressure; //the BME280 pressure value
uint16_t humidity; //the BME280 humididty value
uint16_t voltage; //the battery voltage value
uint8_t statusbyte; //a status byte, not currently used
uint16_t CRCvalue; //the CRC value of the packet data up to this point
uint8_t packetlength; //the packet length that was sent, checked against length received
#define uS_TO_S_FACTOR 1000000 //Conversion factor for micro seconds to seconds
void loop()
{
TXpacketCount++;
Serial.print(TXpacketCount); //print the numbers of sends
Serial.print(F(" Sending > "));
readSensors(); //read the sensor values
printSensorValues(); //print the sensor values
if (sendSensorPacket())
{
Serial.println(F("SentOK"));
}
else
{
Serial.print(F("Send Error - IRQreg,"));
Serial.println(LT.readIrqStatus(), HEX);
}
Serial.print(F("Sleeping zzzz"));
Serial.flush(); //make sure all serial output has gone
//now put the sensor, LoRa device and processor to sleep
sleepBME280(); //sleep the BME280
digitalWrite(VCCPOWER, HIGH); //VCCOUT off. lora device off
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
esp_deep_sleep_start();
//wait a bit ................
Serial.println(F("Why are we here, ESP32 should re-start on wakeup ?")); //the processor has woken up ?
Serial.println();
normalBME280(); //BME280 sensor to normal mode
}
uint8_t sendSensorPacket()
{
//The SX12XX buffer is filled with variables of a known type and in a known sequence. Make sure the
//receiver uses the same variable types and sequence to read variables out of the receive buffer.
uint8_t len;
LT.startWriteSXBuffer(0); //start the write packet to buffer process
LT.writeUint8(Sensor1); //this byte defines the packet type
LT.writeUint8('B'); //this byte identifies the destination node of the packet
LT.writeUint8(1); //this byte identifies the source node of the packet
/************************************************************************
Highlighted section - this is where the actual sensor data is added to the packet
************************************************************************/
LT.writeFloat(temperature); //add the BME280 temperature
LT.writeFloat(pressure); //add the BME280 pressure
LT.writeUint16(humidity); //add the BME280 humididty
LT.writeUint16(voltage); //add the battery voltage
LT.writeUint8(statusbyte); //add the status byte
/************************************************************************/
len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent
addPacketErrorCheck(len); //add the additional CRC error checking to the packet end
//now transmit the packet, set a timeout of 5000mS, wait for it to complete sending
digitalWrite(LED1, HIGH); //turn on LED as an indicator
TXPacketL = LT.transmitSXBuffer(0, (len + 2), 5000, TXpower, WAIT_TX);
digitalWrite(LED1, LOW); //turn off indicator LED
return TXPacketL; //TXPacketL will be 0 if there was an error sending
}
void addPacketErrorCheck(uint8_t len)
{
//calculate the CRC of packet sensor data
CRCvalue = LT.CRCCCITTSX(3, (len - 1), 0xFFFF);
Serial.print(F("Calculated CRC value "));
Serial.println(CRCvalue, HEX);
LT.startWriteSXBuffer(len); //start the write packet again at location of CRC, past end of sensor data
LT.writeUint16(CRCvalue); //add the actual CRC value
LT.endWriteSXBuffer(); //close the packet
}
void readSensors()
{
//read the sensor values into the global variables
temperature = bme280.getTemperature();
pressure = bme280.getPressure();
humidity = bme280.getHumidity();
if (BATVREADON >= 0)
{
voltage = readBatteryVoltage(); //read resistor divider across battery
}
else
{
voltage = 9999; //set a default value
}
statusbyte = 0x55; //manually set this for now, its a test
}
void printSensorValues()
{
Serial.print(F("Temperature,"));
Serial.print(temperature, 1);
Serial.print(F("c,Pressure,"));
Serial.print(pressure, 0);
Serial.print(F("Pa,Humidity,"));
Serial.print(humidity);
Serial.print(F("%,Voltage,"));
Serial.print(voltage);
Serial.print(F("mV,Status,"));
Serial.print(statusbyte, HEX);
Serial.print(F(" "));
Serial.flush();
}
void sleepBME280()
{
//write this register value to BME280 to put it to sleep
writeBME280reg(BME280_REGISTER_CONTROL, B01111100);
}
void normalBME280()
{
//write this register value to BME280 to put it to read mode
writeBME280reg(BME280_REGISTER_CONTROL, B01111111);
}
void writeBME280reg(byte reg, byte regvalue)
{
//write a register value to the BME280
Wire.beginTransmission((uint8_t) BME280_ADDRESS);
Wire.write((uint8_t)reg);
Wire.write((uint8_t)regvalue);
Wire.endTransmission();
}
uint16_t readBatteryVoltage()
{
uint16_t temp;
uint16_t volts = 0;
byte index;
if (BATVREADON >= 0)
{
digitalWrite(BATVREADON, HIGH); //turn on MOSFET connecting resitor divider in circuit
}
temp = analogRead(BATTERYAD);
for (index = 0; index <= 4; index++) //sample AD 5 times
{
temp = analogRead(BATTERYAD);
volts = volts + temp;
}
volts = ((volts / 5) * ADMultiplier);
if (BATVREADON >= 0)
{
digitalWrite(BATVREADON, LOW); //turn off MOSFET connecting resitor divider in circuit
}
return volts;
}
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); //for PCB LED
led_Flash(2, 125);
if (VCCPOWER >= 0)
{
pinMode(VCCPOWER, OUTPUT); //For controlling power to external devices
digitalWrite(VCCPOWER, LOW); //VCCOUT on. lora device on
}
if (BATVREADON >= 0)
{
pinMode(BATVREADON, OUTPUT);
}
Serial.begin(9600);
Serial.println();
Serial.println(F("Reset"));
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("lora Device pins initialised"));
led_Flash(2, 125);
}
else
{
Serial.println(F("Device error"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates LoRa device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println(F("Setup lora device"));
if (!bme280.init())
{
Serial.println("BME280 Device error!");
led_Flash(100, 15); //long very fast speed flash indicates BME280 device error
}
Serial.println(F("Initialised BME280"));
Serial.println();
Serial.println(F("Transmitter ready"));
Serial.println();
readSensors(); //do an initial sensor read
}

View File

@@ -0,0 +1,49 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 03/02/20
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 the Tracker boards, the ESP32_Micro_Node, be sure to change
//them to match your own setup. You will also need to connect up the pins for the SPI bus, which on the
//ESP32_Micro_Node are SCK on pin 18, MISO on pin 19 and MOSI on pin 23. Some pins such as DIO1, DIO2 and
//BUZZER may not be in used by this sketch so they do not need to be connected and should be set to -1.
#define NSS 5 //select pin on LoRa device
#define SCK 18 //SCK on SPI3
#define MISO 19 //MISO on SPI3
#define MOSI 23 //MOSI on SPI3
#define NRESET 27 //reset pin on LoRa device
#define LED1 2 //on board LED, high for on
#define DIO0 35 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define BUZZER -1 //pin for buzzer, set to -1 if not used
#define VCCPOWER 14 //pin controls power to external devices
#define BATTERYAD 36 //pin for reading supply voltage
#define BATVREADON 25 //when high turns on the resistor divider to measure voltage, -1 if not used
#define ADMultiplier 11.65 //Multiplier for conversion of AD reading to mV
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 14; //LoRa transmit power in dBm
#define BME280_ADDRESS 0x76 //I2C bus address of BME280
#define BME280_REGISTER_CONTROL 0xF4 //BME280 register number for power control
const uint16_t TIME_TO_SLEEP = 16; //Time ESP32 will go to sleep (in seconds)

View File

@@ -0,0 +1,358 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 21/01/20
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 receives a LoRa packet without using a processor buffer, the LoRa devices
internal buffer is read direct for the received sensor data.
The sensor used in the matching '17_Sensor_Transmiter' program is a BME280 and the pressure, humidity,
and temperature are being and received. There is also a 16bit value of battery mV and and a 8 bit status
value at the end of the packet.
When a packet is received its printed and assuming the packet is validated, the sensor results are printed
to the serial monitor and screen.
For the sensor data to be accepted as valid the folowing need to match;
The 16bit CRC on the received sensor data must match the CRC value transmitted with the packet.
The packet must start with a byte that matches the packet type sent, 'Sensor1'
The RXdestination byte in the packet must match this node ID of this receiver node, defined by 'This_Node'
In total thats 16 + 8 + 8 = 32bits of checking, so a 1:4294967296 chance (approx) that an invalid
packet is acted on and erroneous values displayed.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
#include <ProgramLT_Definitions.h>
SX127XLT LT;
#include <U8x8lib.h> //get library here > https://github.com/olikraus/u8g2
U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for standard 0.96" SSD1306
//U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for 1.3" OLED often sold as 1.3" SSD1306
uint32_t RXpacketCount; //count of all packets received
uint32_t ValidPackets; //count of packets received with valid data
uint32_t RXpacketErrors; //count of all packets with errors received
bool packetisgood;
uint8_t RXPacketL; //length of received packet
int8_t PacketRSSI; //RSSI of received packet
int8_t PacketSNR; //signal to noise ratio of received packet
uint8_t RXPacketType;
uint8_t RXDestination;
uint8_t RXSource;
float temperature; //the BME280 temperature value
float pressure; //the BME280 pressure value
uint16_t humidity; //the BME280 humididty value
uint16_t voltage; //the battery voltage value
uint8_t statusbyte; //a status byte, not currently used
uint16_t TXCRCvalue; //the CRC value of the packet data as transmitted
void loop()
{
RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout set
digitalWrite(LED1, HIGH); //something has happened
PacketRSSI = LT.readPacketRSSI();
PacketSNR = LT.readPacketSNR();
if (RXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_Received_OK(); //its a valid packet LoRa wise, but it might not be a packet we want
}
digitalWrite(LED1, LOW);
Serial.println();
//SPI.endTransaction();
}
void packet_Received_OK()
{
//a LoRa packet has been received, which has passed the internal LoRa checks, including CRC, but it could be from
//an unknown source, so we need to check that its actually a sensor packet we are expecting, and has valid sensor data
uint8_t len;
uint8_t contenterrors; //keep a count of errors found in packet
RXpacketCount++;
Serial.print(RXpacketCount);
Serial.print(F(",PacketsReceived,"));
LT.startReadSXBuffer(0);
RXPacketType = LT.readUint8();
RXDestination = LT.readUint8();
RXSource = LT.readUint8();
/************************************************************************
Highlighted section - this is where the actual sensor data is read from
the packet
************************************************************************/
temperature = LT.readFloat(); //the BME280 temperature value
pressure = LT.readFloat(); //the BME280 pressure value
humidity = LT.readUint16(); //the BME280 humididty value
voltage = LT.readUint16(); //the battery voltage value
statusbyte = LT.readUint8(); //a status byte, not currently used
/************************************************************************/
len = LT.endReadSXBuffer(); //note len is bytes read from packet, may be different to actual packet length
printreceptionDetails(); //print details of reception, RSSI etc
Serial.println();
contenterrors = checkPacketValid(len); //pass length of packet to check routine
if (contenterrors == 0)
{
Serial.println(F(" Packet is good"));
ValidPackets++;
printSensorValues(); //print the sensor values
Serial.println();
printPacketCounts(); //print count of valid packets and errors
displayscreen1();
Serial.println();
}
else
{
Serial.println(F(" Packet is not valid"));
RXpacketErrors++;
disp.clearLine(7);
disp.setCursor(0, 7);
disp.print(F("Errors "));
disp.print(RXpacketErrors);
}
}
uint8_t checkPacketValid(uint8_t len)
{
//this function checks if the packet is valid and will be displayed
uint8_t errors = 0;
if (RXPacketType != Sensor1) //is it a Sensor1 type packet
{
errors++;
}
if (RXDestination != This_Node) //was the packet sent to this receiver node ?
{
errors++;
}
if (!checkCRCvalue(len)) //is the sent CRC value of sensor data valid ?
{
errors++;
}
Serial.println();
Serial.print(F("Error Check Count = "));
Serial.print(errors);
return errors;
}
bool checkCRCvalue(uint8_t len)
{
uint16_t CRCSensorData;
//uint8_t msb, lsb;
CRCSensorData = LT.CRCCCITTSX(3, (len-1), 0xFFFF); //calculate the CRC of packet sensor data
Serial.print(F("(CRC of Received sensor data "));
Serial.print(CRCSensorData, HEX);
Serial.print(F(")" ));
//SPI.endTransaction();
TXCRCvalue = ((LT.getByteSXBuffer(17) << 8) + (LT.getByteSXBuffer(16)));
Serial.print(F("(CRC transmitted "));
Serial.print(TXCRCvalue, HEX);
Serial.print(F(")" ));
if (TXCRCvalue != CRCSensorData)
{
Serial.print(F(" Sensor Data Not Valid"));
return false;
}
else
{
Serial.print(F(" Sensor Data is Valid"));
return true;
}
}
void printSensorValues()
{
Serial.print(F("Temperature,"));
Serial.print(temperature, 1);
Serial.print(F("c,Pressure,"));
Serial.print(pressure, 0);
Serial.print(F("Pa,Humidity,"));
Serial.print(humidity);
Serial.print(F("%,Voltage,"));
Serial.print(voltage);
Serial.print(F("mV,Status,"));
Serial.print(statusbyte, HEX);
Serial.print(F(",CRC,"));
Serial.print(TXCRCvalue, HEX);
Serial.flush();
}
void printreceptionDetails()
{
Serial.print(F("RSSI"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL());
}
void printPacketCounts()
{
Serial.print(F("ValidPackets,"));
Serial.print(ValidPackets);
Serial.print(F(",Errors,"));
Serial.print(RXpacketErrors);
}
void packet_is_Error()
{
uint16_t IRQStatus;
RXpacketErrors++;
IRQStatus = LT.readIrqStatus();
if (IRQStatus & IRQ_RX_TIMEOUT)
{
Serial.print(F("RXTimeout "));
}
else
{
Serial.print(F("PacketError "));
printreceptionDetails();
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus();
Serial.println();
disp.clearLine(7);
disp.setCursor(0, 7);
disp.print(F("Errors "));
disp.print(RXpacketErrors);
}
}
void displayscreen1()
{
//show sensor data on display
disp.clearLine(0);
disp.setCursor(0, 0);
disp.print(F("Sensor "));
disp.print(RXSource);
disp.clearLine(1);
disp.setCursor(0, 1);
disp.print(temperature, 1);
disp.print(F("c"));
disp.clearLine(2);
disp.setCursor(0, 2);
disp.print(pressure, 0);
disp.print(F("Pa"));
disp.clearLine(3);
disp.setCursor(0, 3);
disp.print(humidity);
disp.print(F("%"));
disp.clearLine(4);
disp.setCursor(0, 4);
disp.print(voltage);
disp.print(F("mV"));
disp.clearLine(6);
disp.setCursor(0, 6);
disp.print(F("ValidPkts "));
disp.print(ValidPackets);
disp.setCursor(0, 7);
disp.print(F("Errors "));
disp.print(RXpacketErrors);
}
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(VCCPOWER, OUTPUT); //this pin switches power for external devices, lora and SD card
digitalWrite(VCCPOWER, LOW); //turn power on
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
Serial.begin(9600);
disp.begin();
disp.setFont(u8x8_font_chroma48medium8_r);
disp.clear();
disp.setCursor(0, 0);
disp.print(F("Check LoRa"));
disp.setCursor(0, 1);
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
disp.print(F("LoRa OK"));
led_Flash(2, 125);
}
else
{
disp.print(F("Device error"));
Serial.println(F("Device error"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println(F("Receiver ready"));
Serial.println();
}

View File

@@ -0,0 +1,49 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 17/12/19
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 the Tracker boards, the ESP32_Micro_Node, be sure to change
//them to match your own setup. You will also need to connect up the pins for the SPI bus, which on the
//ESP32_Micro_Node are SCK on pin 18, MISO on pin 19 and MOSI on pin 23. Some pins such as DIO1, DIO2 and
//BUZZER may not be in used by this sketch so they do not need to be connected and should be set to -1.
#define NSS 5 //select pin on LoRa device
#define SCK 18 //SCK on SPI3
#define MISO 19 //MISO on SPI3
#define MOSI 23 //MOSI on SPI3
#define NRESET 27 //reset pin on LoRa device
#define LED1 2 //on board LED, high for on
#define DIO0 35 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define BUZZER -1 //pin for buzzer, set to -1 if not used
#define VCCPOWER 14 //pin controls power to external devices
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//*************** Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 2; //LoRa TX power
#define packet_delay 1000 //mS delay between packets
#define This_Node 'B' //this is the node that the remote sensors send data to
//**************** Setup Display Parameters Here ****************
//const uint8_t dispfont = u8x8_font_chroma48medium8_r; //display font from u8g2 library

View File

@@ -0,0 +1,268 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 03/02/20
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 program tests the sleep mode and register retention of the SX127X in sleep mode,
it assumes an ESP32 processor module. The LoRa settings to use are specified in the 'Settings.h' file.
To retain the program memory, so that the program restarts after sleep at the next instructions after
going into sleep mode the ESP32 light sleep function is used.
A packet is sent, containing the text 'Before Device Sleep' and the LoRa device and ESP32 are put to sleep.
The ESP32 internal RTC timer should wakeup the processor in 15 seconds (approx) and lora register
values should be retained. The device then attempts to transmit another packet 'After Device Sleep'
without re-loading all the lora settings. The receiver should see 'After Device Sleep' for the first
packet and 'After Device Sleep' for the second.
For unknown reasons the ESP32 pulses the pin used by NRESET when going into sleep modes, so the program
turns it into an input for the duration of the sleep to avoid resetting the lora device.
The program also has the option of using a logic pin to control the power to the lora and SD card
devices, which can save power in sleep mode. If the hardware is fitted to your board these devices are
powered on by setting the VCCPOWER pin low. If your board does not have this feature set VCCPOWER to -1.
Tested on a 'bare bones' ESP32 the current in light sleep mode was 1670uA.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
SX127XLT LT;
boolean SendOK;
int8_t TestPower;
uint8_t TXPacketL;
/***********************************************************
//ESP32 specific settings
***********************************************************/
#define uS_TO_S_FACTOR 1000000 //Conversion factor for micro seconds to seconds
#define TIME_TO_SLEEP 15 //Time ESP32 will go to sleep (in seconds)
RTC_DATA_ATTR int16_t bootCount = 0;
RTC_DATA_ATTR uint16_t sleepcount = 0;
void loop()
{
Serial.print(F("Bootcount "));
Serial.println(bootCount);
Serial.print(F("Sleepcount "));
Serial.println(sleepcount);
Serial.println();
LT.printRegisters(0x00, 0x7F);
Serial.println();
digitalWrite(LED1, HIGH);
Serial.print(TXpower);
Serial.print(F("dBm "));
Serial.print(F("TestPacket1> "));
Serial.flush();
if (Send_Test_Packet1())
{
packet_is_OK();
}
else
{
packet_is_Error();
}
Serial.println();
delay(packet_delay);
pinMode(NRESET, INPUT); //change NRESET pin to INPUT mode
LT.setSleep(CONFIGURATION_RETENTION); //preserve register settings in sleep.
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
Serial.println(F("Start Sleep"));
Serial.flush();
sleepcount++;
esp_light_sleep_start();
Serial.println();
Serial.println();
Serial.println(F("Awake !"));
Serial.flush();
digitalWrite(LED1, HIGH);
LT.wake();
digitalWrite(NRESET, HIGH); //set NRESET high before turning it back to an output
pinMode(NRESET, INPUT); //set NRESET as an output
Serial.print(TXpower);
Serial.print(F("dBm "));
Serial.print(F("TestPacket2> "));
Serial.flush();
if (Send_Test_Packet2())
{
packet_is_OK();
}
else
{
packet_is_Error();
}
Serial.println();
delay(packet_delay);
}
void packet_is_OK()
{
Serial.print(F(" "));
Serial.print(TXPacketL);
Serial.print(F(" Bytes SentOK"));
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //get the IRQ status
Serial.print(F("SendError,"));
Serial.print(F("Length,"));
Serial.print(TXPacketL);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus();
digitalWrite(LED1, LOW); //this leaves the LED on slightly longer for a packet error
}
bool Send_Test_Packet1()
{
uint8_t bufffersize;
uint8_t buff[] = "Before Device Sleep";
TXPacketL = sizeof(buff);
buff[TXPacketL - 1] = '*';
if (sizeof(buff) > TXBUFFER_SIZE) //check that defined buffer is not larger than TX_BUFFER
{
bufffersize = TXBUFFER_SIZE;
}
else
{
bufffersize = sizeof(buff);
}
TXPacketL = bufffersize;
LT.printASCIIPacket( (uint8_t*) buff, bufffersize);
digitalWrite(LED1, HIGH);
if (LT.transmit( (uint8_t*) buff, TXPacketL, 10000, TXpower, WAIT_TX))
{
digitalWrite(LED1, LOW);
return true;
}
else
{
return false;
}
}
bool Send_Test_Packet2()
{
uint8_t bufffersize;
uint8_t buff[] = "After Device Sleep";
TXPacketL = sizeof(buff);
buff[TXPacketL - 1] = '*';
if (sizeof(buff) > TXBUFFER_SIZE) //check that defined buffer is not larger than TX_BUFFER
{
bufffersize = TXBUFFER_SIZE;
}
else
{
bufffersize = sizeof(buff);
}
TXPacketL = bufffersize;
LT.printASCIIPacket( (uint8_t*) buff, bufffersize);
digitalWrite(LED1, HIGH);
if (LT.transmit( (uint8_t*) buff, TXPacketL, 10000, TXpower, WAIT_TX))
{
digitalWrite(LED1, LOW);
return true;
}
else
{
return false;
}
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
if (VCCPOWER >= 0)
{
pinMode(VCCPOWER, OUTPUT); //For controlling power to external devices
digitalWrite(VCCPOWER, LOW); //VCCOUT on. lora device on
}
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("5_LoRa_TX_Sleep_Timed_Wakeup_ESP32 Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.print(F("Transmitter ready - TXBUFFER_SIZE "));
Serial.println(TXBUFFER_SIZE);
Serial.println();
}

View File

@@ -0,0 +1,43 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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. Some pins such as DIO1,
//DIO2, BUZZER may not be in used by this sketch so they do not need to be
//connected and should be included and be set to -1.
#define NSS 5 //select pin on LoRa device
#define NRESET 27 //reset pin on LoRa device
#define LED1 2 //on board LED, high for on
#define DIO0 35 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define VCCPOWER 14 //pin controls power to external devices
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup lora Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const int8_t TXpower = 10; //LoRa transmit power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets
#define TXBUFFER_SIZE 32 //RX buffer size

View File

@@ -0,0 +1,408 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 03/02/20
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 program is an example of a basic GPS tracker. The program reads the GPS,
waits for an updated fix and transmits location and altitude, number of satellites in view, the HDOP
value, the fix time of the GPS and the battery voltage. This transmitter can be also be used to
investigate GPS performance. At startup there should be a couple of seconds of recognisable text from
the GPS printed to the serial monitor. If you see garbage or funny characters its likley the GPS baud
rate is wrong. If the transmitter is turned on from cold, the receiver will pick up the cold fix time,
which is an indication of GPS performance. The GPS will be powered on for around 4 seconds before the
timing of the fix starts. Outside with a good view of the sky most GPSs should produce a fix in around
45 seconds. The number of satellites and HDOP are good indications to how well a GPS is working.
The program writes direct to the LoRa devices internal buffer, no memory buffer is used.
The LoRa settings are configured in the Settings.h file.
The program has the option of using a pin to control the power to the GPS (GPSPOWER), if the GPS module
or board being used has this feature. To not use this feature set the define for GPSPOWER in the
Settings.h file to '#define GPSPOWER -1'. Also set the GPSONSTATE and GPSOFFSTATE to the appropriate logic
levels.
The program also has the option of using a logic pin to control the power to the lora and SD card
devices, which can save power in sleep mode. If the hardware is fitted to your board these devices are
powered on by setting the VCCPOWER pin low. If your board does not have this feature set VCCPOWER to -1.
There is also an option of using a logic pin to turn the resistor divider used to read battery voltage on
and off. This reduces current used in sleep mode. To use the feature set the define for pin BATVREADON
in 'Settings.h' to the pin used. If not using the feature set the pin number to -1.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#define authorname "Stuart Robinson"
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
#include <ProgramLT_Definitions.h>
SX127XLT LT;
#include <TinyGPS++.h> //get library here > http://arduiniana.org/libraries/tinygpsplus/
TinyGPSPlus gps; //create the TinyGPS++ object
uint8_t TXStatus = 0; //used to store current status flag bits of Tracker transmitter (TX)
uint8_t TXPacketL; //length of LoRa packet (TX)
float TXLat; //Latitude from GPS on Tracker transmitter (TX)
float TXLon; //Longitude from GPS on Tracker transmitter (TX)
float TXAlt; //Altitude from GPS on Tracker transmitter (TX)
uint8_t TXSats; //number of GPS satellites seen (TX)
uint32_t TXHdop; //HDOP from GPS on Tracker transmitter (TX)
uint16_t TXVolts; //Volts (battery) level on Tracker transmitter (TX)
uint32_t TXGPSFixTime; //GPS fix time in hot fix mode of GPS on Tracker transmitter (TX)
uint32_t TXPacketCount, TXErrorsCount; //keep count of OK packets and send errors
void loop()
{
if (gpsWaitFix(WaitGPSFixSeconds))
{
sendLocation(TXLat, TXLon, TXAlt, TXHdop, TXGPSFixTime);
Serial.println();
Serial.print(F("Waiting "));
Serial.print(Sleepsecs);
Serial.println(F("s"));
delay(Sleepsecs * 1000); //this sleep is used to set overall transmission cycle time
}
else
{
send_Command(NoFix); //send notification of no GPS fix.
}
}
bool gpsWaitFix(uint16_t waitSecs)
{
//waits a specified number of seconds for a fix, returns true for good fix
uint32_t endwaitmS, GPSonTime;
bool GPSfix;
float tempfloat;
uint8_t GPSchar;
GPSonTime = millis();
GPSserial.begin(9600); //start GPSserial
Serial.print(F("Wait GPS Fix "));
Serial.print(waitSecs);
Serial.println(F("s"));
endwaitmS = millis() + (waitSecs * 1000);
while (millis() < endwaitmS)
{
if (GPSserial.available() > 0)
{
GPSchar = GPSserial.read();
gps.encode(GPSchar);
}
if (gps.location.isUpdated() && gps.altitude.isUpdated())
{
GPSfix = true;
Serial.print(F("Have GPS Fix "));
TXGPSFixTime = millis() - GPSonTime;
Serial.print(TXGPSFixTime);
Serial.println(F("mS"));
TXLat = gps.location.lat();
TXLon = gps.location.lng();
TXAlt = gps.altitude.meters();
TXSats = gps.satellites.value();
TXHdop = gps.hdop.value();
tempfloat = ( (float) TXHdop / 100);
Serial.print(TXLat, 5);
Serial.print(F(","));
Serial.print(TXLon, 5);
Serial.print(F(","));
Serial.print(TXAlt, 1);
Serial.print(F(","));
Serial.print(TXSats);
Serial.print(F(","));
Serial.print(tempfloat, 2);
Serial.println();
break; //exit while loop reading GPS
}
}
//if here then there has either been a fix or no fix and a timeout
if (GPSfix)
{
setStatusByte(GPSFix, 1); //set status bit to flag a GPS fix
}
else
{
setStatusByte(GPSFix, 0); //set status bit to flag no fix
Serial.println();
Serial.println(F("Timeout - No GPSFix"));
Serial.println();
GPSfix = false;
}
GPSserial.end(); //serial RX interrupts interfere with SPI, so stop GPSserial
return GPSfix;
}
void sendLocation(float Lat, float Lon, float Alt, uint32_t Hdop, uint32_t fixtime)
{
uint8_t len;
uint16_t IRQStatus;
Serial.print(F("Send Location"));
TXVolts = readSupplyVoltage(); //get the latest supply\battery volts
LT.startWriteSXBuffer(0); //initialise buffer write at address 0
LT.writeUint8(LocationPacket); //indentify type of packet
LT.writeUint8(Broadcast); //who is the packet sent too
LT.writeUint8(ThisNode); //tells receiver where is packet from
LT.writeFloat(Lat); //add latitude
LT.writeFloat(Lon); //add longitude
LT.writeFloat(Alt); //add altitude
LT.writeUint8(TXSats); //add number of satellites
LT.writeUint32(Hdop); //add hdop
LT.writeUint8(TXStatus); //add tracker status
LT.writeUint32(fixtime); //add GPS fix time in mS
LT.writeUint16(TXVolts); //add tracker supply volts
len = LT.endWriteSXBuffer(); //close buffer write
digitalWrite(LED1, HIGH);
TXPacketL = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX);
digitalWrite(LED1, LOW);
if (TXPacketL)
{
TXPacketCount++;
Serial.println(F(" - Done "));
Serial.print(F("SentOK,"));
Serial.print(TXPacketCount);
Serial.print(F(",Errors,"));
Serial.println(TXErrorsCount);
}
else
{
//if here there was an error transmitting packet
TXErrorsCount++;
IRQStatus = LT.readIrqStatus(); //read the the interrupt register
Serial.print(F(" SendError,"));
Serial.print(F("Length,"));
Serial.print(TXPacketL); //print transmitted packet length
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX); //print IRQ status
LT.printIrqStatus(); //prints the text of which IRQs set
Serial.println();
}
}
void setStatusByte(uint8_t bitnum, uint8_t bitval)
{
//program the status byte
if (bitval == 0)
{
bitClear(TXStatus, bitnum);
}
else
{
bitSet(TXStatus, bitnum);
}
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
//flash LED to show tracker is alive
uint16_t index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void send_Command(char cmd)
{
bool SendOK;
uint8_t len;
Serial.print(F("Send Cmd "));
Serial.write(cmd);
LT.startWriteSXBuffer(0);
LT.writeUint8(cmd); //packet addressing used indentify type of packet
LT.writeUint8(Broadcast); //who is the packet sent to
LT.writeUint8(ThisNode); //where is packet from
LT.writeUint16(TXVolts);
len = LT.endWriteSXBuffer();
digitalWrite(LED1, HIGH);
SendOK = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX); //timeout set at 10 seconds
digitalWrite(LED1, LOW);
if (SendOK)
{
Serial.println(F(" - Done"));
}
else
{
Serial.println(F(" - Error"));
}
}
uint16_t readSupplyVoltage()
{
//ESP32 uses the 3.3V VCC as reference
uint16_t temp;
uint16_t volts = 0;
byte index;
if (BATVREADON >= 0)
{
digitalWrite(BATVREADON, HIGH); //turn on MOSFET connecting resitor divider in circuit
}
temp = analogRead(SupplyAD);
for (index = 0; index <= 4; index++) //sample AD 5 times
{
temp = analogRead(SupplyAD);
volts = volts + temp;
}
volts = ((volts / 5) * ADMultiplier);
if (BATVREADON >= 0)
{
digitalWrite(BATVREADON, LOW); //turn off MOSFET connecting resitor divider in circuit
}
return volts;
}
void GPSON()
{
if (GPSPOWER >= 0)
{
digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS
}
}
void GPSOFF()
{
if (GPSPOWER)
{
digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS
}
}
void setup()
{
uint32_t endmS;
if (VCCPOWER >= 0)
{
pinMode(VCCPOWER, OUTPUT); //this pin switches power for external devices, lora and SD card
digitalWrite(VCCPOWER, LOW); //turn device power on
}
if (GPSPOWER >= 0)
{
pinMode(GPSPOWER, OUTPUT);
GPSON();
}
if (BATVREADON >= 0)
{
pinMode(BATVREADON, OUTPUT);
}
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("23_Simple_GPS_Tracker_Transmitter_ESP32 Starting"));
//SPI.begin();
SPI.begin(SCK, MISO, MOSI, NSS); //alternative format for SPI3, VSPI; SPI.begin(SCK,MISO,MOSI,SS)
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
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();
TXVolts = readSupplyVoltage();
Serial.print(F("Supply "));
Serial.print(TXVolts);
Serial.println(F("mV"));
send_Command(PowerUp); //send power up command, includes supply mV
Serial.println(F("Startup GPS check"));
GPSserial.begin(9600);
endmS = millis() + echomS;
while (millis() < endmS)
{
while (GPSserial.available() > 0)
Serial.write(GPSserial.read());
}
Serial.println();
Serial.println();
Serial.println(F("Wait for first GPS fix"));
gpsWaitFix(WaitFirstGPSFixSeconds);
sendLocation(TXLat, TXLon, TXAlt, TXHdop, TXGPSFixTime);
}

View File

@@ -0,0 +1,71 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 03/02/20
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 the Tracker boards, the ESP32_Micro_Node, be sure to change
//them to match your own setup. You will also need to connect up the pins for the SPI bus, which on the
//ESP32_Micro_Node are SCK on pin 18, MISO on pin 19 and MOSI on pin 23. Some pins such as DIO1, DIO2 and
//BUZZER may not be in used by this sketch so they do not need to be connected and should be set to -1.
#define NSS 5 //select on LoRa device
#define SCK 18 //SCK on SPI3
#define MISO 19 //MISO on SPI3
#define MOSI 23 //MOSI on SPI3
#define NRESET 27 //reset on LoRa device
#define DIO0 35 //DIO0 on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1
#define LED1 2 //On board LED, high for on
#define BUZZER -1 //Buzzer if fitted, high for on. Set to -1 if not used
#define VCCPOWER 14 //controls power to lora and SD card, set to -1 if not used
#define SupplyAD 36 //pin for reading supply\battery voltage
#define BATVREADON 25 //turns on battery resistor divider, high for on
#define ADMultiplier 11.65 //Multiplier for conversion of AD reading to mV
#define RXpin 17 //pin number for GPS RX input into Arduino - TX from GPS
#define TXpin 16 //pin number for GPS TX output from Arduino- RX into GPS
#define GPSPOWER 26 //Pin that controls power to GPS, set to -1 if not used
#define GPSONSTATE LOW //logic level to turn GPS on via pin GPSPOWER
#define GPSOFFSTATE HIGH //logic level to turn GPS off via pin GPSPOWER
#define GPSserial Serial2 //define GPSserial as ESP32 Serial2
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_062; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 10; //LoRa transmit power in dBm
#define ThisNode 'T' //a character that identifies this tracker
//**************************************************************************************************
// GPS Settings
//**************************************************************************************************
#define GPSBaud 9600 //GPS Baud rate
#define WaitGPSFixSeconds 30 //time in seconds to wait for a new GPS fix
#define WaitFirstGPSFixSeconds 1800 //time to seconds to wait for the first GPS fix at startup
#define Sleepsecs 5 //seconds between transmissions, this delay is used to set overall transmission cycle time
#define echomS 2000 //number of mS to run GPS echo at startup

View File

@@ -0,0 +1,624 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 21/03/20
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 - TThis program is an example of a functional GPS tracker receiver using lora.
It is capable of picking up the trackers location packets from many kilometres away with only basic antennas.
The program receives the location packets from the remote tracker transmitter and writes them on an OLED
display and also prints the information to the Arduino IDE serial monitor. The program can read a locally
attached GPS and when that has a fix, will display the distance and direction to the remote tracker.
The program writes direct to the lora devices internal buffer, no memory buffer is used. The lora settings
are configured in the Settings.h file.
The receiver recognises two types of tracker packet, the one from the matching program '23_GPS_Tracker_Transmitter'
(LocationPacket, 27 bytes) which causes these fields to be printed to the serial monitor;
Latitude, Longitude, Altitude, Satellites, HDOP, TrackerStatusByte, GPS Fixtime, Battery mV, Distance, Direction,
Distance, Direction, PacketRSSI, PacketSNR, NumberPackets, PacketLength, IRQRegister.
This is a long packet which at the long range LoRa settings takes just over 3 seconds to transmit.
The receiver also recognises a much shorter location only packet (LocationBinaryPacket, 11 bytes) and when
received this is printed to the serial monitor;
Latitude, Longitude, Altitude, TrackerStatusByte, Distance, Direction, PacketRSSI, PacketSNR, NumberPackets,
PacketLength, IRQRegister.
Most of the tracker information (for both types of packet) is shown on the OLED display. If there has been a
tracker transmitter GPS fix the number\identifier of that tracker is shown on row 0 right of screen and if there
is a recent local (receiver) GPS fix an 'R' is displayed row 1 right of screen.
When the tracker transmitter starts up or is reset its sends a power up message containing the battery voltage
which is shown on the OLED and printer to the serial monitor.
The program has the option of using a pin to control the power to the GPS, if the GPS module being used has this
feature. To use the option change the define in Settings.h;
'#define GPSPOWER -1' from -1 to the pin number being used. Also set the GPSONSTATE and GPSOFFSTATE defines to
the appropriate logic levels.
The program by default uses software serial to read the GPS, you can use hardware serial by commenting out this
line in the Settings.h file;
#define USE_SOFTSERIAL_GPS
And then defining the hardware serial port you are using, which defaults to Serial1.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <SPI.h>
#include <SX127XLT.h>
SX127XLT LT;
#include "Settings.h"
#include <ProgramLT_Definitions.h>
#include <U8x8lib.h> //https://github.com/olikraus/u8g2
U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //standard 0.96" SSD1306
//U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //1.3" OLED often sold as 1.3" SSD1306
#include <TinyGPS++.h> //http://arduiniana.org/libraries/tinygpsplus/
TinyGPSPlus gps; //create the TinyGPS++ object
#ifdef USE_SOFTSERIAL_GPS
#include <SoftwareSerial.h>
SoftwareSerial GPSserial(RXpin, TXpin);
#else
#define GPSserial HardwareSerialPort //hardware serial port (eg Serial1) is configured in the Settings.h file
#endif
uint32_t RXpacketCount; //count of received packets
uint8_t RXPacketL; //length of received packet
int8_t PacketRSSI; //signal strength (RSSI) dBm of received packet
int8_t PacketSNR; //signal to noise ratio (SNR) dB of received packet
uint8_t PacketType; //for packet addressing, identifies packet type
uint8_t Destination; //for packet addressing, identifies the destination (receiving) node
uint8_t Source; //for packet addressing, identifies the source (transmiting) node
uint8_t TXStatus; //status byte from tracker transmitter
uint8_t TXSats; //number of sattelites in use
float TXLat; //latitude
float TXLon; //longitude
float TXAlt; //altitude
float RXLat; //latitude
float RXLon; //longitude
float RXAlt; //altitude
uint32_t TXHdop; //HDOP, indication of fix quality, horizontal dilution of precision, low is good
uint32_t TXGPSFixTime; //time in mS for fix
uint16_t TXVolts; //supply\battery voltage
uint16_t RXVolts; //supply\battery voltage
float TXdistance; //calculated distance to tracker
uint16_t TXdirection; //calculated direction to tracker
uint16_t RXerrors;
uint32_t TXupTimemS; //up time of TX in mS
uint32_t LastRXGPSfixCheck; //used to record the time of the last GPS fix
bool TXLocation = false; //set to true when at least one tracker location packet has been received
bool RXGPSfix = false; //set to true if the local GPS has a recent fix
uint8_t FixCount = DisplayRate; //used to keep track of number of GPS fixes before display updated
void loop()
{
RXPacketL = LT.receiveSXBuffer(0, 0, NO_WAIT); //returns 0 if packet error of some sort
while (!digitalRead(DIO0))
{
readGPS(); //If the DIO pin is low, no packet arrived, so read the GPS
}
//something has happened in receiver
digitalWrite(LED1, HIGH);
if (BUZZER > 0)
{
digitalWrite(BUZZER, HIGH);
}
RXPacketL = LT.readRXPacketL();
PacketRSSI = LT.readPacketRSSI();
PacketSNR = LT.readPacketSNR();
if (RXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
digitalWrite(LED1, LOW);
if (BUZZER > 0)
{
digitalWrite(BUZZER, LOW);
}
Serial.println();
}
void readGPS()
{
if (GPSserial.available() > 0)
{
gps.encode(GPSserial.read());
}
if ( millis() > (LastRXGPSfixCheck + NoRXGPSfixms))
{
RXGPSfix = false;
LastRXGPSfixCheck = millis();
dispscreen1();
}
if (gps.location.isUpdated() && gps.altitude.isUpdated())
{
RXGPSfix = true;
RXLat = gps.location.lat();
RXLon = gps.location.lng();
RXAlt = gps.altitude.meters();
printRXLocation();
LastRXGPSfixCheck = millis();
if ( FixCount == 1) //update screen when FIXcoount counts down from DisplayRate to 1
{
FixCount = DisplayRate;
dispscreen1();
}
FixCount--;
}
}
bool readTXStatus(byte bitnum)
{
return bitRead(TXStatus, bitnum);
}
void printRXLocation()
{
Serial.print(F("LocalGPS "));
Serial.print(RXLat, 5);
Serial.print(F(","));
Serial.print(RXLon, 5);
Serial.print(F(","));
Serial.print(RXAlt, 1);
Serial.println();
}
void readPacketAddressing()
{
LT.startReadSXBuffer(0);
PacketType = LT.readUint8();
Destination = LT.readUint8();
Source = LT.readUint8();
LT.endReadSXBuffer();
}
void packet_is_OK()
{
//uint16_t IRQStatus;
float tempfloat;
RXpacketCount++;
readPacketAddressing();
if (PacketType == PowerUp)
{
LT.startReadSXBuffer(0);
LT.readUint8(); //read byte from SXBuffer, not used
LT.readUint8(); //read byte from SXBuffer, not used
LT.readUint8(); //read byte from SXBuffer, not used
TXVolts = LT.readUint16(); //read tracker transmitter voltage
LT.endReadSXBuffer();
Serial.print(F("Tracker Powerup - Battery "));
Serial.print(TXVolts);
Serial.println(F("mV"));
dispscreen2();
}
if (PacketType == LocationPacket)
{
//packet has been received, now read from the SX12XX FIFO in the correct order.
Serial.print(F("LocationPacket "));
TXLocation = true;
LT.startReadSXBuffer(0); //start the read of received packet
PacketType = LT.readUint8(); //read in the PacketType
Destination = LT.readUint8(); //read in the Packet destination address
Source = LT.readUint8(); //read in the Packet source address
TXLat = LT.readFloat(); //read in the tracker latitude
TXLon = LT.readFloat(); //read in the tracker longitude
TXAlt = LT.readFloat(); //read in the tracker altitude
TXSats = LT.readUint8(); //read in the satellites in use by tracker GPS
TXHdop = LT.readUint32(); //read in the HDOP of tracker GPS
TXStatus = LT.readUint8(); //read in the tracker status byte
TXGPSFixTime = LT.readUint32(); //read in the last fix time of tracker GPS
TXVolts = LT.readUint16(); //read in the tracker supply\battery volts
TXupTimemS = LT.readUint32(); //read in the TX uptime in mS
RXPacketL = LT.endReadSXBuffer(); //end the read of received packet
if (RXGPSfix) //if there has been a local GPS fix do the distance and direction calculation
{
TXdirection = (int16_t) TinyGPSPlus::courseTo(RXLat, RXLon, TXLat, TXLon);
TXdistance = TinyGPSPlus::distanceBetween(RXLat, RXLon, TXLat, TXLon);
}
else
{
TXdistance = 0;
TXdirection = 0;
}
Serial.write(PacketType);
Serial.write(Destination);
Serial.write(Source);
Serial.print(F(","));
Serial.print(TXLat, 5);
Serial.print(F(","));
Serial.print(TXLon, 5);
Serial.print(F(","));
Serial.print(TXAlt, 1);
Serial.print(F(","));
Serial.print(TXSats);
Serial.print(F(","));
tempfloat = ( (float) TXHdop / 100); //need to convert Hdop read from GPS as uint32_t to a float for display
Serial.print(tempfloat, 2);
Serial.print(F(","));
Serial.print(TXStatus);
Serial.print(F(","));
Serial.print(TXGPSFixTime);
Serial.print(F("mS,"));
Serial.print(TXVolts);
Serial.print(F("mV,"));
Serial.print((TXupTimemS/1000));
Serial.print(F("s,"));
Serial.print(TXdistance, 0);
Serial.print(F("m,"));
Serial.print(TXdirection);
Serial.print(F("d"));
printpacketDetails();
dispscreen1(); //and show the packet detail it on screen
return;
}
if (PacketType == LocationBinaryPacket)
{
//packet from locator has been received, now read from the SX12XX FIFO in the correct order.
TXLocation = true;
Serial.print(F("LocationBinaryPacket "));
LT.startReadSXBuffer(0);
PacketType = LT.readUint8();
Destination = LT.readUint8();
Source = LT.readUint8();
TXLat = LT.readFloat();
TXLon = LT.readFloat();
TXAlt = LT.readInt16();
TXStatus = LT.readUint8();
RXPacketL = LT.endReadSXBuffer();
if (RXGPSfix) //if there has been a local GPS fix do the distance and direction calculation
{
TXdirection = (int16_t) TinyGPSPlus::courseTo(RXLat, RXLon, TXLat, TXLon);
TXdistance = TinyGPSPlus::distanceBetween(RXLat, RXLon, TXLat, TXLon);
}
else
{
TXdistance = 0;
TXdirection = 0;
}
Serial.write(PacketType);
Serial.write(Destination);
Serial.write(Source);
Serial.print(F(","));
Serial.print(TXLat, 5);
Serial.print(F(","));
Serial.print(TXLon, 5);
Serial.print(F(","));
Serial.print(TXAlt, 0);
Serial.print(F("m,"));
Serial.print(TXStatus);
Serial.print(F(","));
Serial.print(TXdistance, 0);
Serial.print(F("m,"));
Serial.print(TXdirection);
Serial.print(F("d"));
printpacketDetails();
dispscreen1();
return;
}
}
void printpacketDetails()
{
uint16_t IRQStatus;
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Length,"));
Serial.print(RXPacketL);
IRQStatus = LT.readIrqStatus();
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
}
void packet_is_Error()
{
uint16_t IRQStatus;
if (BUZZER >= 0)
{
digitalWrite(BUZZER, LOW);
delay(100);
digitalWrite(BUZZER, HIGH);
}
IRQStatus = LT.readIrqStatus(); //get the IRQ status
RXerrors++;
Serial.print(F("PacketError,RSSI"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL()); //get the real packet length
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus();
digitalWrite(LED1, LOW);
if (BUZZER >= 0)
{
digitalWrite(BUZZER, LOW);
delay(100);
digitalWrite(BUZZER, HIGH);
}
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
unsigned int index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void dispscreen1()
{
//show received packet data on display
float tempfloat;
disp.clearLine(0);
disp.setCursor(0, 0);
disp.print(TXLat, 5);
disp.clearLine(1);
disp.setCursor(0, 1);
disp.print(TXLon, 5);
disp.clearLine(2);
disp.setCursor(0, 2);
disp.print(TXAlt,0);
disp.print(F("m"));
disp.clearLine(3);
disp.setCursor(0, 3);
disp.print(F("RSSI "));
disp.print(PacketRSSI);
disp.print(F("dBm"));
disp.clearLine(4);
disp.setCursor(0, 4);
disp.print(F("SNR "));
if (PacketSNR > 0)
{
disp.print(F("+"));
}
if (PacketSNR == 0)
{
disp.print(F(" "));
}
if (PacketSNR < 0)
{
disp.print(F("-"));
}
disp.print(PacketSNR);
disp.print(F("dB"));
if (PacketType == LocationPacket)
{
disp.clearLine(5);
disp.setCursor(0, 5);
tempfloat = ((float) TXVolts / 1000);
disp.print(F("Batt "));
disp.print(tempfloat, 2);
disp.print(F("v"));
}
disp.clearLine(6);
disp.setCursor(0, 6);
disp.print(F("Packets "));
disp.print(RXpacketCount);
disp.clearLine(7);
if (RXGPSfix)
{
disp.setCursor(15, 1);
disp.print(F("R"));
}
else
{
disp.setCursor(15, 1);
disp.print(F(" "));
disp.setCursor(0, 7);
disp.print(F("No Local Fix"));
}
if (RXGPSfix && TXLocation) //only display distance and direction if have received tracker packet and have local GPS fix
{
disp.clearLine(7);
disp.setCursor(0, 7);
disp.print(TXdistance, 0);
disp.print(F("m "));
disp.print(TXdirection);
disp.print(F("d"));
}
if (readTXStatus(GPSFix))
{
disp.setCursor(15, 0);
disp.write(Source);
}
}
void dispscreen2()
{
//show tracker powerup data on display
float tempfloat;
disp.clear();
disp.setCursor(0, 0);
disp.print(F("Tracker Powerup"));
disp.setCursor(0, 1);
disp.print(F("Battery "));
tempfloat = ((float) TXVolts / 1000);
disp.print(tempfloat, 2);
disp.print(F("v"));
}
void GPSON()
{
if (GPSPOWER >= 0)
{
digitalWrite(GPSPOWER, GPSONSTATE); //power up GPS
}
}
void GPSOFF()
{
if (GPSPOWER >= 0)
{
digitalWrite(GPSPOWER, GPSOFFSTATE); //power off GPS
}
}
void setup()
{
uint32_t endmS;
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("25_GPS_Tracker_Receiver_With_Display_and_GPS_ESP32 Starting"));
if (BUZZER >= 0)
{
pinMode(BUZZER, OUTPUT);
}
SPI.begin();
disp.begin();
disp.setFont(u8x8_font_chroma48medium8_r);
Serial.print(F("Checking LoRa device - ")); //Initialize LoRa
disp.setCursor(0, 0);
if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
{
Serial.println(F("Receiver ready"));
disp.print(F("Receiver ready"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No LoRa device responding"));
disp.print(F("No LoRa device"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println();
Serial.println(F("Startup GPS check"));
endmS = millis() + echomS;
//now startup GPS
if (GPSPOWER >= 0)
{
pinMode(GPSPOWER, OUTPUT);
}
GPSON();
GPSserial.begin(GPSBaud);
while (millis() < endmS)
{
while (GPSserial.available() > 0)
Serial.write(GPSserial.read());
}
Serial.println();
Serial.println();
Serial.println(F("Receiver ready"));
Serial.println();
}

View File

@@ -0,0 +1,60 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 definitiosn to match your own setup. Some pins such as DIO1,
//DIO2, BUZZER SWITCH1 may not be in used by this sketch so they do not need to be
//connected and should be set to -1.
#define NSS 5 //select on LoRa device
#define NRESET 27 //reset on LoRa device
#define DIO0 35 //DIO0 on LoRa device, used for RX and TX done
#define LED1 82 //On board LED, high for on
#define BUZZER -1 //Buzzer if fitted, high for on. Set to -1 if not used
#define RXpin 16 //pin number for GPS RX input into Arduino - TX from GPS
#define TXpin 17 //pin number for GPS TX output from Arduino- RX into GPS
#define GPSPOWER 26 //Pin that controls power to GPS, set to -1 if not used
#define GPSONSTATE LOW //logic level to turn GPS on via pin GPSPOWER
#define GPSOFFSTATE HIGH //logic level to turn GPS off via pin GPSPOWER
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_062; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF12; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 10; //LoRa transmit power in dBm
//**************************************************************************************************
// GPS Settings
//**************************************************************************************************
//#define USE_SOFTSERIAL_GPS //need to include this if we are using softserial for GPS
#define HardwareSerialPort Serial2 //if using hardware serial enable this define for hardware serial port
#define GPSBaud 9600 //GPS Baud rate
#define WaitGPSFixSeconds 30 //time to wait for a new GPS fix
#define echomS 2000 //number of mS to run GPS echo for at startup
#define NoRXGPSfixms 15000 //max number of mS to allow before no local fix flagged
#define DisplayRate 7 //when working OK the GPS will get a new fix every second or so
//this rate defines how often the display should be updated

View File

@@ -0,0 +1,192 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 23/02/20
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 test program for using the LoRa device to transmit upper side band FSK
RTTY. With the LoRa device in FSK direct mode, the frequency of the generated carrier is shifted up
or down at the correct baud rate depending on whether a logic 0 or 1 is being sent.
The desired shift in frequency is defined in the Settings.h file as 'FrequencyShift'. When the program
starts the actual frequency shift will be calculated according to the discrete frequency steps the
LoRa device can be set to. There are settings for number of data bits, number of start bits and the
value of parity which can be ParityNone, ParityOdd, ParityEven, ParityZero or ParityOne.
Before the actual data transmission starts you can send a series of marker pips which are short bursts
of up shifted carrier which will be heard as beeps in a correctly tuned receiver. These pips can aid
in setting the receiver decode frequemcy to match the transmission. on some LoRa devices, such as the SX127x
series there can be considerable temperature induced frequency drift. This drift can be caused by outside
temperature changes or the RF device self heating when transmit is turned on. The duration of the pips,
the gaps between them and the period of leadin carrier before the data starts can all be set. To send no
pips just set the number to 0.
The FSK RTTY routines use the micros() function for timing, and a check is made at the begging of a
character to send to see if micros() migh overflow during the transmission of the character. This check
assumes the lowest baud rate of 45baud, and if an overflow is likley, there will be a short in transmission
pause to allow the overflow to occur.
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the lora device is SPI based
#include <SX127XLT.h> //include the appropriate SX12XX library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
//Choose whichever test pattern takes your fancy
//uint8_t testBuffer[] = "0123456789* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"; //This string is sent as AFSK RTTY, 7 bit, 2 Stop bit, no parity, 300 baud.
//uint8_t testBuffer[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789";
//uint8_t testBuffer[] = "UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU";
uint8_t testBuffer[] = "$$MyFlight1,2213,14:54:37,51.48230,-3.18136,15,6,3680,23,66,3,0*2935";
uint8_t freqShiftRegs[3]; //to hold returned registers that set frequency
void loop()
{
uint8_t index;
printRegisterSetup(FrequencyShift);
Serial.println();
LT.startFSKRTTY(FrequencyShift, NumberofPips, PipPeriodmS, PipDelaymS, LeadinmS);
if (micros() > 0xF8000000)
{
Serial.print(F("Waiting micros()"));
while(micros() < 0xFFFB6000);
}
Serial.print(F("Start RTTY micros() = "));
Serial.println(micros(),HEX);
LT.transmitFSKRTTY(13, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send carriage return
LT.transmitFSKRTTY(10, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send line feed
for (index = 0; index < (sizeof(testBuffer)-1); index++)
{
LT.transmitFSKRTTY(testBuffer[index], DataBits, StopBits, Parity, BaudPerioduS, LED1);
Serial.write(testBuffer[index]);
}
LT.transmitFSKRTTY(13, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send carriage return
LT.transmitFSKRTTY(10, DataBits, StopBits, Parity, BaudPerioduS, LED1); //send line feed
Serial.println();
Serial.print(F("END RTTY micros() = "));
Serial.println(micros(),HEX);
digitalWrite(LED1, LOW);
Serial.println();
Serial.println();
Serial.println(micros(),HEX);
LT.setMode(MODE_STDBY_RC);
delay(2000);
}
void printRegisterSetup(uint32_t shift)
{
uint32_t nonShiftedFreq, ShiftedFreq;
uint32_t freqShift;
float exactfreqShift;
LT.setRfFrequency(Frequency, Offset); //ensure base frequecy is set
LT.getRfFrequencyRegisters(freqShiftRegs); //fill buffer with frequency setting registers values
nonShiftedFreq = ( (uint32_t) freqShiftRegs[0] << 16 ) + ( (uint32_t) freqShiftRegs[1] << 8 ) + freqShiftRegs[2];
Serial.print(F("NoShift Registers 0x"));
Serial.println(nonShiftedFreq, HEX);
LT.setRfFrequency((Frequency + shift), Offset); //set shifted frequecy
LT.getRfFrequencyRegisters(freqShiftRegs); //fill buffer with frequency setting registers values
ShiftedFreq = ( (uint32_t) freqShiftRegs[0] << 16 ) + ( (uint32_t) freqShiftRegs[1] << 8 ) + freqShiftRegs[2];
Serial.print(F("Shifted Registers 0x"));
Serial.println(ShiftedFreq, HEX);
freqShift = ShiftedFreq - nonShiftedFreq;
exactfreqShift = freqShift * FREQ_STEP;
Serial.print(F("FSKRTTY register shift "));
Serial.println(freqShift,HEX);
Serial.print(F("FSKRTTY frequency shift "));
Serial.print(exactfreqShift, 8);
Serial.println(F("hZ"));
LT.setRfFrequency(Frequency, Offset); //ensure base frequecy is set
}
void printRegisterBuffer()
{
Serial.print(freqShiftRegs[0],HEX);
Serial.print(F(" "));
Serial.print(freqShiftRegs[1],HEX);
Serial.print(F(" "));
Serial.print(freqShiftRegs[2],HEX);
Serial.println();
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("71_FSKRTTY_Transmitter_Test_ESP32 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));
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
LT.setupDirect(Frequency, Offset);
Serial.print(F("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,43 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 23/02/20
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 needed. You will also need to connect up the pins for the SPI bus, which
//are SCK on pin 18, MISO on pin 19 and MOSI on pin 23.
#define NSS 5 //select pin on LoRa device
#define NRESET 27 //reset pin on LoRa device
#define LED1 2 //on board LED, high for on
#define DIO0 35 //DIO0 pin on LoRa device, used for RX and TX done
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup Direct Modem Parameters Here ! ***************
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint16_t deviation = 10000; //deviation, total frequency shift low to high
const float adjustfreq = 0.9; //adjustment to tone frequency
const int8_t TXpower = 10; //LoRa transmit power in dBm
//******* Setup FSKRTTY Settings here ! ***************
uint32_t FrequencyShift = 400; //hertz frequency shift, approx, in 61.03515625hz steps
uint8_t NumberofPips = 2; //number of marker pips to send
uint16_t PipDelaymS = 500; //mS between pips, carrier off
uint16_t PipPeriodmS = 100; //mS length of pip
uint16_t BaudPerioduS = 10000; //uS period for baud, 10000uS for 100baud
uint16_t LeadinmS = 1000; //ms of leadin, shifted carrier
uint8_t DataBits = 7; //number of databits, normally 7 or 8
uint8_t StopBits = 2; //number of stopbits, normally 1 or 2
uint8_t Parity = ParityNone; //parity on data bits, ParityNone, ParityOdd, ParityEven, ParityZero, ParityOne

View File

@@ -0,0 +1,898 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 08/06/20
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 tracker intended for use as a high altitude balloon (HAB) tracker. The
program sends out a standard format payload with LoRa that is compatible with the HABHUB online tracking
system.
The HAB payload is constructed thus;
PayloadID,Sequence,Time,Lat,Lon,Alt,Satellites,Volts,Temperature,Resets,Status,Errors,TXGPSfixms,Checksum
Field 0 1 2 3 4 5 6 7 8 9 10 11 12 13
The LoRa and frequency settings can be changed in the Settings.h file. There is the option of sending
out a much shorter Search mode binary location only payload. This is intended for ground based searching
and locating. The frequency and LoRa settings of the Search mode packet can be different to the Tracker
mode used by the HAB payload. There is also the option of sending the HAB payload in FSK RTTY format,
see the Settings.h file for all the options. FSK RTTY gets sent at the same frequency as the Tracker mode
HAB packet.
There is a matching Balloon Tracker Receiver program which writes received data to the Serial monitor as well
as a small OLED display.
In the Settings.h file you can set the configuration for either a Ublox GPS or a Quectel L70\L80. The GPSs
are configured for high altitude balloon mode.
It is strongly recommended that a FRAM option is fitted for this transmitter. The sequence, resets and error
nembers are stred in non-volatile memory. This defaults to EEPROM which has a limited endurance of only
100,000 writes, so in theory the limt is reached after the transmission of 100,000 hab packets. The use of
a FRAM will extend the life of the tracker to circa 100,000,000,000,000 transmissions.
Changes:
240420 - Change to work with Easy Pro Mini style modules
300420 - Improve error detection for UBLOX GPS library
ToDo:
Serial monitor baud rate is set at 115200
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <Arduino.h>
#include <SX127XLT.h> //include the appropriate library
SX127XLT LT; //create a library class instance called LT
#include "Settings.h"
#include "ProgramLT_Definitions.h"
//**************************************************************************************************
// HAB tracker data - these are the variables transmitted in payload
//**************************************************************************************************
uint32_t TXSequence; //sequence number of payload
uint8_t TXHours; //Hours
uint8_t TXMinutes; //Minutes
uint8_t TXSeconds; //Seconds
float TXLat; //latitude from GPS
float TXLon; //longitude from GPS
uint16_t TXAlt; //altitude from GPS
uint8_t TXSatellites; //satellites used by GPS
uint16_t TXVolts; //measured tracker supply volts
int8_t TXTemperature; //measured temperature
uint16_t TXResets; //number of tracker resets
uint8_t TXStatus = 0; //used to store current status flag bits
uint16_t TXErrors; //number of tracker Errors
uint32_t TXGPSfixms; //fix time of GPS
uint32_t TXGPSHdop; //HDOP value of GPS
uint8_t hours, mins, secs, day, month;
uint16_t year;
//**************************************************************************************************
uint8_t TXPacketL; //length of LoRa packet sent
uint8_t TXBUFFER[TXBUFFER_SIZE]; //buffer for packet to send
#include Memory_Library
#include <SD.h>
#include <SPI.h>
File logFile;
char filename[] = "/LOG0000.txt"; //filename used as base for creating logfile, 0000 replaced with numbers
bool SDfound;
#include <TinyGPS++.h> //http://arduiniana.org/libraries/tinygpsplus/
TinyGPSPlus gps; //create the TinyGPS++ object
#define GPSserial HARDWARESERIALPORT
#include GPS_Library //include previously defined GPS Library
#include <OneWire.h> //get library here > https://github.com/PaulStoffregen/OneWire
OneWire oneWire(ONE_WIRE_BUS); //create instance of OneWire library
#include <DallasTemperature.h> //get library here > https://github.com/milesburton/Arduino-TXTemperature-Control-Library
DallasTemperature sensor(&oneWire); //create instance of dallas library
uint32_t GPSstartms; //start time waiting for GPS to get a fix
void loop()
{
Serial.println(F("Start Loop"));
GPSstartms = millis();
if (!gpsWaitFix(WaitGPSFixSeconds))
{
GPS_OutputOff();
sendCommand(NoFix); //report a GPS fix error
delay(1000); //give receiver enough time to report NoFix
}
Serial.println();
if (SDfound)
{
Serial.print(F("Write data to "));
Serial.print(filename);
if (logGPSfix(filename)) //log fix data to SD card
{
setStatusByte(SDError, 0); //write to SD OK, clear error flag
}
else
{
cardFail(2);
setStatusByte(SDError, 1); //flag SD card error
}
Serial.println();
}
do_Transmissions(); //do the transmissions
Serial.println(F("Sleep"));
LT.setSleep(CONFIGURATION_RETENTION); //put LoRa device to sleep, preserve lora register settings
Serial.flush(); //make sure no serial output pending before goint to sleep
delay(SleepTimesecs * 1000);
Serial.println(F("Wake"));
LT.wake(); //wake the LoRa device from sleep
}
void do_Transmissions()
{
//this is where all the transmisions get sent
uint32_t startTimemS;
uint8_t index;
incMemoryUint32(addr_SequenceNum); //increment Sequence number
if (readConfigByte(SearchEnable))
{
setSearchMode();
TXPacketL = buildLocationOnly(TXLat, TXLon, TXAlt, TXStatus); //put location data in SX12xx buffer
Serial.print(F("Search packet > "));
Serial.print(TXLat, 5);
Serial.print(F(","));
Serial.print(TXLon, 5);
Serial.print(F(","));
Serial.print(TXAlt);
Serial.print(F(","));
Serial.print(TXStatus);
digitalWrite(LED1, HIGH);
startTimemS = millis();
TXPacketL = LT.transmitSXBuffer(0, TXPacketL, 10000, SearchTXpower, WAIT_TX);
printTXtime(startTimemS, millis());
reportCompletion();
Serial.println();
}
delay(1000); //gap between transmissions
setTrackerMode();
TXPacketL = buildHABPacket();
Serial.print(F("HAB Packet > "));
printBuffer(TXBUFFER, (TXPacketL + 1)); //print the buffer (the packet to send) as ASCII
digitalWrite(LED1, HIGH);
startTimemS = millis();
TXPacketL = LT.transmit(TXBUFFER, (TXPacketL + 1), 10000, TrackerTXpower, WAIT_TX); //will return packet length sent if OK, otherwise 0 if transmit error
digitalWrite(LED1, LOW);
printTXtime(startTimemS, millis());
reportCompletion();
Serial.println();
delay(1000); //gap between transmissions
if (readConfigByte(FSKRTTYEnable))
{
LT.setupDirect(TrackerFrequency, Offset);
LT.startFSKRTTY(FrequencyShift, NumberofPips, PipPeriodmS, PipDelaymS, LeadinmS);
startTimemS = millis() - LeadinmS;
Serial.print(F("FSK RTTY > $$"));
Serial.flush();
LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync
LT.transmitFSKRTTY('$', BaudPerioduS, LED1); //send a '$' as sync
for (index = 0; index <= (TXPacketL - 1); index++) //its TXPacketL-1 since we dont want to send the null at the end
{
LT.transmitFSKRTTY(TXBUFFER[index], BaudPerioduS, LED1);
Serial.write(TXBUFFER[index]);
}
LT.transmitFSKRTTY(13, BaudPerioduS, LED1); //send carriage return
LT.transmitFSKRTTY(10, BaudPerioduS, LED1); //send line feed
LT.endFSKRTTY(); //stop transmitting carrier
digitalWrite(LED1, LOW); //LED off
printTXtime(startTimemS, millis());
TXPacketL += 4; //add the two $ at beginning and CR/LF at end
reportCompletion();
Serial.println();
}
}
void printTXtime(uint32_t startmS, uint32_t endmS)
{
Serial.print(F(" "));
Serial.print(endmS - startmS);
Serial.print(F("mS"));
}
void reportCompletion()
{
Serial.print(F(" "));
if (TXPacketL == 0)
{
Serial.println();
reporttransmitError();
}
else
{
Serial.print(TXPacketL);
Serial.print(F("bytes"));
setStatusByte(LORAError, 0);
}
}
void printBuffer(uint8_t *buffer, uint8_t size)
{
uint8_t index;
for (index = 0; index < size; index++)
{
Serial.write(buffer[index]);
}
}
uint8_t buildHABPacket()
{
//build the HAB tracker payload
uint16_t index, j, CRC;
uint8_t Count, len;
char LatArray[12], LonArray[12];
TXSequence = readMemoryUint32(addr_SequenceNum); //Sequence number is kept in non-volatile memory so it survives TXResets
TXResets = readMemoryUint16(addr_ResetCount); //reset count is kept in non-volatile memory so it survives TXResets
TXVolts = readSupplyVoltage();
TXTemperature = (int8_t) readTempDS18B20();
TXErrors = readMemoryUint16(addr_TXErrors);
dtostrf(TXLat, 7, 5, LatArray); //format is dtostrf(FLOAT,WIDTH,PRECISION,BUFFER);
dtostrf(TXLon, 7, 5, LonArray); //converts float to character array
len = sizeof(TXBUFFER);
memset(TXBUFFER, 0, len); //clear array to 0s
Count = snprintf((char*) TXBUFFER,
TXBUFFER_SIZE,
"$$%s,%u,%02d:%02d:%02d,%s,%s,%d,%d,%d,%d,%u,%u,%u,%u",
FlightID,
TXSequence,
TXHours,
TXMinutes,
TXSeconds,
LatArray,
LonArray,
TXAlt,
TXSatellites,
TXVolts,
TXTemperature,
TXResets,
TXStatus,
TXErrors,
TXGPSfixms
);
CRC = 0xffff; //start value for CRC16
for (index = 2; index < Count; index++) //element 2 is first character after $$ at start (for LoRa)
{
CRC ^= (((uint16_t)TXBUFFER[index]) << 8);
for (j = 0; j < 8; j++)
{
if (CRC & 0x8000)
CRC = (CRC << 1) ^ 0x1021;
else
CRC <<= 1;
}
}
TXBUFFER[Count++] = '*';
TXBUFFER[Count++] = Hex((CRC >> 12) & 15); //add the checksum bytes to the end
TXBUFFER[Count++] = Hex((CRC >> 8) & 15);
TXBUFFER[Count++] = Hex((CRC >> 4) & 15);
TXBUFFER[Count] = Hex(CRC & 15);
return Count;
}
char Hex(uint8_t lchar)
{
//used in CRC calculation in buildHABPacket
char Table[] = "0123456789ABCDEF";
return Table[lchar];
}
uint8_t buildLocationOnly(float Lat, float Lon, uint16_t Alt, uint8_t stat)
{
uint8_t len;
LT.startWriteSXBuffer(0); //initialise buffer write at address 0
LT.writeUint8(LocationBinaryPacket); //identify type of packet
LT.writeUint8(Broadcast); //who is the packet sent too
LT.writeUint8(ThisNode); //tells receiver where is packet from
LT.writeFloat(Lat); //add latitude
LT.writeFloat(Lon); //add longitude
LT.writeInt16(Alt); //add altitude
LT.writeUint8(stat); //add tracker status
len = LT.endWriteSXBuffer(); //close buffer write
return len;
}
void reporttransmitError()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the the interrupt register
Serial.print(F("TXError,"));
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX); //print IRQ status
LT.printIrqStatus(); //prints the text of which IRQs set
incMemoryUint16(addr_TXErrors); //increase the error count
setStatusByte(LORAError, 1);
}
void incMemoryUint32(uint32_t addr)
{
uint32_t val = readMemoryUint32(addr);
val++;
writeMemoryUint32(addr, val);
}
void incMemoryUint16(uint32_t addr)
{
uint16_t val = readMemoryUint16(addr);
val++;
writeMemoryUint16(addr, val);
}
void setStatusByte(uint8_t bitnum, uint8_t bitval)
{
//program the status byte
if (bitval == 0)
{
bitClear(TXStatus, bitnum);
}
else
{
bitSet(TXStatus, bitnum);
}
}
uint8_t readConfigByte(uint8_t bitnum)
{
return bitRead(Default_config1, bitnum);
}
void setTrackerMode()
{
Serial.println(F("setTrackerMode"));
LT.setupLoRa(TrackerFrequency, Offset, TrackerSpreadingFactor, TrackerBandwidth, TrackerCodeRate, TrackerOptimisation);
}
void setSearchMode()
{
Serial.println(F("setSearchMode"));
LT.setupLoRa(SearchFrequency, Offset, SearchSpreadingFactor, SearchBandwidth, SearchCodeRate, SearchOptimisation);
}
uint8_t sendCommand(char cmd)
{
uint8_t len;
TXVolts = readSupplyVoltage();
Serial.print(F("Send Cmd "));
Serial.write(cmd);
Serial.println();
LT.startWriteSXBuffer(0); //start the write packet to buffer process
LT.writeUint8(cmd); //this byte defines the packet type
LT.writeUint8(Broadcast); //destination address of the packet, the receivers address
LT.writeUint8(ThisNode); //source address of this node
LT.writeUint16(TXVolts); //add the battery voltage
LT.writeUint8(TXStatus); //add the status byte
len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent
//now transmit the packet, set a timeout of 5000mS, wait for it to complete sending
digitalWrite(LED1, HIGH); //turn on LED as an indicator
TXPacketL = LT.transmitSXBuffer(0, len, 5000, TrackerTXpower, WAIT_TX);
digitalWrite(LED1, LOW); //turn off indicator LED
return TXPacketL; //TXPacketL will be 0 if there was an error sending
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
//flash LED to show tracker is alive
uint16_t index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH);
delay(delaymS);
digitalWrite(LED1, LOW);
delay(delaymS);
}
}
void clearAllMemory()
{
//clears the whole of non-volatile
Serial.println(F("Clear Memory"));
fillMemory(addr_StartMemory, addr_EndMemory, 0);
}
float readTempDS18B20()
{
float DS18B20TXTemperature;
sensor.requestTemperatures();
DS18B20TXTemperature = sensor.getTempCByIndex(0);
return DS18B20TXTemperature;
}
void printTempDS18B20()
{
float DS18B20TXTemperature;
DS18B20TXTemperature = readTempDS18B20();
Serial.print(F("Temperature "));
Serial.print(DS18B20TXTemperature, 1);
Serial.println(F("c"));
}
void printSupplyVoltage()
{
//get and display supply volts on terminal or monitor
Serial.print(F("Volts "));
Serial.print(readSupplyVoltage());
Serial.println(F("mV"));
}
uint16_t readSupplyVoltage()
{
//relies on 1V1 internal reference and 91K & 11K resistor divider
//returns supply in mV @ 10mV per AD bit read
uint16_t temp;
uint16_t volts = 0;
uint8_t index;
if (BATVREADON >= 0)
{
digitalWrite(BATVREADON, HIGH); //turn MOSFET connection resitor divider in circuit
}
temp = analogRead(SupplyAD);
for (index = 0; index <= 4; index++) //sample AD 5 times
{
temp = analogRead(SupplyAD);
volts = volts + temp;
}
volts = ((volts / 5) * ADMultiplier);
if (BATVREADON >= 0)
{
digitalWrite(BATVREADON, LOW); //turn MOSFET connection resitor divider in circuit
}
return volts;
}
//***********************************************************
// Start GPS Functions
//***********************************************************
void GPSTest()
{
uint32_t endmS;
endmS = millis() + 2000; //run GPS echo for 2000mS
while (millis() < endmS)
{
while (GPSserial.available() > 0)
Serial.write(GPSserial.read());
}
Serial.println();
Serial.println();
Serial.flush();
}
bool gpsWaitFix(uint16_t waitSecs)
{
//waits a specified number of seconds for a fix, returns true for good fix
uint32_t endwaitmS, millistowait, currentmillis;
uint8_t GPSchar;
Serial.flush();
Serial.print(F("Wait GPS Fix "));
Serial.print(waitSecs);
Serial.print(F("s "));
Serial.flush();
GPS_OutputOn();
Serial.flush();
currentmillis = millis();
millistowait = waitSecs * 1000;
endwaitmS = currentmillis + millistowait;
while (GPSserial.read() >= 0); //clear the GPS serial input buffer
while (millis() < endwaitmS)
{
if (GPSserial.available() > 0)
{
GPSchar = GPSserial.read();
gps.encode(GPSchar);
}
if (gps.location.isUpdated() && gps.altitude.isUpdated())
{
TXLat = gps.location.lat();
TXLon = gps.location.lng();
TXAlt = (uint16_t) gps.altitude.meters();
//Altitude is used as an unsigned integer, so that the binary payload is as short as possible.
//However gps.altitude.meters(); can return a negative value which converts to
//65535 - Altitude, which we dont want. So we will assume any value over 60,000M is zero
if (TXAlt > 60000)
{
TXAlt = 0;
}
TXHours = gps.time.hour(),
TXMinutes = gps.time.minute(),
TXSeconds = gps.time.second(),
TXSatellites = gps.satellites.value();
TXGPSHdop = gps.hdop.value();
hours = gps.time.hour();
mins = gps.time.minute();
secs = gps.time.second();
day = gps.date.day();
month = gps.date.month();
year = gps.date.year();
setStatusByte(GPSFix, 1);
TXGPSfixms = millis() - GPSstartms;
Serial.print(F("Have GPS Fix "));
Serial.print(TXGPSfixms);
Serial.print(F("mS"));
Serial.println();
return true;
}
}
//if here then there has been no fix and a timeout
GPS_OutputOff();
setStatusByte(GPSFix, 0); //set status bit to flag no fix
incMemoryUint16(addr_TXErrors);
Serial.println(F("Error No GPS Fix"));
return false;
}
//***********************************************************
// End GPS Functions
//***********************************************************
//*******************************************************************************
// Start SD card routines
//*******************************************************************************
bool logGPSfix(char *buf )
{
float tempfloat;
logFile = SD.open(buf, FILE_APPEND);
if (!logFile)
{
return false;
}
tempfloat = ( (float) TXGPSHdop / 100);
if (hours < 10)
{
logFile.print(F("0"));
}
logFile.print(hours);
logFile.print(F(":"));
if (mins < 10)
{
logFile.print(F("0"));
}
logFile.print(mins);
logFile.print(F(":"));
if (secs < 10)
{
logFile.print(F("0"));
}
logFile.print(secs);
logFile.print(F(","));
logFile.print(day);
logFile.print(F("/"));
logFile.print(month);
logFile.print(F("/"));
logFile.print(year);
logFile.print(F(","));
logFile.print(TXLat, 6);
logFile.print(F(","));
logFile.print(TXLon, 6);
logFile.print(F(","));
logFile.print(TXAlt, 1);
logFile.print(F(","));
logFile.print(TXSatellites);
logFile.print(F(","));
logFile.print(tempfloat, 2);
logFile.print(F(","));
logFile.print(TXVolts);
logFile.print(F(","));
logFile.print(TXTemperature);
logFile.print(F(","));
logFile.print(TXResets);
logFile.print(F(","));
logFile.print(TXStatus);
logFile.print(F(","));
logFile.print(TXErrors);
logFile.print(F(","));
logFile.print(TXGPSfixms);
logFile.println();
logFile.close();
return true;
}
uint8_t setupSDLOG(char *buf)
{
//creats a new filename
uint16_t index;
for (index = 1; index <= 9999; index++) {
buf[4] = index / 1000 + '0';
buf[5] = ((index % 1000) / 100) + '0';
buf[6] = ((index % 100) / 10) + '0';
buf[7] = index % 10 + '0' ;
if (! SD.exists(filename)) {
// only open a new file if it doesn't exist
logFile = SD.open(buf, FILE_WRITE);
break;
}
}
setStatusByte(SDError, 0); //SD card write OK
return index; //return number of logfile created
}
void cardFail(uint8_t num)
{
Serial.print(num); //so we can tell where crd failed
Serial.println(" Card failed, or not present");
led_Flash(100, 25);
}
//*******************************************************************************
// End SD card routines
//*******************************************************************************
void setup()
{
uint32_t i;
uint16_t j;
Serial.begin(115200); //Setup Serial console ouput
Serial.println();
Serial.println();
Serial.println(F("75_Balloon_Tracker_Transmitter_SDLogger_ESP32 Starting"));
memoryStart(Memory_Address); //setup the memory
j = readMemoryUint16(addr_ResetCount);
j++;
writeMemoryUint16(addr_ResetCount, j);
j = readMemoryUint16(addr_ResetCount);
Serial.print(F("TXResets "));
Serial.println(j);
if (GPSPOWER >= 0) //if GPS needs power switching, turn it on
{
pinMode(GPSPOWER, OUTPUT);
digitalWrite(GPSPOWER, GPSONSTATE);
}
if (BATVREADON >= 0)
{
pinMode(BATVREADON, OUTPUT); //for MOSFET controlling battery volts resistor divider
}
#ifdef QUECTELINUSE
Serial.println(F("Quectel GPS library"));
#endif
#ifdef UBLOXINUSE
Serial.println(F("UBLOX GPS library"));
#endif
#ifdef ClearAllMemory
clearAllMemory();
#endif
SPI.begin(); //initialize SPI
if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
{
led_Flash(2, 125);
}
else
{
Serial.println(F("LoRa Device error"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates device error
}
}
setTrackerMode();
Serial.print(F("Config "));
Serial.println(Default_config1, BIN);
j = readMemoryUint16(addr_TXErrors);
Serial.print(F("TXErrors "));
Serial.println(j);
Serial.print(F("TXSequence "));
i = readMemoryUint32(addr_SequenceNum);
Serial.println(i);
Serial.print(F("ThisNode "));
Serial.println(ThisNode);
LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check
Serial.println();
printSupplyVoltage();
printTempDS18B20();
Serial.println();
j = readSupplyVoltage(); //get supply mV
TXStatus = 0; //clear all TX status bits
sendCommand(PowerUp); //send power up command, includes supply mV and config, on tracker settings
Serial.println();
Serial.println("Initializing SD card");
if (!SD.begin(SDCS))
{
cardFail(1);
Serial.println();
SDfound = false;
setStatusByte(SDError, 1); //flag SD card error
}
else
{
Serial.println("Card initialized");
setupSDLOG(filename); //setup logfile name for writing
Serial.print(F("Write file to "));
Serial.println(filename);
SDfound = true;
}
GPS_OutputOn();
GPSTest();
GPS_Setup(); //GPS should have had plenty of time to initialise by now
delay(2000);
if (GPS_CheckConfiguration()) //Check that GPS is configured for high altitude mode
{
Serial.println();
GPS_OutputOff(); //GPS interrupts cause problems with lora device, so turn off for now
setStatusByte(GPSError, 0);
setStatusByte(GPSConfigError, 0);
//Alert user to GPS OK, turn LED on and send a FM tone.
digitalWrite(LED1, HIGH);
Serial.println(F("GPS Config OK")); //check tone indicates navigation model 6 set
Serial.println();
Serial.flush();
LT.setupDirect(TrackerFrequency, Offset); //need direct mode for tones
LT.toneFM(1500, 500, deviation, adjustfreq, TrackerTXpower); //Transmit an FM tone, 1000hz, 3000ms
delay(1000);
digitalWrite(LED1, LOW);
}
else
{
setStatusByte(GPSConfigError, 1);
incMemoryUint16(addr_TXErrors);
Serial.println(F("GPS Error"));
Serial.println();
setTrackerMode();
sendCommand(NoGPS); //make sure receiver knows about GPS error
led_Flash(100, 25); //long very rapid flash for GPS error
}
GPSstartms = millis();
setTrackerMode(); //so that commands indicating wait for a GPS go out
while (!gpsWaitFix(5)) //wait for the initial GPS fix, this could take a while
{
sendCommand(NoFix);
led_Flash(2, 50); //two short LED flashes to indicate GPS waiting for fix
}
LT.setupDirect(TrackerFrequency, Offset); //need direct mode for tones
digitalWrite(LED1, HIGH);
LT.toneFM(500, 2000, deviation, adjustfreq, TrackerTXpower);
digitalWrite(LED1, LOW);
GPS_OutputOn();
delay(2000); //GPS may be in software backup allow time for it to wakeup
GPS_SetCyclicMode(); //set this regardless of whether hot fix mode is enabled
GPS_OutputOff();
}

View File

@@ -0,0 +1,142 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 08/06/20
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.
*******************************************************************************************************/
//**************************************************************************************************
// 1) Hardware related definitions and options - specify lora board type and pins 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 5 //select on LoRa device
#define SCK 18 //SCK on SPI3
#define MISO 19 //MISO on SPI3
#define MOSI 23 //MOSI on SPI3
#define NRESET 27 //reset on LoRa device
#define DIO0 35 //DIO0 on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1
#define LED1 2 //On board LED, high for on
#define BUZZER -1 //Buzzer if fitted, high for on. Set to -1 if not used
#define ONE_WIRE_BUS 32 //for DS18B20 temperature sensor
#define SupplyAD 36 //pin for reading supply\battery voltage
#define BATVREADON 2 //turns on battery resistor divider, high for on
#define ADMultiplier 11.65 //Multiplier for conversion of AD reading to mV
#define SDCS 13 //microSD card select
#define RXpin 17 //pin number for GPS RX input into Arduino - TX from GPS
#define TXpin 16 //pin number for GPS TX output from Arduino- RX into GPS
#define GPSPOWER 26 //Pin that controls power to GPS, set to -1 if not used
#define GPSONSTATE LOW //logic level to turn GPS on via pin GPSPOWER
#define GPSOFFSTATE HIGH //logic level to turn GPS off via pin GPSPOWER
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//**************************************************************************************************
// 2) Program Options
//**************************************************************************************************
#define ClearAllMemory //Clears memory of stored tracker information, counts, errors etc
//**************************************************************************************************
// 3) LoRa modem settings
//**************************************************************************************************
//LoRa Modem Parameters
const uint32_t Offset = 0; //offset frequency for calibration purposes
//Tracker mode
const uint32_t TrackerFrequency = 434000000; //frequency of transmissions
const uint8_t TrackerBandwidth = LORA_BW_062; //LoRa bandwidth
const uint8_t TrackerSpreadingFactor = LORA_SF8; //LoRa spreading factor
const uint8_t TrackerCodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t TrackerOptimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TrackerTXpower = 10; //LoRa TX power in dBm
//Search mode
const uint32_t SearchFrequency = 434000000; //frequency of transmissionsconst
uint8_t SearchBandwidth = LORA_BW_062; //LoRa bandwidth
const uint8_t SearchSpreadingFactor = LORA_SF12; //LoRa spreading factor
const uint8_t SearchCodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t SearchOptimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t SearchTXpower = 10; //LoRa TX power in dBm
const uint16_t deviation = 10000; //deviation in hz for FM tones
const float adjustfreq = 0.9; //adjustment to tone frequency
const byte TXBUFFER_SIZE = 128; //defines the maximum size of the trasnmit buffer;
//**************************************************************************************************
// 4) GPS Options
//**************************************************************************************************
#define GPSBaud 9600 //GPS Baud rate
#define HARDWARESERIALPORT Serial2 //if your using hardware serial for the GPS, define it here
const uint16_t WaitGPSFixSeconds = 60; //when in flight the time to wait for a new GPS fix
#define GPS_Library <UBLOXSerialGPS.h> //use library file for UBLOX GPS
//#define GPS_Library <QuectelSerialGPS.h> //use library file for Quectel GPS
//**************************************************************************************************
// 5) FSK RTTY Settings
//**************************************************************************************************
uint32_t FrequencyShift = 500; //hertz frequency shift for audio
uint8_t NumberofPips = 4; //number of marker pips to send
uint16_t PipDelaymS = 1000; //mS between pips when carrier is off
uint16_t PipPeriodmS = 100; //mS length of pip
uint16_t BaudPerioduS = 10000; //uS period for baud, 10000uS for 100baud
uint16_t LeadinmS = 1000; //ms of leadin constant shifted carrier
//****************************************************************************************************
// 6) Program Default Option settings - This section determines which options are on or off by default,
// these are saved in the Default_config1 byte. These options are set in this way so that it is
// possible (in future program changes) to alter the options remotly.
//**************************************************************************************************
uint8_t OptionOff = 0;
uint8_t OptionOn = 1;
const char option_SearchEnable = OptionOff; //set to OptionOn to enable transmit of Search mode packet
const char option_FSKRTTYEnable = OptionOff; //set to OptionOn to enable transmit of FSKRTTY
#define option_SearchEnable_SUM (option_SearchEnable*1)
#define option_FSKRTTYEnable_SUM (option_FSKRTTYEnable*4)
const unsigned int Default_config1 = (option_SearchEnable_SUM + option_FSKRTTYEnable_SUM);
//const unsigned int Default_config1 = 0x05; //Phew, the default config can always be set manually........
//0x05 would turn on transmit of search mode and FSKRTTY
//**************************************************************************************************
// 7) Memory settings - define the type of memory to use for non-Volatile storage.
// The ESP32 version of the HAB tracker transmitter only supports the use of FRAM here.
//**************************************************************************************************
//#define Memory_Library <FRAM_MB85RC16PNF.h>
#define Memory_Library <FRAM_FM24CL64.h>
int16_t Memory_Address = 0x50; //default I2C address of MB85RC16PNF and FM24CL64 FRAM
//**************************************************************************************************
// 8) HAB Flight Settings
//**************************************************************************************************
char FlightID[] = "Flight1"; //flight ID for HAB packet
const unsigned int SleepTimesecs = 13; //sleep time in seconds after each TX loop
const char ThisNode = '1'; //tracker number for search packet

View File

@@ -0,0 +1,192 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 04/01/20
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 an example of the use of implicit or fixed length LoRa packets.
Implicit packets have no header so both transmitter and receiver need to be programmed with the packet
length in use. The use of spreading factor 6 requires implicit packets and together with a bandwidth
of 500khz, leads to the shortest possible and lowest air time packets.
This example sends a buffer that is 23 characters long and that length must be defined in Settings.h
as the constant 'PacketLength'.
A packet containing ASCII text is sent according to the frequency and LoRa settings specified in the
'Settings.h' file. The pins to access the lora device need to be defined in the 'Settings.h' file also.
The details of the packet sent and any errors are shown on the Serial Monitor, together with the transmit
power used, the packet length and the CRC of the packet. The matching receive program,
'41_LoRa_Receiver_ImplicitPackets' can be used to check the packets are being sent correctly, the
frequency and LoRa settings (in Settings.h) must be the same for the Transmit and Receive program.
Sample Serial Monitor output;
10dBm Packet> Hello World 123456* BytesSent,23 CRC,DAAB TransmitTime,8mS PacketsSent,1
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
uint8_t TXPacketL;
uint32_t TXPacketCount, startmS, endmS;
uint8_t buff[] = "Hello World 1234567890"; //buffer length must be 23, and defined in constant PacketLength
void loop()
{
Serial.print(TXpower); //print the transmit power defined
Serial.print(F("dBm "));
Serial.print(F("Packet> "));
Serial.flush();
TXPacketL = sizeof(buff); //set TXPacketL to length of array, must be 19 characters
buff[TXPacketL - 1] = '*'; //replace null character at buffer end so its visible on reciver
LT.printASCIIPacket(buff, TXPacketL); //print the buffer (the sent packet) as ASCII
digitalWrite(LED1, HIGH);
startmS = millis(); //start transmit timer
if (LT.transmit(buff, TXPacketL, 10000, TXpower, WAIT_TX)) //will return packet length sent if OK, otherwise 0 if transmit error
{
endmS = millis(); //packet sent, note end time
TXPacketCount++;
packet_is_OK();
}
else
{
packet_is_Error(); //transmit packet returned 0, there was an error
}
digitalWrite(LED1, LOW);
Serial.println();
delay(packet_delay); //have a delay between packets
}
void packet_is_OK()
{
//if here packet has been sent OK
uint16_t localCRC;
Serial.print(F(" BytesSent,"));
Serial.print(TXPacketL); //print transmitted packet length
localCRC = LT.CRCCCITT(buff, TXPacketL, 0xFFFF);
Serial.print(F(" CRC,"));
Serial.print(localCRC, HEX); //print CRC of sent packet
Serial.print(F(" TransmitTime,"));
Serial.print(endmS - startmS); //print transmit time of packet
Serial.print(F("mS"));
Serial.print(F(" PacketsSent,"));
Serial.print(TXPacketCount); //print total of packets sent OK
}
void packet_is_Error()
{
//if here there was an error transmitting packet
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the the interrupt register
Serial.print(F("SendError,"));
Serial.print(F("Length,"));
Serial.print(TXPacketL); //print transmitted packet length
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX); //print IRQ status
LT.printIrqStatus(); //prints the text of which IRQs set
}
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 setupLoRa()
{
//this setup is used so as the implicit packet type,LORA_PACKET_FIXED_LENGTH, is used
LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device
LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions
LT.setRfFrequency(Frequency, Offset); //set the operating frequency
LT.calibrateImage(0); //run calibration after setting frequency
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters
LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX
LT.setPacketParams(8, LORA_PACKET_FIXED_LENGTH, PacketLength, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34
LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current
//This is the typical IRQ parameters set, actually excecuted in the transmit function
LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on TX done
}
void setup()
{
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("40_LoRa_Transmitter_ImplicitPacket 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));
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
//this function call sets up the device for LoRa using the settings from the Settings.h file
setupLoRa();
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(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F
Serial.println();
Serial.println();
Serial.print(F("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,40 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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. Some pins such as DIO1,
//DIO2, BUZZER may not be in used by this sketch so they do not need to be
//connected and should be included and be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup LoRa Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF6; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const uint8_t PacketLength = 23; //packet length is fixed
const int8_t TXpower = 10; //LoRa transmit power in dBm
const uint16_t packet_delay = 2000; //mS delay between packets

View File

@@ -0,0 +1,258 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 an example of the use of implicit or fixed length LoRa packets.
Implicit packets have no header so both transmitter and receiver need to be programmed with the packet
length in use. The use of spreading factor 6 requires implicit packets and together with a bandwidth
of 500khz, leads to the shortest possible and lowest air time packets. The program listens for incoming
packets using the LoRa settings in the 'Settings.h'.
This example receives a buffer that is 23 characters long and that length must be defined in Settings.h
as the constant 'PacketLength'.
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, the packet is assumed to be in ASCII printable text,
if its not ASCII text characters from 0x20 to 0x7F, expect weird things to happen on the Serial Monitor.
The LED will flash for each packet received and the buzzer will sound, if fitted.
Sample serial monitor output;
1109s {packet contents} CRC,3882,RSSI,-69dBm,SNR,10dB,Length,19,Packets,1026,Errors,0,IRQreg,50
If there is a packet error it might look like this, which is showing a CRC error,
1189s PacketError,RSSI,-111dBm,SNR,-12dB,Length,0,Packets,1126,Errors,1,IRQreg,70,IRQ_HEADER_VALID,IRQ_CRC_ERROR,IRQ_RX_DONE
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.1"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
uint32_t RXpacketCount;
uint32_t errors;
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
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()
{
setupLoRa();
RXPacketL = LT.receive(RXBUFFER, PacketLength, 0, NO_WAIT); //wait for a packet to arrive with 60seconds (60000mS) timeout
while (!digitalRead(DIO0)); //wait for DIO0 to go high
digitalWrite(LED1, HIGH);
if (BUZZER > 0) //turn buzzer on
{
digitalWrite(BUZZER, HIGH);
}
PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value
PacketSNR = LT.readPacketSNR(); //read the received SNR value
if ( LT.readIrqStatus() == (IRQ_RX_DONE + IRQ_HEADER_VALID))
{
packet_is_OK();
}
else
{
packet_is_Error();
}
if (BUZZER > 0)
{
digitalWrite(BUZZER, LOW); //buzzer off
}
digitalWrite(LED1, LOW); //LED off
Serial.println();
}
void packet_is_OK()
{
uint16_t IRQStatus, localCRC;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
RXpacketCount++;
printElapsedTime(); //print elapsed time to Serial Monitor
Serial.print(F(" "));
LT.readPacket(RXBUFFER, PacketLength);
LT.printASCIIPacket(RXBUFFER, PacketLength); //print the packet as ASCII characters
localCRC = LT.CRCCCITT(RXBUFFER, PacketLength, 0xFFFF); //calculate the CRC, this is the external CRC calculation of the RXBUFFER
Serial.print(F(",CRC,")); //contents, not the LoRa device internal CRC
Serial.print(localCRC, HEX);
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(PacketLength);
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
printElapsedTime(); //print elapsed time to Serial Monitor
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout"));
}
else
{
errors++;
Serial.print(F(" PacketError"));
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL()); //get the real packet length
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus(); //print the names of the IRQ registers set
}
delay(250); //gives a longer buzzer and LED flash for error
}
void printElapsedTime()
{
float seconds;
seconds = millis() / 1000;
Serial.print(seconds, 0);
Serial.print(F("s"));
}
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 setupLoRa()
{
//this setup is used so as the implicit packet type,LORA_PACKET_FIXED_LENGTH, is used
LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device
LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions
LT.setRfFrequency(Frequency, Offset); //set the operating frequency
LT.calibrateImage(0); //run calibration after setting frequency
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters
LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX
LT.setPacketParams(8, LORA_PACKET_FIXED_LENGTH, PacketLength, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34
LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current
//This is the typical IRQ parameters set, actually excecuted in the receive function
LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_RX_DONE, 0, 0); //set for IRQ on RX done
}
void setup()
{
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("41_LoRa_Receiver_ImplicitPacket Starting"));
Serial.println();
if (BUZZER > 0)
{
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
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));
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
//this function call sets up the device for LoRa using the settings from the Settings.h file
setupLoRa();
Serial.println();
LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check
Serial.println();
LT.printOperatingSettings(); //reads and prints the configured operting settings, useful check
Serial.println();
Serial.println();
LT.printRegisters(0x00, 0x4F); //print contents of device registers
Serial.println();
Serial.println();
Serial.print(F("Receiver ready - RXBUFFER_SIZE "));
Serial.println(RXBUFFER_SIZE);
Serial.println();
}

View File

@@ -0,0 +1,45 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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. Some pins such as DIO1,
//DIO2, BUZZER may not be in used by this sketch so they do not need to be
//connected and should be included and be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define BUZZER 4 //pin for buzzer, on when logic high
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup LoRa Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF6; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const uint8_t PacketLength = 23; //packet length is fixed
const int8_t TXpower = 2; //LoRa transmit power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets
#define RXBUFFER_SIZE 32 //RX buffer size

View File

@@ -0,0 +1,99 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/20
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 transmits a packet without using a processor buffer, the LoRa device
internal buffer is filled direct with variables. The program is a simulation of the type of packet
that might be sent from a GPS tracker. Note that in this example a buffer of text is part of the
transmitted packet.
The matching receiving program '9_LoRa_LowMemory_RX' can be used to receive and display the packet
The contents of the packet received, and printed to serial monitor, should be;
TR1 (buffer) - trackerID
51.23456 (float) - latitude
-3.12345 (float) - longitude
199 (uint16_t) - altitude
8 (uint8_t) - number of satellites
3999 (uint16_t) - battery voltage
-9 (int8_t) - temperature
Memory use on an Arduino Pro Mini;
Sketch uses 4958 bytes (15%) of program storage space.
Global variables use 224 bytes (10%) of dynamic memory, leaving 1824 bytes for local variables.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <Arduino.h>
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
SX127XLT LoRa;
void loop()
{
//The SX12XX buffer is filled with variables of a known type and order. Make sure the receiver
//uses the same variable type and order to read variables out of the receive buffer.
char trackerID[] = "TR1";
float latitude = 51.23456;
float longitude = -3.12345;
uint16_t altitude = 199;
uint8_t satellites = 8;
uint16_t voltage = 3999;
int16_t temperature = 9;
uint8_t TXPacketL = 0;
uint8_t BytesSent = 0;
LoRa.startWriteSXBuffer(0); //start the write at SX12XX internal buffer location 0
LoRa.writeBufferChar(trackerID, sizeof(trackerID)); //+4 bytes (3 characters plus null (0) at end)
LoRa.writeFloat(latitude); //+4 = 8 bytes
LoRa.writeFloat(longitude); //+4 = 12 bytes
LoRa.writeUint16(altitude); //+2 = 14 bytes
LoRa.writeUint8(satellites); //+1 = 15 bytes
LoRa.writeUint16(voltage); //+2 = 17 bytes
LoRa.writeInt8(temperature); //+1 = 18 bytes total to send
TXPacketL = LoRa.endWriteSXBuffer(); //closes packet write and returns the length of the packet to send
BytesSent = LoRa.transmitSXBuffer(0, TXPacketL, 5000, TXpower, WAIT_TX); //set a TX timeout of 5000mS
if (BytesSent == 0) //if bytessent is 0, there has been a error
{
Serial.print(F("Send Error"));
}
else
{
Serial.print(BytesSent);
Serial.print(F(" Bytes Sent"));
}
Serial.println();
delay(packet_delay);
}
void setup()
{
Serial.begin(9600);
SPI.begin();
if (!LoRa.begin(NSS, NRESET, DIO0, LORA_DEVICE))
{
Serial.println(F("Device error"));
while (1);
}
LoRa.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.flush();
}

View File

@@ -0,0 +1,30 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/20
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 DIO0 3 //DIO0 on LoRa device, used for RX and TX done
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 10; //LoRa TX power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets

View File

@@ -0,0 +1,168 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/20
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 receives a packet without using a memory buffer, the LoRa device
internal buffer is read direct for variables. The program is a simulation of the type of packet
that might be received from a GPS tracker. Note that in this example a buffer of text is part of the
received packet.
The matching transmitter program '8_LoRa_LowMemory_TX' is used to transmit the packet.
The contents of the packet received, and printed to serial monitor, should be;
TR1 (buffer) - trackerID
51.23456 (float) - latitude
-3.12345 (float) - longitude
199 (uint16_t) - altitude
8 (uint8_t) - number of satellites
3999 (uint16_t) - battery voltage
-9 (int8_t) - temperature
Memory use on an Arduino Pro Mini;
Sketch uses 6290 bytes (19%) of program storage space.
Global variables use 237 bytes (11%) of dynamic memory, leaving 1811 bytes for local variables.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
SX127XLT LoRa;
void loop()
{
uint8_t RXPacketL;
RXPacketL = LoRa.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout
if (RXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
Serial.println();
}
uint8_t packet_is_OK()
{
char receivebuffer[4]; //create receive buffer, make sure this is big enough for buffer sent !!!
float latitude;
float longitude;
uint16_t altitude;
uint8_t satellites;
uint16_t voltage;
int8_t temperature;
uint8_t RXPacketL;
static uint8_t RXpacketCount;
//packet has been received, now read from the SX12xx Buffer using the same variable type and
//order as the transmit side used.
RXpacketCount++;
Serial.print(RXpacketCount);
Serial.print(F(" "));
LoRa.startReadSXBuffer(0); //start buffer read at location 0
LoRa.readBufferChar(receivebuffer); //read in the character buffer
latitude = LoRa.readFloat(); //read in the latitude
longitude = LoRa.readFloat(); //read in the longitude
altitude = LoRa.readUint16(); //read in the altitude
satellites = LoRa.readUint8(); //read in the number of satellites
voltage = LoRa.readUint16(); //read in the voltage
temperature = LoRa.readInt8(); //read in the temperature
RXPacketL = LoRa.endReadSXBuffer(); //finish packet read, get received packet length
Serial.print(receivebuffer); //print the received character buffer
Serial.print(F(","));
Serial.print(latitude, 5);
Serial.print(F(","));
Serial.print(longitude, 5);
Serial.print(F(","));
Serial.print(altitude);
Serial.print(F("m,"));
Serial.print(satellites);
Serial.print(F("sats,"));
Serial.print(voltage);
Serial.print(F("mV,"));
Serial.print(temperature);
Serial.print(F("c "));
printpacketDetails();
return RXPacketL;
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LoRa.readIrqStatus();
if (IRQStatus & IRQ_RX_TIMEOUT)
{
Serial.print(F("RXTimeout"));
}
else
{
Serial.print(F("PacketError"));
printpacketDetails();
Serial.print(F("IRQreg,"));
Serial.print(IRQStatus, HEX);
}
}
void printpacketDetails()
{
int16_t PacketRSSI; //RSSI of received packet
int8_t PacketSNR; //signal to noise ratio of received packet
PacketRSSI = LoRa.readPacketRSSI();
PacketSNR = LoRa.readPacketSNR();
Serial.print(F(" RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB"));
}
void setup()
{
Serial.begin(9600);
SPI.begin();
if (LoRa.begin(NSS, NRESET, DIO0, LORA_DEVICE))
{
Serial.println(F("Device OK"));
}
else
{
Serial.println(F("Device error"));
while (1);
}
Serial.flush();
LoRa.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
}

View File

@@ -0,0 +1,28 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 05/11/20
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 DIO0 3 //DIO0 on LoRa device, used for RX and TX done
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 10; //LoRa TX power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets

View File

@@ -0,0 +1,306 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 program is a remote control transmitter. When one of four switches are made
(shorted to ground) a packet is transmitted with single byte indicating the state of Switch0 as bit 0,
Switch1 as bit 1 and Switch2 as bit 2. To prevent false triggering at the receiver the packet contains a
32 bit number called the TXIdentity which in this example is set to 1234554321. The receiver will only
act on, change the state of the outputs, if the identity set in the receiver matches that of the
transmitter. The chance of a false trigger is fairly remote.
Between switch presses the LoRa device and Atmel microcontroller are put to sleep. A switch press wakes
up the processor from sleep, the switches are read and a packet sent. On a 'bare bones' Arduino setup
the transmitter has a sleep current of approx 2.2uA, so it's ideal for a battery powered remote control
with a potential range of many kilometres.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. These settings
are not necessarily optimised for long range.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
#include <ProgramLT_Definitions.h>
#include <avr/wdt.h> //watchdog timer library, integral to Arduino IDE
#include <avr/sleep.h> //watchdog timer library, integral to Arduino IDE
#include "PinChangeInterrupt.h" //get the library here; https://github.com/NicoHood/PinChangeInterrupt
SX127XLT LT;
uint32_t TXpacketCount;
uint8_t TXPacketL;
volatile bool switch0flag = false;
volatile bool switch1flag = false;
volatile bool switch2flag = false;
volatile bool switch3flag = false;
void loop()
{
uint8_t switches;
digitalWrite(LED1, LOW); //turn off indicator LED
Serial.print(F("Sleeping zzzz"));
Serial.flush(); //make sure all serial output has gone
LT.setSleep(CONFIGURATION_RETENTION); //sleep LoRa device, keeping register settings in sleep.
sleep_permanent(); //sleep Atmel processor permanently for switch wakeup only
digitalWrite(LED1, HIGH);
Serial.println(F(" - Awake !!")); //the processor has woken up
switches = readSwitches(); //read the state of the switches
TXpacketCount++;
Serial.print(TXpacketCount); //print the numbers of sends
Serial.print(F(" Sending > "));
Serial.print(switches, BIN);
if (sendSwitchPacket(switches))
{
Serial.println(F(" SentOK"));
}
else
{
Serial.print(F("Send Error - IRQreg,"));
Serial.print(LT.readIrqStatus(), HEX);
}
Serial.println();
delay(500);
}
uint8_t sendSwitchPacket(uint8_t switches)
{
//The SX12XX buffer is filled with variables of a known type and in a known sequence. Make sure the
//receiver uses the same variable types and sequence to read variables out of the receive buffer.
uint8_t len;
LT.startWriteSXBuffer(0); //start the write packet to buffer process
LT.writeUint8(RControl1); //this byte identifies the type of packet
LT.writeUint32(TXIdentity); //this 32bit integer defines the Identity of the transmiter
LT.writeUint8(switches); //this byte contains the 8 switch values to be sent
len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent
//now transmit the packet, 10 second timeout, and wait for it to complete sending
TXPacketL = LT.transmitSXBuffer(0, len, 10000, TXpower, WAIT_TX);
return TXPacketL; //TXPacketL will be 0 if there was an error sending
}
void sleep_permanent()
{
attachInterrupts();
ADCSRA = 0; //disable ADC
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
noInterrupts (); //timed sequence follows
sleep_enable();
// turn off brown-out enable in software
MCUCR = bit (BODS) | bit (BODSE); //turn on brown-out enable select
MCUCR = bit (BODS); //this must be done within 4 clock cycles of above
interrupts (); //guarantees next instruction executed
sleep_cpu (); //sleep within 3 clock cycles of above
/* wake up here */
sleep_disable();
detachInterrupts();
}
void attachInterrupts()
{
if (SWITCH0 >= 0)
{
attachPCINT(digitalPinToPCINT(SWITCH0), wake0, FALLING);
switch0flag = false;
}
if (SWITCH1 >= 0)
{
attachPCINT(digitalPinToPCINT(SWITCH1), wake1, FALLING);
switch1flag = false;
}
if (SWITCH2 >= 0)
{
attachPCINT(digitalPinToPCINT(SWITCH2), wake2, FALLING);
switch2flag = false;
}
if (SWITCH3 >= 0)
{
attachPCINT(digitalPinToPCINT(SWITCH3), wake3, FALLING);
switch3flag = false;
}
}
void detachInterrupts()
{
if (SWITCH0 >= 0)
{
detachPCINT(digitalPinToPCINT(SWITCH0));
}
if (SWITCH1 >= 0)
{
detachPCINT(digitalPinToPCINT(SWITCH1));
}
if (SWITCH2 >= 0)
{
detachPCINT(digitalPinToPCINT(SWITCH2));
}
if (SWITCH3 >= 0)
{
detachPCINT(digitalPinToPCINT(SWITCH3));
}
}
void wake0()
{
switch0flag = true;
}
void wake1()
{
switch1flag = true;
}
void wake2()
{
switch2flag = true;
}
void wake3()
{
switch3flag = true;
}
uint8_t readSwitches()
{
uint8_t switchByte = 0xFF; //start assuming all switches off
if (switch0flag)
{
bitClear(switchByte, 0); //if the flag is set clear the bit
Serial.println(F("SWITCH0 pressed"));
}
if (switch1flag)
{
bitClear(switchByte, 1); //if the flag is set clear the bit
Serial.println(F("SWITCH1 pressed"));
}
if (switch2flag)
{
bitClear(switchByte, 2); //if the flag is set clear the bit
Serial.println(F("SWITCH2 pressed"));
}
if (switch3flag)
{
bitClear(switchByte, 3); //if the flag is set clear the bit
Serial.println(F("SWITCH3 pressed"));
}
return switchByte;
}
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 setupSwitches()
{
if (SWITCH0 >= 0)
{
pinMode(SWITCH0, INPUT_PULLUP);
}
if (SWITCH1 >= 0)
{
pinMode(SWITCH1, INPUT_PULLUP);
}
if (SWITCH2 >= 0)
{
pinMode(SWITCH2, INPUT_PULLUP);
}
if (SWITCH3 >= 0)
{
pinMode(SWITCH3, INPUT_PULLUP);
}
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
setupSwitches();
Serial.begin(9600);
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
led_Flash(2, 125);
}
else
{
Serial.println(F("Device error"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates LoRa device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println(F("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,47 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 definitiosn to match your own setup. Some pins such as DIO1,
//DIO2, may not be in used by this sketch so they do not need to be connected and
//should be set to -1.
const int8_t NSS = 10; //select on LoRa device
const int8_t NRESET = 9; //reset on LoRa device
const int8_t DIO0 = 3; //DIO0 on LoRa device, used for RX and TX done
const int8_t DIO1 = -1; //DIO1 on LoRa device, normally not used so set to -1
const int8_t DIO2 = -1; //DIO2 on LoRa device, normally not used so set to -1
const int8_t LED1 = 8; //On board LED, logic high is on
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
const int8_t SWITCH0 = 2;
const int8_t SWITCH1 = 4;
const int8_t SWITCH2 = A3;
const int8_t SWITCH3 = A2;
const uint32_t TXIdentity = 1234554321; //define an identity number, the receiver must use the same number
//range is 0 to 4294967296
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 10; //LoRa transmit power in dBm

View File

@@ -0,0 +1,297 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 31/12/19
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 program is a remote control receiver. When a packet is received an 8 bit byte
(SwitchByte) is read and the four outputs (defined in Settings.h) are toggled according to the bits
set in this byte. If the Switch1 byte has bit 0 cleared, then OUTPUT0 is toggled. If the Switch1 byte
has bit 1 cleared, then OUTPUT1 is toggled. If the Switch1 byte has bit 2 cleared, then OUTPUT2 is toggled.
To prevent false triggering at the receiver the packet contains also contains a 32 bit number called the
TXIdentity which in this example is set to 1234554321. The receiver will only act on, change the state
of the outputs, if the identity set in the receiver matches that of the transmitter. The chance of a
false trigger is fairly remote.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define programversion "V1.0"
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
#include <ProgramLT_Definitions.h>
SX127XLT LT;
uint32_t RXpacketCount;
uint16_t errors;
uint8_t RXPacketL; //length of received packet
uint8_t RXPacketType; //type of received packet
int16_t PacketRSSI; //RSSI of received packet
int8_t PacketSNR; //signal to noise ratio of received packet
uint8_t SwitchByte = 0xFF; //this is the transmitted switch values, bit 0 = Switch0 etc
void loop()
{
RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout
digitalWrite(LED1, HIGH); //something has happened
PacketRSSI = LT.readPacketRSSI(); //read the signal strength of the received packet
PacketSNR = LT.readPacketSNR(); //read the signal to noise ratio of the received packet
if (RXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_is_OK();
}
digitalWrite(LED1, LOW);
Serial.println();
}
uint8_t packet_is_OK()
{
//packet has been received, now read from the SX12xx Buffer using the same variable type and
//order as the transmit side used.
uint32_t TXIdentity;
RXpacketCount++;
Serial.print(RXpacketCount);
Serial.print(F(" Packet Received"));
LT.startReadSXBuffer(0); //start buffer read at location 0
RXPacketType = LT.readUint8(); //read in the packet type
TXIdentity = LT.readUint32(); //read in the identity of transmitter
SwitchByte = LT.readUint8(); //read in the Switch values
RXPacketL = LT.endReadSXBuffer(); //finish buffer read
printpacketDetails();
if (RXPacketType != RControl1)
{
Serial.print(F(" Wrong packet type"));
led_Flash(5, 25); //short fast speed flash indicates wrong packet type
return 0;
}
if (TXIdentity != RXIdentity)
{
Serial.print(F(" Transmitter "));
Serial.print(TXIdentity);
Serial.print(F(" not recognised"));
led_Flash(5, 25); //short fast speed flash indicates transmitter not recognised
return 0;
}
if (LT.readRXPacketL() != 6)
{
Serial.print(F(" Wrong Packet Length"));
led_Flash(5, 25); //short fast speed flash indicates transmitter not recognised
return 0;
}
//if we get to here, then the packet is valid so switch outputs accordingly
if (BUZZER >= 0)
{
digitalWrite(BUZZER, HIGH);
}
Serial.print(F(",SwitchByte Received "));
Serial.print(SwitchByte, BIN); //print switch values in binary, if a bit is 0, that switch is active
actionOutputs(SwitchByte);
if (BUZZER >= 0)
{
digitalWrite(BUZZER, LOW);
}
return RXPacketL;
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus();
if (IRQStatus & IRQ_RX_TIMEOUT)
{
Serial.print(F("RXTimeout"));
}
else
{
errors++;
Serial.print(F("PacketError"));
printpacketDetails();
Serial.print(F("IRQreg,"));
Serial.print(IRQStatus, HEX);
}
}
void printpacketDetails()
{
Serial.print(F(" RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL());
}
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 actionOutputs(uint8_t switches)
{
//read the recreived switch byte and toggle outputs as required
if (!bitRead(switches, 0))
{
//toggle Output state
digitalWrite(OUTPUT0, !digitalRead(OUTPUT0)); //toggle Output state
}
if (!bitRead(switches, 1))
{
digitalWrite(OUTPUT1, !digitalRead(OUTPUT1)); //toggle Output state
}
if (!bitRead(switches, 2))
{
digitalWrite(OUTPUT2, !digitalRead(OUTPUT2)); //toggle Output state
}
if (!bitRead(switches, 3))
{
digitalWrite(OUTPUT3, !digitalRead(OUTPUT3)); //toggle Output state
}
}
void setupOutputs()
{
//configure the output pins, if a pin is defiend in 'Settings.h' as -1, its not configured, so stays as input
if (OUTPUT0 >= 0)
{
pinMode(OUTPUT0, OUTPUT);
}
if (OUTPUT1 >= 0)
{
pinMode(OUTPUT1, OUTPUT);
}
if (OUTPUT2 >= 0)
{
pinMode(OUTPUT2, OUTPUT);
}
if (OUTPUT3 >= 0)
{
pinMode(OUTPUT3, OUTPUT);
}
if (BUZZER >= 0)
{
pinMode(BUZZER, OUTPUT);
}
}
void outputCheck(uint8_t number, uint32_t ondelaymS, uint32_t offdelaymS)
{
uint8_t index;
Serial.println(F("Toggling outputs"));
for (index = 1; index <= number; index++)
{
digitalWrite(OUTPUT0, HIGH);
delay(ondelaymS);
digitalWrite(OUTPUT0, LOW);
delay(offdelaymS);
digitalWrite(OUTPUT1, HIGH);
delay(ondelaymS);
digitalWrite(OUTPUT1, LOW);
delay(offdelaymS);
digitalWrite(OUTPUT2, HIGH);
delay(ondelaymS);
digitalWrite(OUTPUT2, LOW);
delay(offdelaymS);
digitalWrite(OUTPUT3, HIGH);
delay(offdelaymS);
digitalWrite(OUTPUT3, LOW);
delay(offdelaymS);
digitalWrite(BUZZER, HIGH);
delay(offdelaymS);
digitalWrite(BUZZER, LOW);
delay(offdelaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
Serial.begin(9600);
setupOutputs();
outputCheck(3, 500, 100);
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
led_Flash(2, 125);
}
else
{
Serial.println(F("Device error"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println(F("Receiver ready"));
}

View File

@@ -0,0 +1,44 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 31/12/19
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 definitiosn to match your own setup. Some pins such as DIO1,
//DIO2, may not be in used by this sketch so they do not need to be connected and
//should be set to -1.
const int8_t NSS = 10; //select on LoRa device
const int8_t NRESET = 9; //reset on LoRa device
const int8_t DIO0 = 3; //DIO0 on LoRa device, used for RX and TX done
const int8_t DIO1 = -1; //DIO1 on LoRa device, normally not used so set to -1
const int8_t DIO2 = -1; //DIO2 on LoRa device, normally not used so set to -1
const int8_t LED1 = 8; //On board LED, logic high is on
const int8_t BUZZER = A5; //buzzer if fitted, set to -1 if not
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
const int8_t OUTPUT0 = 2;
const int8_t OUTPUT1 = 4;
const int8_t OUTPUT2 = A3;
const int8_t OUTPUT3 = A2;
const uint32_t RXIdentity = 1234554321; //define an identity number, the receiver must use the same number
//range is 0 to 4294967296
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting

View File

@@ -0,0 +1,229 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 30/12/19
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 remote control transmitter that uses a LoRa link to transmit the positions
from a simple joystick to a remote receiver. The receiver uses the sent joystick positions to adjust the
positions of servos. The postions of the joysticks potentiometers on the transmitter are read with the
analogueRead() function.
If the joystick has a switch, often made by pressing on the joystick, then this can be used to remote
control an output on the receiver. The switch is read by an interrupt, the interrupt routine sets a flag
byte which is read in loop().
The program is intended as a proof of concept demonstration of how to remote control servos, the program
is not designed as a practical remote control device for RC model cars for instance.
It would be straight forward to make the transmitter program send packets continuously, but in most places
in the world that would break a normal limitation of 10% duty cycle for unlicensed use. Therefore the
program was designed to only transmit at a 10% duty cycle. Thus the fastest (lowest air time) packets are
used, spreading factor 6 at a bandwidth of 500khz. This results in an air time for the 5 byte control
packet of around 4mS, so there are around 25 sent per second.
To have the transmitter program print out the values read from the joystick, comment in the line;
//#define DEBUG
Which is just above the loop() function. With the DEBUG enabled the transmission rate, the rate at which
the control packets are transmitted will be slowed down.
To reduce the risk of the receiver picking up LoRa packets from other sources, the packet sent contains a
'TXidentity' number, valid values are 0 - 65535. The receiver must be setup with the matching identity
number or the received packets will be ignored.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. These settings
are not necessarily optimised for long range.
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
#include <ProgramLT_Definitions.h>
SX127XLT LT;
#include "PinChangeInterrupt.h" //get the library here; https://github.com/NicoHood/PinChangeInterrupt
uint32_t TXpacketCount;
uint8_t TXPacketL;
uint8_t joystickX1value; //variable to read the value from the analog pin
uint8_t joystickY1value; //variable to read the value from the analog pin
volatile bool switch1flag = false;
//#define DEBUG //comment in thie line (remove the two // at the beggining) for debug output
void loop()
{
uint8_t switchByte = 0xFF;
joystickX1value = (uint8_t) (analogRead(joystickX1) / 4) ; //read the joystick X1 pot, turn 0-1023 into 0 to 255
joystickY1value = (uint8_t) (analogRead(joystickY1) / 4); //read the joystick Y1 pot
if (switch1flag)
{
bitClear(switchByte, 1); //if the switch is down clear the bit
digitalWrite(LED1, HIGH); //turn on LED as switch indicator
switch1flag = false;
}
if (!sendJoystickPacket(joystickX1value, joystickY1value, switchByte))
{
Serial.print(F("Send Error - IRQreg,"));
Serial.print(LT.readIrqStatus(), HEX);
}
}
uint8_t sendJoystickPacket(uint16_t X1value, uint16_t Y1value, uint8_t switches)
{
//The SX12XX buffer is filled with variables of a known type and in a known sequence. Make sure the
//receiver uses the same variable types and sequence to read variables out of the receive buffer.
//uint8_t len;
uint32_t packetStartmS, packettimemS;
LT.startWriteSXBuffer(0); //start the write packet to buffer process
LT.writeUint8(RControl1); //this is the packet type
LT.writeUint8(TXIdentity); //this value represents the transmitter number
LT.writeUint8(X1value); //this byte contains joystick pot AD X1 value to be sent
LT.writeUint8(Y1value); //this byte contains joystick pot AD Y1 value to be sent
LT.writeUint8(switches); //switches value
LT.endWriteSXBuffer(); //close the packet, thee are 5 bytes to send
//now transmit the packet, 10 second timeout, and wait for it to complete sending
packetStartmS = millis();
TXPacketL = LT.transmitSXBuffer(0, PacketLength, 10000, TXpower, WAIT_TX);
packettimemS = millis() - packetStartmS;
#ifdef DEBUG
Serial.print(TXIdentity);
Serial.print(F(",X1,"));
Serial.print(joystickX1value);
Serial.print(F(",Y1,"));
Serial.print(joystickY1value);
Serial.print(F(","));
Serial.print(switches, BIN);
Serial.print(F(","));
Serial.print(packettimemS);
Serial.print(F("mS"));
Serial.println();
#endif
digitalWrite(LED1, LOW); //LED off, may have been on due to switch press
delay(packettimemS * 9); //delay for 9 times packet transmit time to ensure 10% duty cycle
return TXPacketL; //TXPacketL will be 0 if there was an error sending
}
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 attachInterrupts()
{
if (SWITCH1 >= 0)
{
attachPCINT(digitalPinToPCINT(SWITCH1), wake1, FALLING);
switch1flag = false;
}
}
void detachInterrupts()
{
if (SWITCH1 >= 0)
{
detachPCINT(digitalPinToPCINT(SWITCH1));
}
}
void wake1()
{
switch1flag = true;
}
void setupSwitches()
{
if (SWITCH1 >= 0)
{
pinMode(SWITCH1, INPUT_PULLUP);
}
}
void setupLoRa()
{
//this setup is used so as the implicit packet type,LORA_PACKET_FIXED_LENGTH, is used
LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device
LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions
LT.setRfFrequency(Frequency, Offset); //set the operating frequency
LT.calibrateImage(0); //run calibration after setting frequency
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters
LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX
LT.setPacketParams(8, LORA_PACKET_FIXED_LENGTH, PacketLength, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34
LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current
//This is the typical IRQ parameters set, actually excecuted in the transmit function
LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on TX done
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
setupSwitches();
Serial.begin(115200);
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
led_Flash(2, 125);
}
else
{
Serial.println(F("Device error"));
while (1)
{
led_Flash(50, 50);
}
}
//this function call sets up the device for LoRa using the settings from the Settings.h file
setupLoRa();
attachInterrupts();
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(F("35_Remote_Control_Servo_Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,47 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 definitiosn to match your own setup. Some pins such as DIO1,
//DIO2, may not be in used by this sketch so they do not need to be connected and
//should be set to -1.
const int8_t NSS = 10; //select on LoRa device
const int8_t NRESET = 9; //reset on LoRa device
const int8_t DIO0 = 3; //DIO0 on LoRa device, used for RX and TX done
const int8_t DIO1 = -1; //DIO1 on LoRa device, normally not used so set to -1
const int8_t DIO2 = -1; //DIO2 on LoRa device, normally not used so set to -1
const int8_t LED1 = 8; //On board LED, logic high is on
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
const int8_t joystickX1 = A2; //analog pin for the joystick 1 X pot
const int8_t joystickY1 = A3; //analog pin for the joystick 1 Y pot
const int8_t SWITCH1 = 2; //switch on joystick, set to -1 if not used
const uint32_t TXIdentity = 123 ; //define a transmitter number, the receiver must use the same number
//range is 0 to 255
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_500; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF6; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const uint8_t PacketLength = 5; //packet length is fixed
const int8_t TXpower = 10; //LoRa transmit power in dBm

View File

@@ -0,0 +1,275 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 30/12/19
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 remote control receiver that uses a LoRa link to control the positions of
servos sent from a remote transmitter.
If the ttransmitter joystick has a switch, often made by pressing on the joystick, then this can be used
to remote control an output on the receiver.
The program is intended as a proof of concept demonstration of how to remote control servos, the program
is not designed as a practical remote control device for RC model cars for instance.
It would be straight forward to make the transmitter program send packets continuously, but in most places
in the world that would break a normal limitation of 10% duty cycle for unlicensed use. Therefore the
program was designed to only transmit at a 10% duty cycle. Thus the fastest (lowest air time) packets are
used, spreading factor 6 at a bandwidth of 500khz. This results in an air time for the 5 byte control
packet of around 4mS, so there are around 25 sent per second.
To have the receiver program print out the joystick values (0-255) read from the received packet, comment
in the line;
//#define DEBUG
Which is just above the loop() function. With the DEBUG enabled then there is a possibility that some
transmitted packets will be missed. With the DEBUG line enabled to servos should also sweep to and fro 3
times at program start-up.
To reduce the risk of the receiver picking up LoRa packets from other sources, the packet sent contains a
'TXidentity' number, valid values are 0 - 255. The receiver must be setup with the matching RXIdentity
number in Settings.h or the received packets will be ignored.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file. These settings
are not necessarily optimised for long range.
Serial monitor baud rate is set at 115200.
*******************************************************************************************************/
#define programversion "V1.0"
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
#include <ProgramLT_Definitions.h>
SX127XLT LT;
#include <Servo.h>
Servo ServoX1; //create the servo object
Servo ServoY1; //create the servo object
uint8_t joystickX1value; //variable to read the value from the analog pin
uint8_t joystickY1value; //variable to read the value from the analog pin
uint8_t RXPacketL; //length of received packet
uint8_t RXPacketType; //type of received packet
//#define DEBUG
void loop()
{
RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort
while (!digitalRead(DIO0)); //wait for DIO0 to go high
if ( LT.readIrqStatus() == (IRQ_RX_DONE + IRQ_HEADER_VALID))
{
packet_is_OK();
}
else
{
packet_is_Error();
}
}
uint8_t packet_is_OK()
{
//packet has been received, now read from the SX12xx Buffer using the same variable type and
//order as the transmit side used.
uint8_t TXIdentity;
uint16_t pulseX1, pulseY1;
uint8_t switchByte = 0xFF; //this is the transmitted switch values, bit 0 = Switch0 etc
LT.startReadSXBuffer(0); //start buffer read at location 0
RXPacketType = LT.readUint8(); //read in the packet type
TXIdentity = LT.readUint8(); //read in the transmitter number
joystickX1value = LT.readUint8(); //this byte contains joystick pot AD X1 value sent
joystickY1value = LT.readUint8(); //this byte contains joystick pot AD Y1 value sent
switchByte = LT.readUint8(); //read in the Switch values
RXPacketL = LT.endReadSXBuffer(); //end buffer read
#ifdef DEBUG
Serial.print(TXIdentity);
Serial.print(F(",X1,"));
Serial.print(joystickX1value);
Serial.print(F(",Y1,"));
Serial.print(joystickY1value);
Serial.print(F(","));
Serial.print(switchByte, BIN);
Serial.println();
#endif
if (RXPacketType != RControl1)
{
Serial.print(F("Packet type "));
Serial.println(RXPacketType);
led_Flash(5, 25); //short fast speed flash indicates wrong packet type
return 0;
}
if (TXIdentity != RXIdentity)
{
Serial.print(F("TX"));
Serial.print(TXIdentity);
Serial.println(F("?"));
return 0;
}
//actionServos
pulseX1 = map(joystickX1value, 0, 255, 1000, 2000); //scale the numbers from the joystick
ServoX1.writeMicroseconds(pulseX1);
pulseY1 = map(joystickY1value, 0, 255, 1000, 2000); //scale the numbers from the joystick
ServoY1.writeMicroseconds(pulseY1); //move the servo to position
//actionOutputs
if (!bitRead(switchByte, 1))
{
digitalWrite(OUTPUT1, !digitalRead(OUTPUT1)); //Toggle Output state
}
return RXPacketL;
}
void packet_is_Error()
{
uint16_t IRQStatus;
int16_t PacketRSSI;
IRQStatus = LT.readIrqStatus();
if (IRQStatus & IRQ_RX_TIMEOUT)
{
Serial.print(F("RXTimeout"));
}
else
{
PacketRSSI = LT.readPacketRSSI(); //read the signal strength of the received packet
Serial.print(F("Err,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm"));
}
Serial.println();
}
void setupOutputs()
{
//configure the output pins, if a pin is defiend in 'Settings.h' as -1, its not configured, so stays as input
if (OUTPUT1 >= 0)
{
pinMode(OUTPUT1, OUTPUT);
}
}
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 sweepTest(uint8_t num)
{
uint16_t index1, index2;
for (index1 = 1; index1 <= num; index1++)
{
for (index2 = 900; index2 <= 2100; index2++)
{
ServoX1.writeMicroseconds(index2);
ServoY1.writeMicroseconds(index2);
}
delay(1000);
for (index2 = 2100; index2 >= 900; index2--)
{
ServoX1.writeMicroseconds(index2);
ServoY1.writeMicroseconds(index2);
}
delay(1000);
}
}
void setupLoRa()
{
//this setup is used so as the implicit packet type,LORA_PACKET_FIXED_LENGTH, is used
LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device
LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions
LT.setRfFrequency(Frequency, Offset); //set the operating frequency
LT.calibrateImage(0); //run calibration after setting frequency
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters
LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX
LT.setPacketParams(8, LORA_PACKET_FIXED_LENGTH, PacketLength, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34
LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current
//This is the typical IRQ parameters set, actually excecuted in the transmit function
LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on TX done
}
void setup()
{
pinMode(LED1, OUTPUT);
led_Flash(2, 125);
setupOutputs();
Serial.begin(115200);
ServoX1.attach(pinservoX1); //connect pin pinservoX1 to ServoX1 object
ServoY1.attach(pinservoY1); //connect pin pinservoY1 to ServoY1 object
#ifdef DEBUG
Serial.println(F("Servo sweep test"));
sweepTest(3);
#endif
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
led_Flash(2, 125);
}
else
{
Serial.println(F("Device error"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates device error
}
}
//this function call sets up the device for LoRa using the settings from the Settings.h file
setupLoRa();
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(F("36_Remote_Control_Servo_Receiver ready"));
Serial.println();
}

View File

@@ -0,0 +1,43 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 02/12/19
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 definitiosn to match your own setup. Some pins such as DIO1,
//DIO2, may not be in used by this sketch so they do not need to be connected and
//should be set to -1.
const int8_t NSS = 10; //select on LoRa device
const int8_t NRESET = 9; //reset on LoRa device
const int8_t DIO0 = 3; //DIO0 on LoRa device, used for RX and TX done
const int8_t DIO1 = -1; //DIO1 on LoRa device, normally not used so set to -1
const int8_t DIO2 = -1; //DIO2 on LoRa device, normally not used so set to -1
const int8_t LED1 = 8; //On board LED, logic high is on
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
const int8_t pinservoX1 = 2; //pin for controlling servo X1
const int8_t pinservoY1 = 4; //pin for controlling servo Y1
const int8_t OUTPUT1 = 8; //this output toggles when joystick switch is pressed on receiver
const uint16_t RXIdentity = 123; //define a receiver number, the transmitter must use the same number
//range is 0 to 255
//******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_500; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF6; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const uint8_t PacketLength = 5; //packet length is fixed

View File

@@ -0,0 +1,127 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 19/09/20
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 LoRa transmitter that transmits a buffer containing text to control a
remote device by sending 'LEDOn' to turn the LED on and 'LEDOff' to turn the LED off.
Sample Serial Monitor output;
86_Buffer_Transmit_Controller Starting
LoRa Device found
Transmitter ready
Send Packet> LEDOn
Send Packet> LEDOff
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
SX127XLT 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 DIO0 3 //DIO0 pin on LoRa device, used for sensing RX and TX done
#define LED1 8 //pin for LED
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
#define TXpower 10 //LoRa transmit power in dBm
#define TXtimeout 10000 //transmit timeout in mS
uint8_t TXPacketL;
uint8_t onpacket[] = "LEDOn"; //send this to turn LED on
uint8_t offpacket[] = "LEDOff"; //send this to turn LED off
#include <SPI.h>
#include <LoRa.h>
void loop()
{
//************************************
//LED on
//************************************
Serial.print(F("Send Packet> ("));
Serial.print(sizeof(onpacket));
Serial.print(F("chars) "));
LT.printASCIIPacket(onpacket, sizeof(onpacket)); //print the buffer (the sent packet) as ASCII
digitalWrite(LED1, HIGH);
LT.transmit(onpacket, sizeof(onpacket), TXtimeout, TXpower, WAIT_TX); //will return packet length sent if OK, otherwise 0 if transmit error
Serial.println();
delay(5000); //have a delay between packets
//************************************
//LED off
//************************************
Serial.print(F("Send Packet> ("));
Serial.print(sizeof(offpacket));
Serial.print(F("chars) "));
LT.printASCIIPacket(offpacket, sizeof(offpacket)); //print the buffer (the sent packet) as ASCII
digitalWrite(LED1, LOW);
LT.transmit(offpacket, sizeof(offpacket), TXtimeout, TXpower, WAIT_TX); //will return packet length sent if OK, otherwise 0 if transmit error
Serial.println();
delay(5000); //have a delay between packets
}
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); //setup pin as output for indicator LED
led_Flash(2, 125);
Serial.begin(9600);
Serial.println();
Serial.println(F("86_Buffer_Transmit_Controller Starting"));
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
LT.setupLoRa(434000000, 0, LORA_SF7, LORA_BW_125, LORA_CR_4_5, LDRO_AUTO); //configure frequency and LoRa settings
Serial.print(F("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,176 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 19/09/20
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 LoRa receiver that listens for packets that are text based commands used
when received to turn a LED on or off. When 'LEDOn' is received the LED is turned on and its turned off
when 'LEDOff' is received.
Sample Serial Monitor output;
87_Buffer_Receive_Controller Starting
LoRa Device found
Receiver ready
2s Received packet > LEDOn,RSSI,-65dBm,SNR,6dB,Length,5 Turn LED on
3s Received packet > LEDOff,RSSI,-62dBm,SNR,5dB,Length,6 Turn LED off
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
SX127XLT 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 DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define LED1 8 //pin for LED
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
#define RXtimeout 60000 //receive timeout in mS
char RXBUFFER[16]; //create the buffer that received packets are copied into
uint8_t RXPacketL; //stores length of packet received
int16_t PacketRSSI; //stores RSSI of received packet
int8_t PacketSNR; //stores signal to noise ratio (SNR) of received packet
char onpacket[] = "LEDOn"; //send this to turn LED on
char offpacket[] = "LEDOff"; //send this to turn LED off
void loop()
{
RXPacketL = LT.receive( (uint8_t*) RXBUFFER, sizeof(RXBUFFER), RXtimeout, WAIT_RX); //wait for a packet to arrive with timeout
PacketRSSI = LT.readPacketRSSI(); //read the received packets RSSI value
PacketSNR = LT.readPacketSNR(); //read the received packets SNR value
if (RXPacketL == 0) //if the LT.receive() function detects an error RXpacketL is 0
{
packet_is_Error();
}
else
{
packet_is_OK();
if (strncmp((char*) RXBUFFER, onpacket, strlen(onpacket)) == 0)
{
Serial.print(F(" Turn LED on"));
digitalWrite(LED1, HIGH);
}
if ( strncmp( (char*) RXBUFFER, offpacket, strlen(offpacket)) == 0)
{
Serial.print(F(" Turn LED off"));
digitalWrite(LED1, LOW);
}
}
Serial.println();
}
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 printElapsedTime()
{
float seconds;
seconds = millis() / 1000;
Serial.print(seconds, 0);
Serial.print(F("s"));
}
void packet_is_OK()
{
printElapsedTime(); //print elapsed time to Serial Monitor
Serial.print(F(" Received packet > "));
LT.printASCIIPacket((uint8_t*)RXBUFFER, RXPacketL); //print the packet as ASCII characters
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(RXPacketL);
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
printElapsedTime(); //print elapsed time to Serial Monitor
Serial.print(F(" Packet error > "));
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout"));
}
else
{
Serial.print(F(" RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL()); //get the real packet length
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus(); //print the names of the IRQ registers set
}
}
void setup()
{
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
led_Flash(2, 125);
Serial.begin(9600);
Serial.println();
Serial.println(F("87_Buffer_Receive_Controller Starting"));
Serial.println();
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
LT.setupLoRa(434000000, 0, LORA_SF7, LORA_BW_125, LORA_CR_4_5, LDRO_AUTO); //configure frequency and LoRa settings
Serial.println(F("Receiver ready"));
}

View File

@@ -0,0 +1,69 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
This programs is supplied as is, it is up to the user of the program to decide if the programs are
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This program blinks an LED connected the pin number defined below. The pin 13 LED,
fitted to some Arduinos is blinked as well. The blinks should be close to one per second. messages are
sent to the Serial Monitor also.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define LED1 8 //pin number for LED, set logic level high for on
#define Program_Version "V1.0"
uint16_t seconds; //used to display time elapsed on Serial Monitor
void loop()
{
Serial.print(seconds);
Serial.println(F(" Seconds")); //this message should print on console at close to once per second
seconds++;
digitalWrite(LED1, HIGH);
digitalWrite(13, HIGH);
delay(100);
digitalWrite(LED1, LOW);
digitalWrite(13, LOW);
delay(890); //should give approx 1 second flash
}
void led_Flash(uint16_t flashes, uint16_t delaymS)
{
//general purpose routine for flashing LED as indicator
uint16_t index;
for (index = 1; index <= flashes; index++)
{
digitalWrite(LED1, HIGH); //LED on
digitalWrite(13, HIGH); //Arduino board LED on
delay(delaymS);
digitalWrite(LED1, LOW); //LED off
digitalWrite(13, LOW); //Arduino board LED off
delay(delaymS);
}
}
void setup()
{
pinMode(LED1, OUTPUT); //setup pin as output for indicator LED
pinMode(13, OUTPUT); //setup pin as output for some Arduino boards that include an LED on pin 13
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(__TIME__);
Serial.print(F(" "));
Serial.println(__DATE__);
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("1_LED_Blink_STM32 Starting"));
}

View File

@@ -0,0 +1,300 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 30/12/19
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 program is stand alone, it is not necessary to install the SX12XX-LoRa library
to use it.
The program checks that a SX127X LoRa device can be accessed by doing a test register write and read.
If there is no device found a message is printed on the serial monitor. The contents of the registers
from 0x00 to 0x7F are printed, there is a copy of a typical printout below. Note that the read back
changed frequency may be slightly different to the programmed frequency, there is a rounding error due
to the use of floats to calculate the frequency.
The Arduino pin numbers that the NSS and NRESET pins on the LoRa device are connected to must be
specified in the hardware definitions section below. The LoRa device type in use, SX1272, SX1276,
SX1277, SX1278 or SX1279 must be specified also.
Typical printout;
2_Register_Test Starting
SX1276-79 Selected
LoRa Device found
Device version 0x12
Frequency at reset 434000000
Registers at reset
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00 00 09 1A 0B 00 52 6C 80 00 4F 09 2B 20 08 02 0A
0x10 FF 6F 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40
0x20 00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55
0x30 90 40 40 00 00 0F 00 00 00 F5 20 82 00 02 80 40
0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B
0x50 14 00 00 12 00 00 00 0F E0 00 0C 00 08 00 5C 78
0x60 00 19 0C 4B CC 0F 01 20 04 47 AF 3F CF 00 53 0B
0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00
Changed Frequency 434099968
Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x00 00 09 1A 0B 00 52 6C 86 66 4F 09 2B 20 08 02 0A
0x10 FF 6F 15 0B 28 0C 12 47 32 3E 00 00 00 00 00 40
0x20 00 00 00 00 05 00 03 93 55 55 55 55 55 55 55 55
0x30 90 40 40 00 00 0F 00 00 00 F5 20 82 00 02 80 40
0x40 00 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B
0x50 14 00 00 12 00 00 00 0F E0 00 0C 00 08 00 5C 78
0x60 00 19 0C 4B CC 0F 01 20 04 47 AF 3F CF 00 53 0B
0x70 D0 01 10 00 00 00 00 00 00 00 00 00 00 00 00 00
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
const uint8_t REG_FRMSB = 0x06; //register number for setting setting and reading frequency, high byte
const uint8_t REG_FRMID = 0x07; //register number for setting setting and reading frequency, mid byte
const uint8_t REG_FRLSB = 0x08; //register number for setting setting and reading frequency, low byte
const uint8_t REG_VERSION = 0x42; //register containg version number of device
const uint8_t DEVICE_SX1272 = 0x10; //SX1272
const uint8_t DEVICE_SX1276 = 0x11; //SX1276
const uint8_t DEVICE_SX1277 = 0x12; //SX1277
const uint8_t DEVICE_SX1278 = 0x13; //SX1278
const uint8_t DEVICE_SX1279 = 0x14; //SX1279
//********* Setup hardware definitions here ! *****************
//These are the pin definitions for one of the Tracker boards, be sure to change them to match your
//own setup. You will also need to connect up the pins for the SPI bus, which on an Arduino Pro Mini are
//SCK pin 13, MISO pin 12, and MOSI pin 11.
#define NSS 10 //SX127X device select
#define NRESET 9 //SX127X reset pin
#define DIO0 -1 //DIO0 pin on LoRa device, not used here so set to -1
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define LORA_DEVICE DEVICE_SX1278 //defines the type of LoRa device used, needed for correct program operation
//**************************************************************/
#include <SPI.h>
void setup()
{
Serial.begin(9600);
Serial.println(F("2_Register_Test_STM32 Starting"));
SPI.begin();
SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
//The begin function setups the hardware pins used by device and then checks if device is found
//the DIO0, DIO1 and DIO2 pins are not used in this example so are set to -1
//the LT.begin fuction can define the pins and device type directly in this way (for SX1278);
//LT.begin(10, 9, -1, -1, -1, DEVICE_SX1278)
if (begin(NSS, NRESET, -1, -1, -1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
}
else
{
Serial.println(F("No device responding"));
}
Serial.print(F("Device version 0x"));
uint8_t deviceversion = readRegister(REG_VERSION);
if (deviceversion < 0x10)
{
Serial.print(F("0"));
}
Serial.println(deviceversion, HEX);
}
void loop()
{
uint32_t frequency;
frequency = getFreqInt(); //read the set frequency following a reset
Serial.print(F("Frequency at reset "));
Serial.println(frequency);
Serial.println(F("Registers at reset")); //show the all registers following a reset
printRegisters(0x00, 0x7F);
Serial.println();
Serial.println();
setRfFrequency(434100000, 0); //change the frequency at reset, in hertz
frequency = getFreqInt(); //read back the changed frequency
Serial.print(F("Changed Frequency "));
Serial.println(frequency); //print the changed frequency, did the write work (allow for rounding errors) ?
printRegisters(0x00, 0x7F); //show the registers after frequency change
Serial.println();
delay(5000);
resetDevice(LORA_DEVICE); //reset the device and start again
}
uint8_t readRegister(uint8_t address)
{
uint8_t regdata;
digitalWrite(NSS, LOW); //set NSS low
SPI.transfer(address & 0x7F); //mask address for read
regdata = SPI.transfer(0); //read the byte
digitalWrite(NSS, HIGH); //set NSS high
return regdata;
}
void writeRegister(uint8_t address, uint8_t value)
{
digitalWrite(NSS, LOW); //set NSS low
SPI.transfer(address | 0x80); //mask address for write
SPI.transfer(value); //write the byte
digitalWrite(NSS, HIGH); //set NSS high
}
uint32_t getFreqInt()
{
//get the current set LoRa device frequency, return as long integer
uint8_t Msb, Mid, Lsb;
uint32_t uinttemp;
float floattemp;
Msb = readRegister(REG_FRMSB);
Mid = readRegister(REG_FRMID);
Lsb = readRegister(REG_FRLSB);
floattemp = ((Msb * 0x10000ul) + (Mid * 0x100ul) + Lsb);
floattemp = ((floattemp * 61.03515625) / 1000000ul);
uinttemp = (uint32_t)(floattemp * 1000000);
return uinttemp;
}
void printRegisters(uint16_t Start, uint16_t End)
{
//prints the contents of SX127x registers to serial monitor
uint16_t Loopv1, Loopv2, RegData;
Serial.print(F("Reg 0 1 2 3 4 5 6 7 8 9 A B C D E F"));
Serial.println();
for (Loopv1 = Start; Loopv1 <= End;)
{
Serial.print(F("0x"));
if (Loopv1 < 0x10)
{
Serial.print(F("0"));
}
Serial.print((Loopv1), HEX);
Serial.print(F(" "));
for (Loopv2 = 0; Loopv2 <= 15; Loopv2++)
{
RegData = readRegister(Loopv1);
if (RegData < 0x10)
{
Serial.print(F("0"));
}
Serial.print(RegData, HEX);
Serial.print(F(" "));
Loopv1++;
}
Serial.println();
}
}
void setRfFrequency(uint64_t freq64, int32_t offset)
{
freq64 = freq64 + offset;
freq64 = ((uint64_t)freq64 << 19) / 32000000;
writeRegister(REG_FRMSB, (uint8_t)(freq64 >> 16));
writeRegister(REG_FRMID, (uint8_t)(freq64 >> 8));
writeRegister(REG_FRLSB, (uint8_t)(freq64 >> 0));
}
void resetDevice(uint8_t device)
{
if (device == DEVICE_SX1272)
{
digitalWrite(NRESET, HIGH);
delay(2);
digitalWrite(NRESET, LOW);
delay(20);
Serial.println(F("SX1272 Selected"));
}
else
{
digitalWrite(NRESET, LOW);
delay(2);
digitalWrite(NRESET, HIGH);
delay(20);
Serial.println(F("SX1276-79 Selected"));
}
}
bool begin(int8_t pinNSS, int8_t pinNRESET, int8_t pinDIO0, int8_t pinDIO1, int8_t pinDIO2, uint8_t device)
{
pinMode(pinNSS, OUTPUT);
digitalWrite(pinNSS, HIGH);
pinMode(pinNRESET, OUTPUT);
digitalWrite(pinNRESET, LOW);
if (pinDIO0 >= 0)
{
pinMode( pinDIO0, INPUT);
}
if (pinDIO1 >= 0)
{
pinMode( pinDIO1, INPUT);
}
if (pinDIO2 >= 0)
{
pinMode( pinDIO2, INPUT);
}
resetDevice(device);
if (checkDevice())
{
return true;
}
return false;
}
bool checkDevice()
{
//check there is a device out there, writes a register and reads back
uint8_t Regdata1, Regdata2;
Regdata1 = readRegister(REG_FRMID); //low byte of frequency setting
writeRegister(REG_FRMID, (Regdata1 + 1));
Regdata2 = readRegister(REG_FRMID); //read changed value back
writeRegister(REG_FRMID, Regdata1); //restore register to original value
if (Regdata2 == (Regdata1 + 1))
{
return true;
}
else
{
return false;
}
}

View File

@@ -0,0 +1,182 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 LoRa test transmitter. A packet containing ASCII text is sent
according to the frequency and LoRa settings specified in the 'Settings.h' file. The pins to access
the SX127X need to be defined in the 'Settings.h' file also.
The details of the packet sent and any errors are shown on the Serial Monitor, together with the transmit
power used, the packet length and the CRC of the packet. The matching receive program, '4_LoRa_Receive'
can be used to check the packets are being sent correctly, the frequency and LoRa settings (in Settings.h)
must be the same for the Transmit and Receive program. Sample Serial Monitor output;
10dBm Packet> {packet contents*} BytesSent,23 CRC,DAAB TransmitTime,54mS PacketsSent,1
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the SX127X device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
uint8_t TXPacketL;
uint32_t TXPacketCount, startmS, endmS;
uint8_t buff[] = "Hello World 1234567890";
void loop()
{
Serial.print(TXpower); //print the transmit power defined
Serial.print(F("dBm "));
Serial.print(F("Packet> "));
Serial.flush();
TXPacketL = sizeof(buff); //set TXPacketL to length of array
buff[TXPacketL - 1] = '*'; //replace null character at buffer end so its visible on reciver
LT.printASCIIPacket(buff, TXPacketL); //print the buffer (the sent packet) as ASCII
digitalWrite(LED1, HIGH);
startmS = millis(); //start transmit timer
if (LT.transmit(buff, TXPacketL, 10000, TXpower, WAIT_TX)) //will return packet length sent if OK, otherwise 0 if transmit error
{
endmS = millis(); //packet sent, note end time
TXPacketCount++;
packet_is_OK();
}
else
{
packet_is_Error(); //transmit packet returned 0, there was an error
}
digitalWrite(LED1, LOW);
Serial.println();
delay(packet_delay); //have a delay between packets
}
void packet_is_OK()
{
//if here packet has been sent OK
uint16_t localCRC;
Serial.print(F(" BytesSent,"));
Serial.print(TXPacketL); //print transmitted packet length
localCRC = LT.CRCCCITT(buff, TXPacketL, 0xFFFF);
Serial.print(F(" CRC,"));
Serial.print(localCRC, HEX); //print CRC of sent packet
Serial.print(F(" TransmitTime,"));
Serial.print(endmS - startmS); //print transmit time of packet
Serial.print(F("mS"));
Serial.print(F(" PacketsSent,"));
Serial.print(TXPacketCount); //print total of packets sent OK
}
void packet_is_Error()
{
//if here there was an error transmitting packet
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the the interrupt register
Serial.print(F(" SendError,"));
Serial.print(F("Length,"));
Serial.print(TXPacketL); //print transmitted packet length
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX); //print IRQ status
LT.printIrqStatus(); //prints the text of which IRQs set
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("3_LoRa_Transmitter_STM32 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));
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
//The function call list below shows the complete setup for the LoRa device using the information defined in the
//Settings.h file.
//The 'Setup LoRa device' list below can be replaced with a single function call;
//LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
//***************************************************************************************************
//Setup LoRa device
//***************************************************************************************************
LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device
LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions
LT.setRfFrequency(Frequency, Offset); //set the operating frequency
LT.calibrateImage(0); //run calibration after setting frequency
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters
LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX
LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34
LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current
LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0); //set for IRQ on RX done
//***************************************************************************************************
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(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F
Serial.println();
Serial.println();
Serial.print(F("Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,39 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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. Some pins such as DIO1,
//DIO2, BUZZER may not be in used by this sketch so they do not need to be
//connected and should be included and be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup LoRa Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const int8_t TXpower = 10; //LoRa transmit power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets

View File

@@ -0,0 +1,247 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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 SX127X need to be defined in the 'Settings.h' file also.
There is a printout of the valid packets received, the packet is assumed to be in ASCII printable text,
if its not ASCII text characters from 0x20 to 0x7F, expect weird things to happen on the Serial Monitor.
The LED will flash for each packet received and the buzzer will sound, if fitted.
Sample serial monitor output;
1109s Hello World 1234567890*,CRC,DAAB,RSSI,-61dBm,SNR,9dB,Length,23,Packets,1026,Errors,0,IRQreg,50
If there is a packet error it might look like this, which is showing a CRC error,
1189s PacketError,RSSI,-111dBm,SNR,-12dB,Length,0,Packets,1126,Errors,1,IRQreg,70,IRQ_HEADER_VALID,IRQ_CRC_ERROR,IRQ_RX_DONE
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the SX127X device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h" //include the setiings file, frequencies, LoRa settings etc
SX127XLT LT; //create a library class instance called LT
uint32_t RXpacketCount;
uint32_t errors;
uint8_t RXBUFFER[RXBUFFER_SIZE]; //create the buffer that received packets are copied into
uint8_t RXPacketL; //stores length of packet received
int8_t PacketRSSI; //stores RSSI of received packet
int8_t PacketSNR; //stores signal to noise ratio of received packet
void loop()
{
RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 60000, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout
digitalWrite(LED1, HIGH); //something has happened
if (BUZZER > 0) //turn buzzer on
{
digitalWrite(BUZZER, HIGH);
}
PacketRSSI = LT.readPacketRSSI(); //read the recived RSSI value
PacketSNR = LT.readPacketSNR(); //read the received SNR value
if (RXPacketL == 0) //if the LT.receive() function detects an error, RXpacketL == 0
{
packet_is_Error();
}
else
{
packet_is_OK();
}
if (BUZZER > 0)
{
digitalWrite(BUZZER, LOW); //buzzer off
}
digitalWrite(LED1, LOW); //LED off
Serial.println();
}
void packet_is_OK()
{
uint16_t IRQStatus, localCRC;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
RXpacketCount++;
printElapsedTime(); //print elapsed time to Serial Monitor
Serial.print(F(" "));
LT.printASCIIPacket(RXBUFFER, RXPacketL); //print the packet as ASCII characters
localCRC = LT.CRCCCITT(RXBUFFER, RXPacketL, 0xFFFF); //calculate the CRC, this is the external CRC calculation of the RXBUFFER
Serial.print(F(",CRC,")); //contents, not the LoRa device internal CRC
Serial.print(localCRC, HEX);
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(RXPacketL);
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LT.readIrqStatus(); //read the LoRa device IRQ status register
printElapsedTime(); //print elapsed time to Serial Monitor
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
Serial.print(F(" RXTimeout"));
}
else
{
errors++;
Serial.print(F(" PacketError"));
Serial.print(F(",RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL()); //get the real packet length
Serial.print(F(",Packets,"));
Serial.print(RXpacketCount);
Serial.print(F(",Errors,"));
Serial.print(errors);
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus(); //print the names of the IRQ registers set
}
delay(250); //gives a longer buzzer and LED flash for error
}
void printElapsedTime()
{
float seconds;
seconds = millis() / 1000;
Serial.print(seconds, 0);
Serial.print(F("s"));
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("4_LoRa_Receiver Starting"));
Serial.println();
if (BUZZER > 0)
{
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, HIGH);
delay(50);
digitalWrite(BUZZER, LOW);
}
SPI.begin();
//SPI beginTranscation is normally part of library routines, but if it is disabled in the library
//a single instance is needed here, so uncomment the program line below
//SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125);
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
//The function call list below shows the complete setup for the LoRa device using the information defined in the
//Settings.h file.
//The 'Setup LoRa device' list below can be replaced with a single function call;
//LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
//***************************************************************************************************
//Setup LoRa device
//***************************************************************************************************
LT.setMode(MODE_STDBY_RC); //got to standby mode to configure device
LT.setPacketType(PACKET_TYPE_LORA); //set for LoRa transmissions
LT.setRfFrequency(Frequency, Offset); //set the operating frequency
LT.calibrateImage(0); //run calibration after setting frequency
LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO); //set LoRa modem parameters
LT.setBufferBaseAddress(0x00, 0x00); //where in the SX buffer packets start, TX and RX
LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL); //set packet parameters
LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD); //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34
LT.setHighSensitivity(); //set for highest sensitivity at expense of slightly higher LNA current
LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_RX_DONE, 0, 0); //set for IRQ on RX done
//***************************************************************************************************
Serial.println();
LT.printModemSettings(); //reads and prints the configured LoRa settings, useful check
Serial.println();
LT.printOperatingSettings(); //reads and prints the configured operting settings, useful check
Serial.println();
Serial.println();
LT.printRegisters(0x00, 0x4F); //print contents of device registers, normally 0x00 to 0x4F
Serial.println();
Serial.println();
Serial.print(F("Receiver ready - RXBUFFER_SIZE "));
Serial.println(RXBUFFER_SIZE);
Serial.println();
}

View File

@@ -0,0 +1,44 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/12/19
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. Some pins such as DIO1,
//DIO2, BUZZER may not be in used by this sketch so they do not need to be
//connected and should be included and be set to -1.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define BUZZER 4 //pin for buzzer, on when logic high
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup LoRa Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting, normally set to auto
const int8_t TXpower = 2; //LoRa transmit power in dBm
const uint16_t packet_delay = 1000; //mS delay between packets
#define RXBUFFER_SIZE 32 //RX buffer size

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

View File

@@ -0,0 +1,38 @@
## STM32 - SX127X Library Example Programs
I decided to check if my SX127X library and examples would work with a STM32 board. When I require a micro controller that needs more pins or memory than a ATmega328P, my goto processor has been the ATMeg1284P. This has 128k of flash memory and 16K of RAM, so 4 times the flash and 8 times the RAM of an ATmega328P based Pro Mini. The 1284P still only runs at 8Mhz (3.3V) which can be considered slow in a modern context and more non-pinchange interrupts would be a definite advantage, so I decided to give a STM32 a go. With the STM32 there is the potential to use devices with much greater speed, flash, RAM and IO pins.
I chose an XNucleo F103RB since that will easily take one of my Arduino shields that uses breadboard friendly modules, so it would simple and quick to test out the SX127X lora library examples. The board is pictured below;
![Picture 1](/pictures/STM32_and_Shield.jpg)
The slim board at the top right of the picture is the supplied STLink programmer.
I installed the STM32 core for Arduino;
[https://github.com/stm32duino/Arduino/_Core/_STM32](https://github.com/stm32duino/Arduino_Core_STM32)
Plugged in my Arduino shield, inserted the STlink programmer supplied with the board (see picture above) and connected the 'USB to USART' port to my PC so that I could monitor Serial Monitor stuff.
I loaded the **1\_LED\_Blink\_STM32** program, then set-up the Arduino IDE as in the picture below;
Arduino_IDE_for _STM32
![Picture 1](/pictures/Arduino_IDE_for_STM32.jpg)
The blink program loaded and worked just fine.
Next the **2\_Register\_Test\_STM32** was loaded and that worked too.
Then the **3\_LoRa\_Transmitte\r_STM32** program was tried. I connected up my Realtek SDR and SDR#\Airspy combo and I could see lora packets being sent at 434Mhz. Hooked up another ATMega board as a receiver and it showed packets were being sent and received correctly.
I changed the XNucleo board over to the **4\_LoRa\_Receiver\_STM32** program and that could receive lora packets OK.
In conclusion, the SX127X example lora transmit and receive programs worked on the STM32 with no changes needed.
**Stuart Robinson**
**February 2020**

View File

@@ -0,0 +1,332 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 17/12/19
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 transmits a LoRa packet without using a processor buffer, the LoRa
devices internal buffer is filled directly with variables.
The sensor used is a BME280. The pressure, humidity, and temperature are read and transmitted. There
is also a 16bit value of battery mV (simulated) and and a 8 bit status value at the packet end.
Although the LoRa packet transmitted and received has its own internal CRC error checking, you could
still receive packets of the same length from another source. If this valid packet were to be used
to recover the sensor values, you could be reading rubbish. To reduce the risk of this, when the packet
is transmitted the CRC value of the actual sensor data is calculated and sent out with the packet.
This CRC value is read by the receiver and used to check that the received CRC matches the supposed
sensor data in the packet. As an additional check there is some addressing information at the beginning
of the packet which is also checked for validity. Thus we can be relatively confident when reading the
received packet that its genuine and from this transmitter. The packet is built and sent in the
sendSensorPacket() function, there is a 'highlighted section' where the actual sensor data is added to
the packet.
Between readings the LoRa device, BME280 sensor, and Atmel microcontroller are put to sleep in units of
8 seconds using the Atmel processor internal watchdog.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file.
Each sending sensor needs its own address and needs to know the address of the receiver its sending to.
This information is in the Settings.h file, see this section;
******* Setup node addressing here ! ***************
const uint8_t TXPacketType = Sensor1; //the packet type sent
const uint8_t TXDestination = 'B' //the destination address of the receiver.
const uint8_t TXSource = 1; //the source address, the address of this node.
The TXDestination byte needs to match the RXDestination set in the receiver. The TXSource byte identifies
a particular sender node, and needs to be different for each sender.
How often the sensor data is sent is controlled by this line in the Settings.h file;
const uint8_t sleeps = 112; //number of 8 second sleeps, gap between transmissions
In the above case 112 sleeps is approximatly 112 x 8 = 900seconds, 15 minutes.
There is also an option of using a logic pin to turn the resistor divider used to read battery voltage on
and off. This reduces current used in sleep mode. To use the feature set the define for pin BATVREADON
in 'Settings.h' to the pin used. If not using the feature set the pin number to -1.
The Atmel watchdog timer is a viable option for a very low current sensor node. A 'bare bones' ATmega328P
with regulator and LoRa device has a sleep current of 6.6uA, add the LoRa devices and BME280 sensor
module and the average sleep current only rises to 7.9uA.
One of these transmitter programs is running on a long term test with a 150mAh battery, to see how long
the battery actually lasts, details at the link below;
https://stuartsprojects.github.io/2020/02/20/just-how-long-can-a-sensor-battery-last.html
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <SPI.h>
#include <SX127XLT.h>
#include <ProgramLT_Definitions.h>
#include "Settings.h"
#include <avr/wdt.h> //watchdog timer library, integral to Arduino IDE
#include <LowPower.h> //get the library here; https://github.com/rocketscream/Low-Power
SX127XLT LT;
#include <Seeed_BME280.h> //get library here; https://github.com/Seeed-Studio/Grove_BME280
BME280 bme280; //create an instance of the BME280 senosor
#include <Wire.h>
uint32_t TXpacketCount;
uint8_t TXPacketL;
float temperature; //the BME280 temperature value
float pressure; //the BME280 pressure value
uint16_t humidity; //the BME280 humididty value
uint16_t voltage; //the battery voltage value
uint8_t statusbyte; //a status byte, not currently used
uint16_t CRCvalue; //the CRC value of the packet data up to this point
uint8_t packetlength; //the packet length that was sent, checked against length received
void loop()
{
TXpacketCount++;
Serial.print(TXpacketCount); //print the numbers of sends
Serial.print(F(" Sending > "));
readSensors(); //read the sensor values
printSensorValues(); //print the sensor values
if (sendSensorPacket())
{
Serial.println(F("SentOK"));
}
else
{
Serial.print(F("Send Error - IRQreg,"));
Serial.println(LT.readIrqStatus(), HEX);
}
Serial.print(F("Sleeping zzzz"));
Serial.flush(); //make sure all serial output has gone
//now put the sensor, LoRa device and processor to sleep
sleepBME280(); //sleep the BME280
LT.setSleep(CONFIGURATION_RETENTION); //sleep LoRa device, keeping register settings in sleep.
sleep8seconds(sleeps); //sleep Atmel processor in units of approx 8 seconds
//wait a bit ................
Serial.println(F(" - Awake !!")); //the processor has woken up
Serial.println();
normalBME280(); //BME280 sensor to normal mode
}
uint8_t sendSensorPacket()
{
//The SX12XX buffer is filled with variables of a known type and in a known sequence. Make sure the
//receiver uses the same variable types and sequence to read variables out of the receive buffer.
uint8_t len;
LT.startWriteSXBuffer(0); //start the write packet to buffer process
LT.writeUint8(Sensor1); //this byte defines the packet type
LT.writeUint8(TXDestination); //destination address of the packet, the receivers address
LT.writeUint8(TXSource); //source address of this node
/************************************************************************
Highlighted section - this is where the actual sensor data is added to the packet
************************************************************************/
LT.writeFloat(temperature); //add the BME280 temperature
LT.writeFloat(pressure); //add the BME280 pressure
LT.writeUint16(humidity); //add the BME280 humididty
LT.writeUint16(voltage); //add the battery voltage
LT.writeUint8(statusbyte); //add the status byte
/************************************************************************/
len = LT.endWriteSXBuffer(); //close the packet, get the length of data to be sent
addPacketErrorCheck(len); //add the additional CRC error checking to the packet end
//now transmit the packet, set a timeout of 5000mS, wait for it to complete sending
digitalWrite(LED1, HIGH); //turn on LED as an indicator
TXPacketL = LT.transmitSXBuffer(0, (len + 2), 5000, TXpower, WAIT_TX);
digitalWrite(LED1, LOW); //turn off indicator LED
return TXPacketL; //TXPacketL will be 0 if there was an error sending
}
void addPacketErrorCheck(uint8_t len)
{
//calculate the CRC of packet sensor data
CRCvalue = LT.CRCCCITTSX(3, (len - 1), 0xFFFF);
Serial.print(F("Calculated CRC value "));
Serial.println(CRCvalue, HEX);
LT.startWriteSXBuffer(len); //start the write packet again at location of CRC, past end of sensor data
LT.writeUint16(CRCvalue); //add the actual CRC value
LT.endWriteSXBuffer(); //close the packet
}
void readSensors()
{
//read the sensor values into the global variables
temperature = bme280.getTemperature();
pressure = bme280.getPressure();
humidity = bme280.getHumidity();
if (BATVREADON >= 0)
{
voltage = readBatteryVoltage(); //read resistor divider across battery
}
else
{
voltage = 9999; //set a default value
}
statusbyte = 0x55; //manually set this for now, its a test
}
void printSensorValues()
{
Serial.print(F("Temperature,"));
Serial.print(temperature, 1);
Serial.print(F("c,Pressure,"));
Serial.print(pressure, 0);
Serial.print(F("Pa,Humidity,"));
Serial.print(humidity);
Serial.print(F("%,Voltage,"));
Serial.print(voltage);
Serial.print(F("mV,Status,"));
Serial.print(statusbyte, HEX);
Serial.print(F(" "));
Serial.flush();
}
void sleep8seconds(uint32_t sleeps)
{
//uses the lowpower library
uint32_t index;
for (index = 1; index <= sleeps; index++)
{
//sleep 8 seconds
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}
}
void sleepBME280()
{
//write this register value to BME280 to put it to sleep
writeBME280reg(BME280_REGISTER_CONTROL, B01111100);
}
void normalBME280()
{
//write this register value to BME280 to put it to read mode
writeBME280reg(BME280_REGISTER_CONTROL, B01111111);
}
void writeBME280reg(byte reg, byte regvalue)
{
//write a register value to the BME280
Wire.beginTransmission((uint8_t) BME280_ADDRESS);
Wire.write((uint8_t)reg);
Wire.write((uint8_t)regvalue);
Wire.endTransmission();
}
uint16_t readBatteryVoltage()
{
//relies on 1V1 internal reference and 91K & 11K resistor divider
//returns supply in mV @ 10mV per AD bit read
uint16_t temp;
uint16_t volts = 0;
byte index;
if (BATVREADON >= 0)
{
digitalWrite(BATVREADON, HIGH); //turn on MOSFET connecting resitor divider in circuit
}
analogReference(INTERNAL);
temp = analogRead(BATTERYAD);
for (index = 0; index <= 4; index++) //sample AD 5 times
{
temp = analogRead(BATTERYAD);
volts = volts + temp;
}
volts = ((volts / 5) * ADMultiplier) + DIODEMV;
if (BATVREADON >= 0)
{
digitalWrite(BATVREADON, LOW); //turn off MOSFET connecting resitor divider in circuit
}
return volts;
}
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);
if (BATVREADON >= 0)
{
pinMode(BATVREADON, OUTPUT);
}
Serial.begin(9600);
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
led_Flash(2, 125);
}
else
{
Serial.println(F("Device error"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates LoRa device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
if (!bme280.init())
{
Serial.println("BME280 Device error!");
led_Flash(100, 15); //long very fast speed flash indicates BME280 device error
}
Serial.println(F("Transmitter ready"));
Serial.println();
readSensors(); //do an initial sensor read
}

View File

@@ -0,0 +1,55 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 17/12/19
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 definitiosn to match your own setup. Some pins such as DIO1,
//DIO2, may not be in used by this sketch so they do not need to be connected and
//should be set to -1.
#define NSS 10 //select on LoRa device
#define NRESET 9 //reset on LoRa device
#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1
#define LED1 8 //On board LED, high for on
#define BATVREADON 8 //when high turns on the resistor divider to measure voltage, -1 if not used
#define BATTERYAD A7 //Resitor divider for battery connected here, -1 if not used
#define ADMultiplier 10.00 //adjustment to convert AD value read into mV of battery voltage
#define DIODEMV 98 //mV voltage drop accross diode @ low idle current
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
// ******* Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 14; //LoRa transmit power in dBm
#define BME280_ADDRESS 0x76 //I2C bus address of BME280
#define BME280_REGISTER_CONTROL 0xF4 //BME280 register number for power control
const uint8_t sleeps = 112; //number of 8 second sleeps, gap between transmissions
// ******* Setup node addressing here ! ***************
const uint8_t TXPacketType = Sensor1; //the packet type sent
const uint8_t TXDestination = 'B'; //the destination address of the receiver where the packet is being sent to
const uint8_t TXSource = 2; //the source address, the address of this node, where the packet came from

View File

@@ -0,0 +1,361 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 16/10/20
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 receives a LoRa packet without using a processor buffer, the LoRa devices
internal buffer is read direct for the received sensor data.
The sensor used in the matching '17_Sensor_Transmiter' program is a BME280 and the pressure, humidity,
and temperature are being and received. There is also a 16bit value of battery mV and and a 8 bit status
value at the end of the packet.
When a packet is received,its printed and assuming the packet is validated, the sensor results are printed to the serial monitor
and screen.
For the sensor data to be accepted as valid the folowing need to match;
The 16bit CRC on the received sensor data must match the CRC value transmitted with the packet.
The packet must start with a byte that matches the packet type sent, 'Sensor1'
The RXdestination byte in the packet must match this node ID of this receiver node, defined by 'This_Node'
In total thats 16 + 8 + 8 = 32bits of checking, so a 1:4294967296 chance (approx) that an invalid
packet is acted on and erroneous values displayed.
The pin definitions, LoRa frequency and LoRa modem settings are in the Settings.h file.
With a standard Arduino Pro Mini and SSD1306 display the current consumption was 20.25mA with the
display and 16.6mA without the display.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#include <SPI.h>
#include <SX127XLT.h>
#include "Settings.h"
#include <ProgramLT_Definitions.h>
SX127XLT LT;
uint32_t RXpacketCount; //count of all packets received
uint32_t ValidPackets; //count of packets received with valid data
uint32_t RXpacketErrors; //count of all packets with errors received
bool packetisgood;
uint8_t RXPacketL; //length of received packet
int16_t PacketRSSI; //RSSI of received packet
int8_t PacketSNR; //signal to noise ratio of received packet
uint8_t RXPacketType;
uint8_t RXDestination;
uint8_t RXSource;
float temperature; //the BME280 temperature value
float pressure; //the BME280 pressure value
uint16_t humidity; //the BME280 humididty value
uint16_t voltage; //the battery voltage value
uint8_t statusbyte; //a status byte, not currently used
uint16_t TXCRCvalue; //the CRC value of the packet data as transmitted
//for SSD1306
#include <U8x8lib.h> //get library here > https://github.com/olikraus/u8g2
U8X8_SSD1306_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for standard 0.96" SSD1306
#define default_font u8x8_font_chroma48medium8_r
//for SH1106
//#include <U8x8lib.h> //get library here > https://github.com/olikraus/u8g2
//U8X8_SH1106_128X64_NONAME_HW_I2C disp(U8X8_PIN_NONE); //use this line for 1.3" OLED often sold as 1.3" SSD1306
//#define default_font u8x8_font_chroma48medium8_r
void loop()
{
RXPacketL = LT.receiveSXBuffer(0, 0, WAIT_RX); //returns 0 if packet error of some sort, no timeout set
digitalWrite(LED1, HIGH); //something has happened
PacketRSSI = LT.readPacketRSSI();
PacketSNR = LT.readPacketSNR();
if (RXPacketL == 0)
{
packet_is_Error();
}
else
{
packet_Received_OK(); //its a valid packet LoRa wise, but it might not be a packet we want
}
digitalWrite(LED1, LOW);
Serial.println();
}
void packet_Received_OK()
{
//a LoRa packet has been received, which has passed the internal LoRa checks, including CRC, but it could be from
//an unknown source, so we need to check that its actually a sensor packet we are expecting, and has valid sensor data
uint8_t len;
uint8_t contenterrors; //keep a count of errors found in packet
RXpacketCount++;
Serial.print(RXpacketCount);
Serial.print(F(",PacketsReceived,"));
LT.startReadSXBuffer(0);
RXPacketType = LT.readUint8(); //the packet type received
RXDestination = LT.readUint8(); //the destination address the packet was sent to
RXSource = LT.readUint8(); //the source address, where the packet came from
/************************************************************************
Highlighted section - this is where the actual sensor data is read from
the packet
************************************************************************/
temperature = LT.readFloat(); //the BME280 temperature value
pressure = LT.readFloat(); //the BME280 pressure value
humidity = LT.readUint16(); //the BME280 humididty value
voltage = LT.readUint16(); //the battery voltage value
statusbyte = LT.readUint8(); //a status byte, not currently used
/************************************************************************/
len = LT.endReadSXBuffer();
printreceptionDetails(); //print details of reception, RSSI etc
Serial.println();
contenterrors = checkPacketValid(len); //pass length of packet to check routine
if (contenterrors == 0)
{
Serial.println(F(" Packet is good"));
ValidPackets++;
printSensorValues(); //print the sensor values
Serial.println();
printPacketCounts(); //print count of valid packets and errors
displayscreen1();
Serial.println();
}
else
{
Serial.println(F(" Packet is not valid"));
RXpacketErrors++;
disp.clearLine(7);
disp.setCursor(0, 7);
disp.print(F("Errors "));
disp.print(RXpacketErrors);
}
}
uint8_t checkPacketValid(uint8_t len)
{
//this function checks if the packet is valid and will be displayed
uint8_t errors = 0;
if (RXPacketType != Sensor1) //is it a Sensor1 type packet
{
errors++;
}
if (RXDestination != This_Node) //was the packet sent to this receiver node ?
{
errors++;
}
if (!checkCRCvalue(len)) //is the sent CRC value of sensor data valid ?
{
errors++;
}
Serial.println();
Serial.print(F("Error Check Count = "));
Serial.print(errors);
return errors;
}
bool checkCRCvalue(uint8_t len)
{
uint16_t CRCSensorData;
CRCSensorData = LT.CRCCCITTSX(3, (len-1), 0xFFFF); //calculate the CRC of packet sensor data
Serial.print(F("(CRC of Received sensor data "));
Serial.print(CRCSensorData, HEX);
Serial.print(F(")" ));
TXCRCvalue = ((LT.getByteSXBuffer(len + 1) << 8) + (LT.getByteSXBuffer(len)));
Serial.print(F("(CRC transmitted "));
Serial.print(TXCRCvalue, HEX);
Serial.print(F(")" ));
if (TXCRCvalue != CRCSensorData)
{
Serial.print(F(" Sensor Data Not Valid"));
return false;
}
else
{
Serial.print(F(" Sensor Data is Valid"));
return true;
}
}
void printSensorValues()
{
Serial.print(F("Temp,"));
Serial.print(temperature, 1);
Serial.print(F("c,Press,"));
Serial.print(pressure, 0);
Serial.print(F("Pa,Humidity,"));
Serial.print(humidity);
Serial.print(F("%,Voltage,"));
Serial.print(voltage);
Serial.print(F("mV,Status,"));
Serial.print(statusbyte, HEX);
Serial.print(F(",CRC,"));
Serial.print(TXCRCvalue, HEX);
Serial.flush();
}
void printreceptionDetails()
{
Serial.print(F("RSSI,"));
Serial.print(PacketRSSI);
Serial.print(F("dBm,SNR,"));
Serial.print(PacketSNR);
Serial.print(F("dB,Length,"));
Serial.print(LT.readRXPacketL());
}
void printPacketCounts()
{
Serial.print(F("ValidPackets,"));
Serial.print(ValidPackets);
Serial.print(F(",Errors,"));
Serial.print(RXpacketErrors);
}
void displayscreen1()
{
//show sensor data on display
disp.clearLine(0);
disp.setCursor(0, 0);
disp.print(F("Sensor "));
disp.print(RXSource);
disp.clearLine(1);
disp.setCursor(0, 1);
disp.print(temperature, 1);
disp.print(F("c"));
disp.clearLine(2);
disp.setCursor(0, 2);
disp.print(pressure, 0);
disp.print(F("Pa"));
disp.clearLine(3);
disp.setCursor(0, 3);
disp.print(humidity);
disp.print(F("%"));
disp.clearLine(4);
disp.setCursor(0, 4);
disp.print(voltage);
disp.print(F("mV"));
disp.clearLine(6);
disp.setCursor(0, 6);
disp.print(F("ValidPkts "));
disp.print(ValidPackets);
disp.setCursor(0, 7);
disp.print(F("Errors "));
disp.print(RXpacketErrors);
}
void packet_is_Error()
{
uint16_t IRQStatus;
RXpacketErrors++;
IRQStatus = LT.readIrqStatus();
if (IRQStatus & IRQ_RX_TIMEOUT)
{
Serial.print(F("RXTimeout "));
}
else
{
Serial.print(F("PacketError "));
printreceptionDetails();
Serial.print(F(",IRQreg,"));
Serial.print(IRQStatus, HEX);
LT.printIrqStatus();
Serial.println();
disp.clearLine(7);
disp.setCursor(0, 7);
disp.print(F("Errors "));
disp.print(RXpacketErrors);
}
}
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);
Serial.begin(9600);
disp.setCursor(0, 0);
disp.print(F("Check LoRa"));
disp.setCursor(0, 1);
SPI.begin();
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
disp.print(F("LoRa OK"));
led_Flash(2, 125);
}
else
{
disp.print(F("Device error"));
Serial.println(F("Device error"));
while (1)
{
led_Flash(50, 50); //long fast speed flash indicates device error
}
}
LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);
Serial.println(F("Receiver ready"));
Serial.println();
}

View File

@@ -0,0 +1,45 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 29/02/20
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 definitiosn to match your own setup. Some pins such as DIO1,
//DIO2, may not be in used by this sketch so they do not need to be /connected and
//should be set to -1.
#define NSS 10 //select on LoRa device
#define NRESET 9 //reset on LoRa device
#define DIO0 3 //DIO0 on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 on LoRa device, normally not used so set to -1
#define LED1 8 //On board LED, high for on
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
//*************** Setup LoRa Test Parameters Here ! ***************
//LoRa Modem Parameters
const uint32_t Frequency = 434000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_125; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF7; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint8_t Optimisation = LDRO_AUTO; //low data rate optimisation setting
const int8_t TXpower = 2; //LoRa TX power
#define packet_delay 1000 //mS delay between packets
//******* Setup node addressing here ! ***************
#define This_Node 'B' //this identifies this node, needs to match TXDestination on senders

View File

@@ -0,0 +1,103 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 21/03/20
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 program reads the internal temperature sensor in the SX127X range of devices.
The temeprature sensor needs calibrating, so run a test, check what the error is (could be +\- 10C or
more) and calculate the value for the temperature_compensate constant. This constant will be different
for each individual device.
Serial monitor baud rate is set at 9600.
*******************************************************************************************************/
#define Program_Version "V1.0"
//These are the pin definitions for one of the Tracker boards, be sure to change them to match
//your own setup.
#define NSS 10 //SX127X device select
#define NRESET 9 //SX127X reset pin
#define LED1 8 //for on board LED, put high for on
#define LORA_DEVICE DEVICE_SX1278 //this is the device we are using
#include <SPI.h>
#include <SX127XLT.h> //load the appropriate library
SX127XLT LT;
const int8_t temperature_compensate = 0; //value, degrees centigrade, to add to read temperature for calibration. Can be negative
//this compensate value will be different for each LoRa device instance, so best to
//label and record values for each device
void loop()
{
int8_t temperature_register;
LT.resetDevice();
temperature_register = LT.getDeviceTemperature();
Serial.print(F("Temperature Register Raw "));
Serial.println(temperature_register);
Serial.print(F("Temperature Compensated "));
Serial.print(temperature_register + temperature_compensate);
Serial.println(F("c"));
Serial.println();
delay(2000);
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("39_LoRa_SX127x_Temperature_Read Starting"));
SPI.begin();
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, -1, -1, -1, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
Serial.println(F("Temperature Sensor Ready"));
Serial.println();
}

View File

@@ -0,0 +1,175 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 23/02/20
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 - A silly program really, but does demonstrate that you can shift a carrier generated
by the LoRa device in FSK mode fast enough to play audio tones that can be picked up on an FM UHF
handheld receiver. The tones are not true FM but the receiver does not know that.
Serial monitor baud rate is set at 9600
*******************************************************************************************************/
#define Program_Version "V1.0"
#include <SPI.h> //the lora device is SPI based so load the SPI library
#include <SX127XLT.h> //include the appropriate library
#include "Settings.h" //include the settings file, frequencies etc
#include "pitches.h" //lookup file for notes
SX127XLT LT; //create a library class instance called LT
void loop()
{
Serial.print(TXpower); //print the transmit power defined
Serial.print(F("dBm "));
Serial.println(F("PlayTune> "));
Serial.println();
playpart1();
playpart2();
LT.toneFM(NOTE_F4, 250, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_GS4, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_F4, 350, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_A4, 125, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_C5, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_A4, 375, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_C5, 125, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_E5, 650, deviation, adjustfreq, TXpower);
delay(500);
playpart2();
LT.toneFM(NOTE_F4, 250, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_GS4, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_F4, 375, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_C5, 125, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_F4, 375, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_C5, 125, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_A4, 650, deviation, adjustfreq, TXpower);
LT.setMode(MODE_STDBY_RC); //turns off carrier
Serial.println();
delay(2000); //have a delay between packets
}
void playpart1()
{
LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_F4, 350, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_C5, 150, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_A4, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_F4, 350, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_C5, 150, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_A4, 650, deviation, adjustfreq, TXpower);
delay(500);
LT.toneFM(NOTE_E5, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_E5, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_E5, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_F5, 350, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_C5, 150, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_GS4, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_F4, 350, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_C5, 150, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_A4, 650, deviation, adjustfreq, TXpower);
delay(500);
}
void playpart2()
{
LT.toneFM(NOTE_A5, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_A4, 300, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_A4, 150, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_A5, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_GS5, 325, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_G5, 175, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_FS5, 125, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_F5, 125, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_FS5, 250, deviation, adjustfreq, TXpower);
delay(500);
LT.toneFM(NOTE_AS4, 250, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_DS5, 500, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_F5, 325, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_CS5, 175, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_C5, 125, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_AS4, 125, deviation, adjustfreq, TXpower);
LT.toneFM(NOTE_C5, 250, deviation, adjustfreq, TXpower);
delay(500);
}
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); //setup pin as output for indicator LED
led_Flash(2, 125); //two quick LED flashes to indicate program start
Serial.begin(9600);
Serial.println();
Serial.print(F(__TIME__));
Serial.print(F(" "));
Serial.println(F(__DATE__));
Serial.println(F(Program_Version));
Serial.println();
Serial.println(F("59_Play_Star_Wars_Tune 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));
//setup hardware pins used by device, then check if device is found
if (LT.begin(NSS, NRESET, DIO0, DIO1, DIO2, LORA_DEVICE))
{
Serial.println(F("LoRa Device found"));
led_Flash(2, 125); //two further quick LED flashes to indicate device found
delay(1000);
}
else
{
Serial.println(F("No device responding"));
while (1)
{
led_Flash(50, 50); //long fast speed LED flash indicates device error
}
}
LT.setupDirect(Frequency, Offset);
Serial.print(F("Tone Transmitter ready"));
Serial.println();
}

View File

@@ -0,0 +1,32 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 23/02/20
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. Some pins such as DIO1,
//DIO2 are not used by this particular sketch so they are set to -1 and not connected.
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define LED1 8 //on board LED, high for on
#define DIO0 3 //DIO0 pin on LoRa device, used for RX and TX done
#define DIO1 -1 //DIO1 pin on LoRa device, normally not used so set to -1
#define DIO2 -1 //DIO2 pin on LoRa device, normally not used so set to -1
#define LORA_DEVICE DEVICE_SX1278 //we need to define the device we are using
//******* Setup Direct Modem Parameters Here ! ***************
const uint32_t Frequency = 434000000; //frequency of transmissions in hertz
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint16_t deviation = 10000; //deviation in hz, total frequency shift low to high
const float adjustfreq = 0.9; //adjustment to tone frequency
const int8_t TXpower = 10; //LoRa transmit power in dBm

View File

@@ -0,0 +1,94 @@
//File from https://www.arduino.cc/en/Tutorial/toneMelody
//This note table was originally written by Brett Hagman, on whose work the Arduino tone() command was based.
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978

Some files were not shown because too many files have changed in this diff Show More