This example describes how to create a smart lock for your door, chest, or whatever. It opens up when a valid NFC tag is detected. It might be an RFID card or sticker.
To make the lock we need to read an NFC tag, compare its UID to the specified one, and turn on the relay to open the electromagnetic lock. Also, we’ll add a text LCD to notify a user about the current state.
Here is a circuit of the device:
You can build the device according to the schematics using modules from various vendors or even create own all-in-one PCB. One of the possible options is Troyka Module System by Amperka which makes wiring trivial:
Here is a wiring scheme:
Note, that jumper on the slot shield joins
V2 with the
Vin pin. So we power up the Arduino with the 12V and this voltage will be passed to the relay for the solenoid lock.
We are going to use the xod-dev/pn532-nfc library for NFC scanner interfacing. It provides nodes to read and write NFC tags using modules build around the popular PN532 chip, as well as nodes to compare and validate the tags.
First of all, let’s implement scanning of NFC tag and retrieving of its UID. Fortunately, there is a quick-start node
xod-dev/pn532-nfc/nfc-scanner that scans for an NFC tag and retrieves its UID. Place it and bind the correct
IRQ port: we chose
To ensure it’s working, place an
unpack-nfc-uid node, link it with
nfc-scanner, and place one
watch node per output to see the values. Upload the program to the microcontroller with the debug mode turned on. Place an NFC tag next to the NFC reader module. You should see some bytes in the watch nodes.
OK, the NFC scanner works reading UIDs of NFC tags. Let’s create a node which will represent the UID that will be considered a valid token for the device. Write down the bytes you have seen at the previous step to the paper and create a new patch named
key-token. Place the
nfc-uid node onto this patch node, bind the UID bytes, and output its result to the
Now we are going to compare a UID scanned by the module to the reference
key-token we have made. For this, there is a
validate-uid node in the
xod-dev/pn532-nfc library. Switch back to the main patch and place
validate-uid. For the
REF input use the
key-token node you’ve just created: place one onto the patch. Link another input with the scanner node. The
validate-uid node outputs two booleans
BAD to express one of the possible states:
Upload the program with the debugger enabled, bring some tags to the scanner and see how
Let’s make the lock open if we see the valid NFC tag. Place the
xod/common-hardware/relay node and link the
GOOD pin to its
ON pin. Do not forget to bind the correct port: we use
Put the valid NFC tag on the scanner and ensure the lock opens.
The smart lock is working already. But it’s hard to recognize whether the lock does not open because something broke or the tag is invalid. Let’s add a text LCD to show messages: “Access granted”, “Access denied”, or “Waiting for tag”.
XOD has a standard library to work with text LCD displays with parallel or I²C interfacing:
Place one of quick-start nodes from the
xod-dev/text-lcd library which fits your model of a text LCD:
text-lcd-parallel-16x2. In this example we’re using
To switch the messages, we place one more node:
xod/core/select. Drag the handle on its edge to get three pairs of inputs. Bind the text values to
X3 pins. These pins have a generic type, so do not forget to surround the string values with quotes.
Link the first output of the
select node to the
L1 input pin of the text LCD node. The
select node outputs one of the values from X𝑛 to its output on receiving a pulse on the pair S𝑛 pin. Let’s link
For the last input, we have to be sure there is no tag detected, and it’s neither
BAD. Place a
nor node, link its inputs to
BAD outputs, finally, link its output with the
S3 input pin.
So far, so good. Now we have useful messages on the text LCD. But it’s inconvenient that the lock opens only while the tag is touching the NFC reader. Let’s keep it open for three more seconds after the user removed the tag. We’ll keep both “Access granted” or “Access denied” messages for the same delay as well.
It’s time to make a simple state-machine with three states:
The “Granted” and “Denied” states can be switched one to another at any moment. But the “Idle” state can be turned on only when the delay of the active state is over. It also is the default state when the device boots. Let’s implement the states using the boolean logic and a special node for dealing with delays.
xod/core standard library contains a useful node for such cases:
overrun. It delays switching
EN from true to false for the specified amount of time.
Let’s enable overrun on any tag is detected. The node emits a pulse on the
DONE output when overrun is over. First, we implement our state “Idle”: place the
any node, link it with the
DONE output and bind the
Boot value to the second input pin. This way the idle state will be activated on the boot or when the delay of overrun is over. Let’s link it to the
S3 using a pair of bus nodes.
overrun node outputs
true to the
ACT pin while the delay is in progress. For our case, this means we are still in “Granted” or “Denied” state. To check whether we are in the “Granted” state, use the
and node with
ACT as inputs. It will output
true only when the state machine is in the “Granted” state. That’s what we need. Once access is granted we should engage the relay and show the corresponding message on the display, and keep the system in this state. Use a
flip-flop node for this. We’ll set the flip-flop to
true once the access is granted. We should reset the flip-flop whenever the access is denied or we enter the idle state.
Well done! You did it.
What if you want to grant access for the multiple tokens?
Create a few more patches like a
key-token, validate each of them and combine all
GOOD outputs using the
or node and all
BAD outputs using the
You’ve got a working smart NFC lock. You can improve it or make something different using the same modules or parts of the program. But we have some ideas to improve the same lock, which can help you get a deeper knowledge of programming in XOD: