jgromes / RadioLib

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

SX126x Receive Interrupt output packet is incorrect and repeats #50

Closed lshalkhauser closed 4 years ago

lshalkhauser commented 4 years ago

Issue: When using the SX126x receive interrupt example, the received data is incorrect and repeats for 3 to 20 seconds. Below is a snippit of the transmitted and received data. Is there something I am doing wrong to cause this?

radiocapture

Setup:

Some other facts:

Transmitter:

/*
   RadioLib SX126x Receive Example

   This example listens for LoRa transmissions using SX126x Lora modules.
   To successfully receive data, the following settings have to be the same
   on both transmitter and receiver:
    - carrier frequency
    - bandwidth
    - spreading factor
    - coding rate
    - sync word
    - preamble length

   Other modules from SX126x family can also be used.

   For full API reference, see the GitHub Pages
   https://jgromes.github.io/RadioLib/
*/

// include the library
#include <RadioLib.h>

void enableRX(void);
void enableTX(void);

#define RADIO_RXEN 11
#define RADIO_TXEN 12

SX1262 lora = new Module(10, 2, -1, 5);

void setup() {
  Serial.begin(115200);
  delay(1000);
  pinMode(13, OUTPUT);
  Serial.println("Tets");

  Serial.print(F("[SX1262] Initializing ... "));

  int state = lora.begin(915.0, 125.0, 7, 5, 0x1424, 22, 8);
  //lora.setCurrentLimit(65);

  if (state == ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }

  if (lora.setTCXO(2.4) == ERR_INVALID_TCXO_VOLTAGE)
  {
    Serial.println(F("Selected TCXO voltage is invalid for this module!"));
  }

  enableTX();

}

void loop() {
  unsigned long p = millis();
  String k = String(p);
  int state = lora.transmit(k);
  Serial.println("Transmitting: " + String(p));

  delay(1000);
}

void enableRX(void)
{
  digitalWrite(RADIO_RXEN, HIGH);
  digitalWrite(RADIO_TXEN, LOW);
  delay(100);
}

void enableTX(void)
{
  digitalWrite(RADIO_RXEN, LOW);
  digitalWrite(RADIO_TXEN, HIGH);
  delay(100);
}

Receiver:

/*
   RadioLib SX126x Receive with Interrupts Example

   This example listens for LoRa transmissions and tries to
   receive them. Once a packet is received, an interrupt is
   triggered. To successfully receive data, the following
   settings have to be the same on both transmitter
   and receiver:
    - carrier frequency
    - bandwidth
    - spreading factor
    - coding rate
    - sync word

   Other modules from SX126x/RFM9x family can also be used.

   For full API reference, see the GitHub Pages
   https://jgromes.github.io/RadioLib/
*/

// include the library
#include <RadioLib.h>

void enableRX(void);
void enableTX(void);

// GPIOs to control E22 RX_EN and TX_EN
#define RADIO_RXEN 4
#define RADIO_TXEN 7

// SX1262 has the following connections:
// NSS pin:   10
// DIO1 pin:  2
// DIO2 pin:  3
// BUSY pin:  9
SX1262 lora = new Module(10, 2, -1, 5);

// or using RadioShield
// https://github.com/jgromes/RadioShield
//SX1262 lora = RadioShield.ModuleA;

void setup() {
  Serial.begin(115200);

  Serial.print(F("[SX1262] Initializing ... "));

  int state = lora.begin(915.0, 125.0, 7, 5, 0x1424, 22, 8);
  //lora.setCurrentLimit(11.9);

  if (state == ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }

  if (lora.setTCXO(2.4) == ERR_INVALID_TCXO_VOLTAGE)
  {
    Serial.println(F("Selected TCXO voltage is invalid for this module!"));
  }

  enableRX();

  lora.setDio1Action(setFlag);

  // start listening for LoRa packets
  Serial.print(F("[SX1262] Starting to listen ... "));
  state = lora.startReceive();
  if (state == ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }

}

// flag to indicate that a packet was received
volatile bool receivedFlag = false;

// disable interrupt when it's not needed
volatile bool enableInterrupt = true;

// this function is called when a complete packet
// is received by the module
// IMPORTANT: this function MUST be 'void' type
//            and MUST NOT have any arguments!
void setFlag(void) {
  // check if the interrupt is enabled
  if(!enableInterrupt) {
    return;
  }

  // we got a packet, set the flag
  receivedFlag = true;
}

void loop() {
  // check if the flag is set
  if(receivedFlag) {
    // disable the interrupt service routine while
    // processing the data
    enableInterrupt = false;

    // reset flag
    receivedFlag = false;

    // you can read received data as an Arduino String
    String str = "";
    int state = lora.readData(str);

    if (state == ERR_NONE) {
      // packet was successfully received
     // Serial.println(F("[SX1262] Received packet!"));

      // print data of the packet
      Serial.print(F("Receiving:\t"));
      Serial.println(str);

    } else if (state == ERR_CRC_MISMATCH) {
      // packet was received, but is malformed
      Serial.println(F("CRC error!"));

    } else {
      // some other error occurred
      Serial.print(F("failed, code "));
      Serial.println(state);

    }

    // we're ready to receive more packets,
    // enable interrupt service routine
    enableInterrupt = true;
  }

}

void enableRX(void)
{
  digitalWrite(RADIO_RXEN, HIGH);
  digitalWrite(RADIO_TXEN, LOW);
  delay(100);
}

void enableTX(void)
{
  digitalWrite(RADIO_RXEN, LOW);
  digitalWrite(RADIO_TXEN, HIGH);
  delay(100);
}
jgromes commented 4 years ago

Can confirm this is indeed happening. Verbose when reading received data from the module looks like this:

SX126x_Receive:
1E  0   A4  0   A4  0   33  0   34  0   31  0   38  0   37  0   39
SX126x_Receive_Interrupt:
1E  0   D4  0   D4  0   35  0   37  0   37  0   35  0   32  0   31

Judging by the status byte (A4 vs D4), it looks like SX126x is still in receive mode when reading data in the interrupt example - this most likely prevented the chip from clearing the buffer after reading. The example is missing lora.standby() to put the module into standby mode before reading data by lora.readData(), and lora.startReceive() to restart listen mode afterwards. I will amend the example asap - thanks for reporting.

jgromes commented 4 years ago

I also want to leave this here:

This is an excellent issue - it contains all the information that was needed to identify and resolve the problem in a few minutes. Very well done!

jgromes commented 4 years ago

@lshalkhauser Could you please try with the new example? Thanks

lshalkhauser commented 4 years ago

It works perfectly now! Thank you for the help and for your amazing library!