There oughta be a smart garage door.

03 December 2020

Probably one of my less impressive projects. Controlling my old garage door opener via MQTT. If you cannot imagine what a garage door looks like when it opens, here is a three minute video of the setup:

Thumbnail of a youtube video about the smart garage door opener, light shining through the opening door.
Click the image to see the video on youtube.com.

Self-deprecating commentary aside, I simply trigger the input of the garage door opener with a relay and determine the garage door position with a Zigbee orientation sensor. Two components that just happened to be available as spares from other projects, but it might help you if you want to do something similar.

The trigger

My garage door opener is a Chamberlain MotorLift 5001, which I inherited from the previous owner of my house. It is a simple device with a simple remote control and a simple wall-mounted push button to trigger the motor from inside the garage. The latter is what makes it extremely simple to hook it up to an Arduino, because it simply closes the contact of two wires, which we can easily simulate with a simple relay switch2. If you remember my irrigation system project, I had a spare relay channel there. And this system just happens to be mounted in the garage.

Photo of the garage door opener and the push button.
The simple garage door opener has an input for a simple push button.

So, in fact, the project presented on this page was literally set up in a few minutes. I just split the cables between garage door opener and push button and attached them to the relay, so it can create an electrical connection. I only needed to add few lines of code in four places.

Photo of an Arduino with a 8-channel relay board and a detail photo of the relay switch.
I already have an Arduino with an 8-channel relay board nearby. Seven of these relays are used by my irrigation system. The eighth channel is available for the garage door opener.

1. I defined two variables, holding the MQTT topic to control the garage door and the pin to switch the relay.

1
2
const char triggerGarageDoorTopic[] = "garage/triggerGarageDoor";
int garageDoorPin = 2;

2. I have to setup the pin for the relay as a digital output and make sure that it starts off.

1
2
pinMode(garageDoorPin, OUTPUT);
digitalWrite(garageDoorPin, HIGH);

3. I need to subscribe to the MQTT topic.

1
mqttClient.subscribe(triggerGarageDoorTopic);

4. And the important four lines: I need to check if an incoming MQTT message corresponds to the trigger topic. If so, I close the relay for 250ms and open it again.

1
2
3
4
5
if (topic == triggerGarageDoorTopic) {
  digitalWrite(garageDoorPin, LOW);
  delay(250);
  digitalWrite(garageDoorPin, HIGH);
}

(Note that this is in context of the irrigation system code, which writes the topic of an incoming message to topic.)

Yes, that’s it. It couldn’t be any simpler. If you are already using my irrigation system code, you can get an updated version on github. If you are not using my irrigation system and are only interested in the garage door function, it probably does not make any sense to start with the much more complex irrigation system. Really, just imitate my Wifi and MQTT code (or find one of many tutorials on the web) and extend it with the few lines above.

Position feedback

The problem with this solution, however, is that it is not yet suitable for any automation. If you carefully keep track of when to trigger the relay and if you make sure not to use the remote control or the push button, it could work out, but if you use any of the other means to control the garage door, you have a big problem: You do not know the position of the door.

The push button, and therefore our relay, is just a trigger. If the door is closed, it will cause it to open. If it is already open, it will close the door. And if it is currently traveling, it will stop the door. So, for anything more fancy than another remote trigger, we need a feedback channel to know its position.

Photo of the Xiaomi Aqara Vibration sensor. A white rectangular box with a little button to connect.
The Xiaomi Aqara Vibration sensor can send the garage door's orientation via Zigbee.

Luckily, I had a bunch of Xiaomi Aqara Vibration Sensors from a project that did not turn out as planned. These are Zigbee sensors that send a message if they detect a vibration3 and I can easily connect them to my “RaspBee” by “dresden electronik” which I use for my Zigbee network. I do not care about vibration, but they also submit their orientation, so I can simply attach them vertically to my garage door and they will report to be in a horizontal position if it is open4.

Photo of the Xiaomi Aqara Vibration sensor attached to the garage door.
The Vibration sensor is simply attached to the door with some sticky tape.

OpenHAB integration

Now, this only needs to be integrated into OpenHAB. This actually turned out to be the trickiest part. On one hand I want to get the item state (the position from the Zigbee sensor) from a entirely different device than I use to set the state (the Arduino via MQTT). On top of this, the “deCONZ” binding for the RaspBee supports the vibration sensor, but it does not expose the orientation channel. Instead, I need to get it from an http request to the deCONZ REST API.

To achieve this, I created an item in /etc/openhab2/items/garage.items of type rollershutter, which receives its status from the http binding (talking to the REST API). It also vetos any autoupdate, because a command to this item will not include a direction (it is just a trigger) and we will learn the state from the vibration sensor instead.

1
2
3
4
Rollershutter garagedoor "Garagentor" {
    http="<[http://192.168.2.5/api/9C838427DE/sensors/61:5000:JS(garagePosition.js)]",
    autoupdate="false"
}

The transformation of the API response to a valid rollershutter position is done by a script in /etc/openhab2/transform/garagePosition.js with a very simple logic. If the device is at an 45° angle, the gravitational force should be equal along the two axes that are not the axis about which the door rotates. If one axis is larger than the other, the door is closed, if the other axis is larger, the door is open.

1
2
3
4
(function(input) {
	var orientation = JSON.parse(input).state.orientation;
	return orientation[1] < -orientation[2] ? 0 : 100;
})(input)

Finally, to send the trigger to the opener, which needs to be done via MQTT, I found it to be an easy solution to create a rule (/etc/openhab2/rules/garage.rules) for this, which simply catches any command and then sends the MQTT message.

1
2
3
4
5
6
7
rule "Garage door opener"
when
    Item garagedoor received command
then
    val mqttActions=getActions("mqtt","mqtt:systemBroker:embedded-mqtt-broker")
    mqttActions.publishMQTT("garage/triggerGarageDoor", "")
end

With these configurations in place, the item can simply be added to a sitemap as a switch. You can also add some coloring to indicate the door’s position.

1
Switch item=garagedoor icon="garagedoor" label="Garagentor" labelcolor=[<50="maroon"] mappings=[50="Öffner"]
Screenshots of the garage door entry in the OpenHAB sitemap app. One of the two shown entries is highlighted in red.
Two screenshots of the same entry in the OpenHAB sitemap. The button triggers the garage door motor and the label is displayed in red if the door is open. (You can probably infer the meaning of the German words here...)

So, yes, this is probably not a project to simply copy because it only makes sense for me as I already had the spare relay switch and the spare orientation sensor. But I thought, it is a neat idea for a project with many possible individual solutions, especially if you want to detect the door state. Just be creative: You are looking at a big garage door moving and rotating, so there are not many sensors5 that could not be used to detect its position.

  1. Yes, those are cobwebs. They are there to emphasize that this is an old garage door opener. 

  2. A Darlington transistor array might be a cheap alternative. Have not tried it myself, though. 

  3. I think that they are supposed to be used as a burglar alarm or to track whether a washing machine is still running. 

  4. Yes, they submit a vector representing the gravitational force in their frame of reference. 

  5. Ok, some spontaneous ideas: Simple solutions would include photo sensors, mechanical contacts or a Reed switch (or any magnetometer). Optical rangefinders or a sonar would be overkill, but if mounted in a clever position they could also detect whether a car is present. You could even use a pressure sensor, but it would probably be a bit tricky to account for weather drift and it is not the most commonplace sensor.