I have two Feather M0s with the RFM95 LoRa radio. I want my Feather to relay serial inputs to radio and vice versa.
However the receiving end never gets a message. Printing the message doesn't print anything, and strlen gives 0.
I've tried adding null terminators and changing the size of the message to send. I've also traced the functions by printing out the variables and nothing seems to be wrong there.
So I think the bug might have to do with how I'm using the RF95 library or how I'm storing the strings. I'm typecasting between char and uint8_t.
Here's some compilable code with the bug in it:
#include <RH_RF95.h>
#include <stdlib.h>
#define CHIPSELECTPIN 8
#define RESETPIN 4
#define INTPIN 3
#define RF95_FREQ 915
RH_RF95 rf95(CHIPSELECTPIN, INTPIN);
uint8_t* p_received_message;
void setup() {
Serial.begin(115200);
pinMode(RESETPIN, OUTPUT);
// Reset LoRa chip
digitalWrite(RESETPIN, LOW);
delay(10);
digitalWrite(RESETPIN, HIGH);
delay(10);
// Initialise LoRa chip
rf95.init();
rf95.setFrequency(RF95_FREQ);
rf95.setTxPower(23, false);
}
void loop() {
handleRadio();
handleSerial();
}
void handleRadio() {
if (rf95.waitAvailableTimeout(100)) {
uint8_t received_message_length;
p_received_message = (uint8_t*) calloc(101, sizeof(char));
if (rf95.recv(p_received_message, &received_message_length)) {
Serial.print("Received radio message:");
Serial.println((char*) p_received_message);
Serial.write(p_received_message, strlen((char*) p_received_message));
}
free(p_received_message);
}
}
void handleSerial() {
if (Serial.available()) {
p_received_message = (uint8_t*) calloc(101, sizeof(char));
Serial.readBytesUntil('\0', p_received_message, 100);
Serial.print("Received serial message:");
Serial.println((char*) p_received_message);
rf95.send(p_received_message, strlen((char*) p_received_message) * sizeof(uint8_t));
rf95.waitPacketSent();
free(p_received_message);
}
}
Thanks!
rf95.waitAvailableTimeout(100)
i guess this statement returns a 0 when there is no data. I also guess it returns a -1 if it finished waiting. And -1 is evaluated to TRUE.
Serial.readBytesUntil('\0', p_received_message, 100);
I am not sure if readBytesUntil() place a final '\0' in your buffer. But I think it does not.
There is no reason to use dynamic memory in your code since you allocate a fixed number of memory anyway (101)
I took your suggestions and changed the following:
I changed the dynamic memory to fixed size buffers and I'm calling memset to reset them.
I'm also now manually adding null terminators on both the radio and serial reads.
Still getting the same issue though.
Code now looks like this:
#include <RH_RF95.h>
#include <stdlib.h>
#define CHIPSELECTPIN 8
#define RESETPIN 4
#define INTPIN 3
#define RF95_FREQ 915
RH_RF95 rf95(CHIPSELECTPIN, INTPIN);
uint8_t p_received_message[101];
void setup() {
Serial.begin(115200);
pinMode(RESETPIN, OUTPUT);
// Reset LoRa chip
digitalWrite(RESETPIN, LOW);
delay(10);
digitalWrite(RESETPIN, HIGH);
delay(10);
// Initialise LoRa chip
rf95.init();
rf95.setFrequency(RF95_FREQ);
rf95.setTxPower(23, false);
}
void loop() {
handleRadio();
handleSerial();
}
void handleRadio() {
if (rf95.waitAvailableTimeout(100)) {
uint8_t received_message_length;
memset(p_received_message, 0, 101);
if (rf95.recv(p_received_message, &received_message_length)) {
p_received_message[received_message_length + 1] = '\0';
Serial.print("Received radio message:");
Serial.println((char*) p_received_message);
Serial.write(p_received_message, strlen((char*) p_received_message));
}
}
}
void handleSerial() {
if (Serial.available()) {
memset(p_received_message, 0, 101);
int length = Serial.readBytesUntil('\0', p_received_message, 100);
p_received_message[length + 1] = '\0';
Serial.print("Received serial message:");
Serial.println((char*) p_received_message);
rf95.send(p_received_message, strlen((char*) p_received_message) * sizeof(uint8_t));
rf95.waitPacketSent();
}
}
The code seems fine to me. I suggest now you should strip down to the basic. Just send a single char and receive it to make sure you do not have the circuit problem.
arduino_new:
The code seems fine to me. I suggest now you should strip down to the basic. Just send a single char and receive it to make sure you do not have the circuit problem.
Or, perhaps try the example programs that come with the library.
The library's example code sends a fixed string. I updated my code to:
uint8_t temp[] = "test";
rf95.send(temp, strlen((char*) temp) * sizeof(uint8_t));
That still sent nothing.
I then tried sending a single character:
uint8_t temp = 'a';
rf95.send(&temp, strlen((char*) &temp) * sizeof(uint8_t));
That worked perfectly.
I thought that maybe the send function can only send one character at a time, but the example code has it sending entire strings at once.
I'm gonna keep messing with with the example code.
gxavier38:
I then tried sending a single character:
uint8_t temp = 'a';
rf95.send(&temp, strlen((char*) &temp) * sizeof(uint8_t));
That worked perfectly.
I'm surprised since the strlen() function requires as input a null terminated cstring and you provide a pointer to a single character without any guarantee that the next byte in memory is a null !
stowite:
I'm surprised since the strlen() function requires as input a null terminated cstring and you provide a pointer to a single character without any guarantee that the next byte in memory is a null !
Do you think strlen could have something to do with it?
There was one time a few months ago where it would send text but wouldn't send the full thing. So it could be related to the length.
For this code though I did try hardcoding a value like 2000 in, but it still sent nothing.