radio.startReceive() not working after a radio.startTransmit() with a Spreadingfactor of 10, 11 or 12
goedzo opened this issue · 3 comments
I am implementing the non-blocking functions for sending and receiving and I wanted to allow receiving immediately after sending (as with the ping-pong example).
I use this logic:
radio.setDio1Action(setFlag);
radio.startTransmit(
-- Wait until flag is set for succesfull completion (via setFlag)
-- After transmit is done ->
radio.startReceive(
-- Handle new incoming messages
This went fine, until I noticed that in some cases, after sending a message, it was impossible to receive any new messages. I was only able to get this going (in some case) by calling setupLoRa() and wait for a couple of seconds for everything to be reinitialized.
After a lot of debugging I found out that when I use a lower spreadingfacter then 10, all went good. So 10, 11 or 12, causes the error that startReveice does not receive anything anymore. I did notice that sometimes an SF of 10 works intermittently, so I except there is some kind of timing issue where sending a message with a bigger spreadingfactor takes too much time for the module to switch to receiving (or something like that).
I tried a lot of ways to make it work again, and my best workaround is now:
radio.sleep(true);
radio.standby();
radio.startReceive(); //Start after processing, otherwise the packet is cleared before reading
Which also doesn't work, but it does avoid that receiving stops completely when I switch modes.
To Reproduce
Minimal Arduino sketch to reproduce the behavior. Please use Markdown to style the code to make it readable (see Markdown Cheatsheet).
void checkLoraPacketComplete(){
if(operationDone) {
//Serial.println("checkLoraPacketComplete - Lora Action complete");
// reset flag
operationDone = false;
if(transmitFlag) {
transmitFlag = false;
Serial.println("SENT COMPLETE");
uint16_t irqStatus = radio.getIrqStatus();
if (irqStatus & RADIOLIB_SX126X_IRQ_TX_DONE) {
//Serial.println(F("Transmission successful!"));
}
else {
Serial.println(F("Transmission not done!!"));
}
int state = radio.finishTransmit();
if (state == RADIOLIB_ERR_NONE) {
// We have sent a package, so listen again
}
else {
Serial.print(F("Sent failed, code "));
char buf[50];
snprintf(buf, sizeof(buf), "Sent Err: %d", state);
showError(buf);
Serial.println(state);
}
/* THE ERROR HAPPENS HERE WHEN SPREADING FACTOR IS 11 or 12 */
radio.sleep(true);
radio.standby();
radio.startReceive(); //Start after processing, otherwise the packet is cleared before reading
}
else {
Serial.println("RECEIVE COMPLETE");
handlePacket();
radio.startReceive(); //Start after processing, otherwise the packet is cleared before reading
}
}
}
Sketch that is causing the module fail
#include "delay.h"
#include "utilities.h"
#include <SPI.h>
#include <GxEPD.h>
#include <GxDEPG0150BN/GxDEPG0150BN.h> // 1.54" b/w
#include <RadioLib.h>
#include <stdint.h>
#include "settings.h" // Include settings.h to use global variables
#include "display.h"
#include "app_modes.h" // Include settings.h to use global variables
#include "lora.h"
SX1262 radio = nullptr; //SX1262
SPIClass *rfPort = nullptr;
// flag to indicate that a packet was sent or received
volatile bool operationDone = false;
// flag to indicate transmission or reception state
bool transmitFlag = false;
void setFlag(void) {
// we sent or received a packet, set the flag
operationDone = true;
//Serial.println("setFlag - Lora Action complete");
}
void checkLoraPacketComplete(){
if(operationDone) {
//Serial.println("checkLoraPacketComplete - Lora Action complete");
// reset flag
operationDone = false;
if(transmitFlag) {
transmitFlag = false;
Serial.println("SENT COMPLETE");
uint16_t irqStatus = radio.getIrqStatus();
if (irqStatus & RADIOLIB_SX126X_IRQ_TX_DONE) {
//Serial.println(F("Transmission successful!"));
}
else {
Serial.println(F("Transmission not done!!"));
}
int state = radio.finishTransmit();
if (state == RADIOLIB_ERR_NONE) {
// We have sent a package, so listen again
}
else {
Serial.print(F("Sent failed, code "));
char buf[50];
snprintf(buf, sizeof(buf), "Sent Err: %d", state);
showError(buf);
Serial.println(state);
}
//Let's reset lora to get receiving again
radio.sleep(true);
radio.standby();
radio.startReceive(); //Start after processing, otherwise the packet is cleared before reading
}
else {
Serial.println("RECEIVE COMPLETE");
handlePacket();
radio.startReceive(); //Start after processing, otherwise the packet is cleared before reading
}
}
}
bool setupLoRa() {
rfPort = new SPIClass(
/*SPIPORT*/NRF_SPIM3,
/*MISO*/ LoRa_Miso,
/*SCLK*/LoRa_Sclk,
/*MOSI*/LoRa_Mosi);
rfPort->begin();
SPISettings spiSettings;
radio = new Module(LoRa_Cs, LoRa_Dio1, LoRa_Rst, LoRa_Busy, *rfPort, spiSettings);
SerialMon.print("[SX1262] Initializing ... ");
// carrier frequency: 868.0 MHz
// bandwidth: 125.0 kHz
// spreading factor: 9
// coding rate: 7
// sync word: 0x12 (private network)
// output power: 14 dBm
// current limit: 60 mA
// preamble length: 8 symbols
// TCXO voltage: 1.6 V (set to 0 to not use TCXO)
// regulator: DC-DC (set to true to use LDO)
// CRC: enabled
int state = radio.begin(868.0);
if (state != ERROR_NONE) {
SerialMon.print(("failed, code "));
SerialMon.println(state);
char buf[30];
snprintf(buf, sizeof(buf), "Lora failed to init: %d", state);
showError(buf);
return false;
}
// set the function that will be called
// when new packet is received
operationDone=false;
radio.setDio1Action(setFlag);
// Stel de spreading factor in met de opgegeven waarde
state = radio.setSpreadingFactor(deviceSettings.spreading_factor);
if (state == RADIOLIB_ERR_NONE) {
Serial.print(F("Spreading factor set to SF"));
Serial.println(deviceSettings.spreading_factor);
} else {
Serial.print(F("Failed to set spreading factor, code "));
Serial.println(state);
}
// Stel het zendvermogen in (tussen -17 en 22 dBm)
if (radio.setOutputPower(22) == RADIOLIB_ERR_INVALID_OUTPUT_POWER) {
Serial.println(F("Selected output power is invalid for this module!"));
return false;
}
// Stel de stroomlimiet in (tussen 45 en 240 mA)
if (radio.setCurrentLimit(80) == RADIOLIB_ERR_INVALID_CURRENT_LIMIT) {
Serial.println(F("Selected current limit is invalid for this module!"));
return false;
}
// Start non-blocking receive
radio.startReceive();
Serial.println(F("LoRa setup completed successfully!"));
return true;
}
void sendPacket(uint8_t* pkt_buf, uint16_t len) {
// Start non-blocking transmission
int state = radio.startTransmit(pkt_buf, len);
transmitFlag = true;
if (state != RADIOLIB_ERR_NONE) {
Serial.print(F("Transmission start failed, code "));
Serial.println(state);
char buf[50];
snprintf(buf, sizeof(buf), "Lora Strt Trnsmt Err: %d", state);
showError(buf);
//Let's reinitialize the radio
setupLoRa();
return;
}
}
int receivePacket(uint8_t* pkt_buf, uint16_t max_len) {
// Get the length of the received packet
uint16_t packet_len = radio.getPacketLength(false);
if(packet_len==0) {
return 0;
}
if (packet_len > max_len) {
// Prevent buffer overflow if the packet is larger than the provided buffer
packet_len = max_len;
}
//Let's check the IRQ status to make sure all data is actually received
uint16_t irqStatus = radio.getIrqStatus();
if (irqStatus & RADIOLIB_SX126X_IRQ_RX_DONE) {
// Read the data into the buffer
int state = radio.readData(pkt_buf, packet_len);
if (state == RADIOLIB_ERR_NONE) {
return packet_len; // Of de werkelijke grootte van het ontvangen pakket
} else {
if (state == RADIOLIB_ERR_RX_TIMEOUT ) {
//This is OK, no data was received
}
else {
Serial.print(F("Receive failed, code "));
char buf[50];
snprintf(buf, sizeof(buf), "Receive Err: %d", state);
showError(buf);
Serial.println(state);
}
return 0;
}
}
else {
return 0;
}
}
void sleepLoRa() {
// Put the LoRa module into sleep mode using RadioLib's sleep function
int state = radio.sleep();
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("LoRa module is now in sleep mode."));
} else {
char buf[50];
snprintf(buf, sizeof(buf), "LoRa Sleep Error: %d", state);
showError(buf); // Show error for LoRa sleep failure
}
}
Expected behavior
radio.startReceive() should be receiving messages again after sending a message with a SPF of 10,11 or 12
Additional info (please complete):
- Device: Lilygo T-Echo
- MCU: Nordic nRF52840 DK
- Link to Arduino core: https://adafruit.github.io/arduino-board-index/package_adafruit_index.json
- Wireless module type SX1262
- Arduino IDE version 2.3.2
- Library version 6.6.0
Thanks for the test. I did the same and you are right, that the ping-pong example does work. I even removed the 1 second delay, and it still works.
So I have no idea why my original code stops receiving. Could it be the case that other stuff takes too long? The T-echo uses an e-paper display that needs quite some time (half a second) to update the screen. Maybe that can cause the issue? I will do some testing by removing the printing on screen when sending. But any suggestions or tips would be very welcome.
p.s. I did had to change some of the settings, and init to work on the t-echo. For reference my updated ping-pong code.
/*
RadioLib SX126x Ping-Pong Example
For default module settings, see the wiki page
https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem
For full API reference, see the GitHub Pages
https://jgromes.github.io/RadioLib/
*/
// include the library
#include <RadioLib.h>
#include <SPI.h>
#ifndef _PINNUM
#define _PINNUM(port, pin) ((port)*32 + (pin))
#endif
// uncomment the following only on one
// of the nodes to initiate the pings
#define INITIATING_NODE
SX1262 radio = nullptr; //SX1262
SPIClass *rfPort = nullptr;
// or using RadioShield
// https://github.com/jgromes/RadioShield
//SX1262 radio = RadioShield.ModuleA;
// or using CubeCell
//SX1262 radio = new Module(RADIOLIB_BUILTIN_MODULE);
// save transmission states between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate transmission or reception state
bool transmitFlag = false;
// flag to indicate that a packet was sent or received
volatile bool operationDone = false;
// this function is called when a complete packet
// is transmitted or received by the module
// IMPORTANT: this function MUST be 'void' type
// and MUST NOT have any arguments!
#if defined(ESP8266) || defined(ESP32)
ICACHE_RAM_ATTR
#endif
void setFlag(void) {
// we sent or received a packet, set the flag
operationDone = true;
}
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.flush();
// initialize SX1262 with default settings
Serial.print(F("[SX1262] Initializing ... "));
SPIClass *rfPort = nullptr;
rfPort = new SPIClass(
/*SPIPORT*/NRF_SPIM3,
/*MISO*/ _PINNUM(0,23),
/*SCLK*/_PINNUM(0,19),
/*MOSI*/_PINNUM(0,22));
rfPort->begin();
SPISettings spiSettings;
// SX1262 has the following connections:
// NSS pin: 10
// DIO1 pin: 2
// NRST pin: 3
// BUSY pin: 9
radio = new Module(_PINNUM(0,24), _PINNUM(0,20), _PINNUM(0,25) , _PINNUM(0,17),*rfPort,spiSettings);
int state = radio.begin();
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
// set the function that will be called
// when new packet is received
radio.setDio1Action(setFlag);
radio.setSpreadingFactor(12);
#if defined(INITIATING_NODE)
// send the first packet on this node
Serial.print(F("[SX1262] Sending first packet ... "));
transmissionState = radio.startTransmit("Hello World!");
transmitFlag = true;
#else
// start listening for LoRa packets on this node
Serial.print(F("[SX1262] Starting to listen ... "));
state = radio.startReceive();
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F("success!"));
} else {
Serial.print(F("failed, code "));
Serial.println(state);
while (true);
}
#endif
}
void loop() {
// check if the previous operation finished
if(operationDone) {
// reset flag
operationDone = false;
if(transmitFlag) {
// the previous operation was transmission, listen for response
// print the result
if (transmissionState == RADIOLIB_ERR_NONE) {
// packet was successfully sent
Serial.println(F("transmission finished!"));
} else {
Serial.print(F("failed, code "));
Serial.println(transmissionState);
}
// listen for response
radio.startReceive();
transmitFlag = false;
} else {
// the previous operation was reception
// print data and send another packet
String str;
int state = radio.readData(str);
if (state == RADIOLIB_ERR_NONE) {
// packet was successfully received
Serial.println(F("[SX1262] Received packet!"));
// print data of the packet
Serial.print(F("[SX1262] Data:\t\t"));
Serial.println(str);
// print RSSI (Received Signal Strength Indicator)
Serial.print(F("[SX1262] RSSI:\t\t"));
Serial.print(radio.getRSSI());
Serial.println(F(" dBm"));
// print SNR (Signal-to-Noise Ratio)
Serial.print(F("[SX1262] SNR:\t\t"));
Serial.print(radio.getSNR());
Serial.println(F(" dB"));
}
// wait a second before transmitting again
//delay(1000);
// send another one
Serial.print(F("[SX1262] Sending another packet ... "));
transmissionState = radio.startTransmit("Hello World!");
transmitFlag = true;
}
}
}
I haven't seen the rest of your code, so I can't really comment whether the display updates could be causing some issues. Though it it does really take that long, then it would make sense to have a dedicated low-priority thread for it.
Since it is not an issue in the library, I will convert this into a discussion instead.