LoRa Tx Rx lacks range

After a few months of experimenting I eventually found a sketch which exactly fits my Tx and Rx needs.

The following sketch worked perfectly at a 250 meter range for just 10 days and then just "Stopped".

Testing revealed that the Tx and Rx unit would work perfectly at a range of 2 meters but more distabce than that message is "send to wait failed".

Am using "Duinotech Shields" at 915 Mh with Arduino Mega.

Using "<RHReliableDatagram.h> and <RH_RF95.h>" I have tried 4 different "shields " and 4 different "Mega" in all different combinations but range is always limited to 2 Meters.

If I use "<SPI.h> and <LoRa.h>" sketch from Sanddeep, I get back my 250 meters range no problem.

I am thinking that maybe there is a file in the RadioHead .pde that may need to be changed.

Any constructive advice would be appreciated

//........................................SENDER...TX....PORT 5................................
#include <RHReliableDatagram.h>
#include <RH_RF95.h>
#include <SPI.h>

#define CLIENT_ADDRESS 1
#define SERVER_ADDRESS 2
//.................................RTC.................
#include <Wire.h>
#include <ds3231.h>
 struct ts t;
  
RH_RF95 driver;

RHReliableDatagram manager(driver, CLIENT_ADDRESS);


unsigned int senD1 = 0;
unsigned int senD2 = 0;
unsigned int senD3 = 0;



void setup()
{
  Serial.begin(9600);
//.....................................SET UP LEDs...................
for (int aaa = 22;aaa<35;aaa++){
  pinMode((aaa),OUTPUT);
  digitalWrite((aaa),LOW);
  delay(300);
  digitalWrite((aaa),HIGH);
  
  }
//............................................RTC
Wire.begin();
  DS3231_init;
 
//   t.hour=13; 
 //   t.min=19;
 //  t.sec=5;
//   t.mday=25;
//    t.mon=4;
//   t.year=2020;
//  DS3231_set(t); 

//............................................TX  
  while (!Serial) ; // Wait for serial port to be available
  if (!manager.init())
    Serial.println("init failed");
  // 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:
//  driver.setTxPower(23, false);
  // If you are using Modtronix inAir4 or inAir9,or any other module which uses the
  // transmitter RFO pins and not the PA_BOOST pins
  // then you can configure the power transmitter power for -1 to 14 dBm and with useRFO true.
  // Failure to do that will result in extremely low transmit powers.
//  driver.setTxPower(14, true);
}

uint8_t data[] = "Hello World!";
// Dont put this on the stack:
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];

struct message_t {
  int value1;
  int value2;
  int value3;
} message;




void TimE(){
   Serial.print(t.mday);
  Serial.print("/");
  Serial.print(t.mon);
  Serial.print("/");
  Serial.print(t.year);
  Serial.print("  ");
  Serial.print(t.hour);
  Serial.print(":");
  Serial.print(t.min);
  Serial.print(".");
  Serial.println(t.sec);
  }


  
void TX(){
 // Send a message to manager_server
 message.value1 = senD1;
  message.value2 = senD2;
  message.value3 = senD3;
  if (manager.sendtoWait((uint8_t *)&message, sizeof(message), SERVER_ADDRESS))
  {
    Serial.print(" Sent.......... ");Serial.print(message.value1);Serial.print(" , ");Serial.print(message.value2);Serial.print(" , ");Serial.println(message.value3);
    // Now wait for a reply from the server
    uint8_t len = sizeof(buf);
    uint8_t from;   
    if (manager.recvfromAckTimeout(buf, &len, 2000, &from))
    {
      Serial.println("Receipt Acknowledged ");
     
    }
    else
    {
      Serial.println("No reply, is rf95_reliable_datagram_server running?");
    }
  }
  else
    Serial.println("sendtoWait failed");
  delay(2000); 
  }
//........................................SENDER...TX....PORT 5................................  
void loop()
{
  //........................GET CURRENT TIME...............
 DS3231_get(&t);
 //TimE();// Only if Needed to go to screen

 //...................................STATIONS DATA ON OFF..
 delay(10000);
int HouR =(t.hour);
int MiN  =(t.min);
Serial.print("  Hour is . ");Serial.print(HouR); Serial.print("  Minute is . ");Serial.println(MiN);

  if ((HouR==14)&& (MiN==10)){
    digitalWrite(22,HIGH);
    senD1 = 22;
    senD2 =  0;
    TX();
    delay(10000);
    }

     if ((HouR==14) && (MiN==2)){
      digitalWrite(22,LOW);
    senD1 = 22;
    senD2 =  1;
    TX();
    delay(10000);
    }
  //........................................SENDER...TX....PORT 5................................
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//................................................RECEIVER.......RX.....PORT 4................................
#include <RHReliableDatagram.h>
#include <RH_RF95.h>
#include <SPI.h>
#define CLIENT_ADDRESS 1
#define SERVER_ADDRESS 2
RH_RF95 driver;
RHReliableDatagram manager(driver, SERVER_ADDRESS);
int aaa = 0;// Loop Variable
void setup()
{
  Serial.begin(9600);
  //................................................... LED SET UP ....................................
 
  //................................................. RECEIVER SETUP ................................
  while (!Serial) ; // Wait for serial port to be available
  if (!manager.init())
    Serial.println("init failed");
}

uint8_t data[] = "Acknowledged";
// Dont put this on the stack:
uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];

struct message_t {
  int value1;
  int value2;
  int value3;
} message;

//................................................RECEIVER.......RX.....PORT 4................................
void loop()
{


  if (manager.available())
  {
    uint8_t len = RH_RF95_MAX_MESSAGE_LEN;
    uint8_t from;
    if (manager.recvfromAck((uint8_t *)&message, &len, &from))
    {
      Serial.println("Received  ");

      if (!manager.sendtoWait(data, sizeof(data), from))
        Serial.println("sendtoWait failed");


      Serial.print(F("value1  "));
      Serial.println(message.value1);
      Serial.print(F("value2  "));
      Serial.println(message.value2);
      Serial.print(F("value3  "));
      Serial.println(message.value3);
      // ...............................................TURNING LED and RELAY ON and OFF .........................
      if ((message.value1 == 22) && (message.value2 == 0)) {
        digitalWrite(22, HIGH);
      }
      if ((message.value1 == 22) && (message.value2 == 1)) {
        digitalWrite(22, LOW);
      }
    }
  }
  //................................................RECEIVER.......RX.....PORT 4................................
}

Farticus:
The following sketch worked perfectly at a 250 meter range for just 10 days and then just "Stopped".

Well, its seems unlikly that the sketch magically re-configured itself to change the settings use by the LoRa device and make the range much worse.

Sounds like a hardware failure and extreme short range for LoRa is a common symptom for modules that have damadged RF outputs, usually caused by operating the device without an antenna or a faulty antenna.

For the RFM95 device, even when configured for the shortest range (highest data rate) and lowest output power the range will be several kilometres, there are no software settings that can cut the range to a couple of meters.

What frequency are your LoRa modules designed to transmit at, are you using this frequency and also have a frequency matched antenna?

I assume 915MHz from your post but the TX code you included has...

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

and I see nothing to change the frequency.
Why switch from the Sanddeep Mistry library that I personally like and use?

The units are marked 915 MHZ.

I would use Sanddeep Sketch except I have no idea how to Tx and Rx integers.

SRnet,

"Well, its seems unlikly that the sketch magically re-configured itself to change the settings use by the LoRa device and make the range much worse. ""

Why then do the "damaged" units work so perfectly with the Sandeep ketch??

It seem a real stretch that all FOUR would go out at exactly the same time.

Farticus:
The units are marked 915 MHZ.

I would use Sanddeep Sketch except I have no idea how to Tx and Rx integers.

The Sanddeep library inherits the print class so you send/receive integers the same way you would with sending them over Serial.
Either print() the integer and use parseInt() to convert back to integer.
Or use write()/read() to send bytes or buffers (like your structure).

Riva:
SRnet,

"Well, its seems unlikly that the sketch magically re-configured itself to change the settings use by the LoRa device and make the range much worse. ""

Why then do the "damaged" units work so perfectly with the Sandeep ketch??

It seem a real stretch that all FOUR would go out at exactly the same time.

Well, appologies, I did miss the;

"If I use "<SPI.h> and <LoRa.h>" sketch from Sanddeep, I get back my 250 meters range no problem"

However, its still true that a configurartion that works one minute should not suddenly stop working the next, unless the modules are faulty. So if the sketch was OK before, it should still be now.

Introducing new sketches muddies the waters somewhat, especially as both the Radionhead and Sandeeps library have their own set of defaults, all of which can affect range, so making comparisons between the effectivness\range using the two libraries is not valid unless the settings are the same.

One observation as @Riva pointed out, the Radiohead librays defaults to 434Mhz, which is not good for 915Mhz modules.

I appreciate your help guys.

In between the time I first got the instance of "reliable datagram" to work and when it failed I had a computer meltdown and lost all my files.

When I tested the units after the failure I had to download a set of new libraries which I am now using.

I was wondering if perhaps I had changed some setting in the orininal .pde file which caused the instance to work but have not changed anything in the recently downloaded .pde files.

I do not know enough to be able to tell if any parameters can be changed in the .pde file.(like MHZ or something else)

I notice the comment:

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

and that would seem to indicate that the .pde can be modified to the correct " 915 MHZ", is this a possibility?

Farticus:
I notice the comment:

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

and that would seem to indicate that the .pde can be modified to the correct " 915 MHZ", is this a possibility?

Yes, the details on how to do that are in the program files for the library, RH_RF95.h in this case.

Farticus:
I was wondering if perhaps I had changed some setting in the orininal .pde file which caused the instance to work but have not changed anything in the recently downloaded .pde files.

I notice the comment:

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

and that would seem to indicate that the .pde can be modified to the correct " 915 MHZ", is this a possibility?

I would stop using the code until the TX frequency is corrected as this will maybe damage the LoRa module if the antenna is not matched to the frequency it transmits on.

Looking at the RadioHead library I see...

   /// Sets the transmitter and receiver 
    /// centre frequency.
    /// \param[in] centre Frequency in MHz. 137.0 to 1020.0. Caution: RFM95/96/97/98 comes in several
    /// different frequency ranges, and setting a frequency outside that range of your radio will probably not work
    /// \return true if the selected frquency centre is within range
    bool        setFrequency(float centre);

So you look like you need a manager.setFrequency(915.0); just after the manager.init();

Riva is it possible you can give me some more information on how to use "parseInt" in the RX sketch.

Farticus:
Riva is it possible you can give me some more information on how to use "parseInt" in the RX sketch.

I linked to the parseInt reference page in #4 and again here and that is the best place to start.

A better option might be to define in detail exactly what data you wish to send & receive.

Thanks Riva.

I followed up on the link regarding "parseInt" and I do not fully understand it's implimentation.Tried to use it but I am sure my coding was wrong.

I want to be able to Tx 3 seperate integers.

First: An integer between 1 and 100.
Second: An integer either 0 or 1.
Third: An integer between 1 and 1440.

Upon receipt of the signal at the RX unit a relay would be turned on or off for so many minutes.

eg. 35, 0, 360 Would turn on relay 35 for 360 minutes.
35, 1 Would turn the relay off.

This is why I need to convert the incoming message to Integers.

The program in its existing format worked flawlessly with the RadioHead Library until all of a sudden the
lack of range reared its ugly head.

I would prefer to use the Sanddeep library if I could understand how to convet the Rx side to Integers

As mentioned, the Sanddeep library inherits from the Print class (technically from Stream which inherits from Print). So, one obvious solution would be to use the techniques of @Robin2's Serial Tutorial.

However, for a packet-based format like LoRa, I'd personally pack the data into a struct and send it in binary. I've never had a problem with RadioHead, but there's no reason you couldn't do the same thing with Sanddeep.

Tx Gfvalvo. Read Tutorials as suggested but cannot find any help as it seem to primarily deal with "Serial".

I liked the Radiohead reliable datagram library but unable to solve the range issue.

I dont have that problem with the Sanddeep library.

Problem is RadioHead Tx's as an integer and receives as a Integer automatically.

It would help greatly if someone would just show me how to modify the Rx code in Sanddeep to convert

the received results to an integer.

Farticus:
It would help greatly if someone would just show me how to modify the Rx code in Sanddeep to convert
the received results to an integer.

Sounds simple, but to be fair if someone is posting a 'solution' it really ought to be an example that has actually been tested. So you need to load up the library and write and test examples for both transmitter and receiver.

Unfortnatly a lot of libraries miss out on practical examples of stuff.

Farticus:
The program in its existing format worked flawlessly with the RadioHead Library until all of a sudden the
lack of range reared its ugly head.

I would prefer to use the Sanddeep library if I could understand how to convet the Rx side to Integers

Why reinvent the wheel when you know you had a working program/library.

Did you try inserting manager.setFrequency(915.0); just after the manager.init(); in your (originally) working code to see if it sets the correct frequency to improve the range.

Farticus:
I would prefer to use the Sanddeep library if I could understand how to convet the Rx side to Integers

You might want to check out this library;

There are three different methods shown on how to send and receive data with the SX126X, SX127X and SX128X devices.

There are the standard examples for TX & RX on how to send simple buffers, that you can use to fill with what you want.

Then TX and RX examples on how to send structures that contain a mixture of character buffers and different integer types and floats.

There is also a series of RX and TX examples that show how to write and read different integers types, floats and character buffers direct into and from the LoRa device, no memory buffer needed.

Farticus:
Tx Gfvalvo. Read Tutorials as suggested but cannot find any help as it seem to primarily deal with "Serial".

Of course, that's why I suggested it. All "Serial" class objects eventually inherit from Stream. The LoRaClass class from the sandeep library also inherits from Stream. So, all the techniques from the Tutorial should be applicable.

That's why these classes are written the way they are, to take advantage of OOP in inheritance. You should take some time to learn about it.

Another option is to use the Serial Transfer Library with sandeep. That library takes a reference to a Stream object --- OOP inheritance again. Are you sensing a theme here?

But first, try @Riva's suggestion to fix your problem with RadioHead.

This Sandeep Library is the only one I can now get to work over any practical distance.

This is my attempt to transmit the 3 seperate integers.

On the RX side they seem to be received as "char" and I am at a loss to understand how I can convert

them back to an Integer.

Could you please show me how to do that?

#include <SPI.h>
#include <LoRa.h>

int staT = 23;
int onofF = 0;

unsigned long  timE = 720;

void setup() {
  Serial.begin(9600);
  pinMode(7, OUTPUT);
  digitalWrite(7, LOW);
  while (!Serial);

  Serial.println("LoRa Sender");

  if (!LoRa.begin(915E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
}

void loop() {
  Serial.println("Sending packet: ");
  Serial.println(staT);
  Serial.println(onofF);
  Serial.println(timE);
  digitalWrite(7, HIGH);
  delay(500);

  // send packet
  LoRa.beginPacket();
  //LoRa.print("hello ");
  LoRa.print(staT);
  LoRa.print(onofF);
  LoRa.print(timE);
  LoRa.endPacket();
  digitalWrite(7, LOW);




  delay(2000);
}
#include <SPI.h>
#include <LoRa.h>

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

  pinMode(7, OUTPUT);
  digitalWrite(7, LOW);
  while (!Serial);

  Serial.println("LoRa Receiver");

  if (!LoRa.begin(915E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
}

void loop() {
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packet
    Serial.println("Received packet '");

    // read packet
    while (LoRa.available()) {
      Serial.println((char)LoRa.read());

    }

    // print RSSI of packet
    //Serial.print("' with RSSI ");
    //Serial.println(LoRa.packetRssi());
    digitalWrite(7, HIGH);
    delay (1000);
    digitalWrite(7, LOW);
  }
}

I do not have enough spare LoRa modules to check the code properly by as LoRa library inherits the print/stream class from Serial I tested using Serial and the below code seems to work okay.

Send

#include <SPI.h>
#include <LoRa.h>

int staT = 23;
int onofF = 0;
unsigned long  timE = 720;

void setup() {
  Serial.begin(115200);
  pinMode(7, OUTPUT);
  digitalWrite(7, LOW);
  while (!Serial);

  Serial.println("LoRa Sender");

  if (!LoRa.begin(915E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
}

void loop() {
  Serial.println("Sending packet: ");
  Serial.println(staT);
  Serial.println(onofF);
  Serial.println(timE);
  
  digitalWrite(7, HIGH);
  delay(500);

  // send packets
  LoRa.beginPacket();
  LoRa.print("T");
  LoRa.print(staT);
  LoRa.print("F");
  LoRa.print(onofF);
  LoRa.print("E");
  LoRa.print(timE);
  LoRa.endPacket();
  delay(100);
  
  digitalWrite(7, LOW);

  delay(2000);
}

}

Receive

#include <SPI.h>
#include <LoRa.h>

int staT = -1;
int onofF = -1;
unsigned long  timE = 11111111;

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

  pinMode(7, OUTPUT);
  digitalWrite(7, LOW);
  while (!Serial);

  Serial.println("LoRa Receiver");

  if (!LoRa.begin(915E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
}

void loop() {
  if(LoRa.parsePacket())
  // if(Serial.available())
  {
    delay(100);
    while(LoRa.available())
    // while(Serial.available())
    {
      char variable = LoRa.read(); // Read first char
      // char variable = Serial.read(); // Read first char
      
      switch(variable)
      {
        case 'T':
        staT = LoRa.parseInt();
        // staT = Serial.parseInt();
        break;
        
        case 'F':
        onofF = LoRa.parseInt();
        // onofF = Serial.parseInt();
        break;
        
        case 'E':
        timE = LoRa.parseInt();
        // timE = Serial.parseInt();
        break;
        
        default:
        Serial.println("Unknown Variable");
      }
    }
      
    Serial.print("T");
    Serial.print(" ");
    Serial.println(staT);
    Serial.print("F");
    Serial.print(" ");
    Serial.println(onofF);
    Serial.print("E");
    Serial.print(" ");
    Serial.println(timE);
    
    digitalWrite(7, HIGH);
    delay (1000);
    digitalWrite(7, LOW);
  }
}