First off thanks in advance. Im fairly new to the arduino world.
So i found a cheap Parallax RFID reader and thought it would be fun to play with.
did some looking and found some example code (included below)
// * Arduino Digital pin 8 to RFID TX
// * Arduino GND to RFID GND
// * Arduino Digital pin 2 to RFID enable
// * Arduino +5V to RFID Vcc pin.
// Modified by Worapoht K.
#include <SoftwareSerial.h>
int val = 0;
char code[10];
int bytesread = 0;
#define rxPin 8
#define txPin 9
// RFID reader SOUT pin connected to Serial RX pin at 2400bps to pin8
void setup()
{
Serial.begin(9600); // Hardware serial for Monitor 9600bps
pinMode(2,OUTPUT); // Set digital pin 2 as OUTPUT to connect it to the RFID /ENABLE pin
digitalWrite(2, LOW); // Activate the RFID reader
}
void loop()
{
SoftwareSerial RFID = SoftwareSerial(rxPin,txPin);
RFID.begin(2400);
if((val = RFID.read()) == 10)
{ // check for header
bytesread = 0;
while(bytesread<10)
{ // read 10 digit code
val = RFID.read();
if((val == 10)||(val == 13))
{ // if header or stop bytes before the 10 digit reading
break; // stop reading
}
code[bytesread] = val; // add the digit
bytesread++; // ready to read next digit
}
if(bytesread == 10)
{ // if 10 digit read is complete
Serial.print("TAG code is: "); // possibly a good TAG
Serial.println(code); // print the TAG code
// ADDED / Check for particular tags
if (code == "0415E9B02D") {
Serial.println("Round Black WORLD TAG");
}
/////
}
bytesread = 0;
delay(1000); // wait for a second
}
}
for the most part it works as expected.
using serial monitor i see everything i expect except when i scan the round black world tag the tag code shows up but it doesnt display "Round Black WORLD TAG" Its almost as if its skipping over that IF statement.
now the question, am i doing it wrong? or am i missing something?
It sounds like you're pretty close, and you're right in your analysis that it's the "if" statement at fault.
It isn't skipping the "if" - the problem is how strings are handled. Without getting too deep into C/C++ and pointers work, you can't use "==" to compare strings.
What you'd need to do is either use the TextString library - see String() - Arduino Reference, or if you just want to compare basic strings like you're trying here, add a strcmp function to your code.
Here's an example that you could cut and paste into your Arduino sketch. I don't think you'd need the "#include <string.h>" line, and then your "if" line would become:
"if (strcmp(code, "0415E9B02D") == 0) {"
I hope that's all right, give a shout if it's not and I'll try compiling it into a sketch myself
well i tried replacing my IF statement with "if (strcmp(code, "0415E9B02D") == 0) {" and got no joy.
im looking into the TextString library but i already have a problem, it tells me to place the resulting folder into "lib/targets/libraries"
which i dont have.
Im running 0012 on MacOS X
would i be able to put it in "hardware/libraries"?
all and all having played with this for a few weeks my lack of familiarity with the programing environment is becoming incredibly frustrating.
im not used to these sort of limitations. PHP has spoiled me i guess
but then again thats what makes it fun, learning something new.
all im really trying to do here is build a simple door lock.
the ability to add a program tag into memory would be nice but ill stick with a hard coded list for now.
I've just tried compiling the strcmp example I pointed to, and the Arduino compiler doesn't like the brackets round the function name. This code compiles for me (but I don't have an Arduino to hand to try it out):
int strcmp(const char *s1, const char *s2)
{
unsigned char uc1, uc2;
/* Move s1 and s2 to the first differing characters
in each string, or the ends of the strings if they
are identical. */
while (*s1 != '\0' && *s1 == *s2) {
s1++;
s2++;
}
/* Compare the characters as unsigned char and
return the difference. */
uc1 = (*(unsigned char *) s1);
uc2 = (*(unsigned char *) s2);
if (uc1 != uc2)
return ((uc1 < uc2) ? -1 : (uc1 > uc2));
else
return 0;
}
If you stick that at the top of your sketch, then the "if (strcmp(code, "0415E9B02D") == 0) {" should work.
I think you're right with being able to put TextString into hardware/libraries, but I'm not an expert on where it looks for the libraries.
i tried putting it in hardware/libraries and got a litany of errors on code that used to verify. I didnt bother copying it but needless to say it was a no go.
I give the code you posted a try and let you know how it goes
here is the code as it stands, maybe im just doing it wrong i dont know
#include <SoftwareSerial.h>
int val = 0;
char code[10];
int bytesread = 0;
// ADDED
int strcmp(const char *s1, const char s2)
{
unsigned char uc1, uc2;
/ Move s1 and s2 to the first differing characters
in each string, or the ends of the strings if they
are identical. */
while (*s1 != '\0' && *s1 == s2) {
s1++;
s2++;
}
/ Compare the characters as unsigned char and
return the difference. /
uc1 = ((unsigned char ) s1);
uc2 = ((unsigned char *) s2);
if (uc1 != uc2)
return ((uc1 < uc2) ? -1 : (uc1 > uc2));
else
return 0;
}
#define rxPin 8 #define txPin 9
// RFID reader SOUT pin connected to Serial RX pin at 2400bps to pin8
void setup()
{
Serial.begin(9600); // Hardware serial for Monitor 9600bps
pinMode(2,OUTPUT); // Set digital pin 2 as OUTPUT to connect it to the RFID /ENABLE pin
digitalWrite(2, LOW); // Activate the RFID reader
}
void loop()
{
SoftwareSerial RFID = SoftwareSerial(rxPin,txPin);
RFID.begin(2400);
if((val == 10)||(val == 13))
{ // if header or stop bytes before the 10 digit reading
break; // stop reading
}
code[bytesread] = val; // add the digit
bytesread++; // ready to read next digit
}
if(bytesread == 10)
{ // if 10 digit read is complete
Serial.print("TAG code is: "); // possibly a good TAG
Serial.println(code); // print the TAG code
// ADDED / Check for Particular tags
if (strcmp(code, "0415E9B02D") == 0) {
Serial.println("Round Black WORLD TAG");
}
}
bytesread = 0;
delay(1000); // wait for a second
}
}
Strings in C and C++ are NUL-terminated, which means there's a '\0' character on the end of them. Although you can't see it, the "0415E9B02D" has a '\0' on the end, and your "code" array doesn't. If you stick
code[bytesread] = '\0';
before the if statement then you should be good. (Actually, you should really do that before the "Serial.println(code);" line, so that it doesn't end up printing any garbage that's after the array)
Are you getting the message "Tag Code is xxxxxxxxxx"? If not, then the problem is not with strcmp, because your code is never reaching there.
There is no need to provide your own strcmp. The Arduino library already provides one that is faster and smaller. This is just wasting space in your binary.
Mikal
EDIT: Adrian has nailed it! (But you still don't need your own version of strcmp.)
EDIT2: Make sure you increase the size of your "code" array to 11 (10+NUL byte), otherwise Ardrian's addition will overrun the buffer.
Oops. Thanks for the comment Mikal - I hadn't realised strcmp was provided in Arduino. Indeed you should use that, but you'll still need to NUL-terminate the array first. Which I've just realised also means that you'll need to make your array 11 chars rather than 10, otherwise you'll overwrite part of 'bytesRead'.
No, the '\0' will be overwritten by the NEXT received character, if any. Your "bytesRead" is the number of bytes that have been read. The array starts at index zero.
Unless it's vitally crucial to avoid writing '\0' multiple times (like in a video signal timing routine), I would write the receiving loop to ALWAYS terminate the buffer EVERY time a new character is appended.
while (...) {
...
code[bytesRead] = received;
bytesRead++;
code[bytesRead] = '\0';
// keep it safe to add strcmp(), print(), etc.
}