RX Data from "(char)LoRa.read()" doesn't match the sent data from the TX

Hi! I have 2 LoRa Sx1278 Ra-02 modules, one working as a TX, and one as a RX. The TX sends an integer code like 1653401, but when reading it on the RX I receive something else, I think this has to do with the "char" form LoRa.read()? How to fix this, so I can receive the sent code?

TX:

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

EasyButton Button(3);

int code = 1653401;

void setup() {
  
  pinMode(13, OUTPUT);
  pinMode(3, INPUT_PULLUP);

  Button.begin();

  Button.onPressed(Radio);

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

  Serial.println("LoRa Sender");

  if (!LoRa.begin(433E6)) {
    Serial.println("Starting LoRa failed!");
    
    digitalWrite(13, HIGH);
    
    while (1);}
  
  LoRa.setTxPower(10);

}

void Radio() {

    LoRa.beginPacket();
    LoRa.print(code);
    LoRa.endPacket();
    delay(1000);

}

void loop() {

  Button.read();

}

RX:

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

int code;

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

  Serial.println("LoRa Receiver");

  if (!LoRa.begin(433E6)) {
    Serial.println("Starting LoRa failed!");
    digitalWrite(9, HIGH);
    while (1);}
}

void loop() {
 
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    
    while (LoRa.available()) {
      
      code = (char)LoRa.read();
      
      if(1653401 == code) {
        
        Serial.print("Correct");
        digitalWrite(9, HIGH);}
    
    }
  }
}

which arduino are you using (8 bit or 32 bit platform) ?

reason I ask is that this does not fit on an int for a 8 bit platform


you only read one byte at a time and don't build up the string, so there is no chance you get 1653401...

you'll get the ASCII code for '1' then '6' then '5' ...

Uh...I don't know if it's an 8bit or 32bit, I use 2 Arduino Pro Mini 3.3v boards

it's 8 bit. The max value you can represent on an int is 32767
use a long if you want to represent 1653401

the other issue remains. You need to receive the message fully and it will be ASCII text - not a value, add a trailing null char to the receiving array to build a cString and convert this text into a long (strtol() can do that). Then you can compare the value.

How would I be doing that? I mean convert the received message? I didn't understand....

you send the text "1653401"
on the receiver side each read() call will get you one byte. So the first read is the initial '1' then '6' then '5' etc...

you need a small buffer that you fill in with the incoming bytes

try this for the receiver (and change the type of code to be long instead of int in the sender)

void loop() {
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    char buffer[packetSize + 1]; // +1 for the trailing null char
    for (int i = 0; i < packetSize; i++) buffer[i] = (char)LoRa.read();
    buffer[packetSize] = '\0';
    Serial.print("the message was: "); 
    Serial.println(buffer);
  }
}

an alternative to transmitting text is to use binary
for example, have a look at need-advice-on-a-home-project

yes - it opens another can of worms (like endianness, padding in structures, variable types format across platforms, ...) but can be explored for sure.

1 Like

Well, what you gave me it's working, but I can't get it to work for my needs, so to summerize what I want to do, the TX sends a code, the RX will activate a servo only if it verified that the message from the TX matches so it wouldn't go crazy over other interference and only listen to the TX commands.
Something like:

if(code == buffer) {Servo.write(90);}

Where the code will be initializated with what value you want

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

long code = 1469543;

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

  Serial.println("LoRa Receiver");

  if (!LoRa.begin(433E6)) {
    Serial.println("Starting LoRa failed!");
    digitalWrite(9, HIGH);
    while (1);}
}

void loop() {
 
  int packetSize = LoRa.parsePacket();
  
  if (packetSize) {
   
    char buffer[packetSize + 1]; // +1 for the trailing null char
    
    for (int i = 0; i < packetSize; i++) buffer[i] = (char)LoRa.read();
    
    buffer[packetSize] = '\0';
    
    Serial.print("the message was: "); 
    
    Serial.println(buffer);
    Serial.print(code);
    if(code == buffer) {Serial.print("Correct");}
  }
}

This is what I want to achieve but it never prints "Correct" even if they are equal.....

Code is a number and the buffer contains a text - they can’t be compared

As I wrote you need to first convert the text into a number and only then you can perform the == comparison.

Look at the strtol() function for transforming the buffer into a long value.

Check it out
https://cplusplus.com/reference/cstdlib/strtol/

long value = strtol(buffer, nullptr, 10);

Then you can use value which is a long for the comparison

PS: here there is no error checking so it assumes that you did receive a number

Now it works, thank you! Is there a way that I can directly convert the message to long?

is the line by @J-M-L

not a "direct" conversion from string to long ?

Be honest - did you understand the message #6?

I've never used it but I think there is a LoRa.readString() function, so may be something like this could work

const long code = 1469543;

...

void loop() {
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    long value = LoRa.readString().toInt(); 
    if (code  == value) {Serial.print("Correct");}
  }
}

Kinda....but not really...

Would all this "decoding" to say, all this converting from char to long, going to affect the range or the accuracy of the LoRa modules?

Wont affect the range.

Not sure what you mean by accuracy ?

The integrity of the data, packet loss, interference....?

The decoding does not interfere with the radio….
It’s needed if you send text and want to transform the text into numbers

Ok thank you!