Here's some code I wrote / took snippets off the web, to build an Arduino Garage Door Opener. There is plenty of code around, but I couldn't find anything complete that would work for me. You need to add in the PubSubClient library (in Arduino IDE, from menu's Sketch, Include Library, Manage Library, search pubsubclient and install the latest version)
I've tied this into OpenHAB/Mosquitto (MQTT broker - required) for home automation, so figured I'd share the code to make it easier. Its based on an Arduino Uno with Ethershield, a small 5V relay that's used to "trigger" the garage door switch (open/close the door), and 2 x reed switches to determine if the door is open or closed. I'm running OpenHAB/Mosquitto on C.H.I.P (http://getchip.com) Had to setup a NAT policy on firewall to redirect requests on 192.168.222.254 (LAN interface of firewall) on port 1883 (MQTT port) to 172.16.221.200 (wireless IP of C.H.I.P on my Wifi network) coz it didn't seem to like routing direct to the wireless IP MQTT port for some reason (maybe firewall related, investigate later as its working in this format)
On the Arduino:
- Pin 8 goes to IN on relay
- 5V goes to VCC on relay
- GND goes to GND on relay
For Reed switches, one cable goes to GND the other goes to:
- For Closed state, pin 2
- For Open state, pin 3
You will need to change the IP addresses in the code to suit your LAN, the IP for the Arduino itself and the IP for the MQTT broker (or in my case, IP of firewall which translates port TCP1883 through to TCP1883 on C.H.I.P) You will have to ensure your OpenHAB configuration is configured to match as well (source at the bottom) otherwise alter the code to suit.
Here's the code (sorry, pasting has lost its indentation for easier reading)
// Garage Door Activation and Status (or code for any relay)
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
// Arduino Pin8 to Relay
#define kickRelay 8 // Relay module - trigger door here
#define led 13 // Onboard LED - Activation Indicator
// Arduino to Reed Switch - Closed (Pin2) / Open (Pin3)
const int switchClosed = 2;
const int switchOpen = 3;
// Door states
enum doorStates {
DOOROPEN = 0,
DOORCLOSED = 1,
DOOROTHER = 2,
};
// Initial door state
doorStates doorState = DOOROTHER;
// IP address of the MQTT Broker
IPAddress MQTT_SERVER(192, 168, 222, 254);
// IP address of this Arduino
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 222, 100);
// Delay timer
unsigned long durationToCheck = 0;
// Define message buffer and publish string
char message_buff[10];
String pubString;
// Ethernet Initalization
EthernetClient ethClient;
// Publish, Subscribe client
PubSubClient mqttClient(MQTT_SERVER, 1883, callback, ethClient);
// Callback to Arduino from MQTT (inbound message arrives for a subscription)
void callback(char* topic, byte* payload, unsigned int length) {
// MQTT Inbound messaging
int iChar = 0;
for(iChar=0; iChar<length; iChar++) {
message_buff[iChar] = payload[iChar];
}
message_buff[iChar] = '\0';
// Convert buffer to string
String msgString = String(message_buff);
Serial.println("Inbound: " + String(topic) +":"+ msgString);
// Trigger Garage Door, briefly light LED as an indicator
if ( msgString == "ACTIVATE" ) {
digitalWrite(kickRelay, HIGH);
digitalWrite(led, HIGH);
delay(1000);
digitalWrite(kickRelay, LOW);
digitalWrite(led, LOW);
}
}
void setup() {
// LED pin = relay notifier
pinMode(led, OUTPUT);
digitalWrite(led, LOW);
// Reed switch pins are inputs / activate internal pullup resistor
pinMode(switchOpen, INPUT);
digitalWrite(switchOpen, HIGH);
pinMode(switchClosed, INPUT);
digitalWrite(switchClosed, HIGH);
// Relay pin is an output
pinMode(kickRelay, OUTPUT);
// Start Network
Ethernet.begin(mac, ip);
delay(1500);
// Start Serial
Serial.begin(9600);
// Display IP for debugging purposes
printIPAddress();
}
void loop() {
// If not MQTT connected, try connecting
if (!mqttClient.connected()) {
// Connect to MQTT broker on the openhab server, retry constantly
while (mqttClient.connect("garagedoor") != 1) {
Serial.println("Error connecting to MQTT (State:" + String(mqttClient.state()) + ")");
delay(1000);
}
// Subscribe to the activate switch on OpenHAB
mqttClient.subscribe("openhab/garage/doorswitch");
}
// Wait a little bit...
if (millis() > (durationToCheck + 10000)) {
durationToCheck = millis();
// Serial.println(String(durationToCheck) + " - " + millis());
// Publish Door Status
if (digitalRead(switchClosed) == LOW) {
doorState = DOORCLOSED;
// Serial.println("Door state is closed");
}
else if (digitalRead(switchOpen) == LOW) {
doorState = DOOROPEN;
// Serial.println("Door state is open");
}
else {
doorState = DOOROTHER;
// Serial.println("Door state is in use or partially open");
}
// Define and send message about door state
pubString = String(doorState);
pubString.toCharArray(message_buff, pubString.length()+1);
mqttClient.publish("openhab/garage/doorstatus", message_buff);
Serial.println("Outbound: " + String("openhab/garage/doorstatus") +":"+ message_buff);
}
mqttClient.loop();
}
// Print IP for debugging, can be removed if needed
void printIPAddress()
{
Serial.print("My IP address: ");
for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
Serial.print(Ethernet.localIP()[thisByte], DEC);
Serial.print(".");
}
Serial.println();
}
In your "openhab.cfg" file, under MQTT Transport section entries contain:
mqtt:mqttbroker.url=tcp://localhost:1883
mqtt:mqttbroker.clientId=openhab
Create a file "switch.map" and put it in the transform folder. File contains:
0=Open
1=Closed
2=Partially Open
In your items file, entries are:
/* Doors */
Number doorStatus "Door Status [MAP(switch.map):%d]" <garagedoor> (All) {mqtt="<[mqttbroker:openhab/garage/doorstatus:state:default]"}
Switch doorButton "Garage Door" <garagedoor> (All) {mqtt=">[mqttbroker:openhab/garage/doorswitch:command:ON:ACTIVATE]"}
In your sitemap file, entries are:
Frame label="Garage Door" {
Text item=doorStatus
Switch item=doorButton mappings=[ON="GO"]
}
For testing the door activation, open Serial Monitor in Arduino then click the 'GO' button to open/close the Garage Door in OpenHAB interface - you should see an inbound "ACTIVE" message coming in on the Arduino serial interface.
For testing the door status, on the OpenHAB/Mosquitto server, run the command:
mosquitto_sub -d -t "openhab/garage/doorstatus"
You should see inbound PUBLISH messages (numbers 0,1 or 2) coming in from the Arduino which indicate the door state (open, closed, partially open)
Hope this helps someone out!
Cheers