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:
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.
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.
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.
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.
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.
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.
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"]
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.
Yes, those are cobwebs. They are there to emphasize that this is an old garage door opener. ↩
A Darlington transistor array might be a cheap alternative. Have not tried it myself, though. ↩
I think that they are supposed to be used as a burglar alarm or to track whether a washing machine is still running. ↩
Yes, they submit a vector representing the gravitational force in their frame of reference. ↩
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. ↩