0

I currently have 2 Arduinos both hooked up to HC-12s and have successfully got them communicating. But I am now trying to be able to process the data sent across and store it as a variable so as to make comparisons. But I'm getting junk data that comes over with the code, which prevents me from being able to do these comparisons.

For example, from one arduino when I sent "stop" I received

stop<⸮=l⸮⸮⸮

I cant figure out what this junk is from, also, I've limited the receivedChars to a size of 4, why am I getting more than 4 characters?

The code from the sender

#include <SoftwareSerial.h>

SoftwareSerial HC12(3, 2); // HC-12 TX Pin, HC-12 RX Pin

void setup() {
  Serial.begin(9600);             // Serial port to computer
  HC12.begin(9600);               // Serial port to HC12
  Serial.print("Checking HC-12 module: ");
  HC12.write("AT");               //Check for response(this is sending data to the HC, the SET pin must be low for this to work)
  delay(1000);
  HC12.write("AT+RX");            //Gets configs of HC-12
}

void loop() {
  while (HC12.available()) {        // If HC-12 has data
    Serial.write(HC12.read());      // Send the data to Serial monitor
  }
  while (Serial.available()) {      // If Serial monitor has data
    HC12.write(Serial.read());      // Send that data to HC-12
  }
}

The simplified receiving code

    #define BYTELENGTH 4 //Limited to 4 chars
       #define ENDMARKER '\n'  //To know when stop stop reading serial
    
       SoftwareSerial HC12(3, 2); // HC-12 TX Pin, HC-12 RX Pin

  Serial.begin(9600); //Fastest it can be on the nano
  HC12.begin(9600); // Serial port to HC12s
      
      char receivedChars[BYTELENGTH - 1];
      int byteIndex;
      char curChar;
      
      while (HC12.available()) {        // If HC-12 has data
        curChar = HC12.read();
        if(curChar != ENDMARKER){
          receivedChars[byteIndex] = curChar;
          byteIndex++;
        }
      }
      if(strcmp(receivedChars,"") != 0){
        Serial.println(receivedChars);
        receivedChars[0] = 0;
      }
2
  • Btw: 9600 baud is not the fastest, that the Nano can get. The HardwareSerial interface Serial can also work with baudrates of up to 2 Megabaud. The problem with these baudrates is only, that you cannot provide the data in that speed. But 9600 baud is rather slow, even for the Nano. The real bottleneck here is the SoftwareSerial library. I think it can handle up to 38400 baud without problems. 11520 baud might also work, though I think that is very hard at the limit.
    – chrisl
    Sep 20 at 9:28
  • The software serial is temporary, just for testing. I did have everything at 115200 baud but was running into issues. That would explain that one!
    – dka13
    Sep 20 at 11:07
1

I would say you are printing data outside of your char array, because you didn't terminate the C-string in it and the size of your array is too small.

You have

#define BYTELENGTH 4 //Limited to 4 chars
char receivedChars[BYTELENGTH - 1];

so your char array is only 3 elements big. When you want to save a string in that array, you always need to terminate it with a null character \0 (which is also zero in decimal representation). So in that char array you only have space for 2 characters. But your message "stop" is 4 characters long, so you need a char array with at least 5 elements. If you are not in an extreme tight memory situation I would suggest using a buffer with a bit headroom above your biggest message (to be sure, that nothing breaks, if you later use messages that are a bit longer). So more like this:

#define BYTELENGTH 10 //Limited to 4 chars
char receivedChars[BYTELENGTH + 1]; // message length + null character termination

And then you need to change your receiving code to add a null character at the end of the message. Also you might want to actually use the newline character \n as message delimiting (which you are currently not doing):

bool full_message_received = false;

void loop(){
    while (HC12.available()) {        // If HC-12 has data
        curChar = HC12.read();
        if(curChar != ENDMARKER){
          receivedChars[byteIndex] = curChar;
          byteIndex++;
        } else {
          receivedChars[byteIndex] = '\0'; // terminating the c-string
          full_message_received = true; // marking the message as fully received
        }
    }
    if(full_message_received){
        Serial.println(receivedChars);
        receivedChars[0] = 0;
        full_message_received = false;
    }
}

What happens, if I don't terminate the string with a null character? All the functions, that handle C-strings (like strcmp() or also Serial.print()) use the null character to determine, at which point the string is at its end. They don't know the size of your array, so they just read byte after byte, until they reach the null character. They even read more data than is in your array. The junk characters are most likely exactly, what currently is placed in the memory directly after your array. Serial.print() doesn't know, that they don't belong to the C-string, since you didn't use the null character to tell it that. It just keeps printing characters, until it reaches a byte, that is zero.

You even wrote data to memory outside of the array. Depending on what comes directly after your array in the memory this can be without any problems, but you might also overwrite some other data, without knowing, what that data is. That can lead to very weird and hard to debug problems. Be sure to never write outside of your array. You might break things in weird ways.

3
  • So when ENDMARKER is reached (in this case \n), you are telling it to terminate the rest of the array. Then when I print it out or do anything with it, I shouldn't be reaching into additional memory spaces. But then I'm not even seeing the \n because the array length is too short. So to fix it, I need to make sure my array can fit at least 4 chars, + the \n (which should be sent by the other Arduinos serial monitor right?), then have my code searching for it and terminate the array after it. Am I understanding correctly?
    – dka13
    Sep 20 at 12:42
  • nearly correct. You need your array to fit 4 chars + the terminating null character. In my code above I don't include the \n in the array. Normally you don't need that character in there, since it is only used for delimiting individual messages on the serial interface. And the \n is also read and printed, if your array is too small. But then this data overwrites the memory space after the array, which can be very bad.
    – chrisl
    Sep 20 at 13:09
  • So for preventing writing and reading outside the array you need to make the array big enough for every possible message, that you might get. You read until the \n to only read one full message at a time (each individual message delimited by the \n on the serial interface). And for using the received data as a c-string (for example for printing) you need to terminate it with a null character.
    – chrisl
    Sep 20 at 13:11
0

It appears you have a baud rate problem. I am surprised you are getting anything. You need software to start the serial port such as SoftwareSerial mySerial(rxPin, txPin) then in setup mySerial.begin(9600); You need that in each application and the baud rates need to be the same.

I have used SC16IS750 I2C/SPI-to-UART devices as an external UART, they work great and have many nice features such as a 64 bytes of transmit and receive FIFOs. Some versions of this have been obsoleted but they are still available and work fine. You get 8 additional I/Os as well.

3
  • I do have it, just excluded it to avoid posting all my code. Just made the edit. Im guessing there is either something about serial or the char array that im missing thats adding the extra junk
    – dka13
    Sep 20 at 0:52
  • The softwareserial operates in half duplex. It is interrupt driven and if other interrupts are occuring that can cause problems. Here is a link/discussion that may help you a lot. electronics.stackexchange.com/questions/23265/…. The more information given generally the better. If there is additional hardware connected post a schematic with links showing technical information on the devices.
    – Gil
    Sep 20 at 2:20
  • That is actually an issue I've noticed, I'm hoping to get rid of software serial altogether. It just made programming simpler for the time being, but it seems to be causing some issues so I might need to expedite moving over.
    – dka13
    Sep 20 at 12:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.