ESP32 hangs with LoRa

Using the TTGO ESP32 LoRa Oled board. The software hangs randomly, but more often/sooner if there is a second LoRa transmitter nearby. The unit using the code below is set for SF10, the second interfering unit is set to SF9. I suspect the glitch might be in the LoRa.parsePacket() method, but don't have any way to substantiate this.

// ESP32_receiver
char this_file[] = "ESP32_receiver" ;
char descp[] =     "ESP32 TTGO LoRa" ;
char ver[] =       "ver 1.2    12/22/22 " ;
char ver2[] =      "no inputs, SF10" ;
char ver3[] =      " " ;

//Libraries for LoRa
#include <SPI.h>
#include <LoRa.h>

//Libraries for OLED Display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

//define the pins used by the LoRa transceiver module
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 14
#define DIO0 26

//433E6 for Asia
//866E6 for Europe
//915E6 for North America
#define BAND 915E6

//OLED pins
#define OLED_SDA 4
#define OLED_SCL 15 
#define OLED_RST 16
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);

byte t1L ;
byte t1H ;
byte t2L ;
byte t2H ;
byte counter ;
byte sync_b ;
int T_1 ;
int T_2 ;

String LoRaData;
unsigned long loop_Time ;
 

// ===================================================================
void setup() { 
  //initialize Serial Monitor
	Serial.begin(9600);
  
  //reset OLED display via software
	pinMode(OLED_RST, OUTPUT);
	digitalWrite(OLED_RST, LOW);
	delay(20);
	digitalWrite(OLED_RST, HIGH);

	//initialize OLED
	Wire.begin(OLED_SDA, OLED_SCL);
	if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C, false, false)) {
									// Address 0x3C for 128x32
		Serial.println(F("SSD1306 allocation failed"));
		for(;;); // Don't proceed, loop forever
	}
  
// ----------------version message ------------------------
	Serial.println(this_file) ; //file name
	Serial.println(descp) ;     //description
	Serial.println(ver) ;       //version and date
	Serial.println(ver2) ;      //version and date
	Serial.println(ver3) ;      //version and date
	Serial.println() ;
// ------------ end of version message --------------------

// show version on OLED display
	display.clearDisplay();
	display.setTextColor(WHITE);
	display.setTextSize(1);
	display.setCursor(0,0);
	display.print(this_file);
	display.setCursor(0,20);
	display.print(descp);
	display.setCursor(0,30);
	display.print(ver);
	display.setCursor(0,40); 
	display.print(ver2);  
	display.display();

	delay(5000) ; // reading time
  
  //SPI LoRa pins
	SPI.begin(SCK, MISO, MOSI, SS);
  //setup LoRa transceiver module
	LoRa.setPins(SS, RST, DIO0);

	if (!LoRa.begin(BAND)) {
		Serial.println("Starting LoRa failed!");
		while (1); // stop phere
	}
  
	display.clearDisplay();
	Serial.println("LoRa Initializing OK!");
	display.setCursor(0,10);
	display.println("LoRa Initializing OK!");
	display.display(); 

	loop_Time = millis() ;  
	pinMode(2, OUTPUT) ;
	
	LoRa.setSpreadingFactor(10);
}
// ===========================================================

void loop() {
// flash the onboard LED every 5 seconds
	if((millis() - loop_Time) > 5000) {
		digitalWrite(2, 1) ;
		delay(200) ;
		digitalWrite(2, 0) ;
		loop_Time = millis() ;
	}

// parse packet
	int packetSize = LoRa.parsePacket();
	if (packetSize == 6) {
		Serial.print("Received packet ");

//read packet
		sync_b = LoRa.read(); // 
		if(sync_b == 0x55) {  // user flag is good
			counter = LoRa.read();
			t1L = LoRa.read();
			t1H = LoRa.read();
			t2L = LoRa.read();
			t2H = LoRa.read();

			T_1 = t1H<<8 | t1L ;
			T_2 = t2H<<8 | t2L ;
			// fix the 4-byte integer sign bit problem
			if(T_1 > 20000) T_1 = T_1 - 65536 ;
			if(T_2 > 20000) T_2 = T_2 - 65536 ;

			//print RSSI of packet
			int rssi = LoRa.packetRssi();
			Serial.print(" with RSSI ");    
			Serial.println(rssi);

			if((T_1<12000) && (T_2<12000)) { // Less than +120
				if((T_1>-3000) && (T_2>-3000)) { // > -30
			// Display the packet message
					display.clearDisplay();
					display.setTextSize(1);
					display.setCursor(0,0);
					display.print("LORA Receiver: ");
					display.println(counter) ;
					display.setTextSize(3);
					display.setCursor(0,15);
					display.print(" ") ;
					if(!(T_1<0)) {
						if(T_1<10000) display.print(" ") ;
						if(T_1<1000) display.print(" ") ;
					} else {
						if(abs(T_1)<1000) display.print(" ") ;
					}
					display.print(T_1/100.0, 1);   
					display.setCursor(0,40);
					display.print(" ") ;
					if(!(T_2<0)) {
						if(T_2<10000) display.print(" ") ;
						if(T_2<1000) display.print(" ") ;
					} else {
						if(abs(T_2)<1000) display.print(" ") ;
					}
					display.print(T_2/100.0, 1); 
					display.display(); 
				}
			}
		}
		// garbled packet: dump any remaing bytes
		while (LoRa.available()) {
			sync_b = LoRa.read(); //
		}
	} else {
		// packet error: dump the packet
		while (LoRa.available()) {
			sync_b = LoRa.read(); //
		}
	}
}

Anyone else experiencing this kind of code freeze?

Don't go nuts over the

if(T_1 > 20000) T_1 = T_1 - 65536 ;

line. That's a kludge fix for not extending the sign bit in the 4-byte integer used in the ESP32 and despite considerable hazing over this, it works perfectly.

ESP32
I did what I thought was a rather thorough test a few years back with ESP32 but I did not have multiple units contending for spectrum.

Receive + OLED

/* https://robotzero.one/heltec-wifi-lora-32/
 * Sketch uses 146842 bytes (14%) of program storage space. Maximum is 1044464 bytes.
 * Global variables use 11628 bytes (3%) of dynamic memory, leaving 283284 bytes for local variables. Maximum is 294912 bytes.
*/

#include <U8x8lib.h>
#include <LoRa.h>

String receivedText;
String receivedRssi;

// WIFI_LoRa_32 ports
// GPIO5  -- SX1278's SCK
// GPIO19 -- SX1278's MISO
// GPIO27 -- SX1278's MOSI
// GPIO18 -- SX1278's CS
// GPIO14 -- SX1278's RESET
// GPIO26 -- SX1278's IRQ(Interrupt Request)

#define SS      18
#define RST     14
#define DI0     26
#define BAND    902E6

// the OLED used
U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(/* clock=*/ 15, /* data=*/ 4, /* reset=*/ 16);

void setup() {

  SPI.begin(5, 19, 27, 18);
  LoRa.setPins(SS, RST, DI0);

  Serial.begin(115200);
  while (!Serial); //if just the the basic function, must connect to a computer
  delay(1000);

  u8x8.begin();
  u8x8.setFont(u8x8_font_chroma48medium8_r);

  Serial.println("LoRa Receiver");
  u8x8.drawString(0, 1, "LoRa Receiver");

  if (!LoRa.begin(BAND)) {
    Serial.println("Starting LoRa failed!");
    u8x8.drawString(0, 1, "Starting LoRa failed!");
    while (1);
  }
}

void loop() {

  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packet
    Serial.print("Received packet '");
    u8x8.drawString(0, 4, "PacketID");

    // read packet
    while (LoRa.available()) {
      receivedText = (char)LoRa.read();
      Serial.print(receivedText);
      char currentid[64];
      receivedText.toCharArray(currentid, 64);
      u8x8.drawString(9, 4, currentid);
    }

    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
    u8x8.drawString(0, 5, "PacketRS");
    receivedRssi = LoRa.packetRssi();
    char currentrs[64];
    receivedRssi.toCharArray(currentrs, 64);
    u8x8.drawString(9, 5, currentrs);
  }

}


Transmit

/* https://www.alictronix.com/archives/860
 * Sketch uses 155594 bytes (14%) of program storage space. Maximum is 1044464 bytes.
 * Global variables use 11612 bytes (3%) of dynamic memory, leaving 283300 bytes for local variables. Maximum is 294912 bytes.
 */


#include <SPI.h>
#include <LoRa.h>
#include <SSD1306.h>
#include <Arduino.h>

//OLED pins to ESP32 GPIOs via this connecthin:
//OLED_SDA — GPIO4
//OLED_SCL — GPIO15
//OLED_RST — GPIO16

SSD1306 display(0x3c, 4, 15);



// WIFI_LoRa_32 ports

// GPIO5 — SX1278’s SCK
// GPIO19 — SX1278’s MISO
// GPIO27 — SX1278’s MOSI
// GPIO18 — SX1278’s CS
// GPIO14 — SX1278’s RESET
// GPIO26 — SX1278’s IRQ(Interrupt Request)

#define SS 18
#define RST 14
#define DI0 26
#define BAND 902E6 //915E6

int counter = 0;

void setup() {
  pinMode(25, OUTPUT); //Send success, LED will bright 1 second

  pinMode(16, OUTPUT);
  digitalWrite(16, LOW); // set GPIO16 low to reset OLED
  delay(50);
  digitalWrite(16, HIGH);

  Serial.begin(115200);
  while (!Serial); //If just the the basic function, must connect to a computer

  // Initialising the UI will init the display too.
  display.init();
  display.flipScreenVertically();
  display.setFont(ArialMT_Plain_10);
  display.setTextAlignment(TEXT_ALIGN_LEFT);
  display.drawString(5, 5, "LoRa Sender");
  display.display();

  SPI.begin(5, 19, 27, 18);
  LoRa.setPins(SS, RST, DI0);
  Serial.println("LoRa Sender");
  if (!LoRa.begin(BAND)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
  Serial.println("LoRa Initial OK!");
  display.drawString(5, 20, "LoRa Initializing OK!");
  display.display();
  delay(2000);
}

void loop() {
  Serial.print("Sending packet: ");
  Serial.println(counter);

  display.clear();
  display.setFont(ArialMT_Plain_16);
  display.drawString(3, 5, "Sending packet ");
  display.drawString(50, 30, String(counter));
  display.display();

  // send packet
  LoRa.beginPacket() ;
  LoRa.print("Hello ") ;
  LoRa.print(counter) ;
  LoRa.endPacket();

  counter++;
  digitalWrite(25, HIGH); // turn the LED on (HIGH is the voltage level)
  delay(1000); // wait for a second
  digitalWrite(25, LOW); // turn the LED off by making the voltage LOW
  delay(1000); // wait for a second

  delay(3000);
}


if you comment out the OLED code does the Lora part then work
have a look at post decimals-strings-and-lora which has multiple slaves traansmitting to a master

After a couple days of testing, with just one transmitter, I'm not seeing any freezes. I'm going to move the receivers farther away from the second transmitter and see if they are OK with two approximately equal strength signals (previously the second transmitter was only 5' from the receivers).

So, Horace, I think this eliminates the OLED code as a problem.

One code change I made may have helped a little, eg, dump any data in the que if the packet seems corrupted:

		// garbled packet: dump any remaing bytes
		while (LoRa.available()) {
			sync_b = LoRa.read(); //

This "dump" doesn't seem to adversely affect anything--I'm seeing all the packet sequence numbers.

Are your units both in metal miniboxes? RF may be simply causing havoc with the unshielded boards.

No boxes. The two receivers are prototypes sitting on perf boards. I admit I never considered RFI as an issue, since I've got about 56 wifi units scattered all over the house and everybody has been happy, so far.

So far, after 4 hours operating 40' away from the second transmitter, no problems. Tomorrow the #1 transmitter will be moved about 1000' away, so the relative signal strength (tx #1 to tx #2 at the receivers) will be significantly different, again. I'll report what happens.

RF is a nasty energy source at 2.4/5 GHz:

The Simplest Way To Spot 2.4GHz RF | Hackaday

It for can illuminate a LED, you can override digital signaling, too.

It just occurred to me that it's probably not RFI, since the two receivers for transmitter #2 are sitting about 1' from tx #2 and they haven't exhibited any problem. The receivers that were freezing were set up to receive a different message from tx #1 and they were set to a different spreading factor. So it wasn't being close that was the problem.

I think it is something related to the LoRa.parsePacket() method, like header or sync byte getting corrupted. I have to admit, I have no clue how that method works or what it does if the message length is longer than the receiver code is designed to handle.

I bow to your view as you are hands on and I'm in a lazy chair in front of a fireplace in Atlanta ... sitting here with lights off as the local power company has sent out a pre-blackout warning due to grid reserves being depleted as adjacent states are also in increased electrical usage due to severe cold.

Personal peeve/opinion: how stupid GA Power for thinking adjacent states will have surplus on the electric grid. Add to that a 12% rate increase in 2023 and clearly, IMO, there is a lack of brain power in the corporate higher structure.

:+1:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.