How to write incoming software serial bytes into an array

Hello

I have an RFID reader that sends 7 bytes at a time when it reads a card, using the following code

#include <SoftwareSerial.h>

SoftwareSerial mySerial(6,7);

void setup() {
  Serial.begin(9600);
  while (!Serial);
  mySerial.begin(9600);
  delay(1000);
  Serial.println("Setup Complete!");

}

void loop() {
    while(!mySerial.available()); // wait for the serial port to send data
    
    int incomingByte = mySerial.read();
    
    Serial.println(incomingByte,HEX);
  }

I would like to get all these incoming bytes into a 7 element array, but they all seem to come at once rather than individually, so if I try to write then to consecutive elements of an array nothing happens - the program just jumps back to the start of loop. I’m sure this is a simple task, but I think my basic problem is that I don’t really understand Software Serial.

The excellent serial input basics tutorial may be of interest.

Thanks, I've looked at that but it doesn't seem to deal with SoftwareSerial

Serial input is the same with software serial as hardware serial. I use the methods of the tutorial with software serial all the time.

Try this code. Tested on my Uno by sending from serial monitor through a USB-TTL convrter connected to pins 6 and 7 to Uno with hardware serial connected to a separate instance of serial monitor. All that is modified from the tutorial is to change the receiver to software serial by including the library, creating a software serial object, initializing it and using the object to read the incoming serial data.

The received data is in a null terminated character array (string) called receivedChars. Test the newData flag to see if new data is available. Clear the flag to be able to receive a new data set.

// Robin2's Example 2 - Receive with an end-marker modified to work with software serial
// by groundfungus aka c. goulding

#include <SoftwareSerial.h>

SoftwareSerial ssPort(6, 7);

const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data

boolean newData = false;

void setup()
{
   Serial.begin(9600);
   ssPort.begin(9600);
   Serial.println("<Arduino is ready>");
}

void loop()
{
   recvWithEndMarker();
   showNewData();
}

void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char rc;

   while (ssPort.available() > 0 && newData == false)
   {
      rc = ssPort.read();

      if (rc != endMarker)
      {
         receivedChars[ndx] = rc;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         ndx = 0;
         newData = true;
      }
   }
}

void showNewData()
{
   if (newData == true)
   {
      Serial.print("This just in ... ");
      Serial.println(receivedChars);
      newData = false;
   }
}

For this code to work, line endings in serial monitor must be set to Newline.

newline.jpg

newline.jpg

Thanks - I don't have an end marker from the RFID card, so I think I basically need to count 7 bytes to know that all have come through. With your code, all I get is "this just in" followed by nothing. But I'm slowly starting to understand - I think

The end marker is a new line character in that code, but it can be changed in the code. What, exactly, does the RFID card send? Can you provide some samples? Perhaps the RFID sends something that can be used as an end marker.

With the original posted code I tend to get something like this

Setup Complete!
88
8A
A
28
2C
2F
C6

But the last byte is different for each card, so can't serve as a marker

Is the first byte always the same - if so you could use that as a start-marker from which to start counting.

If you provide a link to the datasheet for your RFID device it will be easier to help.

...R

Can I ask which library that you are using for the RFID? There may be an option in the library to set up the outgoing data set to add a newline or some terminating character.

Is the first byte always the same? No, it varies. At least, according to the bytes that turn up on the serial monitor in the original sketch. However, I think there is more to it than this. The full data sheet is annoyingly password protected except to customers, but I’ve saved a jpg of some of it here

I wrote a slightly more complex sketch, like this:

#include <SoftwareSerial.h>
int inBuffer[21];
byte bufIndx = 0;
SoftwareSerial mySerial(6, 7);

void setup() {
  Serial.begin(9600);
  while (!Serial);
  mySerial.begin(9600);
  delay(1000);
  Serial.println("Setup Complete!");

}

void loop() {
  bufIndx = 0;
  while (!mySerial.available()); // wait for the serial port to send data


  if (mySerial.available() > 0) {
    Serial.println();
    while (mySerial.available() > 0) {
      inBuffer[bufIndx] = mySerial.read();
      bufIndx ++;
    }
    inBuffer[bufIndx] = 0;
  }
  for (int i = 0; i < 21; i++) Serial.println (inBuffer[i], DEC);
}

This produces some odd results, for example the first read of a card produces this

136
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
14849

then the next read of the same card produces this:

138
10
40
44
47
198
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
9222

and then again

136
0
40
44
47
198
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
5377

then this

138
10
40
44
47
198
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
2822

So there is a lot of inconsistency (and a lot of zeros). This is strange to me because the original sketch produces completely consistent results. I’m guessing that the software serial and the running code are somehow out of sync (I’ve tried changing the software serial baud rate but it only makes things worse).

I’m not using any library for the RFID reader - it’s a quite basic 125kHz model which just uses serial output.

it's a quite basic 125kHz model which just uses serial output.

Are you sure that the output is TTL level (0 to 5V) serial and not RS232 output levels (±12V)?

The image says "03 end code (fixed)". Can you try the code that I posted but change the end marker to 0x03 and report the output?

void recvWithEndMarker()
{
   static byte ndx = 0;
   char endMarker = 0x03;  // change end marker to 0x03
   char rc;

"This produces some odd results, for example the first read of a card produces this"

You may be reading the serial buffer much faster than the characters are arriving. Try putting a delay(3) after the
bufIndx ++; to see if that helps.

The image says "03 end code (fixed)".

The image also says "02 start code(fixed)"

I've not seen these values in any of your reported readings. There is also no reference to a 7 byte message.

zoomkat:
"This produces some odd results, for example the first read of a card produces this"

You may be reading the serial buffer much faster than the characters are arriving. Try putting a delay(3) after the
bufIndx ++; to see if that helps.

Thank you - this seems to have fixed the problem. It has also produced the missing 2 start code and 3 end code, and I now have 13 bytes (including the first and last) rather than 7.

robertjenkins:
It has also produced the missing 2 start code and 3 end code,

So now that you know the start and end marjers try the 3rd example in Serial Input Basics

You will probably want to change the array receivedChars to a byte array - for example

byte receivedBytes[numChars];

You could also change numChars to numBytes but it is not essential.

...R