I'm new to Arduino and building an RFID Door strike using the Freetronics kit. I've had issues reading RFID's as the use of softwareserial in the code is producing unusual results.
To test and demonstrate the problem, I have simply used the standard code for softwareserial available when you first install the Arduino software called "SoftwareSerialExample"
The result of loading this, is I get the appropriate message "Goodnight Moon!" from the Serial Monitor at 57600 Baud, but from the software serial output at 4800 Baud I get "üÿÿþÿ"
No combination of Bauds produces an output.
How this translates to the RFID code, is the RFID simply cannot be read. If however I use a simpler RFID code that merely takes the RFID code from the TX pin, it reads fine.
I have searched tireless for potential solutions. Although I have found some posts alluding to a Baud doubling problem, or someone expression a similar issue, I'm yet to find an actual solution to this problem. Any help would be greatly appreciated.
Now that you have your first post out of the way, you can post links. And code. Well, you could do that before. Might I suggest that use "use the force".
If you are running software serial at 57,600 it would be too fast. I tested at 38,400 software serial was working ok. First use hardware serial to get successful communication with the RFID reader, note the baud rate, then use software serial at that rate and try again. Good luck.
mentalpopcorn:
The result of loading this, is I get the appropriate message "Goodnight Moon!" from the Serial Monitor at 57600 Baud, but from the software serial output at 4800 Baud I get "üÿÿþÿ"
That might be the symptom of a floating pin on the SoftwareSerial RX pin. Have you definitely used pins 2 & 3 in your code, and connected a link wire between those two pins?
I did try "using the force" but after 24 hours I realised I wasn't getting anywhere.
I have tried different baud rates and matching the baud rate on code that works, but I get the same result.
Here is some of the code I have been using.
This code produces "Goodnight Moon!" at 9600 and "~æ?þ?`??" from 19200.
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.println("Goodnight moon!");
// set the data rate for the SoftwareSerial port
mySerial.begin(19200);
mySerial.println("Hello, world?");
}
void loop() // run over and over
{
if (mySerial.available())
Serial.write(mySerial.read());
if (Serial.available())
mySerial.write(Serial.read());
}
If I use softwareserial in my RFID code I get an equivalent result. However if I don't and use the below code, the RFID reads fine.
void setup() {
Serial.begin(9600); // connect to the serial port
}
void loop () {
byte i = 0;
byte val = 0;
byte code[6];
byte checksum = 0;
byte bytesread = 0;
byte tempbyte = 0;
if(Serial.available() > 0) {
if((val = Serial.read()) == 2) { // check for header
bytesread = 0;
while (bytesread < 12) { // read 10 digit code + 2 digit checksum
if( Serial.available() > 0) {
val = Serial.read();
if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) { // if header or stop bytes before the 10 digit reading
break; // stop reading
}
// Do Ascii/Hex conversion:
if ((val >= '0') && (val <= '9')) {
val = val - '0';
} else if ((val >= 'A') && (val <= 'F')) {
val = 10 + val - 'A';
}
// Every two hex-digits, add byte to code:
if (bytesread & 1 == 1) {
// make some space for this hex-digit by
// shifting the previous hex-digit with 4 bits to the left:
code[bytesread >> 1] = (val | (tempbyte << 4));
if (bytesread >> 1 != 5) { // If we're at the checksum byte,
checksum ^= code[bytesread >> 1]; // Calculate the checksum... (XOR)
};
} else {
tempbyte = val; // Store the first hex digit first...
};
bytesread++; // ready to read next digit
}
}
// Output to Serial:
if (bytesread == 12) { // if 12 digit read is complete
Serial.print("5-byte code: ");
for (i=0; i<5; i++) {
if (code[i] < 16) Serial.print("0");
Serial.print(code[i], HEX);
Serial.print(" ");
}
Serial.println();
Serial.print("Checksum: ");
Serial.print(code[5], HEX);
Serial.println(code[5] == checksum ? " -- passed." : " -- error.");
Serial.println();
}
bytesread = 0;
}
}
}
When I use the RFID Code I get a response via the Serial Monitor. I get a 5 byte code and checksum.
If I use the RFID code using softwareserial, I get the following response.
RFID reader starting up
Tag read: FFFFFFFFFF
Checksum: FF -- passed.
Tag not authorized
/**
* RFID Access Control Single
*
* This project implements a single stand-alone RFID access control
* system that can operate independently of a host computer or any
* other device. It uses either an ID-12 RFID reader module from ID
* Innovations or an RDM630 RFID reader module from Seeed Studio to
* scan for 125KHz RFID tags, and when a recognised tag is identified
* it toggles an output for a configurable duration, typically 2
* seconds. The output can then be used to control a relay to trip an
* electric striker plate to release a door lock.
*
* Because this project is intended to provide a minimal working system
* it does not have any provision for database updates to be managed
* externally from a host, so updates to the accepted cards must be
* made by changing the values in the code, recompiling the program,
* and re-uploading it to the Arduino. It does however report card
* readings (both successful and unsuccessful) via the serial
* connection so you can monitor the system using a connected computer.
*
* Some of this code was inspired by Tom Igoe's excellent RFID tutorial
* which is detailed on his blog at:
* http://www.tigoe.net/pcomp/code/category/PHP/347
* And also from the ID-12 example code on the Arduino Playground at:
* http://www.arduino.cc/playground/Code/ID12
*
* Copyright Jonathan Oxer <jon@oxer.com.au>
* http://www.practicalarduino.com/projects/medium/rfid-access-control
*/
// Set up the serial connection to the RFID reader module. In order to
// keep the Arduino TX and RX pins free for communication with a host,
// the sketch uses the SoftwareSerial library to implement serial
// communications on other pins.
#include <SoftwareSerial.h>
// The RFID module's TX pin needs to be connected to the Arduino. Module
// RX doesn't need to be connected to anything since we won't send
// commands to it, but SoftwareSerial requires us to define a pin for
// TX anyway so you can either connect module RX to Arduino TX or just
// leave them disconnected.
// If you have built the circuit exactly as described in Practical
// Arduino, use pins D2 / D3:
#define rxPin 4
#define txPin 5
// If you are using the Freetronics RFID Lock Shield, use pins D4 / D5:
/* #define rxPin 4 */
/* #define txPin 5 */
// Create a software serial object for the connection to the RFID module
SoftwareSerial rfid = SoftwareSerial( rxPin, txPin );
// Set up outputs for the strike plate and status LEDs.
// If you have built the circuit exactly as described in Practical
// Arduino, use pins D12 and D13:
#define strikePlate 6
#define ledPin 7
// If you are using the Freetronics RFID Lock Shield, use pins D6 / D7:
/* #define strikePlate 6 */
/* #define ledPin 7 */
// Specify how long the strike plate should be held open.
#define unlockSeconds 2
// The tag database consists of two parts. The first part is an array of
// tag values with each tag taking up 5 bytes. The second is a list of
// names with one name for each tag (ie: group of 5 bytes).
char* allowedTags[] = {
"0104F5B523", // Tag 1
"04146E8BDD", // Tag 2
"0413BBBF23", // Tag 3
};
// List of names to associate with the matching tag IDs
char* tagName[] = {
"Jonathan Oxer", // Tag 1
"Hugh Blemings", // Tag 2
"Dexter D Dog", // Tag 3
};
// Check the number of tags defined
int numberOfTags = sizeof(allowedTags)/sizeof(allowedTags[0]);
int incomingByte = 0; // To store incoming serial data
/**
* Setup
*/
void setup() {
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
pinMode(strikePlate, OUTPUT);
digitalWrite(strikePlate, LOW);
Serial.begin(38400); // Serial port for connection to host
rfid.begin(9600); // Serial port for connection to RFID module
Serial.println("RFID reader starting up");
}
/**
* Loop
*/
void loop() {
byte i = 0;
byte val = 0;
byte checksum = 0;
byte bytesRead = 0;
byte tempByte = 0;
byte tagBytes[6]; // "Unique" tags are only 5 bytes but we need an extra byte for the checksum
char tagValue[10];
// Read from the RFID module. Because this connection uses SoftwareSerial
// there is no equivalent to the Serial.available() function, so at this
// point the program blocks while waiting for a value from the module
if((val = rfid.read()) == 2) { // Check for header
bytesRead = 0;
while (bytesRead < 12) { // Read 10 digit code + 2 digit checksum
val = rfid.read();
// Append the first 10 bytes (0 to 9) to the raw tag value
if (bytesRead < 10)
{
tagValue[bytesRead] = val;
}
// Check if this is a header or stop byte before the 10 digit reading is complete
if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) {
break; // Stop reading
}
// Ascii/Hex conversion:
if ((val >= '0') && (val <= '9')) {
val = val - '0';
}
else if ((val >= 'A') && (val <= 'F')) {
val = 10 + val - 'A';
}
// Every two hex-digits, add a byte to the code:
if (bytesRead & 1 == 1) {
// Make space for this hex-digit by shifting the previous digit 4 bits to the left
tagBytes[bytesRead >> 1] = (val | (tempByte << 4));
if (bytesRead >> 1 != 5) { // If we're at the checksum byte,
checksum ^= tagBytes[bytesRead >> 1]; // Calculate the checksum... (XOR)
};
} else {
tempByte = val; // Store the first hex digit first
};
bytesRead++; // Ready to read next digit
}
// Send the result to the host connected via USB
if (bytesRead == 12) { // 12 digit read is complete
tagValue[10] = '\0'; // Null-terminate the string
Serial.print("Tag read: ");
for (i=0; i<5; i++) {
// Add a leading 0 to pad out values below 16
if (tagBytes[i] < 16) {
Serial.print("0");
}
Serial.print(tagBytes[i], HEX);
}
Serial.println();
Serial.print("Checksum: ");
Serial.print(tagBytes[5], HEX);
Serial.println(tagBytes[5] == checksum ? " -- passed." : " -- error.");
// Show the raw tag value
//Serial.print("VALUE: ");
//Serial.println(tagValue);
// Search the tag database for this particular tag
int tagId = findTag( tagValue );
// Only fire the strike plate if this tag was found in the database
if( tagId > 0 )
{
Serial.print("Authorized tag ID ");
Serial.print(tagId);
Serial.print(": unlocking for ");
Serial.println(tagName[tagId - 1]); // Get the name for this tag from the database
unlock(); // Fire the strike plate to open the lock
} else {
Serial.println("Tag not authorized");
}
Serial.println(); // Blank separator line in output
}
bytesRead = 0;
}
}
/**
* Fire the relay to activate the strike plate for the configured
* number of seconds.
*/
void unlock() {
digitalWrite(ledPin, HIGH);
digitalWrite(strikePlate, HIGH);
delay(unlockSeconds * 1000);
digitalWrite(strikePlate, LOW);
digitalWrite(ledPin, LOW);
}
/**
* Search for a specific tag in the database
*/
int findTag( char tagValue[10] ) {
for (int thisCard = 0; thisCard < numberOfTags; thisCard++) {
// Check if the tag value matches this row in the tag database
if(strcmp(tagValue, allowedTags[thisCard]) == 0)
{
// The row in the database starts at 0, so add 1 to the result so
// that the card ID starts from 1 instead (0 represents "no match")
return(thisCard + 1);
}
}
// If we don't find the tag return a tag ID of 0 to show there was no match
return(0);
}