Proximity keyless entry

PKE will unlock your car when you approach it and lock it when you walk away. It's ideally suited if your car has central locking, but no remote.

Finished CAR and USR boards

How it works

The solution consists of two electronics - one in the vehicle (let's call it CAR, left on the picture above) and one you carry around (let's call it USR, right on the picture above). They communicate using NRF24L01 modules you can get cheaply on eBay.

CAR and USR share 3 secrets:

  • 128 bit AES key 1
  • 128 bit AES key 2
  • 64 bit Application ID

All three secrets are stored in the MCU's internal EEPROM. They can be set using the bootloader.

A typical communication:

  1. CAR is always on (listening for messages), since the battery powering it is relatively large.
  2. USR sleeps most of the time, energy conservation is its main concern.
  3. USR wakes up every second and transmits a ping message to CAR.
  4. Upon receiving ping, CAR constructs a message that is part constant (App ID) and part random (internal counters some of which never repeat).
  5. CAR encrypts the message with AES key 1 and transmits it.
  6. USR receives the message, decrypts it and checks that the constant part of the message is as expected. This check prevents interrogating USR with random bits.
  7. If the constant part checks out, USR encrypts the message with AES key 2 and transmits it.
  8. CAR receives the message and decrypts it. If the message is identical to the one it sent, it unlocks the vehicle.
  9. With the vehicle unlocked, CAR expects another valid communication within the timeout period (default 3.5s). If none occur, CAR locks the vehicle.

There are a few more details for those interested:

  • Included in the ping message is USR's battery voltage. Since CAR has a buzzer it warns the driver when USR's battery is low using an audible alarm.
  • After CAR receives a ping and transmits a "challenge", if no valid reply is received, CAR waits for 0.8s before replying to the next ping. This is to prevent interrogation for crypto material.
  • A minimum of 3.5s must elapse between any lock/unlock operation.
  • The NRF chip has 4 output power levels (TX) and 2 input gains (RX). The code uses the lowest settings so communication works only within a few meters.
  • The CAR's green LED is lit when communication is established (vehicle supposed to be open). Use this to test operation before vehicle installation.


Is powered by a single LiIon or LiPo cell. A 1000mAh battery should last for about 3 weeks. When the battery starts running low, USR will start blinking its LED. Connecting the module to a USB port will recharge it. The charging IC is set for 450mA charging current, so a 1000mAh battery should take some 2.5 hours to charge. You can repurpose an old phone's LiPo battery, like I did with the BL-5C, or buy a new single cell specifically for this project from places like HobbyKing. If you decide on an old phone battery, be fast when soldering the terminals as the plastic around them starts melting rather quickly.

The LDO powering the electronics outputs 3.0V. This is to allow operation down to 3.3V battery voltage. At 3.5V USR considers the battery to be low and starts blinking its LED. At 3.3V USR stops working.

Don't connect anything higher than 4.2V to supply input of the board. Doing so will damage the LDO and/or the battery charging IC.

USR board USR schematics

Qty Value / Farnell code Device Size Parts
1 330R resistor 0805 R1
2 2k resistor 0805 R2, R3
2 47k resistor 0805 R4, R5
1 10n multilayer 0805 C1
1 10u multilayer 1206 C2
2 1u multilayer 0805 C3, C4
2 100n multilayer 0805 C5, C6
1 red chipled 0805 LED1
1 1841614 ATmega88 TQFP-32 IC1
1 1135394 TPS73030 SOT23-5 IC2
1 1439477 MCP73811 SOT23-5 IC3
1 2112367 MINI USB X1


Most vehicles with central locking have 2 wires - lock and unlock, that control the doors. Shorting these wires to GND will perform the corresponding function. You will have to identify these wires for your vehicle. Additionally, there are usually two turn signal control wires (one for each side) that, similarly, when shorted to GND will light up the corresponding turn signals. Connecting the latter is optional and up to you. I'm not using them.

The board has 4 outputs numbered 1,2,3,4:

  1. Unlock control
  2. Lock control
  3. Turn signal control (optional)
  4. Buzzer negative (optional, but very useful for USR low battery warning)

The board's + and - input should be connected to a source of constant supply (not affected by the state of ignition). The positive + is also available next to the buzzer pin (4) for easier wiring. Finally there's an IGN (ignition) input. A +12V presence on this input inhibits the board's locking/unlocking operation. Connecting this input is theoretically optional, but highly recommended to prevent spurious locks/unlocks when driving. A must if you've connected the turn signals to indicate lock/unlock operation.

The board draws approx. 25mA @ 12V.

CAR board CAR schematics

Qty Value / Farnell code Device Size Parts
1 330R resistor 0805 R1
3 2k resistor 0805 R2, R3, R7
1 47k resistor 0805 R4
2 10k resistor 0805 R5, R6
2 10u tantalum 16V 1206 C1, C2
2 100n multilayer 0805 C5, C6
1 1N4148 (or equiv.) SOD123 D1
1 green chipled 0805 LED1
1 BC849 (or equiv.) SOT23-BEC Q1
1 1841614 ATmega88 TQFP-32 IC1
1 1202826 LM1117-3.3 SOT223 IC2
1 1652420 ULN2803ADW SO18L IC3
1 12V buzzer wired


You can have both boards made from the Gerbers below or alternatively you can get them from me, provided I have some in stock. Mail me and ask. Order the NRF modules from eBay while you wait, making sure they look exactly like the ones I'm using. If you don't have a USB to serial converter already, consider ordering one of those as well. The serial lines must be at 3.3V levels, anything higher will damage the MCU.

Program the bootloader to both chips. You can do this either before or after soldering the chip to the board. If after, The MOSI/MISO/SCK lines are available on the NRF connector while the RST line is brought out of the chip and marked for this purpose. The NRF module will not interfere with programming the chip.

  • Ext fuse: 0x00
  • High fuse: 0xdd
  • Low fuse: 0xe2
  • Lock fuse: 0x0c

The avrdude command line to do this using usbasp programmer is:

avrdude -p atmega88 -c usbasp -U flash:w:bl.hex -U efuse:w:0x00:m -U hfuse:w:0xdd:m -U lfuse:w:0xe2:m -U lock:w:0x0c:m

Now that the bootloader is programmed, you need to do two things:

  1. Set the AES keys and application IDs (randomness)
  2. Program the actual application (CAR and USR)

Both of these are done via the serial interface using the bootloader.

The CAR board has the serial lines marked and available on the main connector. The USR board has the serial lines connected to the USB data lines. USB D- (white wire) is the MCU's RX line, while D+ (green wire) is the MCU's TX line. Make yourself an adapter by cutting an old mini USB cable and connecting both wires plus GND to your USB to serial converter. Alternatively you can temporarily solder some wires to the RX/TX protection resistors (R2, R3).

A few notes on bootloader operation:

  1. MCU's fuses are set such that the bootloader is run after reset or power up.
  2. Bootloader can program flash and EEPROM.
  3. Bootloader's protocol uses human readable ASCII format, i.e. you can interact with the bootloader yourself with a terminal.
  4. If no communication is done with the bootloader for 10s, bootloader jumps to application start.
  5. When there is no application yet programmed, the flash contains 0xffs which are nops in AVR language so the bootloader is restarted when PC reaches it (immediately in human time).

For more details, refer to bootloader source. It's quite short.

Connect the CAR electronics. Verify that communication with the bootloader is working using a terminal (9600 baud). You should get {V,1} when bootloader starts which is the bootloader announcing its version.

Get 40 (16 for AES k1, 16 for AES k2 and 8 for App ID) random bytes from random.org. Remove spaces between them and construct a string like this. The string should be exactly 84 characters long (40 bytes in hex notation plus 2 brackets, W and a comma).


This is a write to buffer command to bootloader, with the random bytes. Do not use the same random bytes you see here. Copy the string to clipboard and copy it to terminal. The bootloader should respond with:


Where xxxx is the CRC of the bytes you sent. The CRC isn't important for this step. Immediately (within 10s) after receiving this confirmation, write:


This is the write to EEPROM command with starting address set to 0x0010. The bootloader will use the bytes in its buffer (that you've provided with the previous command) to program the EEPROM starting at the specified address. The application (that you have yet to program) expects to find it's AES keys and App ID at this address. If everything went ok, the bootloader should respond with:


Close the terminal and use prg.py (included with the hexes) to program application code. You will likely have to install some additional python modules required by the script. Look at the source to get a list with links.

Find the USB to serial converter's device identifier (com15 in the example) and do:

prg.py com15 car.hex

To program the CAR code. No errors should be reported by the script. Reopen the terminal and wait 10s for bootloader to start the application. The buzzer should sound, that's the CAR code signalling its start, and the following should be output on the serial interface:


Verify the bytes are the same as the ones you've programmed. The ID1 and ID2 bytes might be the other way around due to endianness. That doesn't matter.

Do the same steps with the USR electronics, except this time program usr.hex instead of car.hex. Verify that the key and ID output given by CAR is exactly the same as USR. With both electronics programmed, powered up and in relative proximity, the green LED on CAR should turn on. Moving the USR electronics a few meters away, powering it off or putting it in a metal box should cause the same LED on CAR to turn off. If that's the case congratulations, you're ready to install CAR in your vehicle!

Enclosure of the USR board is up to you. If you have a 3D printer, print one. The board and battery fit the size of a credit card, so I used two Mifare RFID cards, 4 pieces of two sided tape and 5mm depron to build an enclosure like this.

USR enclosure build 1 USR enclosure build 1 USR enclosure build 1

Once enclosed, if for any reason you need to reenter the bootloader, send uppercase B to USR. With CAR, just cycle its power.


Gerbers | Source, compiled hexes and prg.py

The compile the sources, spi.c and spi.h from my AVR library are required.