A typical application might see the Arduino, shield, and power supply all mounted either under the floor of your house or inside a ceiling, with wires running through the wall to the RFI
Trang 1between all the pins If you drill a small hole through the shield just big enough for the pin to fit through, you’ll probably find that the pin will short-circuit to ground when you solder it in place We had to drill a large hole that cleared the pin by a good margin and then solder a jumper wire to the pin while keeping the joint clear of the edges of the hole
A short length of heat-shrink tubing is a good idea to prevent short-circuits if the wire is bumped
(see Figure 14-9)
Figure 14-9 Connection to “common” connection on relay through a hole drilled in the shield
Once the relay is in place, use a short length of hookup wire to join one of the coil connections to the
“NO” (normally open) connection and then to the +12V terminal on the power connection Then fit the second 1N4001 power diode across the coil connections so that the end with the band (the cathode) is
joined to the coil connection that is linked to +12V
The purpose of the diode is to short out any reverse-voltage charge that is induced across the relay coil when it turns off Without this protection diode in place a high-voltage reverse spike could damage other parts in the circuit Even if you don’t see a failure immediately, it can still cause degradation of
parts over time
Insert the transistor so that the collector pin connects to the relay coil connection at the nonbanded (anode) end of the diode Use a short length of hookup wire to join the emitter pin of the transistor to the ground bus on the shield (see Figure 14-10) The actual selection of diode isn’t particularly critical
because it’s just being used as a simple electronic switch in this application As long as it’s a small NPN transistor you should be fine, so it could be a 2N2222, a BC547, a BC548, or any other common NPN low-power switching transistor
Trang 2Figure 14-10 Pinout of BC547 and 2N2222 transistors
Next, insert the 4K7 resistor so that it connects to Arduino digital I/O pin 12 at one end and the transistor’s base lead at the other The resistor limits current flowing through the output pin but allows it
to bias the transistor either on or off to match the state of the output Don’t connect the base of the resistor directly to the I/O pin, or the ATMega CPU will see it as a short-circuit to ground and deliver maximum current flow into it unnecessarily
As you can see in the schematic in Figure 14-4, the relay coil has one end connected to +12V while the other end connects to the transistor’s collector The transistor emitter connects to ground, so if the transistor is turned on hard the collector will also be pulled to ground and the relay coil will see 12V difference across the connections and be turned on If the transistor is turned off, the collector voltage will float high thanks to conductivity through the coil which will see 0V across it and be turned off Fit the second 2-pin PCB-mount screw terminal with one terminal pin connected to the ground bus
on the shield Then connect the other terminal pin to the relay common connection using a short length
of jumper wire passing through the hole in the shield to connect directly to the pin
Indicator LEDs
Fitting indicator LEDs is optional but it can be handy when testing and also help provide feedback once
it has been installed near a door On the prototype, we fitted two LEDs, with a red LED to indicate
“locked” and a green LED to indicate “unlocked.” However, because the two LEDs are used in such a way that only one is on at a time, we used a little trick to control them both from a single output pin Because there are so few pins used in this project, that’s not really necessary, but it can be a handy thing
to know for other projects and simplifies the software a little
As you can see in the schematic one of the LEDs is connected via a 680R current-limiting resistor to +5V, while the other is connected via a similar resistor to ground By joining them both to the same output, we can turn on one or the other depending on whether the output is high or low In normal operation the output will be low so the red LED will be illuminated, but when a tag has been successfully read and the output goes high, the red LED turns off and the green LED turns on Of course when the output is in a high-impedance “floating” state both LEDs will be dimly illuminated, so when power is first applied they will both glow until the sketch sets the state of the output
The LEDs could even have been connected to the same digital output as the transistor so that when the transistor (and hence the strike plate) is off the red LED will be illuminated, and when the transistor turns on the green LED will illuminate However, that limits your ability to use them to indicate other events, such as a bad read, without triggering the strike plate
If you are going to mount the Arduino some distance from the RFID reader, you will need to use long enough leads to reach from the reader location to the Arduino A typical application might see the Arduino, shield, and power supply all mounted either under the floor of your house or inside a ceiling, with wires running through the wall to the RFID reader mounted beside the door and the strike plate
Trang 3Figure 14-11 Header and jumper in place for connection to indicator LED assembly
If you are mounting your reader module inside a box or behind a blank electrical wall plate like the one we used in our prototype, start by drilling holes to fit the red and green LEDs and clip or glue them into position When mounting them, remember that you will be linking the anode (long) lead of the
green LED and the cathode (short) lead of the red LED together with resistors, so orient them
appropriately
Once the LEDs are in place, solder the two 680R resistors in series and bridge them from one LED to the other as shown in Figure 14-12 The central joint of the two resistors will be connected to the
Arduino’s digital output
Cut off a length of three-core cable, such as a strip of ribbon cable, long enough to reach from the
mounting location of the Arduino to the mounting point for the reader Connect a 3-pin female header
to one end and solder the other end to the LEDs and the center point of the resistors The +5V lead
connects to the cathode (short) lead of the green LED, while the ground lead connects to the anode
(long) lead of the red LED The pin 13 connection goes to the center of the two resistors
The leads also need physical support because it’s never a good idea to rely on a solder joint to
provide mechanical strength as well as electrical connectivity We used two-part epoxy resin to hold the whole LED assembly in place, including the resistors and the cable, taking the strain off the solder joints The shield is now complete and ready to go, so next you need to assemble an RFID reader module to connect to the 4-pin serial port added to the shield
Trang 4Figure 14-12 Status indicator LEDs mounted in a blank electrical wall plate
Manual Release Button
It may be handy to have a pushbutton mounted inside a protected door so people need to swipe their RFID card on the way in, but anyone can exit simply by pushing a button even if they don't have a card The schematic and parts list show a momentary-action button that can be wired between the
transistor’s collector and ground Whenever the button is pressed it pulls the collector pin to 0V and allows the relay to activate, triggering the strike plate
This method is a very simple way to provide a bypass for the lock because it will function even if the Arduino has failed for some reason It’s not dependent on any of the rest of the circuit being operational for it to function However, it will only operate for as long as the button is pushed, so an alternative approach would be to connect the button to a digital input on the Arduino and have it trigger an
interrupt that in turn fires the transistor output and holds it on for a predetermined interval This way, a quick push of the “exit” button could cause the lock to disengage for several seconds, giving time to pull the door open after releasing the button
Assemble the ID-12 Reader Module
Unfortunately, the ID series RFID modules all have one major annoying idiosyncrasy: instead of having their pins spaced on a 0.1in imperial grid like the vast majority of electronic parts, they’re spaced on a 2mm metric grid Since 0.1in is about 2.54mm, that means it’s impossible to simply plug an ID-12 module into a breadboard or fit it on a prototyping shield unless you either do surgery on the shield to drill additional holes or mount the ID-12 on a breakout board that converts it to a standard 0.1in grid For this project we wanted to mount the module behind a blank wall plate separated from the Arduino and shield so the problem isn’t quite as frustrating as it could have been, but it still makes things awkward If all else fails you could solder wires directly to the appropriate pins on your ID-12, but that won’t provide much mechanical support An alternative is to buy a generic prototyping board with a nonstandard 2mm grid, but that tends to be very expensive and not commonly available Or you could etch a tiny custom circuit board that provides the correct pin spacing for the ID-12 module plus
mounting pads, or buy one ready-made from a supplier such as SparkFun Because this is such a simple PCB, you can easily fabricate it yourself at home using either a resist pen to draw it out by hand or
Trang 5read RFID tags surgically implanted in a colony of Little Penguins!
To put the ID-12 module into the correct mode it’s also necessary to make a few additional
connections between different pins on the module
Pin 2 is the reset pin, which is active-low, so link it to pin 11 (+5V) to prevent the unit from resetting Pin 7 is the format (mode) pin When held high, it puts the module into “Wiegand26” mode to
emulate an older Wiegand-format reader If connected to pin 10, the module goes into a “magnet
emulation” mode in which it pretends to be a magnetic card reader If held low the module goes into
ASCII mode, which happens to be exactly what we want Link pin 7 to pin 1 (ground) for operation with
an Arduino (see Figure 14-13)
Figure 14-13 Schematic of ID-12 module connection to Arduino serial interface
Fit a 4-pin–oriented female header to the other end of the cable to match the connections on the
shield, keeping in mind that you need to reverse TX/RX on the RFID module compared to the Arduino The TX pin on the module (pin 9) needs to go to RX (pin 4) on the Arduino We don’t use it with the
ID-12 module, but for completeness you can also connect the RX pin on the module (pin 8) to the Arduino’s
TX on pin 5
Mount the ID-12 module itself inside your case or front panel, keeping it flat against the case The
read range can be quite limited and nearby metal could alter the tuning, so the closer you can get it to
the location of the tag the more reliable it will be For our prototype we mounted the ID-12 inside a
blank wall plate along with the indicator LEDs (see Figure 14-14)
Trang 6Figure 14-14 ID-12 module mounted behind a blank electrical wall plate
A link to the ID-12 datasheet is provided on the project page on the Practical Arduino web site
Assemble the RDM630 Reader
The RDM630 is supplied with a separate reader coil and module, with a very short lead to connect the coil to the module Unlike the ID-12 it doesn’t need any special connections to be made to set it into a mode that works well with an Arduino, so wiring it up is extremely simple (see Figure 14-15)
Trang 7down to gain some clearance
Then fit a 4-pin female header to the other end of the cable to connect to the shield, remembering that RX/TX on the RFID module need to be the opposite of RX/TX on the Arduino Connect the RFID
module TX (P1 pin 1) to the Arduino RX (pin 4), and the module’s RX (P1 pin 2) to the Arduino RX (pin 5)
Of course, we’re not actually using the module RX pin in this project but some RFID modules, including the 134.2kHz variant of the RDM630, allow you to write values to the tag, so wiring it up allows you to
swap the module out in future if you want full read/write capability
Mount the antenna inside your project box or wall plate, keeping it as close to where tags will be
presented as possible and away from metal Mount the RDM630 module beside it and fix it in place
Options include double-sided tape or, if you want to make it more permanent and don’t mind not being able to remove the module later, something like two-part epoxy resin In either case, make sure the cable
is well anchored so no strain is placed on the solder joints
Figure 14-16 shows our prototype with the coil held in place temporarily with tape and the module ready to be glued down
Figure 14-16 RDM630 module mounted behind a blank electrical wall plate
A link to the RDM630 datasheet is provided on the project page on the Practical Arduino web site
Simple Stand-Alone Sketch
RFID has so many possible applications that you can use the basic hardware in this project in a huge
number of ways The RFID Access Control Standalone sketch implements a stand-alone RFID
access-control system that can operate independently of a host computer or any other device It scans
continuously for RFID tags, and when a recognized tag is identified it toggles the relay output for a
configurable duration, typically 2 seconds, to trip an electric strike plate to release a door lock
Trang 8Because this sketch is intended to provide a minimal working system it does not have any provision for updates to the tag database 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 sketch, and reuploading 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 if you want to for datalogging purposes
The first thing the sketch does is set up the serial connection to the RFID reader module The module’s TX pin is connected to RX (pin 4) on the Arduino as per the hardware assembly instructions The module’s RX pin doesn’t need to be connected to anything since we won’t be sending any
commands to it, but the SoftwareSerial library requires us to define a pin for TX so we set it to pin 5 and then ignore it Then we create a software serial object for the connection to the RFID module and call it simply “rfid.”
#include <SoftwareSerial.h>
#define rxPin 4
#define txPin 5
SoftwareSerial rfid = SoftwareSerial( rxPin, txPin );
The system has two outputs: one to drive a relay that applies power to an electric strike plate, and one that controls two status LEDs to show when the system is “locked” (red) or “unlocked” (green) The strike plate relay is driven by digital I/O pin 12, while the status LEDs are connected to digital pin 13
#define strikePlate 12
#define statusPin 13
The length of time the lock will be held open can be configured by changing the value of the
unlockSeconds variable This value is multiplied by 1,000 to convert it to milliseconds later in the sketch The value needs to be long enough to allow a cardholder to swipe their card and then pull the door open, but not so long that they have time to open the door and then close it again before the lock re-engages
#define unlockSeconds 2
The tag database consists of two parts The first part is an array of tag values, with each tag code stored as a separate element in the array It can be a good idea to add comments after each tag so you know which is which This list can be extended simply by adding more rows to it
char* allowedTags[] = {
"0104F5B522", // Tag 1
"04146E8BDE", // Tag 2
"0413BBBF22", // Tag 3
};
The second part of the tag database is a list of names to associate with each tag This array must have the same number of elements as the allowedTags array, so if you add a tag code to allowedTags you also need to add an entry to the tagName array Once again, add comments so you know which name matches which tag; otherwise it can be pretty confusing if you have more than a few tags
char* tagName[] = {
"Jonathan Oxer", // Tag 1
"Hugh Blemings", // Tag 2
"Dexter D Dog", // Tag 3
};
The sketch needs to know how many tags have been defined so that later, when it is looping through the allowedTags array, it knows when to stop We do this with a little trick that doesn’t look like it should work until you realize that C arrays don’t actually hold data directly: they just provide pointers to the values stored elsewhere in memory The result is a seemingly trivial little line that can be a bit brain-bending if you try to figure out how it works
Trang 9int numberOfTags = sizeof(allowedTags)/sizeof(allowedTags[0]);
Then we define a single-byte variable to hold incoming data as we read it from the serial port
byte incomingByte = 0;
The setup function is very simple It sets the two output pins (statusPin and strikePlate) as outputs, sets up communications with a host at 38400bps, sets up the SoftwareSerial object to communicate with the RFID reader module at 9600bps, and then prints a welcome message to the host Both the ID-12 and RDM630 RFID modules operate by default at 9600bps
void setup() {
pinMode(statusPin, OUTPUT);
digitalWrite(statusPin, LOW);
pinMode(strikePlate, OUTPUT);
digitalWrite(strikePlate, LOW);
Serial.begin(38400);
rfid.begin(9600);
Serial.println("RFID reader starting up");
}
The main program loop is quite long and fairly complex, so we’ll step through it a bit at a time It
starts off simply enough by defining some variables that are used in the loop Most of these will be
explained later in the loop or are self-explanatory, but the two to pay close attention to here are
tagBytes[6] and tagValue[10]
The ID-12 reader module works with “Unique” tags that output a 5-byte identification code, so
normally we would only need tagBytes to be a five-element array However, we’ve defined it as having six elements because after reading the tag the sketch calculates the checksum value to make sure there were
no read errors, and the checksum is then added to the end as a sixth element
The tagValue array is an array of characters, and it needs to be 10 elements long because once the 5-byte tag value is converted to an ASCII string it expands to 10 characters As you can see by looking at the list of tags in allowedTags ealier in the program, each one of them is 10 characters long
void loop() {
byte i = 0;
byte val = 0;
byte checksum = 0;
byte bytesRead = 0;
byte tempByte = 0;
byte tagBytes[6];
char tagValue[11];
Reading from the RFID module is done with the SoftwareSerial library, which unfortunately doesn’t have an equivalent to the Serial.available() function This means the sketch can’t loop indefinitely and
check for characters available from the serial port each time it loops through: instead it blocks on waiting for the next character from the port every time it calls rfid.read() That’s the reason this simple version of the system can’t accept commands from the host via the serial console If you sent a command to it, the sketch wouldn’t see it until after the next tag read when it loops through and accesses the serial port
buffer
First, the sketch reads a byte from the rfid virtual serial device and checks whether it’s a header
value
if((val = rfid.read()) == 2) {
Trang 10It then resets the bytesRead counter to 0, and then enters a loop so it will continue accepting values from the RFID reader until it has seen a total of 12 characters: the 10-character tag code itself plus a two-character checksum value
bytesRead = 0;
while (bytesRead < 12) {
val = rfid.read();
In case the system ever gets into a confused state, such as when the ID-12 has sent part of a
sequence of tag values while the program was busy elsewhere, it checks each value to see whether it’s a header or stop byte If a header or stop byte is seen while the program is still in this loop, it assumes something has gone wrong and calls break to jump out of the loop and start again This should help the program recover from bad situations such as partially received values
if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) {
break;
}
We store the tag ID in two different formats for convenience later in the program The first format is
as a series of raw values stored in a character array, with only the actual tag ID itself stored We don’t want to include the checksum, so the program only appends the first 10 characters into elements 0 through 9 in the tagValue array
if (bytesRead < 10)
{
tagValue[bytesRead] = val;
}
The second format requires some processing and then stores each value as a separate element in an array of bytes, so the program does some ASCII/Hex conversion to each value
if ((val >= '0') && (val <= '9')) {
val = val - '0';
}
else if ((val >= 'A') && (val <= 'F')) {
val = 10 + val - 'A';
}
A byte is a total of 8 bits and can hold a value from 0 to decimal 255, while a hexadecimal digit is a 4-bit value (half a byte) from 0 to F We can, therefore, store two hex digits in each byte as a pair of 4-4-bit values The structure of the code here seems a bit backward because the first part of the code is for dealing with the second of a pair of hex digits, while the second part of the code is for dealing with the first
The code first checks if it’s dealing with the second hex digit of a pair If it is, the following
comparison will be true:
if (bytesRead & 1 == 1) {
This part of the code then deals with the second of a pair of hex digits It makes space for this digit in the current byte using a bitwise operator to shift the existing 4 bits in that byte by 4 bits to the left, leaving space for the second 4 bites to be set using the value in bytesRead
tagBytes[bytesRead >> 1] = (val | (tempByte << 4));
It then checks if it has reached the checksum byte, and if so it calculates the checksum using an XOR operation
if (bytesRead >> 1 != 5) {
checksum ^= tagBytes[bytesRead >> 1];
};
This part of the code then deals with the first of a pair of hex digits by simply putting the value