Merge branch '120-migrating-to-radiolib' into release_2023_01

This commit is contained in:
Timm Bogner 2023-01-25 12:02:52 -06:00
commit ec680649c5
7 changed files with 336 additions and 157 deletions

View File

@ -16,6 +16,11 @@
#define SERIAL_ACT sendESPNOW(0x02); bufferLoRa(1); sendESPNOWpeers();
#define MQTT_ACT
#define LORAG_ACT sendSerial();
// Neighbor Actions
#define ESPNOW1_ACT
#define ESPNOW2_ACT
#define LORA1_ACT sendSerial();
#define LORA2_ACT
// Protocols -- Define which protocols the gateway will use.
// Warning: ESP-NOW and WiFi should not be used simultaneously.
@ -30,12 +35,6 @@
#define LORA_NEIGHBOR_1 0x02 // LoRa1 Address
#define LORA_NEIGHBOR_2 0x0F // LoRa2 Address
// Neighbor Actions
#define ESPNOW1_ACT
#define ESPNOW2_ACT
#define LORA1_ACT sendSerial();
#define LORA2_ACT
//Pins for UART data interface (ESP32 only)
#define RXD2 14
#define TXD2 15
@ -54,17 +53,14 @@
#define SPI_MISO 19
#define SPI_MOSI 27
// LoRa Configuration -- Needed only if using LoRa
// LoRa Configuration
#define RADIOLIB_MODULE SX1276 //Tested on SX1276
#define LORA_SS 18
#define LORA_RST 14
#define LORA_DIO0 26
//433E6 for Asia
//866E6 for Europe
//915E6 for North America
#define LORA_BAND 915E6 // LoRa Frequency Band
#define LORA_SF 7 // LoRa Spreading Factor
#define LORA_TXPWR 17 // LoRa TX power in dBm (+2dBm - +20dBm), default is +17dBm. Lower power = less battery use
#define LORA_DIO1 33
#define LORA_TXPWR 17 // LoRa TX power in dBm (: +2dBm - +17dBm (for SX1276-7) +20dBm (for SX1278))
#define LORA_ACK // Request LoRa acknowledgment.
// Buffer Delays - in milliseconds - Uncomment to enable any buffer

View File

@ -19,16 +19,13 @@
#define SPI_MISO 19
#define SPI_MOSI 27
//LoRa Configuration
// LoRa Configuration
#define RADIOLIB_MODULE SX1276 //Tested on SX1276
#define LORA_SS 18
#define LORA_RST 14
#define LORA_DIO0 26
//433E6 for Asia
//866E6 for Europe
//915E6 for North America
//#define LORA_BAND 915E6 // LoRa Frequency Band
//#define LORA_SF 7 // LoRa Spreading Factor
//#define LORA_TXPWR 17 // LoRa TX power in dBm (+2dBm - +20dBm), default is +17dBm
#define LORA_DIO1 33
#define LORA_ACK // Request LoRa acknowledgment. Increases battery usage.
#define LORA_TXPWR 17 // LoRa TX power in dBm (: +2dBm - +17dBm (for SX1276-7) +20dBm (for SX1278))
#define LORA_ACK // Request LoRa acknowledgment.

View File

@ -228,19 +228,19 @@ void printLoraDetails() {
#ifdef USE_LORA
printSmallSectionHeader("LoRa Details:");
#if defined(LORA_BAND)
DBG("LoRa Band used from LORA_BAND : " + String(FDRS_BAND));
#elif defined (GLOBAL_LORA_BAND)
DBG("LoRa Band used from GLOBAL_LORA_BAND : " + String(FDRS_BAND));
#if defined(FDRS_LORA_FREQUENCY)
DBG("LoRa frequency used from FDRS_LORA_FREQUENCY : " + String(FDRS_LORA_FREQUENCY));
#elif defined (GLOBAL_FDRS_LORA_FREQUENCY)
DBG("LoRa frequency used from GLOBAL_FDRS_LORA_FREQUENCY : " + String(FDRS_LORA_FREQUENCY));
#else
DBG("NO LORA_BAND defined! Please define in fdrs_globals.h (recommended) or in fdrs_sensor_config.h");
DBG("NO FDRS_LORA_FREQUENCY defined! Please define in fdrs_globals.h (recommended) or in fdrs_sensor_config.h");
//exit(0);
#endif //LORA-BAND
#endif //LORA-FREQUENCY
#if defined(LORA_SF)
DBG("LoRa SF used from LORA_SF : " + String(FDRS_SF));
DBG("LoRa SF used from LORA_SF : " + String(FDRS_LORA_SF));
#elif defined (GLOBAL_LORA_SF)
DBG("LoRa SF used from GLOBAL_LORA_SF : " + String(FDRS_SF));
DBG("LoRa SF used from GLOBAL_LORA_SF : " + String(FDRS_LORA_SF));
#else
// ASSERT("NO LORA-SF defined! Please define in fdrs_globals.h (recommended) or in fdrs_sensor_config.h");
DBG("NO LORA_SF defined! Please define in fdrs_globals.h (recommended) or in fdrs_sensor_config.h");
@ -248,9 +248,9 @@ void printLoraDetails() {
#endif //LORA_SF
#if defined(LORA_TXPWR)
DBG("LoRa TXPWR used from LORA_TXPWR : " + String(FDRS_TXPWR));
DBG("LoRa TXPWR used from LORA_TXPWR : " + String(FDRS_LORA_TXPWR));
#elif defined (GLOBAL_LORA_TXPWR)
DBG("LoRa TXPWR used from GLOBAL_LORA_TXPWR : " + String(FDRS_TXPWR));
DBG("LoRa TXPWR used from GLOBAL_LORA_TXPWR : " + String(FDRS_LORA_TXPWR));
#else
// ASSERT("NO LORA-TXPWR defined! Please define in fdrs_globals.h (recommended) or in fdrs_sensor_config.h");
DBG("NO LORA_TXPWR defined! Please define in fdrs_globals.h (recommended) or in fdrs_sensor_config.h");

View File

@ -21,7 +21,7 @@
#include <WiFiUdp.h>
#endif
#ifdef USE_LORA
#include <LoRa.h>
#include <RadioLib.h>
#endif
#ifdef USE_LED
#include <FastLED.h>
@ -76,6 +76,12 @@ enum {
#ifdef USE_WIFI
// Internal Globals
// Default values that are assigned if none are present in config
#define GLOBAL_ACK_TIMEOUT 400 // LoRa ACK timeout in ms. (Minimum = 200)
#define GLOBAL_LORA_RETRIES 2 // LoRa ACK automatic retries [0 - 3]
#define GLOBAL_LORA_TXPWR 17 // LoRa TX power in dBm (: +2dBm - +17dBm (for SX1276-7) +20dBm (for SX1278))
// select WiFi SSID configuration
#if defined(WIFI_SSID)
@ -130,42 +136,74 @@ enum {
#else
// ASSERT("NO MQTT password defined! Please define in fdrs_globals.h (recommended) or in fdrs_sensor_config.h");
#endif //MQTT_PASS
#if defined (MQTT_AUTH) || defined (GLOBAL_MQTT_AUTH)
#define FDRS_MQTT_AUTH
#endif //MQTT_AUTH
#endif //USE_WIFI
#ifdef USE_LORA
// select LoRa band configuration
#if defined(LORA_BAND)
#define FDRS_BAND LORA_BAND
#elif defined (GLOBAL_LORA_BAND)
#define FDRS_BAND GLOBAL_LORA_BAND
#else
// ASSERT("NO LORA-BAND defined! Please define in fdrs_globals.h (recommended) or in fdrs_sensor_config.h");
#endif //LORA_BAND
#if defined(LORA_FREQUENCY)
#define FDRS_LORA_FREQUENCY LORA_FREQUENCY
#else
#define FDRS_LORA_FREQUENCY GLOBAL_LORA_FREQUENCY
#endif //LORA_FREQUENCY
// select LoRa SF configuration
#if defined(LORA_SF)
#define FDRS_SF LORA_SF
#elif defined (GLOBAL_LORA_SF)
#define FDRS_SF GLOBAL_LORA_SF
#else
// ASSERT("NO LORA-SF defined! Please define in fdrs_globals.h (recommended) or in fdrs_sensor_config.h");
#define FDRS_LORA_SF LORA_SF
#else
#define FDRS_LORA_SF GLOBAL_LORA_SF
#endif //LORA_SF
// select LoRa TXPWR configuration
// select LoRa ACK configuration
#if defined(LORA_ACK) || defined(GLOBAL_LORA_ACK)
#define FDRS_LORA_ACK
#endif //LORA_ACK
// select LoRa ACK Timeout configuration
#if defined(LORA_ACK_TIMEOUT)
#define FDRS_ACK_TIMEOUT LORA_ACK_TIMEOUT
#else
#define FDRS_ACK_TIMEOUT GLOBAL_ACK_TIMEOUT
#endif //LORA_ACK_TIMEOUT
// select LoRa Retry configuration
#if defined(LORA_RETRIES)
#define FDRS_LORA_RETRIES LORA_RETRIES
#else
#define FDRS_LORA_RETRIES GLOBAL_LORA_RETRIES
#endif //LORA_RETRIES
// select LoRa Tx Power configuration
#if defined(LORA_TXPWR)
#define FDRS_TXPWR LORA_TXPWR
#elif defined (GLOBAL_LORA_TXPWR)
#define FDRS_TXPWR GLOBAL_LORA_TXPWR
#else
// ASSERT("NO LORA-TXPWR defined! Please define in fdrs_globals.h (recommended) or in fdrs_sensor_config.h");
#define FDRS_LORA_TXPWR LORA_TXPWR
#else
#define FDRS_LORA_TXPWR GLOBAL_LORA_TXPWR
#endif //LORA_TXPWR
// select LoRa BANDWIDTH configuration
#if defined(LORA_BANDWIDTH)
#define FDRS_LORA_BANDWIDTH LORA_BANDWIDTH
#else
#define FDRS_LORA_BANDWIDTH GLOBAL_LORA_BANDWIDTH
#endif //LORA_BANDWIDTH
// select LoRa Coding Rate configuration
#if defined(LORA_CR)
#define FDRS_LORA_CR LORA_CR
#else
#define FDRS_LORA_CR GLOBAL_LORA_CR
#endif //LORA_CR
// select LoRa SyncWord configuration
#if defined(LORA_SYNCWORD)
#define FDRS_LORA_SYNCWORD LORA_SYNCWORD
#else
#define FDRS_LORA_SYNCWORD GLOBAL_LORA_SYNCWORD
#endif //LORA_SYNCWORD
#endif //USE_LORA
#define MAC_PREFIX 0xAA, 0xBB, 0xCC, 0xDD, 0xEE // Should only be changed if implementing multiple FDRS systems.
@ -207,15 +245,6 @@ uint8_t ESPNOW1[] = {MAC_PREFIX, ESPNOW_NEIGHBOR_1};
uint8_t ESPNOW2[] = {MAC_PREFIX, ESPNOW_NEIGHBOR_2};
#ifdef USE_LORA
uint16_t LoRa1 = ((mac_prefix[4] << 8) | LORA_NEIGHBOR_1); // Use 2 bytes for LoRa addressing instead of previous 3 bytes
uint16_t LoRa2 = ((mac_prefix[4] << 8) | LORA_NEIGHBOR_2);
uint16_t loraGwAddress = ((selfAddress[4] << 8) | selfAddress[5]); // last 2 bytes of gateway address
uint16_t loraBroadcast = 0xFFFF;
unsigned long receivedLoRaMsg = 0; // Number of total LoRa packets destined for us and of valid size
unsigned long ackOkLoRaMsg = 0; // Number of total LoRa packets with valid CRC
#endif
#if defined (USE_SD_LOG) || defined (USE_FS_LOG)
char logBuffer[512];
uint16_t logBufferPos = 0; // datatype depends on size of sdBuffer
@ -852,7 +881,7 @@ void loopFDRS(){
while (UART_IF.available() || Serial.available()) {
getSerial();
}
getLoRa();
handleLoRa();
#ifdef USE_WIFI
if (!client.connected()) {
reconnect(1, true);

View File

@ -18,10 +18,12 @@
#define GLOBAL_MQTT_USER "Your MQTT Username"
#define GLOBAL_MQTT_PASS "Your MQTT Password"
#define GLOBAL_LORA_BAND 915E6 // LoRa Frequency Band
#define GLOBAL_LORA_SF 7 // LoRa Spreading Factor
#define GLOBAL_LORA_TXPWR 17 // LoRa TX power in dBm (+2dBm - +20dBm), default is +17dBm. Lower power = less battery use
#define GLOBAL_LORA_ACK_TIMEOUT 400 // ms timeout waiting for LoRa ACKs (if enabled). Wouldn't go less than 200ms
#define GLOBAL_LORA_RETRIES 2
#define GLOBAL_LORA_FREQUENCY 915.0 // Carrier frequency in MHz. Allowed values range from 137.0 MHz to 1020.0 MHz (varies by chip).
#define GLOBAL_LORA_SF 7 // LoRa link spreading factor. Allowed values range from 6 to 12.
#define GLOBAL_LORA_BANDWIDTH 125.0 // LoRa link bandwidth in kHz. Allowed values are 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125, 250 and 500 kHz.
#define GLOBAL_LORA_CR 5 // LoRa link coding rate denominator. Allowed values range from 5 to 8.
#define GLOBAL_LORA_SYNCWORD 0x12 // LoRa sync word. Can be used to distinguish different networks. Note that 0x34 is reserved for LoRaWAN.
#endif //FDRS_GLOBALS

View File

@ -1,3 +1,30 @@
#ifdef USE_LORA
RADIOLIB_MODULE radio = new Module(LORA_SS, LORA_DIO0, LORA_RST, LORA_DIO1);
bool transmitFlag = false;// flag to indicate transmission or reception state
volatile bool enableInterrupt = true;// disable interrupt when it's not needed
volatile bool operationDone = false;// flag to indicate that a packet was sent or received
uint16_t LoRa1 = ((mac_prefix[4] << 8) | LORA_NEIGHBOR_1); // Use 2 bytes for LoRa addressing instead of previous 3 bytes
uint16_t LoRa2 = ((mac_prefix[4] << 8) | LORA_NEIGHBOR_2);
uint16_t loraGwAddress = ((selfAddress[4] << 8) | selfAddress[5]); // last 2 bytes of gateway address
uint16_t loraBroadcast = 0xFFFF;
unsigned long receivedLoRaMsg = 0; // Number of total LoRa packets destined for us and of valid size
unsigned long ackOkLoRaMsg = 0; // Number of total LoRa packets with valid CRC
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// check if the interrupt is enabled
if(!enableInterrupt) {
return;
}
// we sent or received packet, set the flag
operationDone = true;
}
#endif
#ifdef USE_LORA
void transmitLoRa(uint16_t* destMac, DataReading * packet, uint8_t len) {
@ -18,10 +45,14 @@ void transmitLoRa(uint16_t* destMac, DataReading * packet, uint8_t len) {
pkt[(len * sizeof(DataReading) + 5)] = (calcCRC & 0x00FF);
DBG("Transmitting LoRa message of size " + String(sizeof(pkt)) + " bytes with CRC 0x" + String(calcCRC, HEX) + " to LoRa MAC 0x" + String(*destMac, HEX));
//printLoraPacket(pkt,sizeof(pkt));
LoRa.beginPacket();
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
LoRa.endPacket();
int state = radio.startTransmit(pkt,sizeof(pkt));
transmitFlag = true;
if (state == RADIOLIB_ERR_NONE) {
} else {
DBG(" failed, code " + String(state));
while (true);
}
}
void transmitLoRa(uint16_t* destMac, SystemPacket * packet, uint8_t len) {
uint16_t calcCRC = 0x0000;
@ -41,9 +72,13 @@ void transmitLoRa(uint16_t* destMac, SystemPacket * packet, uint8_t len) {
pkt[(len * sizeof(SystemPacket) + 5)] = (calcCRC & 0x00FF);
DBG("Transmitting LoRa message of size " + String(sizeof(pkt)) + " bytes with CRC 0x" + String(calcCRC, HEX) + " to LoRa MAC 0x" + String(*destMac, HEX));
//printLoraPacket(pkt,sizeof(pkt));
LoRa.beginPacket();
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
LoRa.endPacket();
int state = radio.startTransmit(pkt,sizeof(pkt));
transmitFlag = true;
if (state == RADIOLIB_ERR_NONE) {
} else {
DBG(" failed, code " + String(state));
while (true);
}
}
#endif //USE_LORA
@ -57,27 +92,30 @@ void printLoraPacket(uint8_t* p,int size) {
}
void begin_lora() {
#ifdef USE_LORA
DBG("Initializing LoRa!");
#ifdef ESP32
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
#endif
LoRa.setPins(LORA_SS, LORA_RST, LORA_DIO0);
if (!LoRa.begin(FDRS_BAND)) {
DBG(" Initialization failed!");
while (1);
#ifdef USE_LORA
int state = radio.begin(FDRS_LORA_FREQUENCY, FDRS_LORA_BANDWIDTH, FDRS_LORA_SF, FDRS_LORA_CR, FDRS_LORA_SYNCWORD, FDRS_LORA_TXPWR, 8, 0);
if (state == RADIOLIB_ERR_NONE) {
DBG("RadioLib initialization successful!");
} else {
DBG("RadioLib initialization failed, code " + String(state));
while (true);
}
radio.setDio0Action(setFlag);
radio.setCRC(false);
DBG("LoRa Initialized. Frequency: " + String(FDRS_LORA_FREQUENCY) + " Bandwidth: " + String(FDRS_LORA_BANDWIDTH) + " SF: " + String(FDRS_LORA_SF) + " CR: " + String(FDRS_LORA_CR) + " SyncWord: " + String(FDRS_LORA_SYNCWORD) + " Tx Power: " + String(FDRS_LORA_TXPWR) + "dBm");
state = radio.startReceive(); // start listening for LoRa packets
if (state == RADIOLIB_ERR_NONE) {
} else {
DBG(" failed, code " + String(state));
while (true);
}
LoRa.setSpreadingFactor(FDRS_SF);
LoRa.setTxPower(FDRS_TXPWR);
DBG("LoRa Initialized. Band: " + String(FDRS_BAND) + " SF: " + String(FDRS_SF) + " Tx Power: " + String(LORA_TXPWR) + " dBm");
#endif // USE_LORA
}
crcResult getLoRa() {
#ifdef USE_LORA
int packetSize = LoRa.parsePacket();
int packetSize = radio.getPacketLength();
if((((packetSize - 6) % sizeof(DataReading) == 0) || ((packetSize - 6) % sizeof(SystemPacket) == 0)) && packetSize > 0) { // packet size should be 6 bytes plus multiple of size of DataReading
uint8_t packet[packetSize];
uint16_t packetCRC = 0x0000; // CRC Extracted from received LoRa packet
@ -85,8 +123,8 @@ crcResult getLoRa() {
uint16_t sourceMAC = 0x0000;
uint16_t destMAC = 0x0000;
LoRa.readBytes((uint8_t *)&packet, packetSize);
radio.readData((uint8_t *)&packet, packetSize);
destMAC = (packet[0] << 8) | packet[1];
sourceMAC = (packet[2] << 8) | packet[3];
packetCRC = ((packet[packetSize - 2] << 8) | packet[packetSize - 1]);
@ -94,10 +132,10 @@ crcResult getLoRa() {
if (destMAC == (selfAddress[4] << 8 | selfAddress[5])) { //Check if addressed to this device (2 bytes, bytes 1 and 2)
//printLoraPacket(packet,sizeof(packet));
if(receivedLoRaMsg != 0){ // Avoid divide by 0
DBG("Incoming LoRa. Size: " + String(packetSize) + " Bytes, RSSI: " + String(LoRa.packetRssi()) + "dBm, SNR: " + String(LoRa.packetSnr()) + "dB, PacketCRC: 0x" + String(packetCRC, HEX) + ", Total LoRa received: " + String(receivedLoRaMsg) + ", CRC Ok Pct " + String((float)ackOkLoRaMsg/receivedLoRaMsg*100) + "%");
DBG("Incoming LoRa. Size: " + String(packetSize) + " Bytes, RSSI: " + String(radio.getRSSI()) + "dBm, SNR: " + String(radio.getSNR()) + "dB, PacketCRC: 0x" + String(packetCRC, HEX) + ", Total LoRa received: " + String(receivedLoRaMsg) + ", CRC Ok Pct " + String((float)ackOkLoRaMsg/receivedLoRaMsg*100) + "%");
}
else {
DBG("Incoming LoRa. Size: " + String(packetSize) + " Bytes, RSSI: " + String(LoRa.packetRssi()) + "dBm, SNR: " + String(LoRa.packetSnr()) + "dB, PacketCRC: 0x" + String(packetCRC, HEX) + ", Total LoRa received: " + String(receivedLoRaMsg));
DBG("Incoming LoRa. Size: " + String(packetSize) + " Bytes, RSSI: " + String(radio.getRSSI()) + "dBm, SNR: " + String(radio.getSNR()) + "dB, PacketCRC: 0x" + String(packetCRC, HEX) + ", Total LoRa received: " + String(receivedLoRaMsg));
}
receivedLoRaMsg++;
// Evaluate CRC
@ -194,11 +232,19 @@ crcResult getLoRa() {
}
else {
DBG("Incoming LoRa packet of " + String(packetSize) + " bytes received from address 0x" + String(sourceMAC, HEX) + " destined for node address 0x" + String(destMAC, HEX));
// printLoraPacket(packet,sizeof(packet));
return CRC_NULL;
}
}
else {
if(packetSize != 0) {
DBG("Incoming LoRa packet of " + String(packetSize) + "bytes not processed.");
// uint8_t packet[packetSize];
// radio.readData((uint8_t *)&packet, packetSize);
// printLoraPacket(packet,sizeof(packet));
return CRC_NULL;
}
}
#endif //USE_LORA
@ -291,6 +337,24 @@ void releaseLoRa(uint8_t interface) {
#endif
}
void handleLoRa(){
#ifdef USE_LORA
if(operationDone) { // the interrupt was triggered
enableInterrupt = false;
operationDone = false;
if(transmitFlag) { // the previous operation was transmission
radio.startReceive(); // return to listen mode
enableInterrupt = true;
transmitFlag = false;
} else { // the previous operation was reception
returnCRC = getLoRa();
if (!transmitFlag) radio.startReceive(); //return to listen if no transmission was begun.
enableInterrupt = true;
}
}
#endif //USE_LORA
}
void releaseSerial() {
DBG("Releasing Serial.");
DynamicJsonDocument doc(24576);

View File

@ -15,33 +15,79 @@
#endif
#ifdef USE_LORA
#include <ArduinoUniqueID.h>
#include <LoRa.h>
#include <RadioLib.h>
#endif
// enable to get detailed info from where single configuration macros have been taken
#define LORA_ACK_TIMEOUT 400 // LoRa ACK timeout in ms. (Minimum = 200)
#define LORA_RETRIES 2 // LoRa ACK automatic retries [0 - 3]
// Internal Globals
// Default values that are assigned if none are present in config
#define GLOBAL_ACK_TIMEOUT 400 // LoRa ACK timeout in ms. (Minimum = 200)
#define GLOBAL_LORA_RETRIES 2 // LoRa ACK automatic retries [0 - 3]
#define GLOBAL_LORA_TXPWR 17 // LoRa TX power in dBm (: +2dBm - +17dBm (for SX1276-7) +20dBm (for SX1278))
#ifdef USE_LORA
// select LoRa band configuration
#if defined(LORA_BAND)
#define FDRS_BAND LORA_BAND
#elif defined (GLOBAL_LORA_BAND)
#define FDRS_BAND GLOBAL_LORA_BAND
#if defined(LORA_FREQUENCY)
#define FDRS_LORA_FREQUENCY LORA_FREQUENCY
#else
// ASSERT("NO LORA-BAND defined! Please define in fdrs_globals.h (recommended) or in fdrs_sensor_config.h");
#endif //LORA_BAND
#define FDRS_LORA_FREQUENCY GLOBAL_LORA_FREQUENCY
#endif //LORA_FREQUENCY
// select LoRa SF configuration
#if defined(LORA_SF)
#define FDRS_SF LORA_SF
#elif defined (GLOBAL_LORA_SF)
#define FDRS_SF GLOBAL_LORA_SF
#define FDRS_LORA_SF LORA_SF
#else
// ASSERT("NO LORA-SF defined! Please define in fdrs_globals.h (recommended) or in fdrs_sensor_config.h");
#define FDRS_LORA_SF GLOBAL_LORA_SF
#endif //LORA_SF
// select LoRa ACK configuration
#if defined(LORA_ACK) || defined(GLOBAL_LORA_ACK)
#define FDRS_LORA_ACK
#endif //LORA_ACK
// select LoRa ACK Timeout configuration
#if defined(LORA_ACK_TIMEOUT)
#define FDRS_ACK_TIMEOUT LORA_ACK_TIMEOUT
#else
#define FDRS_ACK_TIMEOUT GLOBAL_ACK_TIMEOUT
#endif //LORA_ACK_TIMEOUT
// select LoRa Retry configuration
#if defined(LORA_RETRIES)
#define FDRS_LORA_RETRIES LORA_RETRIES
#else
#define FDRS_LORA_RETRIES GLOBAL_LORA_RETRIES
#endif //LORA_RETRIES
// select LoRa Tx Power configuration
#if defined(LORA_TXPWR)
#define FDRS_LORA_TXPWR LORA_TXPWR
#else
#define FDRS_LORA_TXPWR GLOBAL_LORA_TXPWR
#endif //LORA_TXPWR
// select LoRa BANDWIDTH configuration
#if defined(LORA_BANDWIDTH)
#define FDRS_LORA_BANDWIDTH LORA_BANDWIDTH
#else
#define FDRS_LORA_BANDWIDTH GLOBAL_LORA_BANDWIDTH
#endif //LORA_BANDWIDTH
// select LoRa Coding Rate configuration
#if defined(LORA_CR)
#define FDRS_LORA_CR LORA_CR
#else
#define FDRS_LORA_CR GLOBAL_LORA_CR
#endif //LORA_CR
// select LoRa SyncWord configuration
#if defined(LORA_SYNCWORD)
#define FDRS_LORA_SYNCWORD LORA_SYNCWORD
#else
#define FDRS_LORA_SYNCWORD GLOBAL_LORA_SYNCWORD
#endif //LORA_SYNCWORD
#endif //USE_LORA
#ifdef FDRS_DEBUG
@ -87,6 +133,10 @@ uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t gatewayAddress[] = {MAC_PREFIX, GTWY_MAC};
uint16_t gtwyAddress = ((gatewayAddress[4] << 8) | GTWY_MAC);
#ifdef USE_LORA
RADIOLIB_MODULE radio = new Module(LORA_SS, LORA_DIO0, LORA_RST, LORA_DIO1);
bool transmitFlag = false;// flag to indicate transmission or reception state
volatile bool enableInterrupt = true;// disable interrupt when it's not needed
volatile bool operationDone = false;// flag to indicate that a packet was sent or received
uint16_t LoRaAddress = ((UniqueID8[6] << 8) | UniqueID8[7]);
unsigned long transmitLoRaMsgwAck = 0; // Number of total LoRa packets destined for us and of valid size
unsigned long msgOkLoRa = 0; // Number of total LoRa packets with valid CRC
@ -96,7 +146,9 @@ uint8_t incMAC[6];
uint32_t wait_time = 0;
DataReading fdrsData[espnow_size];
DataReading incData[espnow_size];
crcResult esp_now_ack_flag;
crcResult getLoRa();
uint8_t data_count = 0;
bool is_ping = false;
@ -106,6 +158,7 @@ void (*callback_ptr)(DataReading);
uint16_t subscription_list[256] = {};
bool active_subs[256] = {};
#ifdef USE_ESPNOW
// Set ESP-NOW send and receive callbacks for either ESP8266 or ESP32
#if defined(ESP8266)
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
@ -155,8 +208,61 @@ void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
}
}
}
#endif // USE_ESPNOW
#ifdef USE_LORA
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
if(!enableInterrupt) { // check if the interrupt is enabled
return;
}
operationDone = true; // we sent or received packet, set the flag
}
#endif
void handleLoRa(){
#ifdef USE_LORA
if(operationDone) { // the interrupt was triggered
enableInterrupt = false;
operationDone = false;
if(transmitFlag) { // the previous operation was transmission,
radio.startReceive(); // return to listen mode
enableInterrupt = true;
transmitFlag = false;
} else { // the previous operation was reception
returnCRC = getLoRa();
radio.startReceive(); // fixes the problem?
enableInterrupt = true;
}
}
#endif //USE_LORA
}
void begin_lora() {
// #ifdef ESP32
// SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
// #endif
#ifdef USE_LORA
int state = radio.begin(FDRS_LORA_FREQUENCY, FDRS_LORA_BANDWIDTH, FDRS_LORA_SF, FDRS_LORA_CR, FDRS_LORA_SYNCWORD, FDRS_LORA_TXPWR, 8, 0);
if (state == RADIOLIB_ERR_NONE) {
DBG("RadioLib initialization successful!");
} else {
DBG("RadioLib initialization failed, code " + String(state));
while (true);
}
DBG("LoRa Initialized. Frequency: " + String(FDRS_LORA_FREQUENCY) + " Bandwidth: " + String(FDRS_LORA_BANDWIDTH) + " SF: " + String(FDRS_LORA_SF) + " CR: " + String(FDRS_LORA_CR) + " SyncWord: " + String(FDRS_LORA_SYNCWORD) + " Tx Power: " + String(FDRS_LORA_TXPWR) + "dBm");
radio.setDio0Action(setFlag);
radio.setCRC(false);
state = radio.startReceive(); // start listening for LoRa packets
if (state == RADIOLIB_ERR_NONE) {
} else {
DBG(" failed, code " + String(state));
while (true);
}
#endif // USE_LORA
}
void beginFDRS() {
#ifdef FDRS_DEBUG
Serial.begin(115200);
@ -173,7 +279,7 @@ void beginFDRS() {
digitalWrite(POWER_CTRL, 1);
delay(50);
#endif
// Init ESP-NOW for either ESP8266 or ESP32 and set MAC address
// Init ESP-NOW for either ESP8266 or ESP32
#ifdef USE_ESPNOW
DBG("Initializing ESP-NOW!");
WiFi.mode(WIFI_STA);
@ -214,22 +320,7 @@ void beginFDRS() {
#endif
DBG(" ESP-NOW Initialized.");
#endif //USE_ESPNOW
#ifdef USE_LORA
DBG("Initializing LoRa!");
#ifdef ESP32
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
#endif
LoRa.setPins(LORA_SS, LORA_RST, LORA_DIO0);
if (!LoRa.begin(FDRS_BAND)) {
DBG("Unable to initialize LoRa!");
while (1);
}
LoRa.setSpreadingFactor(FDRS_SF);
DBG(" LoRa Initialized.");
DBG("LoRa Band: " + String(FDRS_BAND));
DBG("LoRa SF : " + String(FDRS_SF));
#endif // USE_LORA
begin_lora();
#ifdef DEBUG_CONFIG
// if (resetReason != ESP_RST_DEEPSLEEP) {
//checkConfig();
@ -264,7 +355,6 @@ static uint16_t crc16_update(uint16_t crc, uint8_t a) {
return crc;
}
crcResult getLoRa();
void transmitLoRa(uint16_t* destMAC, DataReading * packet, uint8_t len) {
#ifdef USE_LORA
@ -286,22 +376,26 @@ void transmitLoRa(uint16_t* destMAC, DataReading * packet, uint8_t len) {
pkt[len * sizeof(DataReading) + 4] = (calcCRC >> 8);
pkt[len * sizeof(DataReading) + 5] = (calcCRC & 0x00FF);
#ifdef LORA_ACK // Wait for ACK
int retries = LORA_RETRIES + 1;
int retries = FDRS_LORA_RETRIES + 1;
while(retries != 0) {
if(transmitLoRaMsgwAck != 0)
DBG("Transmitting LoRa message of size " + String(sizeof(pkt)) + " bytes with CRC 0x" + String(calcCRC, HEX) + " to gateway 0x" + String(*destMAC, HEX) + ". Retries remaining: " + String(retries - 1) + ", Ack Ok " + String((float)msgOkLoRa/transmitLoRaMsgwAck*100) + "%");
else
DBG("Transmitting LoRa message of size " + String(sizeof(pkt)) + " bytes with CRC 0x" + String(calcCRC, HEX) + " to gateway 0x" + String(*destMAC, HEX) + ". Retries remaining: " + String(retries - 1));
//printLoraPacket(pkt,sizeof(pkt));
LoRa.beginPacket();
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
LoRa.endPacket();
int state = radio.transmit(pkt,sizeof(pkt));
transmitFlag = true;
if (state == RADIOLIB_ERR_NONE) {
} else {
DBG(" failed, code " + String(state));
while (true);
}
transmitLoRaMsgwAck++;
unsigned long loraAckTimeout = millis() + LORA_ACK_TIMEOUT;
unsigned long loraAckTimeout = millis() + FDRS_ACK_TIMEOUT;
retries--;
delay(10);
while(returnCRC == CRC_NULL && (millis() < loraAckTimeout)) {
returnCRC = getLoRa();
handleLoRa();
}
if(returnCRC == CRC_OK) {
//DBG("LoRa ACK Received! CRC OK");
@ -320,9 +414,13 @@ void transmitLoRa(uint16_t* destMAC, DataReading * packet, uint8_t len) {
#else // Send and do not wait for ACK reply
DBG("Transmitting LoRa message of size " + String(sizeof(pkt)) + " bytes with CRC 0x" + String(calcCRC, HEX) + " to gateway 0x" + String(*destMAC, HEX));
//printLoraPacket(pkt,sizeof(pkt));
LoRa.beginPacket();
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
LoRa.endPacket();
int state = radio.transmit(pkt,sizeof(pkt));
transmitFlag = true;
if (state == RADIOLIB_ERR_NONE) {
} else {
DBG(" failed, code " + String(state));
while (true);
}
transmitLoRaMsgwAck++;
#endif // LORA_ACK
#endif // USE_LORA
@ -348,19 +446,22 @@ void transmitLoRa(uint16_t* destMAC, SystemPacket* packet, uint8_t len) {
pkt[len * sizeof(SystemPacket) + 5] = (calcCRC & 0x00FF);
DBG("Transmitting LoRa message of size " + String(sizeof(pkt)) + " bytes with CRC 0x" + String(calcCRC, HEX) + " to destination 0x" + String(*destMAC, HEX));
//printLoraPacket(pkt,sizeof(pkt));
LoRa.beginPacket();
LoRa.write((uint8_t*)&pkt, sizeof(pkt));
LoRa.endPacket();
int state = radio.startTransmit(pkt,sizeof(pkt));
transmitFlag = true;
if (state == RADIOLIB_ERR_NONE) {
} else {
DBG(" failed, code " + String(state));
while (true);
}
#endif // USE_LORA
}
// getLoRa for Sensors
// USED to get ACKs (SystemPacket type) from LoRa gateway at this point. May be used in the future to get other data
// Return type is crcResult struct - CRC_OK, CRC_BAD, CRC_NULL. CRC_NULL used for non-ack data
crcResult getLoRa() {
#ifdef USE_LORA
int packetSize = LoRa.parsePacket();
int packetSize = radio.getPacketLength();
if((packetSize - 6) % sizeof(SystemPacket) == 0 && packetSize > 0) { // packet size should be 6 bytes plus multiple of size of SystemPacket
uint8_t packet[packetSize];
uint16_t packetCRC = 0x0000; // CRC Extracted from received LoRa packet
@ -368,15 +469,15 @@ crcResult getLoRa() {
uint16_t sourceMAC = 0x0000;
uint16_t destMAC = 0x0000;
uint ln = (packetSize - 6) / sizeof(SystemPacket);
unsigned int ln = (packetSize - 6) / sizeof(SystemPacket);
SystemPacket receiveData[ln];
LoRa.readBytes((uint8_t *)&packet, packetSize);
radio.readData((uint8_t *)&packet, packetSize);
destMAC = (packet[0] << 8) | packet[1];
sourceMAC = (packet[2] << 8) | packet[3];
packetCRC = ((packet[packetSize - 2] << 8) | packet[packetSize - 1]);
DBG("Incoming LoRa. Size: " + String(packetSize) + " Bytes, RSSI: " + String(LoRa.packetRssi()) + "dBm, SNR: " + String(LoRa.packetSnr()) + "dB, PacketCRC: 0x" + String(packetCRC, HEX));
DBG("Incoming LoRa. Size: " + String(packetSize) + " Bytes, RSSI: " + String(radio.getRSSI()) + "dBm, SNR: " + String(radio.getSNR()) + "dB, PacketCRC: 0x" + String(packetCRC, HEX));
if (destMAC == LoRaAddress) { // The packet is for us so let's process it
//printLoraPacket(packet,sizeof(packet));
for(int i = 0; i < (packetSize - 2); i++) { // Last 2 bytes of packet are the CRC so do not include them in calculation
@ -464,7 +565,6 @@ bool sendFDRS() {
DBG("Sending FDRS Packet!");
#ifdef USE_ESPNOW
esp_now_send(gatewayAddress, (uint8_t *) &fdrsData, data_count * sizeof(DataReading));
esp_now_ack_flag = CRC_NULL;
while(esp_now_ack_flag == CRC_NULL){
delay(0);
@ -476,7 +576,6 @@ bool sendFDRS() {
data_count = 0;
return false;
}
#endif
#ifdef USE_LORA
transmitLoRa(&gtwyAddress, fdrsData, data_count);
@ -523,7 +622,6 @@ void sleepFDRS(int sleep_time) {
delay(sleep_time * 1000);
}
void loopFDRS() {
if (is_added) {
if ((millis() - last_refresh) >= gtwy_timeout) {
@ -532,9 +630,6 @@ void loopFDRS() {
}
}
bool seekFDRS(int timeout) {
SystemPacket sys_packet = { .cmd = cmd_ping, .param = 0 };
#ifdef USE_ESPNOW
@ -550,14 +645,11 @@ bool seekFDRS(int timeout) {
}
}
return false;
#endif
}
bool addFDRS(int timeout, void (*new_cb_ptr)(DataReading)) {
bool addFDRS(int timeout, void (*new_cb_ptr)(DataReading)) {
callback_ptr = new_cb_ptr;
SystemPacket sys_packet = { .cmd = cmd_add, .param = 0 };
#ifdef USE_ESPNOW
esp_now_send(gatewayAddress, (uint8_t *) &sys_packet, sizeof(SystemPacket));
@ -612,7 +704,6 @@ bool subscribeFDRS(uint16_t sub_id){
return true;
}
}
DBG("No subscription could be established!");
return false;