Arduino based remote control for electric door

Arduino based remote control for electric door

I recently built a replacement remote control system for an electric garage door after the old remote had given up for the babillionth time.
I’m sure the old one would have been possible to repair once again but it was 35 years old and not much fun.

Old receiver and transmitter

Pictures from left to right:

  1. The front of the old receiver with an indoor open/close button.
  2. Inside of the receiver. Nice and clean and very analog electronic fossil.
  3. The guts from the old transmitter. The case that this used to sit in was removed and reused for the new transmitter.
  4. Backside of the old receiver. The label reads “Chambron Radio Control Model C-2216”. There’s also a letter to Mr. Serviceman.
    Who knows anything about this thing?

The motor to the door is controlled by shorting two cables and thereby closing a circuit. A short pulse is enough to start the motor. If the door is closed it will open. If it’s already open, the door will close. If the motor is moving when the pulse arrives it will change direction.

The new solution

433MHz transmitter (left) and receiver (right)

I wanted a new solution that would be a bit more secure and hopefully have the same range as the old one had and I wanted to base it on an ATmega328P with an Arduino core and some really cheap 433Mhz ASK modulated RX/TX modules that can be found everywhere on eBay.

I have used these RF modules before and know they have a decent range and can penetrate doors, windows and even walls in some cases. They are also easy to interface with using the VirtualWire library for Arduino. The downside is that they only work in one direction.

Even if it wasn’t really necessary in this case I wanted to implement some kind of security or obfuscation of the commands sent over the air. This is something of a challenge with a system that only communicates in one direction since it’s not possible to use a challenge/response based protocol and the Arduino doesn’t have storage enough to store predefined passcode sequenced.
This was what I wanted:

  • Use one time passcodes so that simple sniffing wouldn’t be enough to grant access forever
  • Not have to store the passcode sequence in advance
  • Generate passcodes that don’t seem to follow a clear pattern to complicate analysis of the commands

The protocol I ended up with works like this:

  • The receiver and transmitter are paired to use a sequence of numbers starting at a large random number that is decided by the transmitter. The number is sent to the receiver during the pairing process which more or less is a one time operation.
  • When the transmitter wants to send a open/close command to the door it increases the number by one and hashes the number using MD5
  • The receiver knows which number it expects and when it receives a hash from the transmitter it hashes the expected number and compares the resulting hash with the received hash. If the hash is correct it sends a pulse to the door so that it will be opened or closed. The next expected passcode is simply the last passcode +1.
  • If the hashes didn’t match it increases the expected number one by one and creates new hashes to compare with up to fifty times to allow for missed passcodes that might have been sent when the transmitter was out of range or similar. This gives us a sliding window of 50 valid passcodes. As soon as a matching passcode is found, the receiver is synced with the number received and a pulse is sent to the door.
  • The current numbers are stored in the ATmega EEPROM in both transmitter and receiver.

Hardware

The new transmitter and receiver waiting for installation

I’m using ATmega328P (DIP-28) for both transmitter and receiver. I would probably have used an ATtiny for the transmitter to try and reduce size if it wasn’t for the MD5 library that adds a whopping 12KB to the  binary sketch size making the total sizes around 18KB for both receiver and transmitter.

Transmitter

Since I couldn’t find a suitable pocket size case for the transmitter and a good matching push button I reused the old one. The green LED to the left of the battery pack was added for troubleshooting reasons during installation but I never drilled a hole in the case for that LED due to lack of space.
The button at the top of the PCB is the open/close button. There’s another button on the back side of the PCB that is used during pairing.
The blue cable that is routed from the RF module and around the PCB is the antenna which is a piece of wire that is cut to a quarter of the wavelength equaling 17.3cm.
34.5cm or 69.1cm would also have been OK if there was space enough in the box but looping the antenna round and round in several loops close to each other would not do much good.
The new transmitter resting in the case from the old transmitter (lid open)
The ATmega in the transmitter is running on the internal oscillator at 8MHz to allow the supply voltage to drop to 3.0V. The 16MHz external crystal in the picture is still there but was only used during prototyping. I’m also disabling brownout detection on the ATmega for maximum power savings during power down. The fuses I’m using for setting the clock source to internal oscillator @ 8MHz and disable brownout detection are:
Low Fuses: E2
High Fuses: DA
Extended Fuses: 07

The board definition I put in boards.txt is:

##############################################################
328_8.name=ATmega328, 8MHz Internal OSC, BOD disabled
328_8.upload.protocol=arduino
328_8.upload.maximum_size=30720
328_8.upload.speed=57600
328_8.bootloader.low_fuses=0xE2
328_8.bootloader.high_fuses=0xDA
328_8.bootloader.extended_fuses=0x07
328_8.bootloader.path=atmega
328_8.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex
328_8.bootloader.unlock_bits=0x3F
328_8.bootloader.lock_bits=0x0F
328_8.build.mcu=atmega328p
328_8.build.f_cpu=8000000L
328_8.build.core=arduino
328_8.build.variant=standard
##############################################################

This configuration makes it possible to use a bootloader if desired but I upload the sketch to the chip using an ISP programmer so I don’t have a need for a bootloader in this case.
For other applications using 8MHz internal oscillator, I have always used the ATmegaBOOT bootloader because I’ve not had any luck compiling the Optiboot for this. If someone has a Makefile that is generating a working Optiboot image for 8MHz internal, please let me know in the comments.

Receiver

I got rid of the old receiver case because it was made of thick metal and I was afraid that it could affect the reception in a negative way but it would probably have been OK due to the external antenna. There are plenty of boxes suitable for the transmitter but I settled with a minimal, cheap plastic box for electric installations. I should have picked a bigger one because this was a pretty tight fit.
The connector on the right side is the DC plug for the power supply.
To the left is an LED that flashes during pairing and is lit during reception of data. The button on the same side as the LED is the pairing button.

The antenna which is rolled up outside the box in this picture should normally be stretched out. It consists of 69.1 cm of wire soldered to the antenna connection on the RF module.

The new receiver box with lid, sides and terminals removed

Motor connection

I send the pulses for the motor by running the two wires from the motor through a relay inside the receiver. I pull the relay for a short time using an output on the Arduino whenever a matching hash has been received.
I also added an external momentary push button mounted on the wall that shorts the same two wires so that the door can be opened and closed from the inside without using the remote control.
Receiver installed in garage with indoor open/close momentary button attached

Performance

How well does this solution work?

Range

50 metres (with the transmitter in a car, new batteries in the transmitter and the receive inside the closed garage door)
This is more than enough and just as good as the old system ever was.

Power consumption: Receiver

Approx. 30mA @ 5V
I haven’t done anything to reduce the power consumption on the receiver since it will be powered by a DC adapter.

Power consumption: Transmitter

The transmitter runs straight from three AA batteries that should (until depleted) keep the voltage over  3.0V at all times which is what the RF transmitter module needs to work properly. The maximum 4.5V is also perfectly fine for both RF module and ATmega.
Current during transmission (basically as long as the button is pressed) is ~25mA @ 4.5V
During powerdown which is the normal condition when no button is pressed, the current drops to 0.1uA
This is as low as it gets with an ATmega328P and to achieve this brownout detection has to be disabled.

Possible future improvements

  • Add possibility to use more than one transmitter.
  • Prevent brute force attacks by adding growing delays after incorrect codes
  • Etch custom PCBs, possibly using SMT components for transmitter
  • Add more decoupling capacitors, at least for the receiver.
  • Shrink the transmitter by creating better and smaller case and PCB for the transmitter
  • Fix bugs
  • Well… let’s see how it works

References

Code

Download both sketches and all libraries in one zip file: Code

Schematics

The schemattics for both units in PNG format: Transmitter and Receiver

Video

Advertisements

5 thoughts on “Arduino based remote control for electric door

  1. I’ve been browsing online more than 3 hours today, yet I never found any
    fascinating article like yours. It’s beautiful worth enough for me.
    Personally, if all website owners and bloggers made excellent content as
    you did, the internet will be a lot more
    useful than ever before.

  2. I’m not sure why but this websit is loading extremely slkow for me.
    Is anyone elae having this issue or is it a problem on my end?
    I’ll cheeck back later on and seee if the problem still exists.

  3. I have searched a lot for securing data transmission via RF Link. your solution is very good but did you considered EEPROM write cycles limit when you write every valid code onto eeprom on both sides of transmission?

    I need security solution for remote sensors data transmission every 5 minutes of day so 100k keys a year … and my eeprom will need to be replaced once a year

    1. I have considered the write cycles but I don’t use more than two writes a day or so. I won’t need to worry about replacing the chip anytime soon. At least not for that reason. Even if I did need it I use sockets for the Atmegas so it’s easy to replace them. Batteries are also still perfectly fine after two and a half years of use.

  4. Awsome article and nicely documented approach. I’m gonna use this as a reference for my own implementation of a remote door unlock system for my apartment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s