'Arduino RFM9x LoRa only communicates one direction

I've having trouble getting two-way communication with the basic LoRA TX-RX example on Adafruit's website: https://learn.adafruit.com/adafruit-rfm69hcw-and-rfm96-rfm95-rfm98-lora-packet-padio-breakouts/rfm9x-test

My end goal is to be able to use a generic Mega2560 board with an Adafruit RFM9x LoRa breakout as a "control hub" to take readings off 3-5 remote locations (max 500m away, but generally much less, on rolling farmland with quite a bit of foliage). These remote locations would ideally be a combination of Mega2560's with LoRa breakouts (like the control hub) but also some Adafruit Feather M0's.

My current situation is that I can only get one way communication with Adafruit's basic sketch ("And hello back to you" never arrives back at the transmitter). I've got one Mega2560 + breakout and two Feather M0's currently (all RFM9x), just to get a basic working model. I've read that having different processors can cause timing issues, so I've tried the basic sketch between the Feather's, as well as between one Feather and the 2560 (with both the Feather and 2560 acting as the transmitter/"hub"). The only combination that does give me two way communication in all of that is with a Feather acting as the transmitter, and the 2560 acting as the receiver. So it kind of works? But not ideal.

I want to say it's a hardware issue but I've also tried Sandeep Mistry's LoRa library and his node-gateway example and it works with the 2560 and the Feather in both roles (node and gateway). I may return to that but I'd like to learn how to use the Radiohead library. I did wonder if the RHGenericDriver library should be loaded since I'd guess rf95.waitAvailableTimeout() is the point of failure and isn't referenced in the RH_RF95 library but including it didn't help.

  Serial.println("Waiting for reply..."); delay(10);
  
  if (rf95.waitAvailableTimeout(1000))
  
  { 
    // Should be a reply message for us now   
    if (rf95.recv(buf, &len))
   {

New to all this, be gentle if it's something obvious!

Here's the code I'm currently running on my Mega2560 and Feather M0, which is my ideal setup.

Code for the Mega2560 in TX:

// LoRa 9x_TX
// -*- mode: C++ -*-
// Example sketch showing how to create a simple messaging client (transmitter)
// with the RH_RF95 class. RH_RF95 class does not provide for addressing or
// reliability, so you should only use RH_RF95 if you do not need the higher
// level messaging abilities.
// It is designed to work with the other example LoRa9x_RX

#include <SPI.h>
#include <RH_RF95.h>
//#include <RHGenericDriver.h>
//#include <RHSPIDriver.h>

#define RFM95_CS 6
#define RFM95_RST 7
#define RFM95_INT 2

// Change to 434.0 or other frequency, must match RX's freq!
#define RF95_FREQ 915.0

// Singleton instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);

// Blinky on receipt
#define LED 13

void setup() 
{
  pinMode(RFM95_RST, OUTPUT);
  digitalWrite(RFM95_RST, HIGH);

  while (!Serial);
  Serial.begin(9600);
  delay(100);

  Serial.println("Arduino LoRa TX Test!");

  // manual reset
  digitalWrite(RFM95_RST, LOW);
  delay(10);
  digitalWrite(RFM95_RST, HIGH);
  delay(10);

  while (!rf95.init()) {
    Serial.println("LoRa radio init failed");
    while (1);
  }
  Serial.println("LoRa radio init OK!");

  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
  if (!rf95.setFrequency(RF95_FREQ)) {
    Serial.println("setFrequency failed");
    while (1);
  }
  Serial.print("Set Freq to: "); Serial.println(RF95_FREQ);
  
  // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on

  // The default transmitter power is 13dBm, using PA_BOOST.
  // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then 
  // you can set transmitter powers from 5 to 23 dBm:
 // rf95.setTxPower(13, true);
  //rf95.setPayloadCRC(true);
}

int16_t packetnum = 0;  // packet counter, we increment per xmission

void loop()
{
  Serial.println("Sending to rf95_server");
  // Send a message to rf95_server
  
  char radiopacket[20] = "Hello World #      ";
  itoa(packetnum++, radiopacket+13, 10);
  Serial.print("Sending "); Serial.println(radiopacket);
  radiopacket[19] = 0;
  
  Serial.println("Sending..."); delay(10);
  rf95.send((uint8_t *)radiopacket, 20);

  Serial.println("Waiting for packet to complete..."); delay(10);
  rf95.waitPacketSent();
  // Now wait for a reply
  uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
  uint8_t len = sizeof(buf);

  Serial.println("Waiting for reply..."); delay(10);
  
  if (rf95.waitAvailableTimeout(1000))
  
  { 
    // Should be a reply message for us now   
    if (rf95.recv(buf, &len))
   {
      Serial.print("Got reply: ");
      Serial.println((char*)buf);
      Serial.print("RSSI: ");
      Serial.println(rf95.lastRssi(), DEC);    
    }
    else
    {
      Serial.println("Receive failed");
    }
  }
  else
  {
    Serial.println("No reply, is there a listener around?");
  }

  delay(1000);
}

Code for the Feather M0 in RX:

// Arduino9x_RX
// -*- mode: C++ -*-
// Example sketch showing how to create a simple messaging client (receiver)
// with the RH_RF95 class. RH_RF95 class does not provide for addressing or
// reliability, so you should only use RH_RF95 if you do not need the higher
// level messaging abilities.
// It is designed to work with the other example Arduino9x_TX

#include <SPI.h>
#include <RH_RF95.h>
//#include <RHGenericDriver.h>
//#include <RHSPIDriver.h>

#define RFM95_CS 8
#define RFM95_RST 4
#define RFM95_INT 3

// Change to 434.0 or other frequency, must match RX's freq!
#define RF95_FREQ 915.0

// Singleton instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);

// Blinky on receipt
#define LED 13

void setup() 
{
  pinMode(LED, OUTPUT);     
  pinMode(RFM95_RST, OUTPUT);
  digitalWrite(RFM95_RST, HIGH);

  while (!Serial);
  Serial.begin(9600);
  delay(100);

  Serial.println("Arduino LoRa RX Test!");
  
  // manual reset
  digitalWrite(RFM95_RST, LOW);
  delay(10);
  digitalWrite(RFM95_RST, HIGH);
  delay(10);

  while (!rf95.init()) {
    Serial.println("LoRa radio init failed");
    while (1);
  }
  Serial.println("LoRa radio init OK!");

  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
  if (!rf95.setFrequency(RF95_FREQ)) {
    Serial.println("setFrequency failed");
    while (1);
  }
  Serial.print("Set Freq to: "); Serial.println(RF95_FREQ);

  // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on

  // The default transmitter power is 13dBm, using PA_BOOST.
  // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then 
  // you can set transmitter powers from 5 to 23 dBm:
 // rf95.setTxPower(13, true);
}

void loop()
{
  if (rf95.available())
  {
    // Should be a message for us now   
    uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
    uint8_t len = sizeof(buf);
    
    if (rf95.recv(buf, &len))
    {
      digitalWrite(LED, HIGH);
      RH_RF95::printBuffer("Received: ", buf, len);
      Serial.print("Got: ");
      Serial.println((char*)buf);
       Serial.print("RSSI: ");
      Serial.println(rf95.lastRssi(), DEC);
      
      // Send a reply
      uint8_t message[] = "And hello back to you";
      rf95.send(message, sizeof(message));
      rf95.waitPacketSent();
      Serial.print("Sent a reply of: ");
      Serial.println((char*)message);
      digitalWrite(LED, LOW);
    }
    else
    {
      Serial.println("Receive failed");
    }
  }
}


Solution 1:[1]

I had an issue where two RFM69HCW units set to low bit rates would only communicate in one direction. (Note that the communicated fine in both directions if using higher bit-rates.)

I traced this to a slight difference in the Crystal frequency (by measuring its CW carrier with an SDR).

HOWEVER, on changing the set frequency of one of the units slightly so they matched, the communication direction reversed, but was still only in one direction.

To fix this, I had to adjust the frequency of one unit down before transmit, and then back up again before receive.

I am not sure why this should be the case, as one would have though the Tx and Rx sections used the same frequency reference. But doing the above allowed me reliable connection in both directions at 200bps (433MHz).

Might be worth trying?

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1