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

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.

.

  1. What happens if you use “STM32CubeProgrammer” instead of STM32CubeIDE to upload sketches?
  2. Is there an operation in the STM32CubeIDE to start running the sketch after uploading it? Are there any breakpoints set?
  3. Are you familiar with the operation of STM32CubeIDE?
  1. I tried to upload the program using STM32CubeProgrammer but, it is displaying the same output.
  2. No if we upload program, it start automatically.
  1. I tried to upload the program using STM32CubeProgrammer but, it is displaying the same output.
  1. Has “reset” been removed?
  2. Is the STM32CubeIDE closed?
  3. ST-Link VCC is not connected anywhere?
  4. What happens if you disconnect the ST-Link after uploading and run it with only the USB connected?
  1. No, if I remove the reset button, it does not connect with Stm32Cubeprogrammer.
  2. yes, Stm32cubeide was closed.
  3. No, ST-Link VCC is not connected anywhere.
  4. The output is same(After radio Set RFSwitchTable).
  1. No, if I remove the reset button, it does not connect with Stm32Cubeprogrammer.

My ST-Link can upload without connecting a reset. Press the reset button on LoRa-E5 to connect.
Is “LoRa-E5-HF ” printed on the front of your LoRa-E5 mini package?

I don’t have the actual item in front of me, so I don’t know any more about it. Sorry I can’t help you.
Maybe someone else reading this thread can help.

I am wondering what would happen if you use the same ST-Link that I am using.
LoRa-E5 mini may actually have the firmware rewritten according to the laws of your area of use.

Yes “LoRa-E5-HF” is printed on my LoRa module.

I have a feeling that there is a problem with your use of ST-Link. There is something you have not tried yet, but this is a risk. Please read your ST-Link manual carefully before doing so.

  1. If TVCC is a function to supply power to the target device, then the LoRa-E5 is already powered by the USB connector and should not be connected.
  2. If the function is to detect the target supply voltage, then TVCC should be connected to 3.3V pin on LoRa-E5.

edit:
TVCC means TargetVCC, and I see many articles that say it won’t work unless it is connected. However, I am not sure if your ST-Link is the same.

Hello,
I tried the example of transmit data from Radio library. And it is working fine. But when i am using the receiving code, it stuck in the radio.begin() .

Code for receiving data

/*
   RadioLib STM32WLx 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
   
   This example assumes Nucleo WL55JC1 is used. For other Nucleo boards
   or standalone STM32WL, some configuration such as TCXO voltage and
   RF switch control may have to be adjusted.

   For default module settings, see the wiki page
   https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem

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

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

// no need to configure pins, signals are routed to the radio internally
STM32WLx radio = new STM32WLx_Module();

// set RF switch configuration for Nucleo WL55JC1
// NOTE: other boards may be different!
//       Some boards may not have either LP or HP.
//       For those, do not set the LP/HP entry in the table.
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_LP, {HIGH, HIGH, HIGH}},
  {STM32WLx::MODE_TX_HP, {LOW,  HIGH}},
  END_OF_MODE_TABLE,
};

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

  // set RF switch control configuration
  // this has to be done prior to calling begin()
  radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);

  // initialize STM32WL with default settings, except frequency
  Serial.print(F("[STM32WL] Initializing ... "));
  int state = radio.begin(868.0);
  if (state == RADIOLIB_ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }

  // set appropriate TCXO voltage for Nucleo WL55JC1
  state = radio.setTCXO(1.7);
  if (state == RADIOLIB_ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }

  // set the function that will be called
  // when new packet is received
  radio.setDio1Action(setFlag);

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

  // if needed, 'listen' mode can be disabled by calling
  // any of the following methods:
  //
  // radio.standby()
  // radio.sleep()
  // radio.transmit();
  // radio.receive();
  // radio.readData();
  // radio.scanChannel();
}

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

// 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) {
  // we got a packet, set the flag
  receivedFlag = true;
}

void loop() {
  // check if the flag is set
  if(receivedFlag) {
    // reset flag
    receivedFlag = false;

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

    // you can also read received data as byte array
    /*
      byte byteArr[8];
      int numBytes = radio.getPacketLength();
      int state = radio.readData(byteArr, numBytes);
    */

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

      // print data of the packet
      Serial.print(F("[STM32WL] Data:\t\t"));
      Serial.println(str);

      // print RSSI (Received Signal Strength Indicator)
      Serial.print(F("[STM32WL] RSSI:\t\t"));
      Serial.print(radio.getRSSI());
      Serial.println(F(" dBm"));

      // print SNR (Signal-to-Noise Ratio)
      Serial.print(F("[STM32WL] SNR:\t\t"));
      Serial.print(radio.getSNR());
      Serial.println(F(" dB"));

    } else if (state == RADIOLIB_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);

    }

    // put module back to listen mode
    radio.startReceive();
  }
}

Code for transmitting data

/*
  RadioLib STM32WLx Transmit with Interrupts Example

  This example transmits LoRa packets with one second delays
  between them. Each packet contains up to 256 bytes
  of data, in the form of:
  - Arduino String
  - null-terminated char array (C-string)
  - arbitrary binary data (byte array)

  For default module settings, see the wiki page
  https://github.com/jgromes/RadioLib/wiki/Default-configuration#sx126x---lora-modem

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

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

// no need to configure pins, signals are routed to the radio internally
STM32WLx radio = new STM32WLx_Module();

// set RF switch configuration for Nucleo WL55JC1
// NOTE: other boards may be different!
//       Some boards may not have either LP or HP.
//       For those, do not set the LP/HP entry in the table.
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_LP, {HIGH, HIGH, HIGH}},
  {STM32WLx::MODE_TX_HP, {LOW,  HIGH}},
  END_OF_MODE_TABLE,
};

// save transmission state between loops
int transmissionState = RADIOLIB_ERR_NONE;

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

  // set RF switch control configuration
  // this has to be done prior to calling begin()
  radio.setRfSwitchTable(rfswitch_pins, rfswitch_table);

  // initialize STM32WL with default settings, except frequency
  Serial.print(F("[STM32WL] Initializing ... "));
  int state = radio.begin(868.0);
  if (state == RADIOLIB_ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }

  // set appropriate TCXO voltage for Nucleo WL55JC1
  state = radio.setTCXO(1.7);
  if (state == RADIOLIB_ERR_NONE) {
    Serial.println(F("success!"));
  } else {
    Serial.print(F("failed, code "));
    Serial.println(state);
    while (true);
  }

  // set the function that will be called
  // when packet transmission is finished
  radio.setDio1Action(setFlag);

  // start transmitting the first packet
  Serial.print(F("[STM32WL] Sending first packet ... "));

  // you can transmit C-string or Arduino string up to
  // 256 characters long
  transmissionState = radio.startTransmit("Hello World!");
  Serial.print("transmission: ");
  Serial.print(transmissionState);

  // you can also transmit byte array up to 256 bytes long
  /*
    byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
                      0x89, 0xAB, 0xCD, 0xEF};
    state = radio.startTransmit(byteArr, 8);
  */
}

// flag to indicate that a packet was sent
volatile bool transmittedFlag = false;

// this function is called when a complete packet
// is transmitted by the module
// IMPORTANT: this function MUST be 'void' type
//            and MUST NOT have any arguments!
void setFlag(void) {
  // we sent a packet, set the flag
  transmittedFlag = true;
}

// counter to keep track of transmitted packets
int count = 0;

void loop() {
  // check if the previous transmission finished
  if(transmittedFlag) {
    // reset flag
    transmittedFlag = false;

    if (transmissionState == RADIOLIB_ERR_NONE) {
      // packet was successfully sent
      Serial.println(F("transmission finished!"));

      // NOTE: when using interrupt-driven transmit method,
      //       it is not possible to automatically measure
      //       transmission data rate using getDataRate()

    } else {
      Serial.print(F("failed, code "));
      Serial.println(transmissionState);

    }

    // clean up after transmission is finished
    // this will ensure transmitter is disabled,
    // RF switch is powered down etc.
    radio.finishTransmit();

    // wait a second before transmitting again
    delay(1000);

    // send another one
    Serial.print(F("[STM32WL] Sending another packet ... "));

    // you can transmit C-string or Arduino string up to
    // 256 characters long
    String str = "Hello World! #" + String(count++);
    transmissionState = radio.startTransmit(str);

    // you can also transmit byte array up to 256 bytes long
    /*
      byte byteArr[] = {0x01, 0x23, 0x45, 0x67,
                        0x89, 0xAB, 0xCD, 0xEF};
      transmissionState = radio.startTransmit(byteArr, 8);
    */
  }
}