Hello everyone. Can anyone help me figure out a fix to this? My repeater node is able to receive data from 3 sensor nodes through LoRa. The problem is when I try to LoRaWAN (repeater to gateway), the repeater is suddenly unable to receive any data. When I tried troubleshooting, I removed the state machine and repeater was able to receive data again. I think the LoRa and the configuration of the LoRaWAN stack are conflicting. It would be a lifesaver if someone could help. Thank you!
My code:
#include “LoRaWan_APP.h”
#include “Arduino.h”
#define RF_FREQUENCY 915000000 // Hz
#define TX_OUTPUT_POWER 14 // dBm
#define LORA_BANDWIDTH 0 // [0: 125 kHz, 1: 250 kHz, 2: 500 kHz, 3: Reserved]
#define LORA_SPREADING_FACTOR 7 // [SF7…SF12]
#define LORA_CODINGRATE 1 // [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
#define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT 0 // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false
#define RX_TIMEOUT_VALUE 1000
#define BUFFER_SIZE 51 // Define the payload size here
char txpacket[BUFFER_SIZE];
char rxpacket[BUFFER_SIZE];
static RadioEvents_t RadioEvents;
int16_t txNumber;
int16_t rssi, rxSize;
bool lora_idle = true;
unsigned long previousMillis = 0;
const long interval = 10000;
struct SensorData {
float surface_velocity;
float flow_rate;
float water_level;
bool received;
};
SensorData sensors[3];
/* OTAA para*/
uint8_t devEui[] = { 0x12, 0x3A, 0xBC, 0x4F, 0x56, 0x78, 0x9A, 0xBC };
uint8_t appEui[] = { 0x78, 0x56, 0x34, 0x12, 0xAB, 0xCD, 0xEF, 0x01 };
uint8_t appKey[] = { 0xAF, 0x4C, 0x3E, 0xD8, 0x92, 0x1A, 0x47, 0xFC, 0x5D, 0x69, 0xB1, 0x7E, 0x84, 0x36, 0xCB, 0x29 };
/* ABP para*/
uint8_t nwkSKey[] = { 0x15, 0xb1, 0xd0, 0xef, 0xa4, 0x63, 0xdf, 0xbe, 0x3d, 0x11, 0x18, 0x1e, 0x1e, 0xc7, 0xda, 0x85 };
uint8_t appSKey[] = { 0xd7, 0x2c, 0x78, 0x75, 0x8c, 0xdc, 0xca, 0xbf, 0x55, 0xee, 0x4a, 0x77, 0x8d, 0x16, 0xef, 0x67 };
uint32_t devAddr = (uint32_t)0x007e6ae1;
/LoraWan channelsmask, default channels 0-7/
uint16_t userChannelsMask[6] = { 0x00FF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };
/LoraWan region, select in arduino IDE tools/
LoRaMacRegion_t loraWanRegion = ACTIVE_REGION;
/LoraWan Class, Class A and Class C are supported/
DeviceClass_t loraWanClass = CLASS_A;
/the application data transmission duty cycle. value in [ms]./
uint32_t appTxDutyCycle = 10000;
/OTAA or ABP/
bool overTheAirActivation = true;
/ADR enable/
bool loraWanAdr = true;
/* Indicates if the node is sending confirmed or unconfirmed messages */
bool isTxConfirmed = true;
/* Application port /
uint8_t appPort = 2;
/!
- Number of trials to transmit the frame, if the LoRaMAC layer did not
- receive an acknowledgment. The MAC performs a datarate adaptation,
- according to the LoRaWAN Specification V1.0.2, chapter 18.4, according
- to the following table:
- Transmission nb | Data Rate
- ----------------|-----------
- 1 (first) | DR
- 2 | DR
- 3 | max(DR-1,0)
- 4 | max(DR-1,0)
- 5 | max(DR-2,0)
- 6 | max(DR-2,0)
- 7 | max(DR-3,0)
- 8 | max(DR-3,0)
- Note, that if NbTrials is set to 1 or 2, the MAC will not decrease
- the datarate, in case the LoRaMAC layer did not receive an acknowledgment
*/
uint8_t confirmedNbTrials = 4;
static void prepareTxFrame(uint8_t port) {
char aggregatedData[BUFFER_SIZE];
// Initialize overflow_time to 0.00
float overflow_time = 0.00;
// Calculate the differences in water level and velocity
float level_diff_12 = fabs(sensors[0].water_level - sensors[1].water_level);
float level_diff_23 = fabs(sensors[1].water_level - sensors[2].water_level);
float velocity_diff_12 = fabs(sensors[0].surface_velocity - sensors[1].surface_velocity);
float velocity_diff_23 = fabs(sensors[1].surface_velocity - sensors[2].surface_velocity);
// Determine block status based on the table
int block_bet_12 = 0;
int block_bet_23 = 0;
int drainage_cap_80 = 0;
// Check for sensor 1 and 2
if ((level_diff_12 >= 0.00 && level_diff_12 <= 0.15) && (velocity_diff_12 >= 0.15)) {
block_bet_12 = 1;
} else if ((level_diff_12 > 0.15 && level_diff_12 <= 0.30) && (velocity_diff_12 >= 0.15)) {
block_bet_12 = 1;
} else if (level_diff_12 > 0.30) {
block_bet_12 = 1;
}
// Check for sensor 2 and 3
if ((level_diff_23 >= 0.00 && level_diff_23 <= 0.15) && (velocity_diff_23 >= 0.15)) {
block_bet_23 = 1;
} else if ((level_diff_23 > 0.15 && level_diff_23 <= 0.30) && (velocity_diff_23 >= 0.15)) {
block_bet_23 = 1;
} else if (level_diff_23 > 0.30) {
block_bet_23 = 1;
}
// If any warning status is triggered, set overflow_time
if (block_bet_12 || block_bet_23) {
overflow_time = get_overflow_time();
}
// Check if water level reaches 80% of the drainage height (0.528m)
if (sensors[0].water_level >= 0.528 || sensors[1].water_level >= 0.528 || sensors[2].water_level >= 0.528) {
drainage_cap_80 = 1;
}
snprintf(aggregatedData, BUFFER_SIZE, “%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%d,%d,%.2f,%d”,
sensors[0].surface_velocity, sensors[0].flow_rate, sensors[0].water_level,
sensors[1].surface_velocity, sensors[1].flow_rate, sensors[1].water_level,
sensors[2].surface_velocity, sensors[2].flow_rate, sensors[2].water_level,
block_bet_12, block_bet_23, overflow_time, drainage_cap_80);
appDataSize = strlen(aggregatedData);
memcpy(appData, aggregatedData, appDataSize);
}
void setup() {
Serial.begin(115200);
Mcu.begin();
deviceState = DEVICE_STATE_INIT;
txNumber = 0;
rssi = 0;
RadioEvents.RxDone = OnRxDone;
Radio.Init(&RadioEvents);
Radio.SetChannel(RF_FREQUENCY);
Radio.SetRxConfig(MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
0, true, 0, 0, LORA_IQ_INVERSION_ON, true);
memset(sensors, 0, sizeof(sensors));
}
void loop() {
unsigned long currentMillis = millis();
if (lora_idle) {
lora_idle = false;
Serial.println(“into RX mode”);
Radio.Rx(0);
}
Radio.IrqProcess();
switch (deviceState) {
case DEVICE_STATE_INIT:
#if (LORAWAN_DEVEUI_AUTO)
LoRaWAN.generateDeveuiByChipID();
#endif
LoRaWAN.init(loraWanClass, loraWanRegion);
break;
case DEVICE_STATE_JOIN:
LoRaWAN.join(); // Join LoRaWAN network
break;
case DEVICE_STATE_SEND:
prepareTxFrame(appPort); // Prepare the data to send
LoRaWAN.send(); // Send data via LoRaWAN
clearSensorData(); // Clear the sensor data buffer
deviceState = DEVICE_STATE_CYCLE; // Move to the next state
break;
case DEVICE_STATE_CYCLE:
// Schedule next packet transmission
//txDutyCycleTime = appTxDutyCycle + randr(-APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND);
//LoRaWAN.cycle(txDutyCycleTime); // Go into cycle state
deviceState = DEVICE_STATE_SLEEP; // Move to sleep state
break;
case DEVICE_STATE_SLEEP:
LoRaWAN.sleep(loraWanClass); // Put LoRaWAN to sleep
break;
default:
deviceState = DEVICE_STATE_INIT; // Initialize the device state if unknown
break;
}
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
aggregateData();
deviceState = DEVICE_STATE_SEND; // Trigger LoRaWAN send state
lora_idle = true;
}
}
void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr) {
Serial.println(“OnRxDone called”);
if (size > BUFFER_SIZE) {
Serial.println(“Received packet is too large”);
return;
}
memcpy(rxpacket, payload, size);
rxpacket[size] = ‘\0’; // Null-terminate the string
// Parse the received data
int received_node_id;
float received_surface_velocity;
float received_flow_rate;
float received_water_level;
int parsedItems = sscanf(rxpacket, "%d,%f,%f,%f ", &received_node_id, &received_surface_velocity, &received_flow_rate, &received_water_level);
if (parsedItems == 4 && received_node_id >= 1 && received_node_id <= 3) {
sensors[received_node_id - 1].surface_velocity = received_surface_velocity;
sensors[received_node_id - 1].flow_rate = received_flow_rate;
sensors[received_node_id - 1].water_level = received_water_level;
sensors[received_node_id - 1].received = true;
// Output the received values
Serial.printf("\r\nReceived Node ID: %d\n", received_node_id);
Serial.printf("Received Surface Velocity: %.6f m/s\n", received_surface_velocity);
Serial.printf("Received Flow Rate: %.6f m/s^2\n", received_flow_rate);
Serial.printf("Received Water Level: %.6f m\n", received_water_level);
Serial.printf("RSSI: %d dBm, SNR: %d\n", rssi, snr);
} else {
Serial.println(“Failed to parse the received data”);
}
Radio.Sleep(); // Put the radio to sleep
lora_idle = true; // Set flag to allow switching back to RX mode
}
void aggregateData() {
Serial.println(“Aggregating data from all sensors:”);
for (int i = 0; i < 3; i++) {
if (sensors[i].received) {
Serial.printf(“Sensor %d - Surface Velocity: %.2f m/s, Flow Rate: %.2f m/s^2, Water Level: %.2f m\n”,
i + 1, sensors[i].surface_velocity, sensors[i].flow_rate, sensors[i].water_level);
} else {
Serial.printf(“Sensor %d - No data received\n”, i + 1);
}
}
}
void clearSensorData() {
memset(sensors, 0, sizeof(sensors));
Serial.println(“Sensor data cleared for next interval”);
}
float get_overflow_time() {
float V = 70.455;
float Q_in = sensors[0].flow_rate;
float Q_out = sensors[2].flow_rate;
float Q_net = Q_in - Q_out;
float of_time = V / Q_net;
return of_time;
}