LoRa P2P Comms problem between RAK4630 and RFM9x

I have a RAK4630 communicating to another RAK4630 using LoRa P2P … everything works fine

#ifndef __LORA_RADIO_H__
#define __LORA_RADIO_H__

#ifndef LORA_SPREADING_FACTOR
    /*********
     * The larger spreading factors therefore give more range, the trade off is that higher
     * spreading factor packets take longer to transmit.
     ***************************************************************************/
    #define LORA_SPREADING_FACTOR 7             // [SF7..SF12]
    #define LORA_BANDWIDTH 0                    // [0: 125 kHz, 1: 250 kHz, 2: 500 kHz, 3: Reserved]
    /**
     * supported by the Semtech chip
     * 7.8Khz, 10.4Khz, 15.6Khz, 20.8Khz, 31.25Khz, 41.7Khz, 62.5Khz, 125Khz, 250Khz, 500Khz.
     *   A low bandwidth signal, such as 7.8Khz will give the best (longest distance) performance
     */
    #define LORA_CODINGRATE 1                   // [1: 4/5, 2: 4/6,  3: 4/7,  4: 4/8]
    #define LORA_PREAMBLE_LENGTH 8              // Same for Tx and Rx
    #define LORA_SYMBOL_TIMEOUT 0               // Symbols
    #define LORA_FIX_LENGTH_PAYLOAD_ON false
    #define LORA_IQ_INVERSION_ON false
    #define TX_OUTPUT_POWER 22  

    #define TX_TIMEOUT_VALUE 500
    #define RX_TIMEOUT_VALUE 500

#endif // !LORA_SPREADING_FACTOR


#endif // __LORA_RADIO_H__

We need to also receive comms from other units; the particular unit however in this case is a Seeeduino Xiao, connected to an Adafruit RFM9x Lora Radio breakout board.

The RFM9x uses the following simple sketch

#include <Arduino.h>
#include <SPI.h>
#include <RH_RF95.h>

#define RFM95_CS 7
#define RFM95_INT 6
#define LORA_frequency 868.3


RH_RF95 rf95(RFM95_CS, RFM95_INT);

void setup()
{
  Serial.begin(115200);
  delay(100);
  uint32_t timestamp = millis();
  while(millis() - timestamp < 2000)
    ;

  Serial.println("LoRa radio TX Test");
  while (!rf95.init())  { Serial.println("LoRa radio init failed"); delay(1000); }
  while (!rf95.setFrequency(LORA_frequency)) 
  {
    Serial.print("Setting Freq to: "); Serial.print(LORA_frequency); Serial.println(" failed"); delay(1000);
  }
  rf95.setTxPower(20);
  rf95.setPayloadCRC(false);
  rf95.setModeTx();
}

int packetnum = 0; // packet counter, we increment per xmission
void loop()
{
  char message[24] = { 0 };
  snprintf(message, 24, "Hello World # %d", packetnum++);

  Serial.printf("Sending [%u] %s on ", strlen(message), message); Serial.println(LORA_frequency); 
  rf95.send((uint8_t *)message, strlen(message));
 
  Serial.println("\tWaiting for packet to complete..."); 
  rf95.waitPacketSent(); 
  delay(1000);
}

This sketch reports sending data between the lengths of 15 and 17 (messages 0-999):

Sending [15] Hello World # 8 on 868.30
	Waiting for packet to complete...
Sending [15] Hello World # 9 on 868.30
	Waiting for packet to complete...
Sending [16] Hello World # 10 on 868.30
	Waiting for packet to complete...
Sending [16] Hello World # 11 on 868.30
	Waiting for packet to complete...
Sending [16] Hello World # 12 on 868.30
	Waiting for packet to complete...
Sending [16] Hello World # 13 on 868.30
	Waiting for packet to complete...

however upon receiving the messages, the RAK reports that the message size is between 19 and 21 respectively, and this is a log of what was received:

Waiting to receive on 868300000
::Received(868300000Hz)    [21]	[ÿÿ]
Waiting to receive on 868300000
::Received(868300000Hz)    [21]	[ÿÿ]
Waiting to receive on 868300000
::Received(868300000Hz)    [21]	[ÿÿ]
Waiting to receive on 868300000
::Received(868300000Hz)    [21]	[ÿÿ]
Waiting to receive on 868300000
::Received(868300000Hz)    [21]	[ÿÿ]
Waiting to receive on 868300000
::Received(868300000Hz)    [21]	[ÿÿ]
Waiting to receive on 868300000
::Received(868300000Hz)    [21]	[ÿÿ]
Waiting to receive on 868300000
::Received(868300000Hz)    [21]	[ÿÿ]

Surely it cannot be the case that we need to use the same LoRa transceiver at both ends? LoRa is just a radio signal, right? So any LoRa decoder listening on the same frequency should be able to decode the message, right?

Hello Bill,

I have to dig into my boxes and try to find a RF module other than SX1262 :grin: but I remember that a long time ago I tested SX1262 against an RFMxx module.

In the mean time, can you share your Radio.SetRxConfig() and the onRxDone callback of the RAK4631.

Hi @beegee ,

this is the call to Radio.SetRxConfig (values shown in the LoRa setting of the previous post.

void EnableReceiver(void)
{
  Radio.SetChannel(RECEIVE_FREQUENCY);

  Radio.SetRxConfig(MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
          LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
          LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
          0, true, 0, 0, LORA_IQ_INVERSION_ON, true);
           
  Radio.Rx(RX_TIMEOUT_VALUE);
}

And this is the event handler for onRxDoneApplicationMessage_t is pretty much a wrapper for char[] message; uint8_t size; which we use to put onto a queue for a different Task to deal with, so all we do here is construct an instance and then use that as a parameter for the event callback of our own RadioTransceiver_t class.

void RadioTransceiver_t::ReceiveCompleted(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
{
  SignalRx();
  while(size > 0 && payload[size-1]== char(0))
    size -= 1;

  uint8_t theMessage[size];
  memset(theMessage, 0, size);
  memcpy(theMessage, payload, size);

  if(_receiverEvents != NULL && _receiverEvents->OnReceived != NULL)
  {
      _receiverEvents->OnReceived(ApplicationMessage_t((char*)theMessage, size), rssi);
  }
  
#if !defined(TRANSMITTER)
#if defined(CONNECTED_FOR_DEBUG)
  Serial.printf("::Received(%iHz)    [%i]\t[%s]\n", RECEIVE_FREQUENCY, size, payload);
#endif //  defined(CONNECTED_FOR_DEBUG)
#endif // !defined(TRANSMITTER)
}

Hi Bill,

On the RFM module you set CRC off. But on the RAK4631 you set CRC to on in Radio.SetRxConfig. Try to switch off CRC on the RAK4631 as well. (However I would recommend to have CRC enabled on both sides.)

Definition of function SetRxConfig:

void (*SetRxConfig)(RadioModems_t modem, uint32_t bandwidth,
						uint32_t datarate, uint8_t coderate,
						uint32_t bandwidthAfc, uint16_t preambleLen,
						uint16_t symbTimeout, bool fixLen,
						uint8_t payloadLen,
						bool crcOn, bool freqHopOn, uint8_t hopPeriod,
						bool iqInverted, bool rxContinuous);

In ReceiveCompleted, can you (just for debugging) simply print out the payload to see what was received and how many bytes before you process the message?

Serial.printf("Received %d bytes\n", size);
for (int idx = 0; idx < size; idx++)
{
	Serial.printf("%02X ", payload[idx]);
}
Serial.println("");

I don’t know what SignalRx() is doing and I am not sure why there should be any 0x00 at the end of the payload. The payload arriving in the RX callback should be exactly the payload you send from the RFM transceiver.

ah, yes, this is the result of me sending you a code snippet whilst I’m in the middle of playing around with various settings in order to determine what is wrong in this case.

Serial.printf("::Received(%iHz)    [%i]\t[%s]\n", RECEIVE_FREQUENCY, size, payload);

isn’t this line doing exactly what you asked? -though admittedly I’m not printing out the HEX codes. I’ll put that stuff in and get back with the resultant log

This is just posting a message onto a queue which indicates that the LED needs to flash

Me neither to be honest, however when this routine was written, we found that we were getting some garbled data and this appeared to be the solution to that -and even now, I have no idea why that was the case.

Received 21 bytes
FF FF 00 00 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 23 20 32 35 33 
Copied 21 bytes
FF FF 00 00 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 23 20 32 35 33 
Received 21 bytes
FF FF 00 00 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 23 20 32 35 34 
Copied 21 bytes
FF FF 00 00 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 23 20 32 35 34 
Received 21 bytes
FF FF 00 00 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 23 20 32 35 35 
Copied 21 bytes
FF FF 00 00 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 23 20 32 35 35 
Received 21 bytes
FF FF 00 00 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 23 20 32 35 36 
Copied 21 bytes
FF FF 00 00 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 23 20 32 35 36 
Received 21 bytes
FF FF 00 00 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 23 20 32 35 37 
Copied 21 bytes
FF FF 00 00 48 65 6C 6C 6F 20 57 6F 72 6C 64 20 23 20 32 35 37 
Serial port COM5 closed

and there we have it!! It appears that the RadioHead library is inserting these four bytes FF FF 00 00 , and the snprintf is obviously terminating the string output as soon as it encounters 0x00

I think this advice right here is demonstrative of your experience vs my experience working at this lower level.

I don’t know what I’d do without you @beegee :rofl: :rofl:

1 Like

:joy:
Now that I see it, I somehow remember that RadioHead inserts some kind of node address. Maybe RadioHead has a send function that doesn’t do it.

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