Help with Direct P2P Communication Between LoRa-E5 LE Mini and LilyGO T3 V1.6.1 (No Gateway)

Hi,

I'm trying to set up a direct peer-to-peer (P2P) LoRa communication, without using a LoRaWAN gateway, between two different modules:

  • The transmitter is a Wio-E5 LE Mini from Seeed Studio, connected to sensors (ENS160 and BME280). It’s programmed in MicroPython using a Raspberry Pi Pico and Thonny IDE.
  • The receiver is a LILYGO LoRa32 T3 V1.6.1 board, which should receive the LoRa data and then upload it to a server. For this board, I plan to upload the code using the Arduino IDE.



My goal is for the Wio-E5 to send raw sensor data directly to the LILYGO board via LoRa (not using LoRaWAN), and for the LILYGO to handle the data upload.

Below is my initial MicroPython code attempt for the Wio-E5 (transmitter):

from machine import Pin, UART, I2C
from time import sleep_ms

# Inițializare LED și GPIO
led = Pin('LED', Pin.OUT)
GPIO_22 = Pin(22, Pin.OUT)
GPIO_22.value(0)

# Adrese corecte verificate
BME280_ADDR = 0x77
ENS160_ADDR = 0x53

# Inițializare I2C
i2c = I2C(0, scl=Pin(9), sda=Pin(8), freq=100000)

# Inițializare UART pentru LoRa E5
uart1 = UART(1, baudrate=9600, tx=Pin(4), rx=Pin(5))

def init_bme280():
    """Inițializare și calibrare BME280"""
    try:
        # Reset
        i2c.writeto_mem(BME280_ADDR, 0xE0, bytes([0xB6]))
        sleep_ms(100)
        
        # Citește calibrarea
        cal_data = i2c.readfrom_mem(BME280_ADDR, 0x88, 24)
        cal_T1 = cal_data[1] << 8 | cal_data[0]
        cal_T2 = cal_data[3] << 8 | cal_data[2]
        if cal_T2 > 32767:
            cal_T2 -= 65536
        cal_T3 = cal_data[5] << 8 | cal_data[4]
        if cal_T3 > 32767:
            cal_T3 -= 65536
            
        # Configurare
        i2c.writeto_mem(BME280_ADDR, 0xF2, bytes([0x01]))  # humidity oversampling x1
        i2c.writeto_mem(BME280_ADDR, 0xF4, bytes([0x27]))  # temp/pressure oversampling x1, normal mode
        
        return cal_T1, cal_T2, cal_T3
    except Exception as e:
        print(f"Eroare inițializare BME280: {e}")
        return None

def read_bme280(calibration):
    """Citire și compensare date BME280"""
    try:
        if calibration is None:
            return 20.0, 1013.25, 50.0
            
        cal_T1, cal_T2, cal_T3 = calibration
        
        # Citire date brute
        data = i2c.readfrom_mem(BME280_ADDR, 0xF7, 8)
        
        # Temperatura
        temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
        var1 = ((((temp_raw >> 3) - (cal_T1 << 1))) * cal_T2) >> 11
        var2 = (((((temp_raw >> 4) - cal_T1) * ((temp_raw >> 4) - cal_T1)) >> 12) * cal_T3) >> 14
        t_fine = var1 + var2
        temperature = ((t_fine * 5 + 128) >> 8) / 100
        
        # Presiune și umiditate (simplificat)
        pressure = (((data[0] << 16) | (data[1] << 8) | data[2]) >> 4) / 256.0
        humidity = ((data[6] << 8) | data[7]) / 1024.0
        
        return temperature, pressure, humidity
    except Exception as e:
        print(f"Eroare citire BME280: {e}")
        return 20.0, 1013.25, 50.0

def read_ens160():
    """Citire date ENS160"""
    try:
        # Citire registri
        aqi = i2c.readfrom_mem(ENS160_ADDR, 0x21, 1)[0]
        tvoc_data = i2c.readfrom_mem(ENS160_ADDR, 0x22, 2)
        eco2_data = i2c.readfrom_mem(ENS160_ADDR, 0x24, 2)
        
        tvoc = (tvoc_data[1] << 8) | tvoc_data[0]
        eco2 = (eco2_data[1] << 8) | eco2_data[0]
        
        return aqi, tvoc, eco2
    except Exception as e:
        print(f"Eroare citire ENS160: {e}")
        return 1, 0, 400

def send_at_command(cmd, timeout=1000):  # Timeout mărit
    """Trimite comandă AT și așteaptă răspuns"""
    print(f"Trimitere comandă: AT{cmd}")
    uart1.write(f'AT{cmd}\r\n')
    sleep_ms(timeout)
    
    response = ''
    while uart1.any():
        response += uart1.read(1).decode('utf-8')
    print(f"Răspuns: {response}")
    return response

def configure_lora():
    """Configurează modulul LoRa E5 pentru EU868"""
    print("Configurare LoRa...")
    
    # Reset
    send_at_command('+RESET')
    sleep_ms(1000)
    
    # Test conexiune
    response = send_at_command('')
    if '+AT: OK' not in response:
        print("Eroare comunicare LoRa")
        return False
    
    # Configurare mod și parametri RF
    send_at_command('+MODE=TEST')
    send_at_command('+TEST=RFCFG,868100000,SF7,125,12,15,14')
    
    # Verificare configurare
    response = send_at_command('+TEST=RFCFG?')
    return True

def send_data_packet(data):
    """Trimite pachet de date prin LoRa"""
    print(f"Trimitere date: {data}")
    response = send_at_command(f'+TEST=TXLRSTR,"{data}"', timeout=2000)
    success = 'TX DONE' in response or 'TX OK' in response
    print(f"Status transmisie: {'Succes' if success else 'Eșec'}")
    return success

def main():
    print("Inițializare sistem...")
    
    # Inițializare BME280
    bme280_cal = init_bme280()
    
    # Configurare LoRa
    if not configure_lora():
        print("Eroare configurare LoRa!")
        return
    
    try:
        # Citire senzori
        temp, press, hum = read_bme280(bme280_cal)
        print(f"BME280: T={temp:.1f}°C, P={press:.1f}hPa, H={hum:.1f}%")
        
        aqi, tvoc, eco2 = read_ens160()
        print(f"ENS160: AQI={aqi}, TVOC={tvoc}ppb, eCO2={eco2}ppm")
        
        # Formatare date
        sign = 1 if temp >= 0 else 2
        temp_clean = abs(int(temp * 100))
        press_clean = int(press * 100)
        hum_clean = int(hum * 100)
        
        # Construire pachet
        data_packet = f"{sign}{temp_clean:05d}{press_clean:07d}{hum_clean:06d}{aqi}{tvoc:06d}{eco2:06d}"
        print(f"Pachet de date format: {data_packet}")
        
        # Trimitere date
        led.on()
        if send_data_packet(data_packet):
            print("Date trimise cu succes!")
            for _ in range(3):
                led.off()
                sleep_ms(200)
                led.on()
                sleep_ms(200)
        else:
            print("Eroare trimitere date!")
            for _ in range(5):
                led.off()
                sleep_ms(100)
                led.on()
                sleep_ms(100)
    
    except Exception as e:
        print(f"Eroare generală: {e}")
        led.on()
    
    finally:
        print("Activare Deep Sleep")
        led.off()
        sleep_ms(2000)
        GPIO_22.value(1)

if __name__ == "__main__":
    main()

Could anyone guide me on:

  1. How to configure both boards for P2P communication (modulation settings, frequency, etc.)?
  2. How to make sure they are compatible in raw LoRa mode?
  3. Any example code or documentation for the LilyGO side that supports receiving raw LoRa messages?

Thanks in advance!

Peer-to-peer is the normal setup. Just Google it. The Swiss Guy is a big fan, and DBWS has probably covered it.

Start at the beginning.

Make sure that each setup will communicate with basic send and receives examples to another board of the exact same type and library. If you do that you know the transmit and receive hardware is working.

Mixing standard Arduino libraries on the same hardware can cause issues, but seperate hardware, program environments and libraries, that could be tricky, even for those well experienced with LoRa.

If your starting setup does not work, where would you start to look for a problem .......

There are several LoRa libraries that will work with the ESP32. All such LoRa libraries receive 'raw' packets, its up to your sketch to convert the string of bytes that are a LoRa packet into meaningful data.

as @srnet stated mixing different LoRa modules/libraries etc can be difficult and one should start with a simple sent/receive example

for example, a simple receiver using a grove-E5 LoRa module connected to an ESP32 using the LoRaE5 library

// ESP32 <> Grove-E5 LoRa module

// example p2p_rx.ino from  https://github.com/idreamsi/LoRaE5  

#include <LoRaE5.h>
unsigned char buffer[128] = {0};

#define GROVE_TX 15//21
#define GROVE_RX 16//20

void setup(void)
{
    Serial.begin(115200);
    delay(2000);
    Serial.println("ESP32 Grove-E5 receiver");
    lora.init(GROVE_RX, GROVE_TX);
    lora.init();
    char id[200]={0};
    char version[50]={0};
    lora.getVersion(version, 50);
    Serial.printf("Version = %s  \n",version);
    lora.getId(id, 200);
    Serial.printf("ID = %s\n", id);
    lora.initP2PMode(866, SF7, BW125, 12, 8, 8);
}

void loop(void)
{
    short length = 0;
    short rssi = 0;
    
    memset(buffer, 0, 128);
    length = lora.receivePacketP2PMode(buffer, 128,  &rssi, 1);
    
    if(length)
    {
        Serial.print("Length is: ");
        Serial.println(length);
        Serial.print("RSSI is: ");
        Serial.println(rssi);
        Serial.print("Data is: ");
        for(unsigned char i = 0; i < length; i ++)
        {
            Serial.print("0x");
            Serial.print(buffer[i], HEX);
            Serial.print(" ");
        }
        Serial.println();
    }
}

a Heltec ESP32 LoRa (V2) SX1278 transmitter using SX12XX-LoRa library (which should work with the LILYGO LoRa32 T3 V1.6.1 OK)

// Heltec ESP32 LoRa (V2) SX1278 transmitter

/*******************************************************************************************************
  Programs for Arduino - Copyright of the author Stuart Robinson - 20/01/20

  This program is supplied as is, it is up to the user of the program to decide if the program is
  suitable for the intended purpose and free from errors.
*******************************************************************************************************/


/*******************************************************************************************************
  Program Operation - This is a simple LoRa test transmitter for an ESP32 device. A packet containing
  ASCII text is sent according to the frequency and LoRa settings specified in the 'Settings.h' file.
  The pins to access the SX127X need to be defined in the 'Settings.h' file also.

  The program also has the option of using a logic pin to control the power to the lora and SD card
  devices, which can save power in sleep mode. If the hardware is fitted to your board these devices are
  powered on by setting the VCCPOWER pin low. If your board does not have this feature set VCCPOWER to -1.

  The details of the packet sent and any errors are shown on the Serial Monitor, together with the transmit
  power used, the packet length and the CRC of the packet. The matching receive program, '4_LoRa_Receive'
  can be used to check the packets are being sent correctly, the frequency and LoRa settings (in Settings.h)
  must be the same for the Transmit and Receive program. Sample Serial Monitor output;

  10dBm Packet> {packet contents*}  BytesSent,23  CRC,DAAB  TransmitTime,54mS  PacketsSent,1

  Serial monitor baud rate is set at 9600
*******************************************************************************************************/

#include <SPI.h>                                               //the SX127X device is SPI based so load the SPI library                                         
#include <SX127XLT.h>                                          //include the appropriate library  
#include "Settings.h"                                          //include the setiings file, frequencies, LoRa settings etc   

SX127XLT LT;                                                   //create a library class instance called LT

uint8_t TXPacketL;
uint32_t TXPacketCount, startmS, endmS;

uint8_t buff[] = "0Hello World 1234567890";

void loop()
{
  Serial.print(TXpower);                                       //print the transmit power defined
  Serial.print(F("dBm "));
  Serial.print(F("Packet> "));
  Serial.flush();

  TXPacketL = sizeof(buff);                                    //set TXPacketL to length of array
  buff[TXPacketL - 1] = '*';                                   //replace null character at buffer end so its visible on reciver

  LT.printASCIIPacket(buff, TXPacketL);                        //print the buffer (the sent packet) as ASCII

  digitalWrite(LED1, HIGH);
  startmS =  millis();                                         //start transmit timer
  if (LT.transmit(buff, TXPacketL, 5000, TXpower, WAIT_TX))    //will return packet length sent if OK, otherwise 0 if transmit error
  {
    endmS = millis();                                          //packet sent, note end time
    TXPacketCount++;
    packet_is_OK();
  }
  else
  {
    packet_is_Error();                                 //transmit packet returned 0, there was an error
  }

  digitalWrite(LED1, LOW);
  Serial.println();
  // increment buff[0] or reset to '0'
  if(buff[0]=='9') buff[0]='0'; 
  else buff[0]++;
  delay(5000);//packet_delay);                                 //have a delay between packets
}


void packet_is_OK()
{
  //if here packet has been sent OK
  uint16_t localCRC;

  Serial.print(F("  BytesSent,"));
  Serial.print(TXPacketL);                             //print transmitted packet length
  localCRC = LT.CRCCCITT(buff, TXPacketL, 0xFFFF);
  Serial.print(F("  CRC,"));
  Serial.print(localCRC, HEX);                              //print CRC of sent packet
  Serial.print(F("  TransmitTime,"));
  Serial.print(endmS - startmS);                       //print transmit time of packet
  Serial.print(F("mS"));
  Serial.print(F("  PacketsSent,"));
  Serial.print(TXPacketCount);                         //print total of packets sent OK
}


void packet_is_Error()
{
  //if here there was an error transmitting packet
  uint16_t IRQStatus;
  IRQStatus = LT.readIrqStatus();                  //read the the interrupt register
  Serial.print(F(" SendError,"));
  Serial.print(F("Length,"));
  Serial.print(TXPacketL);                         //print transmitted packet length
  Serial.print(F(",IRQreg,"));
  Serial.print(IRQStatus, HEX);                    //print IRQ status
  LT.printIrqStatus();                             //prints the text of which IRQs set
}


void led_Flash(uint16_t flashes, uint16_t delaymS)
{
  uint16_t index;
  for (index = 1; index <= flashes; index++)
  {
    digitalWrite(LED1, HIGH);
    delay(delaymS);
    digitalWrite(LED1, LOW);
    delay(delaymS);
  }
}


void setup()
{
  pinMode(LED1, OUTPUT);                               //setup pin as output for indicator LED
  led_Flash(2, 125);                                   //two quick LED flashes to indicate program start

  if (VCCPOWER >= 0)
  {
    pinMode(VCCPOWER, OUTPUT);                  //For controlling power to external devices
    digitalWrite(VCCPOWER, LOW);                //VCCOUT on. lora device on
  }

  Serial.begin(115200);
  delay(3000);
  Serial.println();
  Serial.println(F("3_LoRa_Transmitter_ESP32 Starting"));

  //SPI.begin();                                //default setup can be used be used
  SPI.begin(SCK, MISO, MOSI);                   //alternative format for SPI3, VSPI; SPI.begin(SCK,MISO,MOSI,SS)

  //SPI beginTranscation is normally part of library routines, but if it is disabled in library
  //a single instance is needed here, so uncomment the program line below
  //SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));

  //setup hardware pins used by device, then check if device is found
  if (LT.begin(NSS, NRESET, DIO0, LORA_DEVICE))
  {
    Serial.println(F("LoRa Device found"));
    led_Flash(2, 125);                                   //two further quick LED flashes to indicate device found
    delay(1000);
  }
  else
  {
    Serial.println(F("No device responding"));
    while (1)
    {
      led_Flash(50, 50);                                 //long fast speed LED flash indicates device error
    }
  }

  //The function call list below shows the complete setup for the LoRa device using the information defined in the
  //Settings.h file.
  //The 'Setup LoRa device' list below can be replaced with a single function call;
  //LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);

  //***************************************************************************************************
  //Setup LoRa device
  //***************************************************************************************************
  LT.setMode(MODE_STDBY_RC);                              //got to standby mode to configure device
  LT.setPacketType(PACKET_TYPE_LORA);                     //set for LoRa transmissions
  LT.setRfFrequency(Frequency, Offset);                   //set the operating frequency
  LT.calibrateImage(0);                                   //run calibration after setting frequency
  LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, LDRO_AUTO);  //set LoRa modem parameters
  LT.setBufferBaseAddress(0x00, 0x00);                    //where in the SX buffer packets start, TX and RX
  LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL);  //set packet parameters
  LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD);              //syncword, LORA_MAC_PRIVATE_SYNCWORD = 0x12, or LORA_MAC_PUBLIC_SYNCWORD = 0x34
  LT.setHighSensitivity();                                //set for highest sensitivity at expense of slightly higher LNA current
  LT.setDioIrqParams(IRQ_RADIO_ALL, IRQ_TX_DONE, 0, 0);   //set for IRQ on RX done
  //***************************************************************************************************

  Serial.println();
  LT.printModemSettings();                                //reads and prints the configured LoRa settings, useful check
  Serial.println();
  LT.printOperatingSettings();                            //reads and prints the configured operating settings, useful check
  Serial.println();
  Serial.println();
  LT.printRegisters(0x00, 0x4F);                          //print contents of device registers, normally 0x00 to 0x4F
  Serial.println();
  Serial.println();

  Serial.print(F("Transmitter ready"));
  Serial.println();
}

Heltec transmitter serial monitor output

3_LoRa_Transmitter_ESP32 Starting
LoRa Device found

SX1278_PABOOST,866000000hz,SF7,BW125000,CR4:5,LDRO_Off,SyncWord_0x12,IQNormal,Preamble_8
SX1278_PABOOST,SLEEP,Version_12,PacketMode_LoRa,Explicit,CRC_On,AGCauto_On,LNAgain_1

Reg    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
0x00  34 81 1A 0B 00 52 D8 80 00 4F 09 2B 23 01 00 00 
0x10  00 00 00 00 00 00 00 00 10 00 00 00 00 72 74 64 
0x20  00 08 FF FF 00 00 04 00 00 00 00 00 00 50 14 45 
0x30  55 C3 05 27 1C 0A 03 0A 42 12 49 1D 00 AF 00 00 
0x40  70 00 12 24 2D 00 03 00 04 23 00 09 05 84 32 2B 


Transmitter ready
10dBm Packet> 0Hello World 1234567890*  BytesSent,24  CRC,3382  TransmitTime,62mS  PacketsSent,1
10dBm Packet> 1Hello World 1234567890*  BytesSent,24  CRC,481  TransmitTime,62mS  PacketsSent,2
10dBm Packet> 2Hello World 1234567890*  BytesSent,24  CRC,5D84  TransmitTime,62mS  PacketsSent,3
10dBm Packet> 3Hello World 1234567890*  BytesSent,24  CRC,6A87  TransmitTime,62mS  PacketsSent,4
10dBm Packet> 4Hello World 1234567890*  BytesSent,24  CRC,EF8E  TransmitTime,62mS  PacketsSent,5
10dBm Packet> 5Hello World 1234567890*  BytesSent,24  CRC,D88D  TransmitTime,62mS  PacketsSent,6

type or paste code here

Grove-E5 receiver serial monitor output

ESP32 Grove-E5 receiver
Version =
ID = +ID: DevAddr, 42:00:33:26
+ID: DevEui, 2C:F7:F1:20:42:00:33:26
+ID: AppEui, 80:00:00:00:00:00:00:06

Length is: 24
RSSI is: -25
Data is: 0x30 0x48 0x65 0x6C 0x6C 0x6F 0x20 0x57 0x6F 0x72 0x6C 0x64 0x20 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x30 0x2A
Length is: 24
RSSI is: -25
Data is: 0x31 0x48 0x65 0x6C 0x6C 0x6F 0x20 0x57 0x6F 0x72 0x6C 0x64 0x20 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x30 0x2A
Length is: 24
RSSI is: -25
Data is: 0x32 0x48 0x65 0x6C 0x6C 0x6F 0x20 0x57 0x6F 0x72 0x6C 0x64 0x20 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x30 0x2A
Length is: 24
RSSI is: -25
Data is: 0x33 0x48 0x65 0x6C 0x6C 0x6F 0x20 0x57 0x6F 0x72 0x6C 0x64 0x20 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x30 0x2A
Length is: 24
RSSI is: -35
Data is: 0x34 0x48 0x65 0x6C 0x6C 0x6F 0x20 0x57 0x6F 0x72 0x6C 0x64 0x20 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x39 0x30 0x2A

once you have simple transmit/receive test working you know the hardware is working with the libraries etc and can start adding your project code

photo of test setup

Thats a LoRaWAN module I think.

Is it capable of LoRa direct P to P ?

good point - I don't have a Wio-E5 LE Mini so cannot test P2P
the Grove_LoRa_E5 which was used in post 5 will do LoRa P2P and LoRaWAN
I guess it is a case of experimenting with the libraries

a fairly common problem of making the hardware fit the project requirements rather than starting with a requirements specification and then getting hardware which meets the requirements

1 Like

Hello everyone,

I’m working on a LoRa-based project and I’m trying to set up peer-to-peer (P2P) communication between a LoRa-E5 Mini and a LILYGO TTGO LoRa32 V2.1-1.6 with ESP32 — but I haven’t been able to establish a successful connection so far.

My setup is as follows:

Two sensors, ENS160 and BME280, are connected to a Makerverse Nano Power Timer HAT (MKRVRS).

A Raspberry Pi Pico is mounted on the MKRVRS and communicates with the sensors.

The LoRa-E5 Mini is connected via UART to the MKRVRS, and is used to transmit sensor data.

The receiver is a TTGO LoRa32 (ESP32), which should receive the data and forward it to a server.

I already have example code for both sides (transmitter and receiver).

My goal is to use a P2P LoRa connection to send data from the LoRa-E5 Mini to the TTGO ESP32 module.
This project is similar to the following two examples:
(ESP32 LoRa Sensor Monitoring with Web Server (Long Range Communication) | Random Nerd Tutorials)
My project setup is very similar to this example:
:link: LoRa Weather Station with Pico - Core Electronics
However, unlike the tutorial, I’m not using LoRaWAN — I’m working with direct P2P communication. The hardware connections between components are the same.

However, I haven’t been able to get the two LoRa modules to talk to each other.

If anyone has experience with P2P LoRa communication between different chipsets (STM32/Wio-E5 and ESP32/TTGO), or if you’ve worked on similar projects, I’d really appreciate any help or guidance.

Thanks in advance!

In order to communicate, the radio modules must be configured identically, which is not easy using different MCUs and different libraries. Forum members don't recommend that you try.

For help, follow the forum rules and post the code you are using to attempt to establish the communication, and clearly describe the problems you are encountering. Be sure to post links the exact modules you are using.

Here are the links to the exact modules I’m using:

At the moment, I don’t have a well-structured or complete version of the code that I can share. However, I’ve mostly been trying to adapt and modify the example code from the projects I mentioned earlier to fit the specifics of my setup.

In that case, how can you expect help to debug it?

Post again when you have concrete questions that can be answered without writing a "getting started" tutorial.

2 Likes

I have tried, and succeeded, in getting different hardware and software platforms to communicate via LoRa, though not with your particular hardware\software.

Your starting point should be to prove that the boards you have are actually transmitting LoRa and are capable of receiving LoRa.

This is relatively straight forward when you have two sets of each bit of hardware.

And there is the problem, two different bits of hardware either of which might not be working and no known working code for either.

1 Like

the example code of post 5 used a grove-E5 LoRa module as a receiver and a Heltec ESP32 LoRa (V2) SX1278 transmitter

the following uses a grove-E5 LoRa module connected to an ESP32 using the LoRaE5 library as a transmitter

// grove-E5 LoRa module connected to an ESP32 using the LoRaE5 library transmitter

// library https://github.com/idreamsi/LoRaE5/tree/main

// example p2p_rtx.ino from  https://github.com/idreamsi/LoRaE5  


#include <LoRaE5.h>
unsigned char buffer[128] = {0xef, 0xff, 0x55, 3, 4, 5, 6, 7, 8, 9,};

#define GROVE_TX 15//21
#define GROVE_RX 16//20

void setup(void)
{
    SerialUSB.begin(115200);
    lora.init(GROVE_RX, GROVE_TX);
    lora.init();
    char id[200]={0};
    char version[50]={0};
    lora.getVersion(version, 50);
    Serial.printf("Version = %s  \n",version);
    lora.getId(id, 200);
    Serial.printf("ID = %s\n", id);
   // lora.initP2PMode(866, SF7, BW125, 12, 8, 8);
   lora.initP2PMode(866, SF7, BW125, 8, 8);
//    lora.initP2PMode(866, SF12, BW125, 12, 15, 14);
}

void loop(void)
{
    lora.transferPacketP2PMode("Hello World!");
    SerialUSB.println("Send string.");
    delay(3000);
    lora.transferPacketP2PMode(buffer, 10);
    SerialUSB.println("Send hex.");
    delay(3000);
}

Heltec ESP32S3 LoRa (V3) SX1262 receiver code

// Heltec ESP32S3 LoRa (V3) SX1262 receiver

/*******************************************************************************************************
  Programs for Arduino - Copyright of the author Stuart Robinson - 04/04/20

  This program is supplied as is, it is up to the user of the program to decide if the program is
  suitable for the intended purpose and free from errors.
*******************************************************************************************************/

/*******************************************************************************************************
  Program Operation - This is a program that demonstrates the detailed setup of a LoRa test receiver.
  The program listens for incoming packets using the LoRa settings in the 'Settings.h' file. The pins
  to access the lora device need to be defined in the 'Settings.h' file also.

  There is a printout on the Arduino IDE Serial Monitor of the valid packets received, the packet is
  assumed to be in ASCII printable text, if it's not ASCII text characters from 0x20 to 0x7F, expect
  weird things to happen on the Serial Monitor. The LED will flash for each packet received and the
  buzzer will sound, if fitted.

  Sample serial monitor output;

  7s  Hello World 1234567890*,CRC,DAAB,RSSI,-52dBm,SNR,9dB,Length,23,Packets,5,Errors,0,IRQreg,50

  If there is a packet error it might look like this, which is showing a CRC error,

  968s PacketError,RSSI,-87dBm,SNR,-11dB,Length,23,Packets,613,Errors,2,IRQreg,70,IRQ_HEADER_VALID,IRQ_CRC_ERROR,IRQ_RX_DONE

  Serial monitor baud rate is set at 9600.
*******************************************************************************************************/

#include <SPI.h>                                 //the lora device is SPI based so load the SPI library
#include <SX126XLT.h>                            //include the appropriate library   
#include "Settings.h"                            //include the setiings file, frequencies, LoRa settings etc   

SX126XLT LT;                                     //create a library class instance called LT

uint32_t RXpacketCount;
uint32_t errors;

uint8_t RXBUFFER[RXBUFFER_SIZE];                 //create the buffer that received packets are copied into

uint8_t RXPacketL;                               //stores length of packet received
int8_t  PacketRSSI;                              //stores RSSI of received packet
int8_t  PacketSNR;                               //stores signal to noise ratio (SNR) of received packet


void loop()
{
  RXPacketL = LT.receive(RXBUFFER, RXBUFFER_SIZE, 60000, WAIT_RX); //wait for a packet to arrive with 60seconds (60000mS) timeout

  digitalWrite(LED1, HIGH);                      //something has happened

  PacketRSSI = LT.readPacketRSSI();              //read the recived RSSI value
  PacketSNR = LT.readPacketSNR();                //read the received SNR value

  if (RXPacketL == 0)                            //if the LT.receive() function detects an error, RXpacketL is 0
  {
    packet_is_Error();
  }
  else
  {
    packet_is_OK();
  }

  digitalWrite(LED1, LOW);                       //LED off

  Serial.println();
}


void packet_is_OK()
{
  uint16_t IRQStatus, localCRC;

  IRQStatus = LT.readIrqStatus();                 //read the LoRa device IRQ status register

  RXpacketCount++;

  printElapsedTime();                             //print elapsed time to Serial Monitor
  Serial.print(F("  "));
  LT.printASCIIPacket(RXBUFFER, RXPacketL);       //print the packet as ASCII characters

  localCRC = LT.CRCCCITT(RXBUFFER, RXPacketL, 0xFFFF);  //calculate the CRC, this is the external CRC calculation of the RXBUFFER
  Serial.print(F(",CRC,"));                       //contents, not the LoRa device internal CRC
  Serial.print(localCRC, HEX);
  Serial.print(F(",RSSI,"));
  Serial.print(PacketRSSI);
  Serial.print(F("dBm,SNR,"));
  Serial.print(PacketSNR);
  Serial.print(F("dB,Length,"));
  Serial.print(RXPacketL);
  Serial.print(F(",Packets,"));
  Serial.print(RXpacketCount);
  Serial.print(F(",Errors,"));
  Serial.print(errors);
  Serial.print(F(",IRQreg,"));
  Serial.print(IRQStatus, HEX);
}


void packet_is_Error()
{
  uint16_t IRQStatus;
  IRQStatus = LT.readIrqStatus();                   //read the LoRa device IRQ status register

  printElapsedTime();                               //print elapsed time to Serial Monitor

  if (IRQStatus & IRQ_RX_TIMEOUT)                   //check for an RX timeout
  {
    Serial.print(F(" RXTimeout"));
  }
  else
  {
    errors++;
    Serial.print(F(" PacketError"));
    Serial.print(F(",RSSI,"));
    Serial.print(PacketRSSI);
    Serial.print(F("dBm,SNR,"));
    Serial.print(PacketSNR);
    Serial.print(F("dB,Length,"));
    Serial.print(LT.readRXPacketL());               //get the device packet length
    Serial.print(F(",Packets,"));
    Serial.print(RXpacketCount);
    Serial.print(F(",Errors,"));
    Serial.print(errors);
    Serial.print(F(",IRQreg,"));
    Serial.print(IRQStatus, HEX);
    LT.printIrqStatus();                            //print the names of the IRQ registers set
  }

  delay(250);                                       //gives a longer buzzer and LED flash for error

}


void printElapsedTime()
{
  float seconds;
  seconds = millis() / 1000;
  Serial.print(seconds, 0);
  Serial.print(F("s"));
}


void led_Flash(uint16_t flashes, uint16_t delaymS)
{
  uint16_t index;

  for (index = 1; index <= flashes; index++)
  {
    digitalWrite(LED1, HIGH);
    delay(delaymS);
    digitalWrite(LED1, LOW);
    delay(delaymS);
  }
}


void setup()
{
  pinMode(LED1, OUTPUT);                        //setup pin as output for indicator LED
  led_Flash(2, 125);                            //two quick LED flashes to indicate program start

  Serial.begin(115200);
  delay(3000);
  Serial.println();
  Serial.println(F("104_LoRa_Receiver_Detailed_Setup_ESP32 Starting"));
  Serial.println();

  SPI.begin();
  //SPI.begin(SCK, MISO, MOSI);                  //this will work too, allows you to move SPI pins

  //SPI beginTranscation is normally part of library routines, but if it is disabled in the library
  //a single instance is needed here, so uncomment the program line below
  //SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0));

  //setup hardware pins used by device, then check if device is found
  if (LT.begin(NSS, NRESET, RFBUSY, DIO1, LORA_DEVICE))
  {
    Serial.println(F("LoRa Device found"));
    led_Flash(2, 125);
    delay(1000);
  }
  else
  {
    Serial.println(F("No device responding"));
    while (1)
    {
      led_Flash(50, 50);                                       //long fast speed LED flash indicates device error
    }
  }

  //The function call list below shows the complete setup for the LoRa device using the information defined in the
  //Settings.h file.
  //The 'Setup LoRa device' list below can be replaced with a single function call;
  //LT.setupLoRa(Frequency, Offset, SpreadingFactor, Bandwidth, CodeRate, Optimisation);

  //***************************************************************************************************
  //Setup LoRa device
  //***************************************************************************************************
  LT.setMode(MODE_STDBY_RC);
  LT.setRegulatorMode(USE_DCDC);
  LT.setPaConfig(0x04, PAAUTO, LORA_DEVICE);
  LT.setDIO3AsTCXOCtrl(TCXO_CTRL_3_3V);
  LT.calibrateDevice(ALLDevices);                //is required after setting TCXO
  LT.calibrateImage(Frequency);
  LT.setDIO2AsRfSwitchCtrl();
  LT.setPacketType(PACKET_TYPE_LORA);
  LT.setRfFrequency(Frequency, Offset);
  LT.setModulationParams(SpreadingFactor, Bandwidth, CodeRate, Optimisation);
  LT.setBufferBaseAddress(0, 0);
  LT.setPacketParams(8, LORA_PACKET_VARIABLE_LENGTH, 255, LORA_CRC_ON, LORA_IQ_NORMAL);
  LT.setDioIrqParams(IRQ_RADIO_ALL, (IRQ_RX_DONE + IRQ_RX_TX_TIMEOUT), 0, 0);   //set for IRQ on TX done and timeout on DIO1
  LT.setHighSensitivity();  //set for maximum gain
  LT.setSyncWord(LORA_MAC_PRIVATE_SYNCWORD);
  //***************************************************************************************************


  Serial.println();
  LT.printModemSettings();                                     //reads and prints the configured LoRa settings, useful check
  Serial.println();
  LT.printOperatingSettings();                                 //reads and prints the configured operting settings, useful check
  Serial.println();
  Serial.println();
  LT.printRegisters(0x900, 0x9FF);                             //print contents of device registers, normally 0x00 to 0x4F
  Serial.println();
  Serial.println();

  Serial.print(F("Receiver ready - RXBUFFER_SIZE "));
  Serial.println(RXBUFFER_SIZE);
  Serial.println();
}

E5 transmitter serial output

Version =   
ID = +ID: DevAddr, 42:00:33:26
+ID: DevEui, 2C:F7:F1:20:42:00:33:26
+ID: AppEui, 80:00:00:00:00:00:00:06

Send string.
Send hex.
Send string.
Send hex.
Send string.
Send hex.
Send string.
Send hex.
Send string.
Send hex.

Heltec ESP32S3 LoRa (V3) receiver serial output

Heltek LoRa V3 receiver

104_LoRa_Receiver_Detailed_Setup_ESP32 Starting

LoRa Device found

SX1262,866000000hz,SF7,BW125000,CR4:5,LDRO_Off,SyncWord_0x1424,IQNormal,Preamble_8
SX1262,PacketMode_LoRa,Explicit,LNAgain_Boosted

Reg    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
0x900  30 00 00 00 00 64 00 00 00 00 00 00 24 04 47 04 
0x910  00 2F 00 00 00 03 0A 00 15 35 09 00 02 2A 6F 08 
0x920  07 04 05 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x930  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x940  00 07 00 03 02 00 10 00 0A 00 03 04 00 14 0C 00 
0x950  00 00 00 06 00 00 00 00 00 00 00 00 00 00 00 00 
0x960  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x970  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x980  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x990  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x9A0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x9B0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x9C0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x9D0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x9E0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x9F0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

330s  Hello World!,CRC,882A,RSSI,-35dBm,SNR,12dB,Length,12,Packets,14,Errors,0,IRQreg,16
333s  ��Ua	,CRC,50B1,RSSI,-34dBm,SNR,12dB,Length,10,Packets,15,Errors,0,IRQreg,16
336s  Hello World!,CRC,882A,RSSI,-36dBm,SNR,12dB,Length,12,Packets,16,Errors,0,IRQreg,16
339s  ��Ua	,CRC,50B1,RSSI,-35dBm,SNR,12dB,Length,10,Packets,17,Errors,0,IRQreg,16
342s  Hello World!,CRC,882A,RSSI,-33dBm,SNR,12dB,Length,12,Packets,18,Errors,0,IRQreg,16
345s  ��Ua	,CRC,50B1,RSSI,-26dBm,SNR,12dB,Length,10,Packets,19,Errors,0,IRQreg,16
348s  Hello World!,CRC,882A,RSSI,-33dBm,SNR,12dB,Length,12,Packets,20,Errors,0,IRQreg,16
351s  ��Ua	,CRC,50B1,RSSI,-24dBm,SNR,12dB,Length,10,Packets,21,Errors,0,IRQreg,16
354s  Hello World!,CRC,882A,RSSI,-25dBm,SNR,12dB,Length,12,Packets,22,Errors,0,IRQreg,16
357s  ��Ua	,CRC,50B1,RSSI,-25dBm,SNR,13dB,Length,10,Packets,23,Errors,0,IRQreg,16
360s  Hello World!,CRC,882A,RSSI,-24dBm,SNR,12dB,Length,12,Packets,24,Errors,0,IRQreg,16

it is unlikely that anyone has you exact configuration so only examples using similar devices can be provided to give you ideas of suitable libraries etc

always start projects using communications by testing the communication between devices using the simplest example code (usually provided by the libraries)
even then if the LoRa modules and /or host microcontrollers are different it can be difficult to setup the different libraries etc for reliable communication

2 Likes