Init fork from Stuart Robinson's repo

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

View File

@ -0,0 +1,189 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 28/12/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This the transmitter part of a Serial bridge. This tranmitter receives data on
the defined serial port and puts that serial data into a LoRa packet which is then transmitted. A
matching reciever picks up the packet and displays it on the remote Arduinos serial port.
The purpose of the bridge is to allow the serial output of a device, anothor Arduino or sensor for
instance, to be remotely monitored, without the need for a long serial cable.
Serial monitor baud rate should be set at 9600.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LoRa; //create a library class instance called LoRa
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LED1 8 //indicator LED
#define LORA_DEVICE DEVICE_SX1280 //we need to define the LoRa device we are using
#define TXpower 10 //LoRa transmit power in dBm
uint8_t TXPacketL; //length of transmitted packet
uint8_t RXPacketL; //length of received acknowledge
uint16_t PayloadCRC;
uint16_t MessageID; //MessageID identifies each message, 2 bytes at front of packet
uint8_t receivedBytes; //count of serial bytes received
uint8_t Attempts; //number of times to send packet waiting for acknowledge
uint32_t startuS; //used for timeout for serial input
const uint8_t MaxMessageSize = 251; //max size of array to send with received serial
uint8_t Message[MaxMessageSize]; //array for received serial data
const uint32_t Frequency = 2445000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_1600; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF5; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint16_t NetworkID = 0x3210; //a unique identifier to go out with packet = 0x3210;
uint32_t SerialTimeoutuS; //Timeout in uS before assuming message to send is complete
const uint32_t TimeoutCharacters = 10; //number of characters at specified baud rate that are a serial timeout
const uint8_t MaxAttempts = 4; //Maximum attempts to send message and receive acknowledge
const uint32_t ACKtimeoutmS = 50; //Acknowledge timeout in mS
const uint32_t TXtimeoutmS = 1000; //transmit timeout in mS.
#define SerialInput Serial //assign serial port for reading data
#define DebugSerial Serial //assign serial port for debug output
#define SerialInputBaud 9600 //baud rate for the serial
//#define DEBUG //enable define to see debug information
#define SENDREADY //enable define to see Ready control message at start
void loop()
{
#ifdef DEBUG
DebugSerial.println(F("> "));
#endif
Message[0] = lowByte(MessageID);
Message[1] = highByte(MessageID);
MessageID++; //ready for next message
receivedBytes = 2;
while (SerialInput.available() == 0); //wait for serial data to be available
digitalWrite(LED1, HIGH);
startuS = micros();
while (((uint32_t) (micros() - startuS) < SerialTimeoutuS))
{
if (SerialInput.available() > 0)
{
if (receivedBytes >= MaxMessageSize)
{
break;
}
Message[receivedBytes] = SerialInput.read();
startuS = micros(); //restart timeout
receivedBytes++;
}
};
//the only exits from the serial collection loop above are if there is a timeout, or the maximum
//message size is reached.
Attempts = 0;
do
{
#ifdef DEBUG
uint8_t index;
DebugSerial.print(receivedBytes);
DebugSerial.print(F(" "));
DebugSerial.print(MessageID);
DebugSerial.print(F(" > ")); //flag on monitor for transmitting
for (index = 2; index < receivedBytes; index++)
{
DebugSerial.write(Message[index]);
}
DebugSerial.println();
#endif
TXPacketL = LoRa.transmitReliable(Message, receivedBytes, NetworkID, TXtimeoutmS, TXpower, WAIT_TX);
PayloadCRC = LoRa.readUint16SXBuffer(TXPacketL - 2); //need the payload CRC to check for valid ACK
RXPacketL = LoRa.waitReliableACK(NetworkID, PayloadCRC, ACKtimeoutmS);
Attempts++;
}
while ((RXPacketL == 0) && (Attempts <= MaxAttempts));
#ifdef DEBUG
if (RXPacketL == 0)
{
Serial.println(F("NA>"));
}
#endif
}
void setup()
{
pinMode(LED1, OUTPUT);
DebugSerial.begin(9600);
SerialInput.begin(SerialInputBaud);
#ifdef DEBUG
DebugSerial.println();
Serial.println(F(__FILE__));
DebugSerial.println();
#endif
SPI.begin();
if (LoRa.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
#ifdef DEBUG
DebugSerial.println(F("LoRa Device found"));
#endif
}
else
{
DebugSerial.println(F("No LoRa device responding"));
while (1);
}
LoRa.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate);
#ifdef SENDREADY
//Send a ready packet so remorte can check its working, send control message 0x0001
Message[0] = 1;
Message[1] = 0;
Message[2] = 'R';
TXPacketL = LoRa.transmitReliable(Message, 3, NetworkID, TXtimeoutmS, TXpower, WAIT_TX);
delay(1000);
#endif
//now calculate timeout in microseconds based on baud rate and number of characters, assuming a 11bit byte
SerialTimeoutuS = ((1000000 / SerialInputBaud) * 11) * TimeoutCharacters;
#ifdef DEBUG
DebugSerial.print(F("SerialTimeoutuS "));
DebugSerial.println(SerialTimeoutuS);
DebugSerial.println(F("Clear serial buffer"));
#endif
while (SerialInput.available() > 0) //clear serial input
{
SerialInput.read();
}
#ifdef DEBUG
DebugSerial.println(F("Waiting start of serial input"));
#endif
MessageID = 257; //first message to send is 0x0101
}

View File

@ -0,0 +1,218 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 28/12/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This a the receiver part of a Serial bridge. The tranmitter receives data on
the defined serial port and puts that serial data into a LoRa packet which is then transmitted. This
matching reciever picks up the packet and displays it on the receivers serial port.
The purpose of the bridge is to allow the serial output of a device, anothor Arduino or sensor for
instance, to be remotely monitored, without the need for a long serial cable.
Serial monitor baud rate should be set at 9600.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LoRa; //create a library class instance called LT
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LED1 8 //this is output 1
#define LORA_DEVICE DEVICE_SX1280 //we need to define the device we are using
#define TXpower 10 //dBm power to use for ACK
uint8_t RXPacketL; //stores length of packet received
uint8_t RXPayloadL; //stores length of payload received
uint16_t RXPayloadCRC; //CRC of payload included in received packet
uint16_t MessageID; //MessageID identifies each message, 2 bytes at front of packet
uint16_t LastMessageID; //keep track of last received message, display messages start at 0x0100
const uint32_t Frequency = 2445000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_1600; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF5; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint16_t NetworkID = 0x3210; //Message NetworkID identifies each message, automatically appended to packet
const uint32_t ACKdelay1 = 10; //delay in mS before sending acknowledge
const uint32_t ACKdelay2 = 20; //delay in mS before sending acknowledge for message already received
const uint32_t RXtimeout = 60000 ; //receive timeout in mS. set to 0 for no timeout
const uint32_t TXtimeout = 1000; //transmit timeout in mS.
const uint8_t MaxMessageSize = 251 ; //maximum size of serial maeesage to send, 4 bytes needed for NetworkID and payload CRC
uint8_t Message[MaxMessageSize]; //array for receiving message
#define SerialOutput Serial //assign serial port for outputing data
#define DebugSerial Serial //assign serial port for outputing debug data
//#define DEBUG //enable this define to see debug information
void loop()
{
#ifdef DEBUG
DebugSerial.print(F("> "));
#endif
do
{
RXPacketL = LoRa.receiveReliable(Message, MaxMessageSize, NetworkID, RXtimeout, WAIT_RX);
MessageID = Message[0] + (Message[1] * 256); //message number is first two bytes of Message array
if (RXPacketL == 0) //check for a valid packet
{
#ifdef DEBUG
DebugSerial.print(MessageID);
DebugSerial.print(F("E>"));
packet_is_Error();
#endif
break;
}
//if here there is a valid reliable packet
if (MessageID > LastMessageID) //new message should be greater than last message
{
processMessage();
delay(ACKdelay1);
sendACK();
break;
}
if (MessageID <= 256) //is it a control message
{
processControlMessage();
break;
}
if (LastMessageID == MessageID) //have we had this message before, remember TX may miss the sent ACK ?
{
delay(ACKdelay2);
sendACK(); //dont process message, but send ACK again
break; //and go back to receive
}
if (MessageID == 257) //this appears to be a first message, transmitter may have restarted
{
LastMessageID = 257; //reset last message number
processMessage();
delay(ACKdelay1);
sendACK(); //dont process message, but send ACK again
break; //and go back to receive
}
break; //and go back to receive
}
while (1);
}
void processMessage()
{
uint8_t index, endpayload;
endpayload = RXPacketL - 4;
for (index = 2; index < endpayload; index++)
{
SerialOutput.write(Message[index]);
}
#ifdef DEBUG
DebugSerial.print(RXPacketL - 6); //print number of characters in message
DebugSerial.print(F(" "));
DebugSerial.print(MessageID); //print message ID
DebugSerial.print(F(" > "));
DebugSerial.println(); //so each message is on new line
#endif
LastMessageID = MessageID;
}
void processControlMessage()
{
if (MessageID == 1)
{
DebugSerial.println(F("Ready"));
sendACK();
}
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LoRa.readIrqStatus(); //read the LoRa device IRQ status register
DebugSerial.print(F("RXPacketL,"));
DebugSerial.print(RXPacketL);
DebugSerial.print(F(",IRQStatus,0x"));
DebugSerial.println(IRQStatus, HEX);
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
DebugSerial.println(F("RXTimeout"));
}
}
void sendACK()
{
RXPayloadCRC = LoRa.readUint16SXBuffer(RXPacketL - 2); //get sent payload CRC, needed for ACK
digitalWrite(LED1, HIGH);
LoRa.writeUint16SXBuffer(0, MessageID);
LoRa.writeUint16SXBuffer(2, NetworkID);
LoRa.writeUint16SXBuffer(4, RXPayloadCRC);
LoRa.transmitSXBuffer(0, 6, TXtimeout, TXpower, WAIT_TX);
#ifdef DEBUG
DebugSerial.print(MessageID);
DebugSerial.println(F(" A >"));
#endif
digitalWrite(LED1, LOW);
}
void setup()
{
SerialOutput.begin(9600);
DebugSerial.begin(9600);
#ifdef DEBUG
DebugSerial.println();
DebugSerial.println(F(__FILE__));
DebugSerial.println();
#endif
pinMode(LED1, OUTPUT); //set high for on
SPI.begin();
if (LoRa.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
#ifdef DEBUG
DebugSerial.println(F("LoRa Device found"));
delay(1000);
#endif
}
else
{
DebugSerial.println(F("No LoRa device responding"));
while (1);
}
LoRa.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate);
#ifdef DEBUG
DebugSerial.println(F("Receiver ready"));
#endif
LastMessageID = 0x0100; //start value
}

View File

@ -0,0 +1,256 @@
/*******************************************************************************************************
Programs for Arduino - Copyright of the author Stuart Robinson - 28/12/21
This program is supplied as is, it is up to the user of the program to decide if the program is
suitable for the intended purpose and free from errors.
*******************************************************************************************************/
/*******************************************************************************************************
Program Operation - This is the receiver part of a Serial bridge being used to monitor a remote GPS.
The tranmitter receives data from the GPS on the defined serial port and puts that serial data into a
LoRa packet which is then transmitted. This matching reciever picks up the packet and feeds it into the
TinyGPSplus library and which decodes the data into a position fix, which is printed to the serial
monitor. The number of NMEA sentences passing and failing on checksum is also printed to serial monitor.
Serial monitor baud rate should be set at 115200.
*******************************************************************************************************/
#include <SPI.h> //the LoRa device is SPI based so load the SPI library
#include <SX128XLT.h> //include the appropriate library
SX128XLT LoRa; //create a library class instance called LoRa
#define NSS 10 //select pin on LoRa device
#define NRESET 9 //reset pin on LoRa device
#define RFBUSY 7 //busy pin on LoRa device
#define DIO1 3 //DIO1 pin on LoRa device, used for sensing RX and TX done
#define LED1 8 //this is output 1
#define LORA_DEVICE DEVICE_SX1280 //we need to define the LoRa device we are using
#define TXpower 10 //dBm power to use for ACK
uint8_t RXPacketL; //stores length of packet received
uint8_t RXPayloadL; //stores length of payload received
uint16_t RXPayloadCRC; //CRC of payload included in received packet
uint16_t MessageID; //MessageID identifies each message, 2 bytes at front of packet
uint16_t LastMessageID; //keep track of last received message, display messages start at 0x0100
const uint32_t Frequency = 2445000000; //frequency of transmissions
const uint32_t Offset = 0; //offset frequency for calibration purposes
const uint8_t Bandwidth = LORA_BW_1600; //LoRa bandwidth
const uint8_t SpreadingFactor = LORA_SF5; //LoRa spreading factor
const uint8_t CodeRate = LORA_CR_4_5; //LoRa coding rate
const uint16_t NetworkID = 0x3210; //Message NetworkID identifies each message, automatically appended to packet
const uint32_t ACKdelay1 = 10; //delay in mS before sending acknowledge
const uint32_t ACKdelay2 = 20; //delay in mS before sending acknowledge for message already received
const uint32_t RXtimeout = 60000 ; //receive timeout in mS. set to 0 for no timeout
const uint32_t TXtimeout = 1000; //transmit timeout in mS.
const uint8_t MaxMessageSize = 251 ; //maximum size of serial maeesage to send, 4 bytes needed for NetworkID and payload CRC
uint8_t Message[MaxMessageSize]; //array for receiving message
float GPSLat; //Latitude from GPS
float GPSLon; //Longitude from GPS
float GPSAlt; //Altitude from GPS
uint8_t GPSSats; //number of GPS satellites in use
#include <TinyGPS++.h> //get library here > http://arduiniana.org/libraries/tinygpsplus/
TinyGPSPlus gps; //create the TinyGPS++ object
#define SerialOutput Serial //assign serial port for outputing data
#define DebugSerial Serial //assign serial port for outputing debug data
//#define DEBUG //enable this define to see debug information
void loop()
{
#ifdef DEBUG
DebugSerial.print(F("> "));
#endif
do
{
RXPacketL = LoRa.receiveReliable(Message, MaxMessageSize, NetworkID, RXtimeout, WAIT_RX);
MessageID = Message[0] + (Message[1] * 256); //message number is first two bytes of Message array
if (RXPacketL == 0) //check for a valid packet
{
#ifdef DEBUG
DebugSerial.print(MessageID);
DebugSerial.print(F("E>"));
packet_is_Error();
#endif
break;
}
//if here there is a valid reliable packet
if (MessageID > LastMessageID) //new message should be greater than last message
{
processMessage();
delay(ACKdelay1);
sendACK();
break;
}
if (MessageID <= 256) //is it a control message
{
processControlMessage();
break;
}
if (LastMessageID == MessageID) //have we had this message before, remember TX may miss the sent ACK ?
{
delay(ACKdelay2);
sendACK(); //dont process message, but send ACK again
break; //and go back to receive
}
if (MessageID == 257) //this appears to be a first message, transmitter may have restarted
{
LastMessageID = 257; //reset last message number
processMessage();
delay(ACKdelay1);
sendACK(); //dont process message, but send ACK again
break; //and go back to receive
}
break; //and go back to receive
}
while (1);
}
void processMessage()
{
uint8_t index, endpayload;
endpayload = RXPacketL - 4;
for (index = 2; index < endpayload; index++)
{
//SerialOutput.write(Message[index]);
gps.encode(Message[index]);
}
if (gps.location.isUpdated() && gps.altitude.isUpdated() && gps.date.isUpdated())
{
GPSLat = gps.location.lat();
GPSLon = gps.location.lng();
GPSAlt = gps.altitude.meters();
GPSSats = gps.satellites.value();
printGPSfix();
}
#ifdef DEBUG
DebugSerial.print(RXPacketL - 6); //print number of characters in message
DebugSerial.print(F(" "));
DebugSerial.print(MessageID); //print message ID
DebugSerial.print(F(" > "));
DebugSerial.println(); //so each message is on new line
#endif
Serial.println();
Serial.print(F("NMEA "));
Serial.print(gps.passedChecksum()); //print number of valid NMEA sentences
Serial.print(F(" "));
Serial.println(gps.failedChecksum()); //print number of failed NMEA sentences
LastMessageID = MessageID;
}
void printGPSfix()
{
Serial.print(F("GPS Fix > "));
Serial.print(F("Lat,"));
Serial.print(GPSLat, 6);
Serial.print(F(",Lon,"));
Serial.print(GPSLon, 6);
Serial.print(F(",Alt,"));
Serial.print(GPSAlt, 1);
Serial.print(F("m,Sats,"));
Serial.println(GPSSats);
Serial.println();
}
void processControlMessage()
{
if (MessageID == 1)
{
DebugSerial.println(F("Ready"));
sendACK();
}
}
void packet_is_Error()
{
uint16_t IRQStatus;
IRQStatus = LoRa.readIrqStatus(); //read the LoRa device IRQ status register
DebugSerial.print(F("RXPacketL,"));
DebugSerial.print(RXPacketL);
DebugSerial.print(F(",IRQStatus,0x"));
DebugSerial.println(IRQStatus, HEX);
if (IRQStatus & IRQ_RX_TIMEOUT) //check for an RX timeout
{
DebugSerial.println(F("RXTimeout"));
}
}
void sendACK()
{
RXPayloadCRC = LoRa.readUint16SXBuffer(RXPacketL - 2); //get sent payload CRC, needed for ACK
digitalWrite(LED1, HIGH);
LoRa.writeUint16SXBuffer(0, MessageID);
LoRa.writeUint16SXBuffer(2, NetworkID);
LoRa.writeUint16SXBuffer(4, RXPayloadCRC);
LoRa.transmitSXBuffer(0, 6, TXtimeout, TXpower, WAIT_TX);
#ifdef DEBUG
DebugSerial.print(MessageID);
DebugSerial.println(F(" A >"));
#endif
digitalWrite(LED1, LOW);
}
void setup()
{
SerialOutput.begin(115200);
DebugSerial.begin(115200);
#ifdef DEBUG
DebugSerial.println();
DebugSerial.println(F(__FILE__));
DebugSerial.println();
#endif
pinMode(LED1, OUTPUT); //set high for on
SPI.begin();
if (LoRa.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
{
#ifdef DEBUG
DebugSerial.println(F("LoRa Device found"));
delay(1000);
#endif
}
else
{
DebugSerial.println(F("No LoRa device responding"));
while (1);
}
LoRa.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate);
#ifdef DEBUG
DebugSerial.println(F("Receiver ready"));
#endif
LastMessageID = 256; //start value
}