Need help with rf95 LoRa module

Hello,

I am currently trying to use two LoRa modules to operate an emergency cutdown procedure for a weather balloon. I have gotten the basic examples in Radioheads libraries running shown below to transmit “Hello World” and “And hello back to you” back and forth.

My issue comes when I try to obtain the message that was sent and use it to decide if cutdown is needed on the receive side. Something along the lines of “if the transmitted value is equal to 1234 then cutdown”. I am very new to coding and even more new to radio communications and packet transmission, so I am sorry for any blatant issues. Cutdown procedures have already been created and just rely upon tripping a relay by outputting from an arduino pin, so no help should be needed for that.

I do not understand how to obtain the data that was transmitted and use it in later parts of the program. In all of the examples I’ve found online on forums all that was done was printing to the serial monitor, as far as I can tell. Assistance in storing the transmitted data in a new variable and using it to compare it with a different predetermined string would be amazing.

Sorry for any poor formatting in advance, I will attempt to fix it if there is a problem I am made aware of.

Transmission code

// Feather9x_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 Feather9x_RX

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

#define RFM95_INT   3
#define RFM95_CS    4
#define RFM95_RST   2


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

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

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

  Serial.begin(115200);
  while (!Serial) {
    delay(1);
  }

  delay(100);

  Serial.println("Feather 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(23, false);
}

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

void loop()
{
  delay(1000); // Wait 1 second between transmits, could also 'sleep' here!
  Serial.println("Transmitting..."); // 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...");
  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?");
  }

}

Receiving Code

// Feather9x_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 Feather9x_TX

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

#define RFM95_INT   3
#define RFM95_CS    4
#define RFM95_RST   2

// Change to 434.0 or other frequency, must match RX's freq!
#define RF95_FREQ 434.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);

  Serial.begin(115200);
  while (!Serial) {
    delay(1);
  }
  delay(100);

  Serial.println("Feather 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(23, false);
}

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 data[] = "And hello back to you";
      rf95.send(data, sizeof(data));
      rf95.waitPacketSent();
      Serial.println("Sent a reply");
      digitalWrite(LED, LOW);
    }
    else
    {
      Serial.println("Receive failed");
    }
  }
}
  itoa(packetnum++, radiopacket+13, 10);
  Serial.print("Sending "); Serial.println(radiopacket);
  radiopacket[19] = 0;

The NULL is generally type as '\0', not 0. The itoa() function already added a NULL, which is a good thing, because otherwise you would have passed a non-NULL terminated array to a function that expected a string. So, putting a NULL in position 19 is unnecessary.

  rf95.send((uint8_t *)radiopacket, 20);

The correct length is strlen(radiopacket)+1 (to include the NULL terminator), not 20.

Something along the lines of "if the transmitted value is equal to 1234 then cutdown"

Since you are sending "Hello World #1", "Hello World #2", "Hello World #3", etc, the transmitted value will never equal 1234.

You should start by making the transmitter send something meaningful, like "Cutdown". Then, you could use strcmp() to see if you got "Cutdown".

Hi Paul,

Thank you for the help. I have figured out how to transmit "Cutdown" by itself, but my issue now has been getting to a point where I can compare the sent transmission to a different predetermined string that says "Cutdown". I cannot figure out how to use the rf95 transmission. Do you have any ideas?

Thank you!

I cannot figure out how to use the rf95 transmission.

I don't understand this statement. In your initial post, you said that you could send data, and that you could receive data, but that you didn't know how to take action based on what you received.

You could do THAT, by adding the last 6 lines of code below, after the first 6 lines, in the receiver code.

    if (rf95.recv(buf, &len))
    {
      digitalWrite(LED, HIGH);
      RH_RF95::printBuffer("Received: ", buf, len);
      Serial.print("Got: ");
      Serial.println((char*)buf);

      if(strcmp(buf, "Cutdown") == 0)
      {
         // Got the Cutdown command
         cutdown();
      }

Paul you are a lifesaver. I don't know why I didn't understand how to do this before. I think it had to do with what was displayed in the serial monitor when I tried to display 'buf'. I did not know how, or what was stored in 'buf' until now and I could not figure out how to determine what was inside of 'buf'. Thank you for the help, it is very much appreciated.

You might need to cast buf:

if(strcmp((char *) buf, "Cutdown") == 0)

gfvalvo:
You might need to cast buf:

if(strcmp((char *) buf, "Cutdown") == 0)

Thank you for your input gfvalvo, it's working right now with the code that PaulS sent, and I altered the transmission to make sure it was working correctly, but if I run into any issues I will try your suggestion!

Turn up your compiler warnings under File-->Preferences. You'll see that it's unhappy without the cast, just not unhappy enough to puke over it.