The following is a quick high level of how I implemented automated control for my Chamberlain MYQ based garage door. When I bought the new door opener, I incorrectly assumed it contained the automated control. I unfortunately found out that you have to buy the gateway for a $100 dollars. I wanted to find a cheaper option for this, and the below is the result.
Items/Methods Used:
Particle Photon
2xSPDT-Submini Roller Lever Switch (Radioshack 275-0017)
N-Channel MOSFET
Chamberlain Smart Control Panel - 41A7305-1 (Came with Garage Door Opener)
MQTT for garage state(Open/Closed) updates
Batch file to call curl
First, please use this with caution as I hacked my way through it using what I had available to me. I am sure there may be better methods to do this, so feel free to comment and provide feedback.
Limitations:
- This uses the particle api via the web. I have had no issues yet, but intend to move to local network control for the photon in the future.
NOTE: Code and Openhab items/sitemap updated to reflect two switches. I have not updated the picture, but just duplicate the current pictured switch on a different pin for the second one.
Particle Photon code:
//The following utilized pin D7 of the particle to short the pins on a button of the Chamberlain MYQ multi function control
//following a function call from the particle web api curl command. Pin D1 is connected to a roller switch that detects
//when the door is open and sends a publish message to a mosquitto mqtt server.
// This #include statement was automatically added by the Particle IDE.
#include "MQTT/MQTT.h"
//register callback
void callback(char* topic, byte* payload, unsigned int length);
// connection string for mqtt
byte server[] = { xxx,xxx,x,xxx }; //IP of mqtt server
MQTT client(server, 1883, callback); // port of mqtt server
//establish variables
int garageStateOpen = 0; //initial state of the garage is zero unless 1 is detected
int garageStateClosed = 0;
int stateTrackerOpen = 0;
int stateTrackerClosed = 0;
int garageButton = D7; //using digital pin 7 to mimic short on chamberlain panel
int garageSwitchOpen = D1; //using digital pin 1 for roller switch open
int garageSwitchClosed = D0; //using ditital pin 0 for roller switch closed
void setup() {
// connect to the mqtt server
client.connect("sparkclient");
//publish variable to api
Spark.variable("stateOpen", &garageStateOpen, INT);
Spark.variable("stateClosed", &garageStateClosed, INT);
//setup pinmodes
pinMode(garageButton, OUTPUT);
pinMode(garageSwitchOpen, INPUT_PULLDOWN); //using INPUT_PULLDOWN to stop flapping/false HIGHs
pinMode(garageSwitchClosed, INPUT_PULLDOWN);
//establish spark function gd to be called by the particle web api
Spark.function("gd", gdToggle);
//set D7 to High as the Chamberlain button works via a short.
digitalWrite(garageButton, HIGH);
}
void loop() {
//read state of D1 to determine state of switch
garageStateOpen = digitalRead(garageSwitchOpen);
garageStateClosed = digitalRead(garageSwitchClosed);
//monitor state of switch and publish to mqtt. Use a tracker variable comparison to only send update when the state has changed.
if (client.isConnected()) {
client.loop();
}
else {
client.connect("sparkclient");
}
if(garageStateOpen!=stateTrackerOpen) //this determines if there has been a change in state
{
stateTrackerOpen=garageStateOpen; //update the tracker variable to the new state
if (client.isConnected()) {
//mqtt publish based upon the state
if (garageStateOpen==0){
client.publish("/home/garage/garageStateOpen","OFF");
}
if (garageStateOpen==1) {
client.publish("/home/garage/garageStateOpen","ON");
}
}
}
if(garageStateClosed!=stateTrackerClosed) //this determines if there has been a change in state
{
stateTrackerClosed=garageStateClosed; //update the tracker variable to the new state
if (client.isConnected()) {
//mqtt publish based upon the state
if (garageStateClosed==0){
client.publish("/home/garage/garageStateClosed","OFF");
}
if (garageStateClosed==1) {
client.publish("/home/garage/garageStateClosed","ON");
}
}
}
delay(100);
}
// spark function that is called from api with inputs
int gdToggle(String command) {
if (command=="buttonpush") {
digitalWrite(garageButton, LOW); //this causes a short and mimics a physical button push on the chamberlain panel
delay (1000);
digitalWrite(garageButton, HIGH); //set back to HIGH to stop the short
return 1;
}
else {
return -1;
}
}
// recieve message but do nothing, the only use publish, not subscribe
void callback(char* topic, byte* payload, unsigned int length) {
}
Openhab Items:
Switch garageButton "Garage" <garagedoor> {autoupdate="false",imperihab="room:Garage,label:Garage Button"}
String garageState "Garage Door [%s]" <garagedoor> {imperihab="room:Garage,label:Garage"}
Switch garageStateOpen "Garage Open?" <garagedoor> {mqtt="<[mosquitto:/home/garage/garageStateOpen:state:default]"}
Switch garageStateClosed "Garage Closed?" <garagedoor> {mqtt="<[mosquitto:/home/garage/garageStateClosed:state:default]"}
Openhab Sitemap:
Frame label="Garage Door"{
Switch item=garageButton label="Garage" mappings=[ON="GO"]
Text item=garageState
Garage State Rule:
rule "Determine Status of Garage Door"
when
Item garageStateOpen changed or
Item garageStateClosed changed
then
if (garageStateOpen.state == ON){
postUpdate(garageState,"Open")
}
else if (garageStateClosed.state == ON){
postUpdate(garageState,"Closed")
}
else {
postUpdate (garageState,"Ajar")
}
end
To send curl request to the particle api, I had to use the executeCommandLine function in a rule:
rule "Control Garage Door"
when
Item garageButton received command ON
then
sendCommand(garageButton,OFF)
executeCommandLine("c:/openhab/gd.bat")
openhab gd.bat file called by rule:
@ECHO OFF
c:\curl\curl https://api.particle.io/v1/devices/mydeviceid/gd \ -d access_token=myaccessid \ -d params=buttonpush