I've been able to read rfid tags, but there's something about this code that has me stumped.
Here's a couple of snippets and their output, I've tried to simplify the code to illustrate the problem area.
#include <NewSoftSerial.h>
NewSoftSerial mySerialPort(2,3);
#define doorpin 9
char* myTags[] = {"8400070A95","440086361E", "8411111111"};
#define numTags (sizeof(myTags)/sizeof(char *)) //array size
char IDstring[13];
char val = 0;
void setup() {
mySerialPort.begin(9600);
Serial.begin(9600); // connect to the serial port
pinMode(doorpin, OUTPUT);
}
void loop () {
int i;
if (mySerialPort.available() > 0 ) {
if ( (val = mySerialPort.read()) == 02 ) { // look for Start Of Text marker
Serial.println(" ");
for ( i = 0; (val = mySerialPort.read()) != 03 ; i++) {
Serial.print(" ");
IDstring[i] = val;
}
Serial.println();
Serial.print(" IDString[");
IDstring[10] = 0x00; // tie off IDstring at the CR-LF
Serial.print(IDstring);
Serial.println("] ");
Serial.println();
}
}
}
This code prints out, through the serial monitor:
IDString[440086361E]
If I change one of the lines like so:
void loop () {
int i;
if (mySerialPort.available() > 0 ) {
if ( (val = mySerialPort.read()) == 02 ) { // look for Start Of Text marker
//Serial.println(" "); <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Comment this line out
for ( i = 0; (val = mySerialPort.read()) != 03 ; i++) {
Serial.print(" ");
IDstring[i] = val;
}
Serial.println();
Serial.print(" IDString[");
IDstring[10] = 0x00; // tie off IDstring at the CR-LF
Serial.print(IDstring);
Serial.println("] ");
Serial.println();
}
}
}
The only thing that outputs from the serial monitor are spaces. The code outputs the IDstring if I replace the commented out line with Serial.println(" ").
What the heck does this line do? I've tried some other options, but I don't find any reason for this behavior.
Can anyone shed some light on this?
You are attempting to read data that has not yet arrived:
for ( i = 0; (val = mySerialPort.read()) != 03 ; i++) {
Serial.print(" ");
IDstring[i] = val;
}
There is nothing to make this code wait for a byte to be available before it is read. Having the Serial.print() statement in there (and just before the loop) takes time. Coincidentally, during that time, a character arrives on the other port.
if (mySerialPort.available() > 0 ) {
if ( (val = mySerialPort.read()) == 02 ) { // look for Start Of Text marker
delay(10);
// reda until you get End Of Text
for ( i = 0; (val = mySerialPort.read()) != 03 ; i++) {
delay(10);
IDstring[i] = val;
}
Which solved the problem, but I'm not real happy with that solution. This reply to the above mentioned thread looks useful:
Re: Serial.available() requires delay between call
Reply #2 - 02.05.2008 at 08:15:02
I don’t think adding a delay is the best solution for this. There is no guarantee that serial data passed to a senders serial output routine will be available to the receivers input routine in any fixed period of time. If the sender is busy doing something of high priority it may take much more than 10ms for all the data to arrive irrespective of baud rate.
The most reliable solution to this problem is to have something in your protocol to indicate the end of data.
Hmmm... I know what to look for at the end of my data, but it would seem to me I need to constantly wait for myserialport.available() else I'll keep pushing -1 in to IDstring.
Thanks for the reply, I'm on my way to sorting this out.
No. You simply have nothing to read if Serial.available() returns 0. By adding the delay, you allow time for another character to arrive, if the baud rate and delay length are compatible.
but I'm not real happy with that solution.
You shouldn't be. You need to add an end-of-packet marker (any character that will not be part of the expected data). Then, on each pass through loop(), read any serial data pending (while(Serial.available() > 0)) until the end of packet marker arrives (if(inByte == EOP) break;).
Set a flag before the break.
On each pass through loop, see if the flag is set. If so, use the data, clear the buffer, reset the index, and clear the flag. Otherwise, do nothing.