How to Set Up Point-to-Point Communication Between Two LoRa-E5 Mini Modules?

Hi everyone,

I’m currently working on a project involving two LoRa-E5 Mini modules, and I want to establish a point-to-point connection between them. My goal is to transmit data directly from one module to the other without using any LoRaWAN networks or The Things Network (TTN).

I’m looking for guidance, documents, or examples on how to achieve this. Specifically, I would like to know:

  1. How to configure the LoRa-E5 Mini modules for point-to-point communication.
  2. Any relevant libraries or sample code that could help me get started.
  3. Tips on frequency, bandwidth, and other settings for a stable connection.

Any help or pointers to documentation would be greatly appreciated!

Thanks in advance!

Hi there,
So take a look at this one, may help you.

this guy does quality work on here.
HTH
GL :slight_smile: PJ :v:

Thanks a ton for your help @PJ_Glasso

Hello Everyone,
I was following the above mentioned code but facing the issue:

// ******************************************************************************************************
// BSP : STM32 MCU based boards by STMicroelectronics 2.7.1
// Borad select : STM32 based boards / LoRa boars
// Board part number : LoRa-E5 mini (Board to be selected from Tools submenu 'Board part number')
// ******************************************************************************************************
// 1. transmit data 11 bytes(SlaveUID 4, randomNumber 4, Vbatt 2, (previous)veryfiResult 1)
// 2. wait for response from Master
// 3. receive data 11 bytes(MasterUID 4, verifyNumber 4, rssi 1, snr 1, interval 1)
// 4. verify sent randomNumber with received verifyNumber

// 2024/06/29 @msfujino

#include <Arduino.h>
#include <RadioLib.h>           // 6.6.0  RadioLib by Jan Gromes (Library manager)

#define CHECK_INTERVAL  15000   // communication check interval [mS]
#define LED_ERROR     D10       // verify error RED
#define LED_GOOD       D9       // verify good GREEN
// BAT_pad --> 1000k --> A4_pin --> 510k --> D0_pin
#define PIN_VBATT      A4       // battery voltage measurement ADC pin
#define READ_ENABLE    D0       // read PIN_VBATT enable LOW:enable, HIGH:disable

// RM0461 Reference manual Rev 8  37.1.4 IEEE 64-bit unique device ID register (UID64)
#define SLAVE_UID   *((uint32_t*)0x1FFF7580)    // use uid64 for Slave device UID
#define MASTER_UID  0x05358291  // example Master device UID



// \Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1
// \variants\STM32WLxx\WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I\variant_LORA_E5_MINI.h : 173
STM32WLx radio = new STM32WLx_Module();
static const uint32_t rfswitch_pins[] = {PA4, PA5, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
static const Module::RfSwitchMode_t rfswitch_table[] = {
  {STM32WLx::MODE_IDLE,  {LOW,  LOW}},
  {STM32WLx::MODE_RX,    {HIGH, LOW}},
//  {STM32WLx::MODE_TX_HP, {LOW, HIGH}},  // for LoRa-E5 mini
  {STM32WLx::MODE_TX_LP, {HIGH, HIGH}},   // for LoRa-E5-LE mini  
  END_OF_MODE_TABLE,
};

#define dataNum   11                // transmit data 11 bytes (SlaveUID 4, randomNumber 4, Vbatt 2, (previous)veryfiResult 1)
                                    // receive data 11 bytes  (MasterUID 4, verifyNumber 4, rssi 1, snr 1, interval 1)
union unionBuff {                   // buffer for data type conversion
  uint32_t  Buff_u32[dataNum/4];    // SlaveID, MasterID, randomNumber, verifyNumber
  uint16_t  Buff_u16[dataNum/2];    // Vbatt
  int8_t    Buff_i8[dataNum];       // rssi, snr
  uint8_t   Buff_u8[dataNum];       // verifyResult, interval
};
union unionBuff ub;

int8_t rssi;                        // signal RSSI [dBm]
int8_t snr;                         // signal SN ratio [dB]
uint32_t slaveuid = SLAVE_UID;      // Slave device UID
uint32_t masteruid;                 // Master device UID
uint16_t Vbatt;                        // battery voltage data [V]
char printBuff[4];                  // for sprintf()
String  txdata = "";                // transmission data packet string
String  rxdata = "";                // received data packet string
bool rxstatus = false;              // receive status flag
bool receivedFlag = false;          // flag that a packet was received
bool transmittedFlag = false;       // flag that a packet was transmitted
uint8_t receivedInterval;           // Master reveived interval [sec]
uint32_t randomNumber;              // random number to verify that data was sent correctly
uint32_t verifyNumber;              // verify number from Master
uint32_t verifyResult = 0;          // verify result 1:GOOD or 0:ERROR

// *******************************************************************************************************
void setup() {
  Serial.begin(115200);
//  while(!Serial);
  delay(2000);
 
 
  // Radio initialization
  radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);
  Serial.println("After radio Set RFSwitchTable");


  // int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, \
  // uint8_t syncWord = RADIOLIB_SX126X_SYNC_WORD_PRIVATE, int8_t power = 10, \
  // uint16_t preambleLength = 8, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
  int state = radio.begin(922.6, 125.0, 12, 5, 0x12, 13, 8, 1.7, 0);
  Serial.print("State: ");
  Serial.println(state);

  if (state == RADIOLIB_ERR_NONE) {
    Serial.println("radio.begin() success!");
  }
  else {
    Serial.print("failed, code ");
    Serial.println(state);

  }

  // callback function when received or transmitted a packet
  radio.setDio1Action(setFlag);

}

void setFlag(void) 
{
  uint16_t irqstatus = radio.getIrqStatus();
  if(irqstatus == RADIOLIB_SX126X_IRQ_RX_DONE) {
    receivedFlag = true;
  }
  else if(irqstatus == RADIOLIB_SX126X_IRQ_TX_DONE) {
    transmittedFlag = true;
  }
  else {
    receivedFlag = false;
    transmittedFlag = false;
  }
}

// ***********************************************************************************************************
void loop() 
{
  // ++++++++++++++++++++++++++++++++ Slave transmits a packet to Master ++++++++++++++++++++++++
  Serial.println("Transmitting packet ... ");

  // battery voltage measurement
  int n = 256;     // average times
  uint32_t Vadc = 0;
  for(int i = 0; i < n; i++) {
    Vadc = Vadc + analogRead(PIN_VBATT);
  }
  Vadc = Vadc / n;

  // example battery voltage map()data
  uint16_t adc_low = 1449;     // ADC data when battery voltage is low
  uint16_t vbatt_low = 3426;   // low Vbatt [mV]
  uint16_t adc_high = 1623;    // ADC data when battery voltage is high
  uint16_t vbatt_high = 4176;  // high Vbatt [mV]
  Vbatt = map(Vadc, adc_low, adc_high, vbatt_low, vbatt_high);   // Converts to battery voltage 3400 ~ 4200mV

  // Slave transmits data
  ub.Buff_u32[0] = slaveuid;                      // Slave device UID
  randomNumber = random(0x7FFFFFFF);              // for verification
  ub.Buff_u32[1] = randomNumber;
  ub.Buff_u16[4] = Vbatt;                         // battery voltage
  ub.Buff_u8[10] = verifyResult;                  // previous verify result

  uint16_t sec = millis() / 1000;                 // transmission time [sec]
  transmittedFlag = false;
  int state = radio.startTransmit(ub.Buff_u8, dataNum);

  txdata = "";
  for(int i = 0; i < dataNum; i++) {
    sprintf(printBuff, "%02x", ub.Buff_u8[i]);
    txdata += printBuff;
  }
  txdata.toUpperCase();
  Serial.println(txdata);

  Serial.print("Slave UID:\t"); Serial.println(slaveuid, HEX);  
  Serial.print("Time:\t\t"); Serial.print(sec); Serial.println(" sec");
  Serial.print("Vbatt:\t\t"); Serial.print(Vbatt); Serial.println(" mV");
  Serial.print("randomNumber:\t"); Serial.println(randomNumber, HEX);
  Serial.print("VerifyResult:\t"); Serial.println(verifyResult);

    // wait for transmittion completion
  while(!transmittedFlag) {
    delay(1);   // wait for SPI ready
  }

  // error status check
  if (state == RADIOLIB_ERR_NONE) {
    // packet was successfully sent
    Serial.println("transmission finished!");
  } 
  else {
    // some other error occurred
    Serial.print("failed, code ");
    Serial.println(state);
  }

  
}

Issue: radio.begin() is not working.
Output : After radio Set RFSwitchTable.
can anyone help me in this. Thanks a ton
@msfujino

Is your device a “LoRa-E5-LE mini” ?

static const Module::RfSwitchMode_t rfswitch_table[] = {
  {STM32WLx::MODE_IDLE,  {LOW,  LOW}},
  {STM32WLx::MODE_RX,    {HIGH, LOW}},
//  {STM32WLx::MODE_TX_HP, {LOW, HIGH}},  // for LoRa-E5 mini
  {STM32WLx::MODE_TX_LP, {HIGH, HIGH}},   // for LoRa-E5-LE mini  
  END_OF_MODE_TABLE,
}

;

No, my device is LoRa-E5 mini. I have correct it in my code, but still facing same issue.

The sketch in your post 4 works fine in my environment.
Please be more specific.

Issue : radio.begin() is not working.

First, make sure the following two simple sketches work.
If they do not work, then there may be a very basic mistake.
Is the board selected correctly?
Borad select : STM32 based boards / LoRa boars
Board part number : LoRa-E5 mini (Board to be selected from Tools submenu ‘Board part number’)

void setup() {
  Serial.begin(115200);
//  while(!Serial);
  delay(2000);
  Serial.println("BLINK");

  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  Serial.println("BLINK");
  digitalWrite(LED_BUILTIN, LOW);   // ON
  delay(100);
  digitalWrite(LED_BUILTIN, HIGH);  // OFF
  delay(1000);
}

void setup() {
  Serial.begin(115200);
//  while(!Serial);
  delay(2000);
  Serial.println("get STM32WL UID");

}

void loop() {
  Serial.println("get ID");
uint32_t uid64 = *((uint32_t*)0x1FFF7580);
  Serial.println(uid64, HEX);
  Serial.println(HAL_GetUIDw0(), HEX);
  Serial.println(HAL_GetUIDw1(), HEX);
  Serial.println(HAL_GetUIDw2(), HEX);  
  Serial.println("");
  delay(2000);
}

Yeah, I have tested the blink code and it is working fine(I selected the right board).

The sketch in your post 4 works fine in my environment.
Please be more specific.

Issue : radio.begin() is not working.

Is your device printed “LoRa-E5-HF”?

No, It is only printng the “After radio Set RFSwitchTable” as mentioned in code after that it is not printing anything.

Is your device printed “LoRa-E5-HF ”?

Is “LoRa-E5-HF” printed on the front of your LoRa-E5 mini package?

When I run your sketch of POST4, it will appear on the serial monitor as follows.

15:00:52.099 → After radio Set RFSwitchTable
15:00:52.132 → State: 0
15:00:52.132 → radio.begin() success!
15:00:52.132 → Transmitting packet …
15:00:52.198 → 2FEE35052DF451589BFB00
15:00:52.198 → Slave UID: 535EE2F
15:00:52.198 → Time: 2 sec
15:00:52.198 → Vbatt: 64411 mV
15:00:52.198 → randomNumber: 5851F42D
15:00:52.198 → VerifyResult: 0

Don’t know why it’s is not working in my module. I connected st-link with LoRa-E5 mini.

  1. Is “LoRa-E5-HF ” printed on the front of your LoRa-E5 mini package?

  2. Please show me what the serial monitor shows when you run your sketch of POST4.

  3. Show me your setup: what and how are you connecting to the LoRa-E5 mini?
    Are you connecting devices like POST8 in the link?
    Programming LoRa-E5 with Arduino, LoRa-E5 mini Point to Point Comminucation over 24 km - #8 by msfujino

Connection:
Gnd = Gnd
SWDIO = DIO
SWCLK = CLK
RESET = RESET
powering the module using cable.

Code:

#include <Arduino.h>
#include <RadioLib.h>           // 6.6.0  RadioLib by Jan Gromes (Library manager)

#define CHECK_INTERVAL  15000   // communication check interval [mS]
#define LED_ERROR     D10       // verify error RED
#define LED_GOOD       D9       // verify good GREEN
// BAT_pad --> 1000k --> A4_pin --> 510k --> D0_pin
#define PIN_VBATT      A4       // battery voltage measurement ADC pin
#define READ_ENABLE    D0       // read PIN_VBATT enable LOW:enable, HIGH:disable

// RM0461 Reference manual Rev 8  37.1.4 IEEE 64-bit unique device ID register (UID64)
#define SLAVE_UID   *((uint32_t*)0x1FFF7580)    // use uid64 for Slave device UID
#define MASTER_UID  0x05358291  // example Master device UID



// \Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.1
// \variants\STM32WLxx\WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I\variant_LORA_E5_MINI.h : 173
STM32WLx radio = new STM32WLx_Module();
static const uint32_t rfswitch_pins[] = {PA4, PA5, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC};
static const Module::RfSwitchMode_t rfswitch_table[] = {
  {STM32WLx::MODE_IDLE,  {LOW,  LOW}},
  {STM32WLx::MODE_RX,    {HIGH, LOW}},
 {STM32WLx::MODE_TX_HP, {LOW, HIGH}},  // for LoRa-E5 mini
  // {STM32WLx::MODE_TX_LP, {HIGH, HIGH}},   // for LoRa-E5-LE mini  
  END_OF_MODE_TABLE,
};

#define dataNum   11                // transmit data 11 bytes (SlaveUID 4, randomNumber 4, Vbatt 2, (previous)veryfiResult 1)
                                    // receive data 11 bytes  (MasterUID 4, verifyNumber 4, rssi 1, snr 1, interval 1)
union unionBuff {                   // buffer for data type conversion
  uint32_t  Buff_u32[dataNum/4];    // SlaveID, MasterID, randomNumber, verifyNumber
  uint16_t  Buff_u16[dataNum/2];    // Vbatt
  int8_t    Buff_i8[dataNum];       // rssi, snr
  uint8_t   Buff_u8[dataNum];       // verifyResult, interval
};
union unionBuff ub;

int8_t rssi;                        // signal RSSI [dBm]
int8_t snr;                         // signal SN ratio [dB]
uint32_t slaveuid = SLAVE_UID;      // Slave device UID
uint32_t masteruid;                 // Master device UID
uint16_t Vbatt;                        // battery voltage data [V]
char printBuff[4];                  // for sprintf()
String  txdata = "";                // transmission data packet string
String  rxdata = "";                // received data packet string
bool rxstatus = false;              // receive status flag
bool receivedFlag = false;          // flag that a packet was received
bool transmittedFlag = false;       // flag that a packet was transmitted
uint8_t receivedInterval;           // Master reveived interval [sec]
uint32_t randomNumber;              // random number to verify that data was sent correctly
uint32_t verifyNumber;              // verify number from Master
uint32_t verifyResult = 0;          // verify result 1:GOOD or 0:ERROR

// *******************************************************************************************************
void setup() {
  Serial.begin(115200);
//  while(!Serial);
  delay(2000);
 
 
  // Radio initialization
  radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);
  Serial.println("After radio Set RFSwitchTable");


  // int16_t begin(float freq = 434.0, float bw = 125.0, uint8_t sf = 9, uint8_t cr = 7, \
  // uint8_t syncWord = RADIOLIB_SX126X_SYNC_WORD_PRIVATE, int8_t power = 10, \
  // uint16_t preambleLength = 8, float tcxoVoltage = 1.6, bool useRegulatorLDO = false);
  int state = radio.begin(922.6, 125.0, 12, 5, 0x12, 13, 8, 1.7, 0);
  Serial.print("State: ");
  Serial.println(state);

  if (state == RADIOLIB_ERR_NONE) {
    Serial.println("radio.begin() success!");
  }
  else {
    Serial.print("failed, code ");
    Serial.println(state);

  }

  // callback function when received or transmitted a packet
  radio.setDio1Action(setFlag);

}

void setFlag(void) 
{
  uint16_t irqstatus = radio.getIrqStatus();
  if(irqstatus == RADIOLIB_SX126X_IRQ_RX_DONE) {
    receivedFlag = true;
  }
  else if(irqstatus == RADIOLIB_SX126X_IRQ_TX_DONE) {
    transmittedFlag = true;
  }
  else {
    receivedFlag = false;
    transmittedFlag = false;
  }
}

// ***********************************************************************************************************
void loop() 
{
  // ++++++++++++++++++++++++++++++++ Slave transmits a packet to Master ++++++++++++++++++++++++
  Serial.println("Transmitting packet ... ");

  // battery voltage measurement
  int n = 256;     // average times
  uint32_t Vadc = 0;
  for(int i = 0; i < n; i++) {
    Vadc = Vadc + analogRead(PIN_VBATT);
  }
  Vadc = Vadc / n;

  // example battery voltage map()data
  uint16_t adc_low = 1449;     // ADC data when battery voltage is low
  uint16_t vbatt_low = 3426;   // low Vbatt [mV]
  uint16_t adc_high = 1623;    // ADC data when battery voltage is high
  uint16_t vbatt_high = 4176;  // high Vbatt [mV]
  Vbatt = map(Vadc, adc_low, adc_high, vbatt_low, vbatt_high);   // Converts to battery voltage 3400 ~ 4200mV

  // Slave transmits data
  ub.Buff_u32[0] = slaveuid;                      // Slave device UID
  randomNumber = random(0x7FFFFFFF);              // for verification
  ub.Buff_u32[1] = randomNumber;
  ub.Buff_u16[4] = Vbatt;                         // battery voltage
  ub.Buff_u8[10] = verifyResult;                  // previous verify result

  uint16_t sec = millis() / 1000;                 // transmission time [sec]
  transmittedFlag = false;
  int state = radio.startTransmit(ub.Buff_u8, dataNum);

  txdata = "";
  for(int i = 0; i < dataNum; i++) {
    sprintf(printBuff, "%02x", ub.Buff_u8[i]);
    txdata += printBuff;
  }
  txdata.toUpperCase();
  Serial.println(txdata);

  Serial.print("Slave UID:\t"); Serial.println(slaveuid, HEX);  
  Serial.print("Time:\t\t"); Serial.print(sec); Serial.println(" sec");
  Serial.print("Vbatt:\t\t"); Serial.print(Vbatt); Serial.println(" mV");
  Serial.print("randomNumber:\t"); Serial.println(randomNumber, HEX);
  Serial.print("VerifyResult:\t"); Serial.println(verifyResult);

    // wait for transmittion completion
  while(!transmittedFlag) {
    delay(1);   // wait for SPI ready
  }

  // error status check
  if (state == RADIOLIB_ERR_NONE) {
    // packet was successfully sent
    Serial.println("transmission finished!");
  } 
  else {
    // some other error occurred
    Serial.print("failed, code ");
    Serial.println(state);
  }

  
}

Output (Serial monitor):

I am not using SD card

Forget about SD card and display.

  1. My environment has a PC and USB connected and use it for serial monitoring.
  2. ST-Link “reset” is not connected.

I think these are the two differences from your environment.
I think ST-Link is resetting LoRa-E5.

I disconnected the reset than tested it but program does not upload if I disconnect the reset.

  1. Are you using STM32CubeProgrammer to upload your sketches?
  2. Is your serial monitor an ArduinoIDE with USB connection?
  3. Is the ST-Link a genuine ST-Link? Is it a Chinese clone?

Without knowing the details of your setup, I am clueless.

I am using the Arduino ide with USB connection. I am attaching the image of st-link. This St-link is able to upload blink code in the module using STM32CubeIDE.

.