Home Automation blog

Skip to Content

Arduino WIFI Roller Door

Posted by Chris

Date posted:

My garage is detached from the house and is currently too inconvenient to run ethernet to it. So for this project I decided to use an Arduino conpatible wifi shield for the communication, combined with a 4 channel relay module for the switching.

From what I understand it's common for electric roller door controllers to have screw terminals to allow 1st/3rd party hard-wired remotes. Which is perfect for interfacing with the controller from an Arduino (via relays).

Wiring the door controller

Wiring diagram wifi roller door controller

For this project I'm only using two of the four relays to control the Up and Down actions of the roller door. My roller door's controller does support Stop action, but I don't see a need for this (yet).

I'm using digital pins 4 & 5 on the wifi shield to control the relays and passing 12V down the shield's VIN pin to the relay module. When each relay is enabled the door controller's 12V terminal is fed into either the Up terminal or Down terminal.

Unfortunately the wifi shield doesn't have it's own power management. So I've got an Arduino Uno as the base board below the wifi shield purely receiving 12V via the DC jack, powering the wifi shield and passing the 12V to the relay module via the VIN and GND pins. All the program logic is running directly on to the wifi shield.

Flashed using an Arduino USB to serial adaptor, which I've described how to wire in another post. This ESP8266 shield has a "key" button you hold while powering up to enable flash mode.

The code

#include <ESP8266WiFi.h>
#include <PubSubClient.h>



// WIFI
const char wifi_user[] = "XXXX";
const char wifi_pass[] = "XXXX";
WiFiClient esp;



// MQTT
IPAddress mqtt_server(XXX, XXX, XXX, XXX);
PubSubClient mqtt(esp);
String mqtt_client = "garage";
const char mqtt_user[] = "XXXX";
const char mqtt_pass[] = "XXXX";
const char mqtt_sub[] = "device/garage/door";



void setup()
{
	pinMode(4, OUTPUT); // Up
	pinMode(5, OUTPUT); // Down
	
	WiFi.begin(wifi_user, wifi_pass);
	while (WiFi.status() != WL_CONNECTED)
	{
		delay(500);
	}

	randomSeed(micros());

	mqtt.setServer(mqtt_server, 1883);
	mqtt.setCallback(mqttReceive);
}



void loop()
{
	if (!mqtt.connected())
	{
		mqttReconnect();
	}

  	mqtt.loop();
}



void mqttReconnect()
{
	while (!mqtt.connected())
	{
		mqtt_client += String(random(0xffff), HEX);

		if (mqtt.connect(mqtt_client.c_str(), mqtt_user, mqtt_pass))
		{
			mqtt.subscribe(mqtt_sub);
		}
		else
		{
			delay(5000);
		}
	}
}



void mqttReceive(char* topic, byte* payload, unsigned int length)
{
	if (payload[0] == 49)
	{
		// Received 1 = UP
		digitalWrite(4, HIGH);
	}
	else
	{
		// Received 0 = DOWN
		digitalWrite(5, HIGH);
	}

	// Wait 100 ms
	delay(100);

	// All relays to OFF
	digitalWrite(4, LOW);
	digitalWrite(5, LOW);
}

The Node RED flow

Node-RED WIFI roller door flow using Home-Kit

Function: Roller In

HomeKit's door open status is 0, and closed is 1. Which I've got the other way around on my Arduino: 0 is closed, 1 is open. So I've used function nodes to swap and correctly set the values for the HomeKit node:

var obj = { TargetDoorState: 0 };

if (msg.payload == 1) {
    obj.TargetDoorState = 0;
    node.status({text:"OPEN"});
} else {
    obj.TargetDoorState = 1;
    node.status({text:"CLOSED"});
}

msg.payload = obj;
return msg;

Function Roller out

if (msg.payload.TargetDoorState == 1) {
    msg.payload = 0;
    node.status({text:"CLOSE"});
} else {
    msg.payload = 1;
    node.status({text:"OPEN"});
}
return msg;

Delayed status

HomeKit supports Open, Opening, Closed, Closing. So I've artificially setup the door's opened, closed states via the delay node. This prevents HomeKit status being stuck either in Opening, Closing.

Function Roller status In

var obj = {};

switch (parseInt(msg.payload))
{
    case 1:
        obj.CurrentDoorState = 0;
        break;
        
    case 0:
        obj.CurrentDoorState = 1;
        break;
        
    default:
        obj.CurrentDoorState = 1;
        break;
}

msg.payload = obj;

return msg;