Click here to Skip to main content
13,141,429 members (87,135 online)
Click here to Skip to main content
Add your own
alternative version


201 bookmarked
Posted 29 Apr 2016

DIY electronic RFID Door Lock with Battery Backup

, 13 Sep 2017
Rate this:
Please Sign up or sign in to vote.
An electronic door lock that replaces a mechanic key by an RFID card or RFID token.
NEW: This is the first Desfire project that has ever been written for Arduino/Teensy!
With very few changes you can also compile the code on Windows, Linux or other platforms.

About Burglars


Recently the Spiegel published an article about burglars in Germany:

  • Burglars prefer the dark months. In december the insurances report 3 times more housebreakings than in july.
  • The police reports that it is very difficult to find the delinquents. Mostly there are no witnesses and no traces. Only in 2,6% of the housebreakings the culprit can be condemned.
  • Burglars do not only break into houses of rich people. Everybody can be the victim. In nearly every house they find handies, laptops or money in cash. Especially drug addicts chose houses in their near environment.
  • According to the experience of the police the best prevention is a mechanical protection at doors and windows and attentive neighbours. Mostly burglars try only 2 - 3 minutes to break into a house. But in 60% of the cases they are successful.
  • This article tells that the German police observes that more and more housebreakings are organized by professional gangs from Serbia, Romania, Turkey, Albania and Georgia.
  • There is also another article with a map of Germany that shows the cities where the majority of housebreakings take place. The police counted 152.000 cases in 2015 - tendency increasing.

The majority of door locks is highly insecure

Does your door lock protect you against burglars ?
If your key looks like this one:

it surely does not.
Your door can be opened within a few seconds and you don't even notice that someone has entered while you were not at home, because there is no damage, neither at the door nor at the lock. Also your neighbours will not hear anything because lockpicking is absolutely silent.

You don't believe that ?
Then watch this video:


As you have seen: Lockpicking is very easy.
A thief does not even need special tools. He can open your lock with two hairpins!
When you search for "lockpicking" on Youtube you will find 169.000 results.

With electrical vibrators (pick gun) it takes less than 10 seconds to open a lock as you see in this video.

Even for cross locks there are special lockpicking tools that open a lock in 10 seconds as you see in this video.

Better mechanical locks

There are better locks where the key has round holes instead of notches like this KESO 2000 key.

These locks are very expensive. Nevertheless they can also be opened by lockpicking, although it may takes 3 minutes to open them as you see in this video.

Finally locks can be broken with a big plier or opened with a drill as you see in this video.

Conclusion: You will not find a mechanical lock that is really safe.

Copying of keys

If you rent a flat, your tenant can make copies of the key and give them to other persons. So he can sublease your flat. And if he leaves some day and you want to rent the flat anew, you have to change the lock because otherwise the previous tenant can still access the flat.

Electronic door locks

The advantage of an electronic door lock is that the above security issues do not apply.
It is much better to have a safe door lock which prevents that the thief can enter than to have an alarm system which makes noise when the thief is already in. Until the police arrives he will be gone and probably some precious things will be missing. Secure locks are always better than alarm systems or cameras.

What are the options on the market?
I searched for an electronic alternative, but what I found did not satisfy me:

  • There are fingerprint readers, but I did not find a waterproof one, so not usefull for outdoor installation. Additionally you expose an electronic device to the street which a malicious person might destroy easily.
  • There are these electronic door locks that you probably have seen in hotels, that open the door with a card.
    But these are for indoor installation only and they depend on a tiny battery in the lock that soon will expire.
  • None of the electronic solutions that I found will work when you have a power failure because they all lack a powerfull backup battery. A lock that does not open in case of a power failure is useless.
  • Mostly the electronic solutions are much too expensive.

My project

So I designed my own solution with the following characteristics:

  1. Designed for the main door of the building: No electronic device is exposed to the street or to the rain. You just mount an RFID reader on the inside of the door which reads the RFID card through the closed door.
  2. There is nothing visible from the outside of the door that could be manipulated by an intruder.
  3. A powerfull backup battery assures that the device is working even after a power failure of several days.
  4. The microprocessor manages charging the battery.
  5. Provides a very easy to use interface accessible through an USB cable with a terminal program which lets you add or remove users within a few seconds. Even a computer beginner can manage the user authorization quickly.
  6. You can store 64 users with their cards in the EEPROM of the microprocessor. More then 64 users are possible by modifying the source code.
  7. The access to the terminal interface can be protected with a password.
  8. If you or your tenant loses the RFID card, you can easily delete the card from the EEPROM without having to change the mechanical door lock.
  9. I designed a layout for the board that can be soldered by an electronics beginner.
  10. The entire solution is cheap compared with commercial solutions.
  11. Supposed that you have a secure door that cannot be opened with a crowbar, this solution is much cheaper than any insurance that you pay your entire life. I don't pay any insurance anymore.
  12. The entire project has been designed and tested by a very experienced hardware and software engineer.

RFID cards and tokens

What will replace your mechanic key?
You can either chose an RFID card or a token like these:

Mifare RFID cards

The cards are sensible to bending so you should carry them in your wallet rather than the pocket.

Each RFID card or token has a unique ID number, which is assigned by the factory and which cannot be modified afterwards. There are cards (like Mifare Classic) that have a 4 byte ID which allows 2^32 possible ID's and other cards (like MIFARE Desfire) that use a 7 byte ID which allows 2^56 possible ID's: Far more than any mechanic key will ever have.

My project supports any 13,56 MHz cards that comply with the smartcard standards ISO 14443 A and B, or ISO 18092. More details in Wikipedia.

You can compile the source code for two possible operation modes:

  1. For Mifare Classic cards: In this mode only the ID of the card is used to recognize a user and open the door. (not recommended)
  2. For Mifare Desfire cards: In this mode a cryprographic key of 128 bit or 168 bit protects the access to your door.

But even in Mifare Classic mode a brute force attack is impossible because the attacker does not know your card ID, which means that he would have to try 2^32 or even 2^56 possible card ID's. This is not possible because the code running in the Teensy makes a delay of 1 second after an invalid trial to open the door. The attacker would not live long enough to test all possibilities because this would take 140 years.

Mifare Classic Cards

It would be possible to store a secret value on the Mifare Classic cards and protect it with a key. But this does not make sense because the encryption of Mifare Classic has been broken. When Philips designed the Classic cards they made the error to implement a weak cryptographic algorithm (Crypto-1) and trust in "security-through-obscurity". The reason that these cards are so wide spread (over 4 billions sold) is that the algorithm has been kept secret for 14 years. But in 2008 a research team analyzed the chip under a microscope and the algorithm implemented in hardware could be deduced. They found that the key is a 48 bit key with several design flaws. You find more details in Reverse Engineering Mifare Classic cards.pdf in the ZIP file. The result is that today Mifare Classic cards can be cloned in a few seconds including all the data stored in the EEPROM even if the data is protected with a key.

Normally the unique ID of a RFID card is assigned in the factory and cannot be modified afterwards. But on eBay you can buy chinese clones which allow to write any ID to the card. (Search for "UID changeable card")

So it would theoretically be possible that a malicious person reads your Mifare Classic card through your pocket and clones it to get access to your house. This could be done with an Android NFC application that communicates with RFID cards. There are also devices like the Tastic RFID Thief which can read RFID cards from a distance of half a meter. So if you decide to use Mifare Classic cards you should buy a Stainless Steel Wallet which has a metal shield that blocks any external RF frequency getting to your card, so cloning your card becomes impossible:

Stainless Steel Wallet

Old Mifare Desfire Cards

In 2002 Philips introduced the Desfire cards which do not rely on a proprietary algorithm anymore. Desfire uses (as the name says) DES encryption. However for the first generation of Desfire cards an attack has been published that allows to obtain encrypted data from the EEPROM by a Side Channel Attack. With a complex hardware the power consumption of the card is measured during the encryption process. But this attack is far more difficult than the Mifare Classic attack and takes about 7 hours.

You find a video on Youtube where Timo Kaspar from Ruhr University in Bochum, Germany explains (in english) how they hacked the old Desfire cards. At 18:20 minutes he starts speaking about the Desfire attack and how they extracted all the encryption keys from the card, but the rest of the video is also very interesting.

You should not use the old Desfire cards anymore. My project does not support them because they require legacy authentication which is not implemented.

Mifare Desfire EV1 Cards

In 2009 the next generation came on the market: the Mifare Desfire EV1 cards which have been improved once again and until today no attack is known. So if you use Desfire EV1 cards you do not need a Stainless Steel Wallet.

Buying Desfire EV1 cards is more difficult. There are not so many offers and the cheaper ones require that you buy quantities of 50, 100 or even 500 cards. I found these two companies which sell also smaller amounts: RyscCorp and Smartcard Focus. You can also order from Smartcard America who sell via eBay but their shipping is very expensive to other countries.

Be carefull with counterfeit offers from China on eBay: There is no guarantee that chinese clones fulfill the same security criteria as original NXP cards.

Comparison Mifare Classic <-> Desfire

 Mifare ClassicMifare Desfire EV1
Unique Identifier4 bytes
UID can always be read without encryption
7 bytes
UID can always be read without encryption in normal mode, but requires the PICC master key in random ID mode.
EEPROM StorageOn a card with 1kB memory:
16 sectors of 4 blocks of 16 bytes each
(Blocks and sectors have fixed size)
Up to 28 applications of which each can contain up to 32 files of variable size
KeysEach sector can be protected with two keys (key A and key B) with different permissions per keyEach application can be protected with up to 14 different keys with different permissions per key
EncryptionProprietary (Crypto-1, 48 bit)DES (56 bit), 2K3DES (112 bit), 3K3DES (168 bit), AES (128 bit)
SecurityEncryption has been cracked in 2008No attacks known today

While Classic cards are completely static, the Desfire cards store data in "files" of dynamic size that are contained in "applications". What is an application? An application is nothing more than a container for files.

Imagine a RFID card issued to the students of a university.
With the same card the student can eat in the canteen and he can park his car.
In this example there would be two independent applications on the card: One canteen application and one parking application.
The student can charge money for lunch and for parking which is stored in a file in the corresponding application.
Each application has one or multiple encryption keys (the application keys) which allow to change the value stored in the respective application.
Each key may have only read permission, only write permission or both.

Additionally the card has another important key: The PICC master key, which is the "god key".
The PICC master key allows to create and delete applications, assign keys to each application or even format the entire card. But interestingly the PICC master key can NOT access the data stored in the applications.

Neither the canteen nor the parking deck know the PICC master key.
They have only access to their corresponding application but not outside of it.

The RFID reader

The PN532 breakout board from Adafruit (USD $40) has a chip from NXP (former Phillips).
When you order this board, it ships already with a white MIFARE card.
The board has a size of 12 cm x 5 cm and a thickness of 3 mm.
It works internally at 3,3V, but can be fed with 5V.

This board does not only read Mifare cards. It reads also your biometric passport, FeliCa cards and does NFC (Near Field Communication). It also communicates with Mastercard and Visa which have RFID integrated (PayPass, PayWave, ExpressPay), Calypso and many more...

The major advantage of this board over other hardware is that the antenna (printed on the board) is very big (size of a RFID card). This allows larger read distances than other hardware with smaller antennas.
Adafruit says that the antenna detects a card from a distance of up to 10 cm.
This is true for the white Mifare Classic card that ships with the board.
But I have another card (from public transportation) that requires 7,5 cm to be detected.
And I have a token that requires 5,5 cm to be detected. (The antenna in a token is smaller than the antenna of a card)

For Desfire EV1 cards the maximum distance despends on the encryption, because encryption increases the power consumption of the card:

  • If compiled in Classic mode (no encryption used) the distance can be up to 6,3 cm.
  • If compiled in Desfire mode with DES encryption the distance can be up to 5,3 cm.
  • If compiled in Desfire mode with AES encryption the distance can be up to 4,0 cm.

Additionally I measured that the card consumes more power the more memory it has.
A 4 kB card can be read from a larger distance than an 8 kB card. The difference is approx 5 mm.
As my project occupies only a few bytes of the card's EEPROM you should buy the smallest cards that you can find.

You mount the breakout board on the inside of your door.
You can mount a plastic or wooden box on top of it to protect it from mechanical damage.
Into that box you also mount a two-color LED (red / green) that always shows if the system is working properly.

A long flat cable connects it with the main board.
Here you see a foto of the breakout board with the flat cable and the two-color LED connected:

PN532 board

First you must solder two jumpers on the board that define the communication mode.
I2C is too weak over a longer cable because I2C is an open collector bus with pull up resistors.
I use SPI communication with a low speed of 10 kHz.
So you must set the jumpers: SEL0 = OFF and SEL1 = ON.
Read Wikipedia about SPI and I2C.

Intentionally I do not use any plugs here because a soldered connection is much more secure on a door, that may be slammed.

The cable connection between the boards

Between the breakout board (mounted on the inside of the door) and the main board (that you put in a safe place near the door) there is a longer cable required. I use a flat cable of 10 wires.
If you don't want to use a flat cable you can also use a network cable. But network cables have only 8 wires. In this case you can mount the LED at another place (not on the door) and you will need only 8 wires.

SPI buses run normally with speeds of several Megahertz. This cannot be transmitted over longer cables. So I use SPI at a speed of 10kHz. Even over a cable of 3 meters the signals look absolutely clean on the oscilloscope. I suppose that even 10 meters would work without any problem.

When using Defire cards you could even attach an SPI spy to the cable but you will never see a cryptographic key transmitted over the cable. During authentitacion only encrypted random values are transferred and during a key change the new key is sent encrypted with the secret session key that never leaves the Teensy.

Teensy 3.2

The heart of the main board is the microprocessor. I use a Teensy 3.2 from
Teensy has several advantages compared with other Arduino-like boards:

  1. It is very fast (32 bit ARM processor running at 96MHz)
  2. It is very tiny (3,5 cm x 1,5 cm)
  3. It has more RAM (64 kB) and flash program storage (260 kB) than other boards and it has an EEPROM.
    The newer Arduino boards (Due, Zero, 101) have no EEPROM at all, which makes them useless.
  4. It is cheap (USD $20)
  5. The power consumption is low.
  6. It works internally at 3,3V, but can be fed with 5V.
  7. The Teensy library (TeensyDuino) has more and better functionality than the offical Arduino libraries.

First you must destroy a tiny jumper on the bottom side of the Teensy with a cardboard cutter.
Otherwise the 5V coming from the USB cable would be connected directly with the 5V power of the main board.
This would result in a current flowing if the main board is turned on while the computer is turned off or vice versa.

Teensy 3.2

The Battery

To back up the system in case of a power failure I use a 12V lead-acid motorcycle battery. The entire system is running permanently from battery. The battery delivers the high current (1..2 Ampere) required to open the door.

If there is a power failure, the battery can keep the system running for approx five days.

The microprocessor holds the battery voltage permanently at 13,6V. At this voltage (the so called "float charge") the battery has the longest life. If the battery would be charged and discharged in longer intervals the life would be shortened.
A too high voltage (> 14,4V) results in grid corrosion of the positive electrode.
A too low voltage results in sulfation on the negative plate.

At 13,6V the battery has a very high impedance. When you unplug the charger you will see that the voltage falls quickly (within 2 minutes) from 13,6V to 12,8V and then very very slowly to 12,0V (within several days). This is normal.

Lead Acid Battery charge curve

This diagram shows the charge state of a lead-acid battery which can be directly deduced from the voltage.
You see that at 12,8V the battery is 100% full.

You find a lot of details about batteries at

I use the model YTX7A-BS which has 6Ah. (USD $30)
This lead battery is MF (Maintenance Free) which means that you will never have to fill destilled water into it as it was necessary in the good old days. When you buy it, it comes dry with 6 separate tanks of acid. You fill the acid into the battery and after some hours the liquid converts into a gel. Then you close the battery and open it never again.

As the content of the battery is not liquid anymore it is possible to mount the battery in any position. It must not be vertical. You can lay the battery on the back side and mount the main board on top of it to save space.

Lead-Acid batteries don't like high temperatures and you should store them only in charged state, otherwise their life is shortened.

Be very carefull with the battery! If you produce a shortcut, the current that flows will be more than 100 Ampere! Anything between the poles will convert into a cloud of smoke!

The Main Board

RFID Door Access System

The flat cable at the left connects to the RFID reader. The cables at the right connect to the door 1 opener solenoid and to the power line (220V).

Here is the circuit diagram:

RFID Door access system

When the relay switches the door opens. The relay is activated for 100 ms (the interval can be configured in the source code).

The transformator has just the power to charge the battery with 200 mA. The battery should not be charged with a current higher than 10% of it's capacity, otherwise the lifetime would be shortened. For a 6Ah battery this results in a maximum charging current of 600mA.
A 12V transformator delivers a peak voltage of 12V * √2 = 17V. When connected to the battery this voltage collapses to the actual battery's voltage.

The BD680 is a PNP darligton transistor with integrated resistors:
Here this transistor acts like a switch. The Teensy processor measures at one of it's analog input pins (A9) the battery voltage. The battery voltage is kept permanently between 13,5V and 13,7V by switching the BD680 frequently on and off.

When the processor detects that something is wrong with the voltage (< 13,0V or > 14,0V) the red LED will flash to show that there is a problem. The cause may be a power failure or a defect.

The resistor marked with a yellow exclamation mark acts like a fuse. In case of a shortcut in the 7805 or a shortcut in the rectifier it will die and avoid that more than 100A flow through the circuit. This resistor should be 1/4W.

Parts List

  • 1 x Adafruit PN532 (comes with one Mifare Classic card)
  • 1 x Teensy 3.1 or 3.2
  • 1 x Motorcycle battery 12V, 6Ah, MF
  • 1 x Breadboard 13,5 cm x 11 cm (or 13,5 cm x 6 cm if you use an external transformator)
  • 1 x 7805
  • 1 x BD680
  • 2 x BC546
  • 1 x 1N4148
  • 1 x Relay: Solenoid 12V, Switch 220V, 16A
  • 1 x Two-color LED (red / green)
  • 1 x Rectifier at least 80V, 1A or better 400V, 3A for a very long life
  • 1 x Transformator 12V, 0,5A     (12V AC, not more, not less, and no DC power supply!)
  • 1 x Fuse 30 mA
  • 1 x Fuse socket
  • 1 x 0,22 Ω, 1/4W
  • 2 x 820 Ω, 1/4W
  • 3 x 10 kΩ, 1/4W
  • 1 x 220 kΩ, 1%, 1/4W
  • 1 x 15 kΩ, 1%, 1/4W
  • 1 x Rx (see next chapter)
  • 1 x 330 nF, 63V
  • 2 x 1 µF, 50V      (Electrolyte has a longer life than Tantal)
  • 1 x 10 µF, 35V     (Electrolyte has a longer life than Tantal)
  • 1 x Header, 10 pin, male, with gold contacts
  • 1 x Shrouded Box Header, 10 pin, female, with gold contacts
  • 1 x Long flat cable of 10 wires
  • 1 x Long 2-wire cable for door opener (for 2A current)
  • 1 x Power cable with power plug
  • 1 x Thick copper cable, 1 mm diameter, red (for battery)
  • 1 x Thick copper cable, 1 mm diameter, black (for battery)
  • 1 x USB micro cable
  • 1 x Heat shrink tube, diameter 3 mm, length 20 cm (for LED)
  • 2 x Screw M3 + nut + washer (for transformator)
  • Additional Mifare cards or tokens

If you want to open 2 doors independently you need additionally:

  • 1 x Relay: Solenoid 12V, Switch 220V, 16A
  • 1 x 1N4148
  • 1 x BC546
  • 1 x 10k Ω
  • 1 x 330 nF, 63V

If you don't have a local electronic shop you can order everything in this list from DigiKey or Farnell or TME or Newark which are very good online mail-order sellers offering hundreds of thousands of electronic parts.

My circuit has been designed only for a 12V transfomator (AC) and nothing else than that. If you connect a DC power supply you will shorten the life of the BD680 and of the power supply because of the high currents that will flow when the transistor switches.

The Board Layouts

In the ZIP file you find my design for a single layer breadboard to be soldered manually (Board1). This board is very easy to solder even for electronic beginners. It took me only half a day to connect everything.

Additionally you find a Board 2 that has been designed by Josef Krusch on Eagle 7.6. You can open the Eagle files with the freeware version of Eagle. If you want a professional board you can send this board to a company that makes a double layer PCB from it.

On both boards you see two relais. The upper relais is optional. It allows to open two doors independently. If you don't need that you can omit the upper relais, it's BC546, the 10kΩ, the 1N4148 and the 330nF.

How to calculate Rx

The resistor Rx limits the current through the door opener solenoid which you see in the picture below.
Here you see the lock opened (bottom plate removed).
I mount this lock on top of the inside of the door. I removed the former key lock so there is nothing that can be manipulated from the outside.

Scanavini doorlock

First you connect the solenoid to a regulatable DC power supply. Rise the voltage from zero slowly up until the lock opens.
In my case this happens at 2,8V.
But this is too insecure. A higher voltage must be applied to be sure that it always opens.
I chose to apply 3,5V.
Then I measure the current that flows at 3,5V which is 1,3A.

As I have to open two doors simultaneously I connect both solenoids in series.
So I need 7V at a current of 1,3A for both.

At Rx there will be a voltage of 12V - 7V = 5V which results in a resistor of:

R = U/I = 5V/1,3A = 3,8 Ohm

Now calculate the power of the resistor:

P = U*I = 5V*1,3A = 6,5W

If your local electronic shop does not have this value you can switch multiple resistors in parallel.
For example 4 * 15Ω of which each should have a power of 2 Watt.
This will result in a total resistor of 3,75Ω with 8 Watt.

To calculate two resistors in parallel you can use the formula:

R total = (R1 * R2) / (R1 + R2)

The meaning of the LED

The two-color LED should be mounted on the inside of the door or at any place where it is visible.
It constantly shows if everything is working correctly.

Green LED permanently flashing fastEverything is OK
Green LED flashing once for 1 secondThe door is beeing opened for an authorized person
Red LED permanently flashing fastThe battery voltage is out of range. The cause may be a power failure or a defect.
Red LED flashing once for 1 secondAn unauthorized person tries to open the door with an invalid card or token.
Red LED permanently flashing very slowlyShows a comunication problem with the PN532 board. This is a severe error.
The LED is permanently offThis indicates a defect.

Optimizing Power Consumption

Everything has been done to reduce the power consumption:

The highest power consumption comes from the PN532 board: As chipcards and tokens have no battery, they must be powered externally.
The PN532 has to generate a RF field of 13 MHz that feeds power to the chipcard through the antenna. When generating that field, the PN532 consumes 110mA. There is a command that allows to turn the RF field off. But without RF field there is no card detection possible. So what my code does is to turn on the RF field for 100ms to check if there is a card and then turn off the field for 1 second. When the RF field is off the PN532 consumes only 18mA. The result is an average consumption of 26mA.

The power consumption of the Teensy is 40mA at a CPU clock of 96MHz. As such a high speed is not needed, the clock is set to 24MHz which reduces the power consumption to 20mA.

Finally the total current is on average 46mA.

The interval that the relay is powered is optimized. A high current is flowing through the solenoid. You have to test which interval works for your solenoid. You can modify that in source code. In my case the solenoid already works with an interval of 20 ms. But to make it bulletproof I programed 100 ms.

Life Expectations

Today we are used that electronic devices have a short life, especially those that come from China.
But it has not been like this ever since.

Once upon a time there was the good old "Made in Germany" which always meant high quality and long life. I have an amplifier from Grundig that I bought in the beginning of the 1990's. It is still working today. I repaired it only once in neary 30 years!

But already in the 1980's the first japanese products came on the market which were just cheaper but worse in quality. In those years the clients have chosen that they prefer to pay less for a cheaper japanese product than for a high quality german brand. In these years there was a high quality decrease world wide. Today China is continuing these tendencies.

There are even people who suspect that companies build their devices intentionally to have a short life ("Planned Obsolescence"). But this could not be confirmed till this day. The truth is that the industry is in a hard price war. Companies HAVE to design their products cheap because otherwise the client will not buy them. The client is the culprit because he is not willing to pay more for higher quality. Do you remember the war between the cheap japanese VHS and the much better german Video 2000? The worse system won the war because the client didn't want to pay the price that quality costs!

How do companies lower the price? In the first place by using the cheapest electronic parts possible. The result is that often parts are underdesigned. If for example a transistor is designed for a maximum voltage of 1500 Volt and it is running permanently with a voltage of 1200 Volt it is obvious that this transistor will have a short life (approx 5 years), because it is permanently running at it's limits. On the other hand a transistor designed for 100 Volt, but running at 5 Volt will have a significantly longer life (> 30 years). The same applies for currents.

Also mostly the coolers for power transistors or ICs are designed too small (or even missing) to save money and space.

Another common cause for failures are plugs and switches. With the years their contacts oxidate and the connection may get lost completely. Good plugs have golden contacts, but as gold is expensive, companies mostly don't use them.

But also the other extreme exists. Think about high quality electronics that must not fail:
For example in medicine, in a satellite or in a military jet.
Here the engineers surely will NOT chose the cheapest parts (that run at their limits) to make the electronic as fail safe as possible. They may even add electronic parts that take over control when other parts fail. For example 5 condensators switched parallel where one would be enough.

I have repaired electronic devices for many years and a lot of experience which are the electronic parts that fail first. These are generally semiconductors that work with high voltages, high currents and that become hot. Also electrolyte condensators that operate with high currents are failing frequently (which is the most common reason for the death of switched-mode power supplies).

I have designed this door opener for a long life. There are no parts that become hot. The high current for the door opener solenoid is switched by a relay rather than a transistor, because relays are much more robust.

The BD680 tolerates up to 4 Ampere but here it switches only 200 mA. This is equivalent to 5% of it's potential.

I recommend to use a rectifier that tolerates 3 Ampere although only 200 mA are flowing.

You should avoid plugs wherever possible. In my foto you see that the Teensy is soldered directly on the board just to avoid contact problems in the future. The plug for the flat cable should have gold contacts.


The only part that you should replace after some years is the battery.

Finally I suppose that the life expectation of the electronics should be 20 - 30 years or even more.

Loading the firmware into the Teensy

  1. Option A:
    You can either install the Arduino compiler from and the Teensyduino library from and compile the sketch that you find in the ZIP file above. You must configure the compiler settings like this:

  2. Option B:
    Or you don't install anything and load the precompiled firmware directly to a Teensy 3.1 or 3.2 board. You find the HEX file and the TeensyLoader.exe in the ZIP file.

Communicating with the Teensy

You need a Micro USB cable to connect your computer with the Teensy.
First you have to install the Teensy Serial driver that makes the Teensy appear as a virtual COM port on your PC.
You find the driver in the ZIP file.

You can communicate to the Teensy with a terminal program.
You can use the freeware TeraTerm or the Serial Monitor that is built into the Arduino Compiler.

You don't have to care about the baudrate, because theTeensy ignores it (unlike older Arduino boards). The data is always transmitted with USB speed.

If you use the Serial Monitor you must select the COM port (Menu "Tools", see image above) and configure it to send LineFeeds:

If you use TeraTerm you only have to select the COM port:


IMPORTANT: If the Teensy does not have power (if you disconnect the battery) or if you press the "Program" button on the Teensy while the COM port is open in the terminal program you will first have to close the COM port, disconnect the USB cable, reconnect it and then open the COM port anew!
To avoid this you should first close the COM port (Menu "Disconnect" in TeraTerm) before you remove power supply from the Teensy or press the "Program" button.
The reason is that Windows does not remove the COM port while any program has the port still open (although the Teensy has already been disconnected).

Managing Users

After opening the COM port in the terminal program you will first see nothing.
If password protection is enabled you must enter the password now and hit Enter, otherwise you only hit Enter.

In both cases the main menu will appear:

The menu shows the available commands and the actual status.
You can store more than 64 users in the EEPROM if you reduce the amount of characters for the user name.

The first thing that you always have to do on a new Teensy board is to clear the EEPROM:
Type "clear" and hit Enter.

To add access permission for a new user, type "add" followed by the user name and Enter.

As you see, these cards use a 7 byte UID (Desfire).
Apart from storing the card ID and user name in Teensy's EEPROM several steps are executed on a Desfire card. See below.

It is possible to store multiple cards for the same user name.
If you later delete that user with the DEL command all his cards will be deleted at once.
If you prefer to be able to delete the cards individually you can give each card a unique name like "John Hilton 1", "John Hilton 2", etc...

By default a new user can open only door 1. You can give the user permission to open one of the doors or both.

To show all users that are authorized, use the LIST command. Users are sorted alphabetically.

This command deletes a user and his card from the EEPROM so he will not be able to open the door anymore.
The DEL command does not require a card to be present, so the changes made on the card will not be reverted.
Use this command if a user has lost his card.

The RESTORE command also deletes a card and it's user from the EEPROM, but it additionally reverts all changes on the card.
RESTORE resets the PICC master key to the factory default key and deletes the application that has been created on a Desfire default card.

The RESET command pulls the RSTPDN line of the PN532 to LOW for 400ms which resets the board.
Afterwards the chip initialization runs anew and the capabilities of the chip are read.

Apart from this command the PN532 is automatically reset when a communication error has been detected.

This command configures a Desfire card to always send a different random ID and hide it's real UID.
See below for more details about the different operation modes.

Executes a Selftest that tests all Desfire commands. (see below)

The PN532 Communication Protocol

The PN532 uses a very complicated communication protocol. You find the description in the manual in the ZIP file.

PN532 communication

  1. First the Host sends one single byte (DW = Data Write) which tells the PN532 that now data will be sent.
  2. Then the host sends a command frame which contains an instruction to be executed.
  3. Then the host sends one single byte (SR = Status Read) that asks for the status of the PN532.
  4. If the PN532 is not yet ready it responds with a 0x00 byte. This means that the host has to wait. When the PN532 is ready it responds with a 0x01 byte.
  5. Then the host sends one single byte (DR = Data Read) which tells the PN532 that it expects a data packet.
  6. Then the PN532 sends an ACK frame (Acknowledge) which is a fixed sequence of bytes (00, 00, FF, 00, FF, 00). This confirms that the command has been received correctly.
  7. Then the host sends one single byte (SR = Status Read) that asks for the status of the PN532.
  8. When the PN532 is ready it responds with a 0x01 byte.
  9. Then the host sends one single byte (DR = Data Read) which tells the PN532 that it expects a data packet.
  10. And finally the PN532 sends the response frame.

The Data Frames

The Command frame and the Response frame look like this:

PN532 command

The Preamble and Postamble are optional.
The receiver of the packet must first search for the start sequence {00, FF} which marks the begin of the packet.
Then comes the length of the data followed by a length checksum.
The frame identifier (TFI) is 0xD4 if the frame is sent from the host to the PN532 and 0xD5 for the opposite direction.
After the packet data comes a checksum.

The Adafruit Library

A library of 1000 lines of code is required to communicate with the PN532.

From the Adafruit site you can download an Arduino code and samples that show the communication with the PN532. But sadly this code can only be used for testing but the code is sloppy and buggy and cannot be used in production.
I had to rewrite the Adafruit code completely. Here the list of my changes:

  1. Removed all compiler warnings that appeared when compiling Adafruit code.
  2. Bugfix: (Severe bug) Adafruit used strncmp() to compare binary data (which contains zeroes). This is completey wrong -> replaced with memcmp()
  3. Bugfix: (Severe bug) Adafruit code does not check for valid response packets. The checksum is completely ignored. Bytes received before the start code are not skipped!
  4. Bugfix: (Severe bug) Adafruit code used a timeout = 0 (wait forever). This is completely wrong. If the chip does not respond, the code hangs forever! My code is "self healing" which means that even after unplugging the PN532 board and reconnecting it, the chip will be reset and afterwards it works again.
  5. Bugfix: Adafruit code does not allow to distinguish why readPassiveTargetID() returns false. (Because there is no card or because of a communication problem?)
  6. Added support for Value blocks (in Mifare.cpp)
  7. Added memory Dump (in Mifare.cpp)
  8. The IRQ line is not required anymore in I2C mode. Now the software handshake is used instead.
  9. Software SPI slow speed added (to get 10kHz clock)
  10. Implemented the correct wake up procedure (sending PN532_WAKEUP) instead of sending getFirmwareVersion.
  11. Debug output was buggy: The checksum bytes were displayed as 0xFFFFFFFC instead of 0xFC. Removed useless "0x" before each byte.
  12. Detailed debug output was missing.
  13. Added display of valid data bytes inside the packet in debug output.
  14. Using getFirmwareVersion() was very clumsy -> completely rewritten
  15. writeGPIO() rewritten -> no warning about wrong usage anymore.
  16. AuthenticateDataBlock(), ReadDataBlock() and WriteDataBlock() rewritten.
  17. setPassiveActivationRetries() did not have any error checking at all.
  18. Ugly code in writecommand() completely rewritten
  19. Crappy code like this removed: int offset = _usingSPI ? 5 : 6;
  20. The library completely avoids the new operator.

My new PN532 library, that you find in the ZIP file, supports 3 communication modes:

  1. Software SPI:
    This one is used because it allows to throttle the SPI bus to run at 10kHz for transmission over a long cable.
    The advantage of Software SPI is that you can chose any Teensy pin for SCK, MISO, MOSI and SSEL.
  2. Hardware SPI:
    This also works but one disadvantage is that the Teensy uses the same pin for hardware SCK as the built-in LED on the board. (Pin 13) So the LED cannot be used in this mode. Additionally the Teensy library does not allow to set a clock of 10kHz.
  3. I2C:
    This also works but an open collector bus cannot be transmitted over a long cable. I changed the I2C code so that the IRQ line is not needed anymore.

Read Wikipedia about SPI and I2C.

The Desfire EV1 Library

In addition to re-writing the PN532 code I created a new Desfire library (about 2700 lines of code). Currently there is no code available in internet to control Desfire cards with Ardiuno/Teensy.

This is the first library that has ever been written for the Arduino family. You have to change only a few lines in Utils.h and you can compile the library on Visual Studio, Linux or other platforms.

Using my library is very easy and the integrated Selftest gives a living example how to call the functions.
The library completely avoids the new operator.
The code is professional C++ code, reusable, very well structured and commented.

The library will not work with old Desfire cards (deprecated) because legacy authentication is not implemented. You really need EV1 cards.

If you search a datasheet for Desfire EV1 cards you will only find the "short version" on the NXP website which is quite useless.

To get the complete documentation you have to make a Non-Disclosure Agreement (NDA) with NXP where you promise not to give this documentation to anybody else. This NDA is made only with companies. It is incredible that NXP did not learn from their own errors in the past. Did the Mifare Classic desaster not show clearly that "security-through-obscurity" does not work? Is Windows more secure than Linux because Microsoft maintains the source code secret? And does NXP really believe that hiding information still works in the age of file sharing, Wikileaks and Edward Snowden? Or is NXP so naive to believe that a chinese company, that wants to produce a counterfeit card, is not able to obtain that documentation? Whatever might be the idea behind that NDA: Any sane person will agree that it is pure nonsense.
However, I never made that contract with NXP and so I do not have the full documentation.

But this documentation is not needed at all because I found some Desfire open source projects that are hosted on Github: easypay, libfreefare and liblogicalaccess. By studying their code, fixing their bugs, experimenting with the card and with the help of Google I wrote my own Desfire library:

GetCardVersion()Obtains details about the Desfire card like hardware and software version, EEPROM size, week and year of production, a batch number, etc..
FormatCard()Erases ALL content from the card except the PICC master key
Authenticate()Authenticates with a 2K3DES, 3K3DES key (ISO authentication) or an AES key either at the PICC level or at the application level
ChangeKey()Changes the PICC master key or any application key
GetKeyVersion()Gets the key version (an optional value stored in the key)
GetKeySettings()Gets the settings of a key (permissions)
ChangeKeySettings()Changes the settings of a key
GetApplicationIDs()Enumerates all applications on the card
SelectApplication()Selects an application to which the following commands will be sent
DeleteApplication()Deletes an application with all it's files and keys
CreateApplication()Creates a new application with 2K3DES, 3K3DES or AES keys. You can mix different key types on one card.
GetFileIDs()Enumerates all files in an application
GetFileSettings()Gets information about a file (file type, encryption, permissions, size, etc..)
DeleteFile()Deletes a file
CreateStdDataFile()Creates a Standard Data File (the file size can be defined at creation time but not changed later)
ReadFileData()Reads data from a file
WriteFileData()Writes data to a file
EnableRandomIDForever()Enables random ID mode where the card sends another ID each time (!This cannot be reversed!)
GetRealCardID()Obtains the real card UID. (Usefull in random ID mode)
Selftest()Executes a selftest that tests ALL the above commands on an empty card.
You find debug output of the entire selftest with all bytes sent and received in the ZIP file.

Writing this library was really a challenge, especially due to the lack of documentation. It took weeks of my life to finish this project. The most difficult parts are the authentication with a cryptographic key and the key change. During authentication random values are encrypted and exchanged between the card and the host to prove that both sides share the same master key. From these random values a session key is generated. All encryption goes through Cipher Block Chaining, where NXP distinguishes between Enciphering/Deciphering and Send Mode/Receive Mode. The cryptographic initialization vector (IV) is reset only once when authenticating, then for all further commands it must be maintained up to date. If your IV vector comes out of sync with the one that the card has calculated internally you will get an Integrity Error. All the data sent to the card and all the data received from the card must go though a CMAC calculation (something like a hash). Some functions calculate a CMAC, others do not. When changing a key, two CRC32 values have to be calculated and the old key and the new key are XORed, padded and then encrypted with the session key. Each type of key has it's own peculiarities: AES encrypts blocks of 16 byte while DES uses 8 byte blocks and the length of the key itself may be 8, 16 or 24 byte. As a consquence also the length of the random values and the session key vary with the key type. All this stuff is HIGHLY complicated and you have thousands of pitfalls. And the worst of all is that in internet you find nearly no usefull information. I feel like a pioneer in Defire EV1 development.

I have chosen the smallest open source crypto libraries that I could find: AES128 from Texas Instruments and 3DES from Eric Young. Although the entire Desfire source code has about 2700 lines, the size of the compiled code is small:

  1. Compiled for Mifare Classic cards it consumes 18% of the flash memory
  2. Compiled for Mifare Desfire cards it consumes 27% of the flash memory

So all the crypto stuff consumes only 9% of the flash memory. Please note that the compiler omits all functions from compilation that are not in use.

The Three Operation Modes

Depending on the compiler switches and the card types you can have 3 different operation modes:

  1. Compiled with #define USE_DESFIRE false you get Classic mode,
  2. Compiled with #define USE_DESFIRE true and default Desfire cards you get Desfire Default mode,
  3. Compiled with #define USE_DESFIRE true and random ID Desfire cards you get Desfire Random mode.

It depends only on the card if the system is working in Desfire default mode or in Desfire random mode. So these both types of cards can be used mixed at the same time.

To convert a default Desfire card into a random Desfire card you have to execute the command MAKERANDOM.
ATTENTION: If a card has once been converted to use random ID, NXP does not allow to reverse this anymore. (Why??)

 Classic ModeDesfire Default ModeDesfire Random Mode
Supported cardsClassic cards,
Desfire cards with default ID
Desfire cardsDesfire cards
Unsupported cardsDesfire cards with random IDClassic cardsClassic cards
Access to card UIDThe UID can be obtained always.The UID can be obtained always.The card sends a random ID. Getting the real UID requires cryptographic authentication.
User AuthenticationOnly by UID of the card.By the UID of the card and the application master key.By the UID of the card and the PICC master key.
SecurityNot secure because the card can be cloned very easily. In China you can buy cards that allow to write any UID. You need a stainless steel wallet to prevent this.Very secure because currently there are no known attacks on Desfire EV1 cards. The secret application master key (AES or 3K3DES) would be required to clone the card.Very secure because currently there are no known attacks on Desfire EV1 cards. The secret PICC master key (AES or 3K3DES) would be required to clone the card.
Card PersonalizationClassic cards are not personalized. (It would be possible to store secret data on a classic card but due to the broken encryption this would not be secure.)When the card is personalized (with command ADD) the PICC master key is changed into a secret key and a new file in a new application is created on the card that stores a 16 byte secret store value. The file and the application are protected with a secret application master key. The application master key is frozen, so it cannot be changed later. Both, the 16 byte secret store value and the application master key are diversified by deriving them from the card UID, the user name and additional random data that is stored in the EEPROM of the Teensy.When the card is personalized (with command ADD) the PICC master key is changed into a secret key.
Door AccessThe UID of the card is compared with the UID's stored in the EEPROM of the Teensy.The UID of the card is compared with the UID's stored in the EEPROM of the Teensy. After authentication with the diversified application master key the secret store value is read from the file and compared with the expected value.After authentication with the PICC master key the real card UID is read and compared with the UID's stored in the EEPROM of the Teensy.

In source code you can additionally chose which master keys you want to use for Desfire cards:

  1. Compiled with #define USE_AES true you use 128 bit AES keys (max. reader distance: 4,0 cm)
  2. Compiled with #define USE_AES false you use 168 bit 3K3DES keys (max. reader distance: 5,3 cm)

In source code you find the file Secrets.h which contains:

  1. The PICC master key (AES or 3K3DES),
  2. A cryptographic key (3K3DES) to derive the application master key from card ID, user name and random data (for Desfire default mode),
  3. A cryptographic key (3K3DES) to derive the secret store value from card ID, user name and random data (for Desfire default mode).

Before compiling the source code for the fist time you should change these 3 keys to anything else.

ATTENTION: If you already have personalized cards and then change the PICC master key in source code you cannot authenticate these cards anymore. Therefore it is important that you first execute the RESTORE command on all personalized cards and afterwards change the PICC master key in code. The RESTORE command resets the PICC master key to the factory default DES key full of zeroes.

Debug Level 1

If anything goes wrong in the communication you can use the debugging that I have implemented.

Via terminal enter the command "debug 1" to activate basic debugging.
Here you see a part of the debug output at level 1 when a default Desfire card is personalized:

NOTE: You find debug output of the entire selftest in the ZIP file.

Debug Level 2

Enter "debug 2" and additionally the data packets will be shown:

Now you see the commands sent to the PN532 and the responses received from the PN532.
The data bytes are marked between '<' and '>' characters in each valid packet.

The command ReadPassiveTargetID turns on the RF field and checks if there is a card present.
If there is no card, only 3 data bytes are returned (D5 4B 00).
The command SwitchOffRfField turns the RF field off to save battery.

If a card has been detected the response looks like this:

You see that now more bytes are transmitted. They contain the unique ID of the card and additional information about the card.
In this example the code has been compiled for Mifare Classic cards. The ID is 4 bytes long.
When the card is authorized, the door opens and the green LED flashes for 1 second.
If the card is not authorized, the red LED flashes for 1 second and the door does not open.

If the code is compiled for Mifare Desfire cards additional cryptographic operations are executed before the door is opened.

Debug Level 3

Enter "debug 3" to activate detailed debugging:

Now you see each and every byte that is transmitted between the Teensy and the PN532, including the ACK package and the status bytes.


Whenever the Teensy detects that the PN532 did not respond as expected, an error is printed to the terminal.

This example shows the case that the PN532 did not respond at all. The Teensy pulls the RSTPDN line to LOW to reset the chip, sends the WakeUp packet (see Manual) and tries again to communicate with the chip.

Additionally the red LED will flash very slowly so you see immediately that there is a severe error.

If you use Desfire cards you will probably see a Timeout Error from time to time. This happens only when the card is too far away from the antenna of the PN532. This Timeout means that the PN532 did not receive an answer from the card. In this case any further command sent to the card will return another Timeout error. Any communication with the card is stalled. The only way out is to call SwitchOffRfField() and connect again with ReadPassiveTargetID(). The commands executed first (GetKeyVersion() and SelectApplication()) work fine and when it comes to authenticate the communication breaks down. The reason is that encryption increases the power consumption of the card. Strangely AES uses more power than DES. When you use AES the card must be in a distance of 4,0 cm from the PN532. When using DES the distance can be up to 5,3 cm.

Note that there are basically two types of timeouts: (First the Teensy waiting for response from the PN532 and second the PN532 waiting for response from the card) If you put the card directly on the antenna of the reader you should never get a timeout error. Turn on Debugging to see what happens.

Another Teensy project

If you are interested, have a look at my first Teensy project that I published on Codeproject. It uses a Teensy to simulate mouse, keyboard and touchscreen via USB.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer (Senior) ElmüSoft
Chile Chile
Software Engineer since 27 years.

You may also be interested in...

Comments and Discussions

QuestionAuthentication question Pin
Member 1335139016-Aug-17 23:07
memberMember 1335139016-Aug-17 23:07 
AnswerRe: Authentication question Pin
Elmue20-Aug-17 17:27
memberElmue20-Aug-17 17:27 
QuestionMechanical question Pin
donald409-Aug-17 20:31
memberdonald409-Aug-17 20:31 
AnswerRe: Mechanical question Pin
Elmue13-Aug-17 17:52
memberElmue13-Aug-17 17:52 
GeneralRe: Mechanical question Pin
donald4013-Aug-17 20:53
memberdonald4013-Aug-17 20:53 
AnswerRe: Mechanical question Pin
Elmue16-Aug-17 6:08
memberElmue16-Aug-17 6:08 
GeneralRe: Mechanical question Pin
KerimF15-Sep-17 0:09
memberKerimF15-Sep-17 0:09 
QuestionCompiling in VS Pin
HBurga4-Aug-17 20:52
memberHBurga4-Aug-17 20:52 
AnswerMessage Closed Pin
7-Aug-17 15:55
memberElmue7-Aug-17 15:55 
GeneralRe: Compiling in VS Pin
HBurga7-Aug-17 21:14
memberHBurga7-Aug-17 21:14 
AnswerMessage Closed Pin
9-Aug-17 12:57
memberElmue9-Aug-17 12:57 
GeneralRe: Serial interface Pin
HBurga11-Aug-17 0:50
memberHBurga11-Aug-17 0:50 
AnswerMessage Closed Pin
13-Aug-17 17:44
memberElmue13-Aug-17 17:44 
GeneralRe: Serial interface Pin
HBurga13-Aug-17 19:41
memberHBurga13-Aug-17 19:41 
AnswerNew version solves compiler errors Pin
Elmue13-Sep-17 17:16
memberElmue13-Sep-17 17:16 
QuestionCompiling Errors Pin
HBurga30-Jul-17 10:27
memberHBurga30-Jul-17 10:27 
AnswerRe: Compiling Errors Pin
HBurga30-Jul-17 23:37
memberHBurga30-Jul-17 23:37 
AnswerMessage Closed Pin
7-Aug-17 15:46
memberElmue7-Aug-17 15:46 
GeneralRe: Compiling Errors Pin
Tommi768-Sep-17 11:05
memberTommi768-Sep-17 11:05 
AnswerMessage Closed Pin
8-Sep-17 16:09
memberElmue8-Sep-17 16:09 
GeneralRe: Compiling Errors Pin
Tommi769-Sep-17 0:38
memberTommi769-Sep-17 0:38 
GeneralMessage Closed Pin
9-Sep-17 9:19
memberElmue9-Sep-17 9:19 
GeneralSolved: strnicmp and stricmp Pin
Tommi7613-Sep-17 10:42
memberTommi7613-Sep-17 10:42 
AnswerNew version solves compiler errors Pin
Elmue13-Sep-17 17:18
memberElmue13-Sep-17 17:18 
QuestionMore Recent Cards. Pin
Souheil7-Jul-17 1:52
memberSouheil7-Jul-17 1:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.170915.1 | Last Updated 13 Sep 2017
Article Copyright 2016 by Elmue
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid