FORUM

Packets loss

Hello,
I am using SX1276 with ESP32 integrated on Heltech Wireless Lite (V2), working at 915MHz with power of 20dB. The application is very simple - it reads one switch, allows delay of 4 cycles, adds header, packet numerator and process time, and transmits it every 4 seconds (this simple processing takes almost 2 seconds). I see the transmiter functionality through LED that is inverted with every transmission.
The two stations are placed 1 meter apart with parallel antenas.
The receiver checks the alarm status and prints the number of the current and previous packets, the difference between them (minus one, to emphasize the loss). It also prints the packet RSSI and accumulated lost packets.
This trivial configuration is loosing most of the packets. I added many delays, especially in the receiver to make it more forgiving for channel problems (although it is so short distance) - nothing helps.
The following is a typical section of the log:

Message= |01-Al 1979 00019692 9|; >>>>> Alert=0; errors count=0; RSSI=-55; current=19692; previous=19683; diff=8; skipped=95
Message= |01-Al 1979 00019694 9|; >>>>> Alert=0; errors count=0; RSSI=-55; current=19694; previous=19692; diff=1; skipped=96
Nothing was received. Error count=1
Nothing was received. Error count=2
Message= |01-Al 1979 00019747 9|; >>>>> Alert=0; errors count=2; RSSI=-59; current=19747; previous=19694; diff=52; skipped=148

The code:
#include <Arduino.h>
#define tractorVerbose // Enable receiver error messages
//#define tractorVerboseTx // Enable transmitter error messages
// Opeational parameters
#define interLoopsInterval 4000 // milliseconds
#define ef 3
#define switchDelayToAlarm 4 // Count of cycle during which the switch is open till alarm
#define allowedMissingPackets 9 // 9 is max lost transmissions without alarms
#define headerLen 5
#define idStart headerLen + 6
#define idLen 8
#define delayLen 4
#define localStationId 0 // Pointer to commHeader vector; limited by the vector’s size

//                      GPIO     Pin
//                      ====     ===
#define modeSel          34  //   29    Selects between switch side and alarm system side
#define outPort          33  //   30    Buzzer in the switch side, alarm switch in the alarm side
#define alarmSwitch      32  //   31    Sensor in the switch side, not connected in the alarm side
#define buzzer        outPort
#define LED              25

// LoRa Pinout
#define LoRa_SCK          5  //   11
#define LoRa_RST         14  //   26
#define LoRa_CS          18  //    7
#define LoRa_MISO        19  //   12
#define LoRa_IRQ         26  //   25
#define LoRa_MOSI        27  //   32

// LoRa parameters
#define txPowerLevelVal        20
#define frequencyVal           915E6
#define LoRaSyncWordVal        0x43
#define LoRaPreambleLengthVal  8
#define LoRaSpreadingFactorVal 11
#define LoRaSignalBandwidthVal 35000
#define LoRaCodingRate4Val     5

const int    errorFactor  =    interLoopsInterval * ef * allowedMissingPackets;
const String commHeader[] =   {"01-Al", "01-Al", "01-Al"};  // Alarm sensing station 1
const String idPadding    =    "00000000";

RTC_DATA_ATTR uint32_t         loopCount = 0;
RTC_DATA_ATTR uint32_t         alarmDelay;
RTC_DATA_ATTR uint32_t         previousMessageId = 0;
RTC_DATA_ATTR int              skippedMessages = 0;
RTC_DATA_ATTR uint32_t         errCount = 0;
RTC_DATA_ATTR bool             alert = false;
RTC_DATA_ATTR uint32_t         txTime;

#include  "LoRa.h"
/*********************************************************/
void setup() 
{
  Serial.begin(9600);     // initialize serial
  while (!Serial);

// Selective GPIOs setting
  pinMode(alarmSwitch, INPUT_PULLUP);  // Define as input
  pinMode(modeSel, INPUT_PULLUP);      // Define as input
  pinMode(outPort, OUTPUT);            // Define as output
  pinMode(LED, OUTPUT);                // Define as output

// LoRa setup parameters
  LoRa.setPins(LoRa_CS, LoRa_RST, LoRa_IRQ);
  if (!LoRa.begin(frequencyVal, txPowerLevelVal >= 14))
  {
    Serial.println("\nLoRa init failed.");
    while (true);
  }

  LoRa.setTxPower(txPowerLevelVal, RF_PACONFIG_PASELECT_PABOOST);
  LoRa.setSyncWord(LoRaSyncWordVal);
  LoRa.setPreambleLength(LoRaPreambleLengthVal);
  LoRa.enableCrc();
  LoRa.setSpreadingFactor(LoRaSpreadingFactorVal);
  LoRa.setSignalBandwidth(LoRaSignalBandwidthVal);
  LoRa.setCodingRate4(LoRaCodingRate4Val);
  LoRa.receive();

  bool modeF = !digitalRead(modeSel);
  digitalWrite(outPort, modeF);
   digitalWrite(LED, !digitalRead(LED));
   Serial.println("\nInit success. mode - ");
}
/***************** Alarm Sensing side ***************************/
void readSwitches()
{
  uint32_t localTxTime = millis();
#ifdef tractorVerboseTx
  Serial.println("Switch sensing");
#endif // tractorVerboseTx
//  Serial.println("Good morning - switch sensing");
// Read the switches/sensors, prepare the packet and transmit it.
  if(digitalRead(alarmSwitch))  // Open alarm contact - alarm on
  {
    if(alarmDelay > 0)
    {
      alarmDelay--;
      digitalWrite(buzzer, 1);
    }
  }
  else                          // close alarm contact - normal
  {
    digitalWrite(buzzer, 0);
    alarmDelay = switchDelayToAlarm;
  }
  if(loopCount++ == 10000000)
    loopCount = 0;
  String dl = String();
  
 String TxMessage = commHeader[localStationId] + "|"; 
 String tmp = String(txTime);
 TxMessage += idPadding.substring(0, delayLen - tmp.length()) + tmp + "|";
 tmp = String(loopCount);
 TxMessage += idPadding.substring(0, idLen - tmp.length()) + tmp + "|";
  TxMessage += String (alarmDelay);
  LoRa.beginPacket();
  LoRa.print(TxMessage);
  LoRa.endPacket(false);                                 // Delay until TX is done
  LoRa.receive();                                        // Set radio work mode
#ifdef tractorVerboseTx
  Serial.println("Transmitted:" + TxMessage + "; sleep of " + 
                String(interLoopsInterval - txTime) + "mS");
  Serial.flush();
#endif // tractorVerboseTx
  txTime = millis() - localTxTime;
  esp_sleep_enable_timer_wakeup((interLoopsInterval - txTime) * 1000);  // in microseconds
  esp_deep_sleep_start();
}
/***************** Receiver side ***************************/
void receiveAlarms()        // Alarm reporting side
{
//  Serial.print("Alarm receiver: ");
  long currentMillis = millis();
  uint8_t packetSize = 0;
  while(((millis() - currentMillis) < errorFactor) && (packetSize == 0))
  {
    packetSize = LoRa.parsePacket();
    delay(100);
  }
  if (packetSize == 0)                  // No reception - error condition
  {
    errCount++;
    digitalWrite(outPort, false);       // Open the transistor to issue an alarm
#ifdef tractorVerbose
    Serial.println("Nothing was received. Error count=" + String(errCount));
#endif // tractorVerbose
    return;
  }

// A package was received
  String RxMessage = "";
  while (LoRa.available())                             // Aggregate message characters
    RxMessage += (char)LoRa.read();
  LoRa.receive();                                      // Set work mode
  if((RxMessage.length() >= (idStart)) &&              // minimal message length 
     (RxMessage.length() == packetSize) &&             // All characters were collected
     (RxMessage.substring(0, headerLen) == commHeader[localStationId])) // Header complies
  {
    alert = RxMessage[RxMessage.length() - 1] == '0';
    digitalWrite(outPort, !alert);                                // Switch the alarm as needed
#ifdef tractorVerbose                                             // Only for user information

    Serial.print("Message= |" + RxMessage);
    Serial.print("|; >>>>> Alert=" + String(alert));
    Serial.print("; errors count=" + String(errCount));
    Serial.print("; RSSI=" + String(LoRa.packetRssi()));
    
    int currentMessageId = atoi(RxMessage.substring(idStart, idStart + idLen).c_str());
    if(previousMessageId != 0) 
      skippedMessages += currentMessageId - (previousMessageId + 1);
    Serial.print("; current="  + String(currentMessageId)); 
    Serial.print("; previous=" + String(previousMessageId)); 
           
               Serial.print("; diff=" + String(currentMessageId - (previousMessageId + 1))); 
    Serial.print("; skipped=" + String(skippedMessages)); 
    previousMessageId = currentMessageId;

    Serial.println();
#endif // tractorVerbose
  packetSize = 0;                                                 // Clear for the next loop
  }
#ifdef tractorVerbose
  else                                                            // Wrong message - Do nothing
    Serial.println("Short message or is not to me: " + RxMessage); 
#endif // tractorVerbose
}
/****************************************************************/
void loop()
{
//  readSwitches();
  receiveAlarms();
  Serial.flush(); 

}

Try 0x34 at TX and RX