arduino + RF = working, but not quite

Hello,

I’m playing around with my first Arduino project, and I’ve hit a wall. I’ve spent all day Googling around for tutorials etc but can’t seem to find anything solid.

I have two arduino nanos using newsoftserial to communicate via an RF transceiver. The link works great, the problem is data matching.

What I"m trying to do is send a short string of letters/numbers to the receiving Arduino which would then do something if a matching string is received.

The receiving Arduino’s debug output is very erratic, someties it matches the two if statements, 90% of the time it does not even though in the output I can see the “sending1” and “sending2” commands. See below the code blocks for some random output.

Can someone help me out please?

Here is the Transmitting Arduino:

#include <NewSoftSerial.h>
NewSoftSerial comSerial =  NewSoftSerial(4, 5); //rx tx
void setup(){
  comSerial.begin(9600);
  Serial.begin(9600);
}
void loop() {
  comSerial.print("sending1");
  delay(1000);
  comSerial.print("sending2");
  delay(1000);
}

Here is the Receiving Arduino:

#include <NewSoftSerial.h>
NewSoftSerial comSerial =  NewSoftSerial(4, 5); //rx tx
char inData[20];
char inDataBlank[1];
char inChar=-1;
byte index = 0;
void setup(){
  comSerial.begin(9600);
  Serial.begin(9600);
  Serial.write("Power On");
}
char* getSerialData(){
  index = 0;
  if(comSerial.available() > 0) {
  while(comSerial.available() > 0) {
     if(index < 19){
      inChar = comSerial.read(); // Read a character
      inData[index] = inChar; // Store it
      index++; // Increment where to write next
      //inData[index] = '\0'; // Null terminate the string
      }
    }
    Serial.println(String(inData));
    return inData;
    } else {
      return inDataBlank;
    }
}
char Comp(char* This,char* SerialData){
  if(strcmp(SerialData,This) > 0){
    return(1);
  } else {
    return(0);
  }
}
void loop() {
  char* serialdata = getSerialData();
  if(Comp("sending1",serialdata) == 1){
    Serial.println("Motor 1 -> Online\n");
  }
  if(Comp("sending2",serialdata) == 1){
    Serial.println("Motor 1 -> Offline\n");
  }
}

This is the Serial output from the receiving Arduino:

Motor 1 -> Online

sending1
sending1
ng2ding1
sending1
sending2
Motor 1 -> Online

sending2
Motor 1 -> Online

g1nding2
sending2
Motor 1 -> Online

g2nding2

How do you know the radio link is solid?

I suggest you try to fake the receiving end with a terminal program to make sure its sending data correctly, then fake the sending program by typing the data on the terminal.

if you're sending data especially over a radio link, a checksum byte is a good idea. then the receiver can at least have some confidence that it received the data correctly.

char* getSerialData(){

Why does this function return a global variable?

      //inData[index] = '\0'; // Null terminate the string

Why is this commented out. It is most definitely needed.

You would have much better luck sending strings in packets - with a start of packet marker and an end of packet marker. When the start of packet marker arrives, initialize the array and set a flag, started, to true, and another flag, ended, to false. When additional characters arrive, that are not the end of packet marker, append them to the array, followed by the NULL terminator. When the end of packet marker arrives, set the ended flag to true. Only process data when started and ended are true. When done processing the data, set started and ended to false.

Search the forum for "started && ended" for some code.

Thanks for the comments all, while I waited for responses to this post I tried something new which actually seems to work great. The receiver misses 1 transmission once in a while (rarely) for some reason.

Can someone take a quick look and let me know if this is the best way to do this or maybe provide some tips? :slight_smile:

// ARDUINO NANO TRANSMITTER
#include <NewSoftSerial.h>
NewSoftSerial comSerial =  NewSoftSerial(4, 5); //rx tx
int counter = 0;

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

void loop() {
  char sending[6] = {0xC8,0xaf,0x32,counter,0x01,0xC8}; // don't know how to convert an int to hex unfortunately
  comSerial.print(sending); 
  delay(100);
  counter++;
  if(counter == 250) counter = 0;
}
// ARDUINO NANO RECEIVER
#include <NewSoftSerial.h>
NewSoftSerial comSerial =  NewSoftSerial(4, 5); //rx tx

void setup(){
  comSerial.begin(9600);
  Serial.begin(9600);
  Serial.println("Running");
}

void loop() {
  if(comSerial.available()) {
    int index = 0;
    byte response[6];
    while(comSerial.available() > 0 && index < 6) {
      response[index] = comSerial.read();
      index++;
    }    
    // check to make sure the response array contains the start / stop values
    if(((int)response[0] == 200) && ((int)response[5] == 200)){
        Serial.print("   Response: ");
        Serial.print(response[0], DEC);
        Serial.print(",");
        Serial.print(response[1], DEC);
        Serial.print(",");
        Serial.print(response[2], DEC);
        Serial.print(",");
        Serial.print(response[3], DEC);
        Serial.print(",");
        Serial.print(response[4], DEC);
        Serial.print(",");
        Serial.print(response[5], DEC);
        Serial.println("");
    }
  }
}
  char sending[6] = {0xC8,0xaf,0x32,counter,0x01,0xC8};
  comSerial.print(sending);

The char array passed to Serial.print() must be NULL terminated. Yours isn't. The Serial.print() function will continue printing array values beyond the end of your array, until it finds a NULL.

    if(((int)response[0] == 200) && ((int)response[5] == 200)){

You sent 0xC8, but are checking for 200. Why? Send and check the same values.

// don't know how to convert an int to hex unfortunately

The value is stored in binary. The way it is printed, hex, binary, decimal, or some other base, has no relationship to how the value is stored in memory. What is it you think you need to convert to hex?

If 5 out of the 6 bytes you are sending are constant, why do you need to send them?

Hello Paul,

How do I null terminate this char array?

char sending[6] = {0xC8,0xaf,0x32,counter,0x01,0xC8};

You sent 0xC8, but are checking for 200. Why? Send and check the same values.

0xC8 is 200 in DEC so it's checking the same values

The value is stored in binary. The way it is printed, hex, binary, decimal, or some other base, has no relationship to how the value is stored in memory.

I'm not sure why I'm even bothering to transmit in hex values, should all be integers right? That would make a heck of a lot more sense I think.

If 5 out of the 6 bytes you are sending are constant, why do you need to send them?

I'm just testing out the tx / rx, these bytes are going to be dynamically generated.

Thanks for your help!

How do I null terminate this char array?

char sending[6] = {0xC8,0xaf,0x32,counter,0x01,0xC8};

Like so:

char sending[7] = {0xC8,0xaf,0x32,counter,0x01,0xC8, 0x00};

0xC8 is 200 in DEC so it's checking the same values

But, for readability, you should be using 0xC8 on both sides, or 200 on both sides.

I'm not sure why I'm even bothering to transmit in hex values, should all be integers right?

Hex values ARE integers. So are binary values, octal values, and decimal values. I think that what you mean is that the values should all be decimal. If that is the case, the answer is the infamous "it depends". There are cases where a hex value makes more sense than a decimal value. I don't think that holds true, here, though.

Awesome, thanks paul!