jgromes / RadioLib

Universal wireless communication library for embedded devices
https://jgromes.github.io/RadioLib/
MIT License
1.48k stars 373 forks source link

Lora module missing packets in channel scan mode...but no missing packet in contineous receive mode #939

Closed codev123 closed 7 months ago

codev123 commented 7 months ago

thank sir for amazing work! i have been recently implementing a repeater node that receives lora packets from multiple Lora transmitters, and retransmitting when channel is free. The issue i am encountering at this repeater code is that, i am missing packets using this scan method, while i dont miss any packet when i receive packets from multiple transmitters on a receiver that is always in interrupt based receive mode. can you please help me what i am doing wrong.

here is various flags to manage tansmission, reception and scan flags with loop code........ Repeater code:

// save transmission states between loops
int transmissionState = RADIOLIB_ERR_NONE;
// flag to indicate transmission state
bool transmitFlag = false;
// flag to indicate reception state
bool receiveFlag = false;
// flag to indicate that a packet was received or transmitted or channel scan
volatile bool scanFlag = false;
void setFlag(void) {
  // we sent or received a packet or scanned channel, set the flag
  scanFlag = true;
}

void loop() {
  // check if the flag is set
  if (scanFlag) {
    int state = RADIOLIB_ERR_NONE;
    scanFlag = false;  // reset flag
    //if the previous operation was transmission, check for response and print the result
    if (transmitFlag) {
      if (transmissionState == RADIOLIB_ERR_NONE) {
        digitalWrite(txStatus, HIGH);  //LED OFF when packet transmitted
        Serial.println(F("transmission finished!"));
      } else {
        Serial.print(F("failed, code "));
        Serial.println(transmissionState);
      }
      transmitFlag = false;  //reset the Transmission flag
    } else if (receiveFlag) {
      lastDataTime = millis();  // If data is received, update the timestamp
      //read received packet
      int numBytes = sizeof(DataPacket);  // Set the size to the structure size
      state = radio.readData((uint8_t*)&ReceivedPacket, numBytes);
      if ((state == RADIOLIB_ERR_NONE) && (ReceivedPacket.repeaterID == NodeID ) {
          digitalWrite(rxStatus, LOW);  //LED ON when packet received
          //delay(100);
          //Process received data packet details
          Serial.println(F("[SX1268] Received Data packet details................................."));
          Serial.print(F("sensor ID: "));
          Serial.println(ReceivedPacket.sensorID);
          Serial.print(F("pressure: "));
          Serial.println(ReceivedPacket.pressure);

          digitalWrite(rxStatus, HIGH);  //LED OFF when packet received
          //assign received packet to transmit packet buffer to retransmit
          ReceivedPacket.repeaterID = RepeaterID;
          if (bufferIndex < bufferSize) {
            TransmitPacket[bufferIndex] = ReceivedPacket;
            bufferIndex++;
            Serial.print(F("Buffer index: "));
            Serial.println(bufferIndex);
          } else {
            ;// Buffer is full, handle accordingly (e.g., drop the packet or wait)
          }
        } else if (state == RADIOLIB_ERR_RX_TIMEOUT) {
        Serial.println(F("Timed out while waiting for packet!"));
        digitalWrite(rxStatus, HIGH);  //LED OFF when packet received
      } else {
        Serial.println(F("Failed to receive packet, code "));
        Serial.println(state);
      }
      receiveFlag = false;
    } else {
      // check CAD result
      state = radio.getChannelScanResult();
      if (state == RADIOLIB_LORA_DETECTED) {
        // LoRa packet was detected
        Serial.print(F("Packet detected, starting reception... "));
        state = radio.startReceive();
        if (state == RADIOLIB_ERR_NONE) {
          Serial.println(F("success!"));
        } else {
          Serial.print(F("reception failed, code "));
          Serial.println(state);
        }
        // set the flag for ongoing reception
        receiveFlag = true;
      } else if (state == RADIOLIB_CHANNEL_FREE) {  //channel free
        //Serial.println(F("Channel is free!"));
        //received packet, send it to next node
        if (bufferIndex > 0) {
          Serial.print(F("Transmission started..... "));
          digitalWrite(txStatus, LOW);  //LED ON when packet transmission started
          transmissionState = radio.startTransmit((uint8_t*)&TransmitPacket[0], sizeof(DataPacket));
          transmitFlag = true;
          // Shift the remaining elements in the buffer
          for (int i = 0; i < bufferIndex - 1; i++) {
            TransmitPacket[i] = TransmitPacket[i + 1];
          }
          bufferIndex--;
        }
      } else {
        //Serial.print(F("Channel scan Failed, code "));
        //Serial.println(state);
      }
    }
    // if we're not receiving, start scanning again
    if (!receiveFlag && !transmitFlag) {
      //Serial.print(F("Not in Rx/Tx mode....starting for Lora preamble...."));
      state = radio.startChannelScan();
      if (state == RADIOLIB_ERR_NONE) {
        //Serial.println(F("success!"));
      } else {
        //Serial.print(F("failed, code "));
        //Serial.println(state);
      }
    }
  }
}

the receiver code :

// flag to indicate that a packet was received
volatile bool receivedFlag = false;
void setFlag(void) {
  // we got a packet, set the flag
  receivedFlag = true;
}

void loop() {
  // check if the flag is set
  if (receivedFlag) {
    // If data is received, update the timestamp
    lastDataTime = millis();
    // reset flag
    receivedFlag = false;
    //read received packet
    int numBytes = sizeof(DataPacket);  // Set the size to the structure size
    int state = radio.readData((uint8_t*)&ReceivedPacket, numBytes);
    if ((state == RADIOLIB_ERR_NONE) && ReceivedPacket.repeaterID == RepeaterID) {
      //Process received data packet details
      Serial.println(F("[SX1268] Received Data packet details.............................................."));
      Serial.print(F("[SX1268] RSSI:\t\t"));
      Serial.print(radio.getRSSI());
      Serial.println(F(" dBm"));
      Serial.print(F("[SX1268] SNR:\t\t"));
      Serial.print(radio.getSNR());
      Serial.println(F(" dB"));
    } else {
      Serial.println(F("Received packet is not for receiver"));
      digitalWrite(rxStatus, HIGH);  //LED OFF when packet not received
    }
}

so i receive all transmitter packets(Lora transmitters are transmitting when channel is free) using this receiver code but using repeater code i miss packets when time between packets is small.

also, when this issue happen, the preamble is detected, but packet is received after 5-10 seconds later

16:22:40.915 -> Packet detected, starting reception... success!
16:22:57.875 -> [SX1268] Received Data packet details.................................
16:22:57.875 -> sensor ID: 1
16:22:57.875 -> pressure: 214

here packet is detected at 16:22:40, but scanFlag interrupt was active after 17 seconds to receive packet at 16:22:57, any packet received in these 17 seconds will be lost.

normally it should be like this

16:22:40.145 -> Packet detected, starting reception... success!
16:22:40.440 -> [SX1268] Received Data packet details.................................
16:22:40.440 -> sensor ID: 2
16:22:40.440 -> pressure: 208
jgromes commented 7 months ago

Since the repeater code is quite a lot more complex, have you measured how long it takes to switch between packet detection and reception? I don't see any obvious reason why channel scan should miss packets that are received by the receiver code. However, you do have a lot of printing to the Serial port, and this: TransmitPacket[i] = TransmitPacket[i + 1]; - that is copying all of your packets, instead of e.g. shifting a pointer. No idea how large DataPacket is though.

also, when this issue happen, the preamble is detected, but packet is received after 5-10 seconds later

I have to guess here, but I'd say that's the next packet. I think that you are not fast enough when switching from CAD to receive. But overall this does't seem like an issue in the library itself, so I will convert this to a discussion instead.