How to use an ESP32 to open any automated gate or garage door with your smartphone
In this tutorial I’m going to show you how you can integrate yours automated garage doors or gates with your domestic Internet of Things network using an ESP32 board (which I already used in many projects), in order to control them using your mobile smartphone instead of the proprietary RC remote, thus extending the operating range of the gate control almost to any place where there is an internet connection.
To do this, I’m going to use three main components: an ESP32 or 8266 Wi-Fi powered relay board, an MQTT broker inside my home network and finally my smartphone with an MQTT dashboard app installed and properly configured. This solution allow me to control my gates and garage doors, without using no more the proprietary remote controller, which has a very limited operating range.
Also, this solution could be easily integrated with Google Home, as I already did, providing a useful and practical tool to control my gates and garage doors when I’m approaching home by car, thus allowing me to open them using Google Assistant without remove my hands from the steering wheel. But I will talk about Google Home integration in another article, since there is already much to do.
Table of Contents
Open any automated gate or garage door with your smartphone and an ESP32
Requirements
In order to create our gate opener, we need many components. First of all we need an ESP8266 or ESp32 board. In my case, I decided to use a generic ESP32 board, based on the ESP32 microcontroller. You can easily find it on Aliexpress for a 3 or 4 dollars. Then, you need at least a relay module, at least because some gate automation mechanism has multiple inputs to control complete or partial gate opening, like mine. I bought a board with two of these optocouplers, which can handle 28 volt in DC or up to 220 in AC. They can be feed by the ESP32, since they work at 5 volt. Then, we need a power supply or, as in my case, a voltage converter, since many gate automation boards work between 12 and 24 volts, while the ESP32 needs no more than 5 volt. I bought an LM2596 voltage converter, which can handle up to 35 volt as input, converting it to an output as low as 1.2 volt, so inside our operating range.
Finally, at least on the hardware side, we also need many cables for the wiring, both between the ESP32 and the relays, both between the power supply, relays and the gate control board. We also need some raw material and an IP67 box for the boards housing. Finally, moving on the software side, you need an MQTT broker, a smartphone and, of course, a Wi-Fi network.
About the MQTT broker, I decided to make my own broker (Mosquitto) on a Raspberry Pi 3 placed inside my home network, but there are also many online free available MQTT broker, hosted from AWS or Azure, which provide some free messages every day, which, for this kind of use case, should be enough. If you need a lot of messages, AWS MQTT broker has a cost of about 1.5 dollar for 1 billion 5 KB messages, that’s a lot to play with. Remember to use a Private MQTT broker, otherwise anyone can subscribe or publish on your gates topic, thus controlling them.
As mobile application instead, there are many possible MQTT dashboard mobile apps. I picked up THIS ONE, it has a very good looking dashboard, with nice pics and custom buttons, allowing free customisation. Finally, I already have a good Wi-Fi coverage in my garden, so be sure that the interested areas have Wi-Fi coverage, otherwise the system will not work.
Summarising, you need:
- one ESP8266 or ESP32 board (my choice);
- one or more 5V relays (my choice);
- many cables with standard PIN dimension;
- an IP67 box (my choice);
- your own private MQTT broker (Mosquitto, if you have a spare Raspberry Pi inside you home network, or AWS or Azure to create an online broker);
- MQTT Dashboard mobile App;
- your smartphone;
- a 2.4 GHz Wi-FI network.
Total cost should be less than 30$.
If you have many gates or doors to open, you’ll need many devices like these, one for each door or gate to control. So the overall cost depends on how much devices you plan to deploy, but if you buy all the components from Aliexpress, maybe multiple packs of products, you are going to save some money, thus reducing the final system cost to less than 20$ for each node. Also, if you would like to deploy a cheap home made MQTT broker, you can also use a Raspberry Pi Zero, which is just 10$.
Just remember that COTS (Commercially On The Shelf) based available solutions like this one, cost hundreds of dollars, so with our home made system we have huge savings and a lot of fun.
Software setup: allow the ESP32 to control your gate or door
Once we have our ESP32 board, we have to work on the software part. I use the Arduino IDE to program my ESP32 board. However, you can use any other IDE you want. If you decide to use Arduino IDE, be sure to import the right library and COM ports driver. You can check this tutorial.
As already introduced above, I use MQTT protocol and its publish/subscribe approach for the gate control. So, our ESP32 will connect to our Wi-Fi network and then to the MQTT broker, thus performing a subscription to one or more MQTT topics, which will allow use the control of the gate or door. As already stated, I used an ESP32 board, but even a 8266-based solution should work, however you must change some libraries.
Libraries and variables declaration
So, let’s start with the needed libraries. We need many libraries, most of them comes with the ESP32 board installation, while others must be manually installed. Therefore, your sketch need the following libraries:
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <HTTPClient.h>
#include <ESP32httpUpdate.h>
#include <TimeLib.h>
#include <ESP32Ping.h>
PubSubClient and ESP32Ping must be manually download. You can find them HERE and HERE. All the others library should already been installed.
After that, let’s start with some variables declaration:
// Replace the next variables with your SSID/Password combination
const char* ssid = “xxx”;
const char* password = “xxx”;//Firmware version for update
const int FW_VERSION = 3;//Watch Dog Const
const int wdtTimeout = 100000; //time in ms to trigger the watchdog
hw_timer_t *timer = NULL;// Add your MQTT Broker local (or global) IP address, example:
const char* mqtt_server = “192.168.178.51”;// IP to ping for Wi-Fi status checking
IPAddress ip (192, 168, 178, 1); // The remote ip to ping
bool pingResult;// Define clients and variables
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
long wifirssi;// LED & Control Pin
const int ledPin = 2;
const int voltPin = 23;
const int voltPin2 = 22;// Update Check
int realtime = 0;
int interval = 60;
int nxtcheck = 60;
Starting from the beginning, we have to define our Wi-Fi SSID and password variables, followed by our firmware version, which I’ll discuss later. Then, there is the watchdog trigger time variables, our MQTT broker IP or Hostname, and finally the IP of our home network gateway (the central router), which is used to perform a ping test and check if the Wi-Fi connection is dead or alive.
Moving on, there is the Wi-Fi and MQTT client declaration, followed by many support variables for messages and Wi-Fi RSSI, which is useful for debug purpose. Finally, here we have the pin connected to the relay board definition, followed by the firmware update check support variables.
Setup and Wi-Fi function
Let’s move to the setup function, which is used to setup the board at startup. As usual, the first option is used to define the serial port and its baud rate. Then Wi-Fi setup and the check for update function are called, allowing the board to connect to the Wi-Fi network and check if new firmware release are available on the defined server.
// Board Init
void setup() {
Serial.begin(115200);
setup_wifi();
checkForUpdates();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
pinMode(ledPin, OUTPUT);
pinMode(voltPin, OUTPUT);
pinMode(voltPin2, OUTPUT);
digitalWrite(voltPin, HIGH);
digitalWrite(voltPin2, HIGH);timer = timerBegin(0, 80, true); //timer 0, div 80
timerAttachInterrupt(timer, &resetModule, true); //attach callback
timerAlarmWrite(timer, wdtTimeout * 1000, false); //set time in us
timerAlarmEnable(timer); //enable interrupt
}
Going on, the MQTT client functions are called, followed by the pins definition and initialisation. Also, the two pins connected to the relays board are set to HIGH. And finally the watchdog timer is initiated.
Let’s have a look to the Wi-Fi setup function, which perform the connection to our defined wireless network.
// WiFi setup
void setup_wifi() {
delay(10);
int trial = 0;
// We start by connecting to a WiFi network
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(“.”);
trial = trial + 1;
if (trial == 120){
ESP.restart();
}
}
Serial.println(WiFi.localIP());
}
As visible, the function tries to connect to the defined SSID. If the device can’t connect to it for several times, the board is rebooted. Once connected, the IP is printed on the serial console.
WatchDog, Check for Update and connection check
Let’s see now the watchdog and OTA update function. I decided to implement them because, since the board is located in my garden, inside an IP67 box, it’s not so easy access to it for maintenance. Thus, I need an emergency reboot tool – aka, watchdog- in case something goes wrong. Also, I must have the option to update the code remotely, because if I’d like, for example, to control the gate trough Bluetooth (check HERE how Bluetooth can be used for IoT applications), I have to perform some code change an then install the new firmware on the board. Let’s see how these stuffs are done.
The watchdog code is very simple, it’s a function which checks the CPU built hardware timer and, if it is not fed before the time limit set at the beginning, it reboots the board, whatever it happens.
//Watch Dog
void IRAM_ATTR resetModule() {
ets_printf(“reboot\n”);
esp_restart();
}
So, it must be fed before the timer triggers the reboot. To do this, let’s see what’s inside the Loop function:
// Looping function
void loop() {
// Get time
realtime = now();
// Check if is check update time
if (realtime >= nxtcheck){
pingResult = Ping.ping(ip);
// Check if still connected
if (pingResult) {
Serial.println(“SUCCESS!”);
timerWrite(timer, 0); //reset timer (feed watchdog)
} else {
Serial.println(“FAILED!”);
}
// get WiFi RSSi for debug
wifirssi = WiFi.RSSI();
char rssiString[16];
dtostrf(wifirssi, 1, 2, rssiString);
client.publish(“esp32/statusgate2”, rssiString);
// Check update
checkForUpdates();
nxtcheck = nxtcheck + interval;
}
// Check if client is still connected
if (!client.connected()) {
reconnect();
}
client.loop();
}
At the begin, we get the current timestamp, then we check if the time variable is greater or equal the the next check variable. If it is, many things are done.
First of all, a ping test is done, in order to check if our connection is still alive. If it is, we feed the watchdog timer. Then, we get the Wi-Fi RSSI value and we publish it to our debug MQTT topic, in order to evaluate the connection quality between the node and our Wi-Fi router.
Finally, we check if any update is available and then set the next check interval, which is actually fixed to 60 seconds. Well, let’s dive into the check for update function.
// Check for new firmware update
void checkForUpdates()
{
String fwURL = “http://www.webhost.com/firmware/esp32/gate_opener”;
String fwVersionURL = fwURL;
fwVersionURL.concat(“.version”);Serial.println(“Checking for updates at URL”);
HTTPClient httpClient;
httpClient.begin(fwVersionURL);
int httpCode = httpClient.GET();
if(httpCode == 200) {
String newFWVersion = httpClient.getString();int newVersion = newFWVersion.toInt();
if( newVersion > FW_VERSION ) {
Serial.println( “Update” );String fwImageURL = fwURL;
fwImageURL.concat(“.bin”);
t_httpUpdate_return ret = ESPhttpUpdate.update(fwImageURL);switch(ret) {
case HTTP_UPDATE_FAILED:
Serial.printf(“HTTP_UPDATE_FAILD Error (%d): %s”, ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str());
break;case HTTP_UPDATE_NO_UPDATES:
Serial.println(“HTTP_UPDATE_NO_UPDATES”);
break;
}
}
else {
Serial.println(“Already last version”);
}
}
else {
Serial.print( “Firmware version check failed, got HTTP response code “);
Serial.println(httpCode);
}
httpClient.end();
}
In a very short way, this function checks at the defined URL the release version number placed inside a .version file. If it’s greater than the one defined inside the sketch, then the compiled binary (.bin) is downloaded and then installed, thus performing a complete OTA update without connecting the board to a computer. So, when I have to update the code of my gates board, I simply put the the new compiled firmware on my server and then increase the number inside the .version file. Voilà!
MQTT topic check
Let’s now see the key component of the ESp32 gate control system: the MQTT topics check and relays control. The function which perform this operation is the callback function, which is called in the board setup function. Let’s dive into it.
// MQTT Client Callback
void callback(char* topic, byte* message, unsigned int length) {
Serial.print(“Message arrived on topic: “);
Serial.print(topic);
Serial.print(“. Message: “);
String messageTemp;for (int i = 0; i < length; i++) {
Serial.print((char)message[i]);
messageTemp += (char)message[i];
}// If a message is received on the topic esp32/output, you check if the message is either “on” or “off”.
// Changes the output state according to the message
if (String(topic) == “esp32/opengate2”) {
if(messageTemp == “on”){
digitalWrite(voltPin, LOW);
delay(400);
digitalWrite(voltPin, HIGH);
}
else if(messageTemp == “off”){
digitalWrite(voltPin, HIGH);
}
}if (String(topic) == “esp32/opengate2partial”) {
if(messageTemp == “on”){
digitalWrite(voltPin2, LOW);
delay(400);
digitalWrite(voltPin2, HIGH);
}
else if(messageTemp == “off”){
digitalWrite(voltPin2, HIGH);
}
}
}
So, as it is possible to see, the first operation which is performed is to print the received message and tis topic. Then, many IF statement check if the topic and the message are compatible with the built-in functions. In my case, since I have two relays, I also have two topics, thus two IF statements which checks the messages received on the subscribed topics.
Once the on message is received on one of the two topics, the pin related signal is set to LOW (by default it is HIGH) for 400 ms, allowing the gate control mechanism to receive the input and thus open or close the gate, depending on its status. After 400 ms, the pin is set again to HIGH. The same thing is done on the second MQTT topic, where a different pin status is changed.
MQTT Client broker connection
Finally, we have the MQTT client connection function, which ensure that our client is connected to the broker and subscribed to the described topics. As visible, there are some parameters that must be set. They are, the MQTT broker username and password, followed by the topics which we would like to subscribe.
// Reconnect Client to Broker if disconnected
void reconnect() {
// Loop until we’re reconnected
while (!client.connected()) {
// Attempt to connect
if (client.connect(“ESP32Gate2”, “username”, “password”)) {
// Subscribe
client.subscribe(“esp32/led2”);
client.subscribe(“esp32/opengate2”);
client.subscribe(“esp32/opengate2partial”);
} else {
// Wait 5 seconds before retrying
delay(5000);
}
}
}
The function will try to connect to the broker and, if there are some problems, it will retry again after five seconds, until it is connected.
All the source code can be found HERE in my repository.
Hardware setup: connecting ESP32 with relay module and voltage converter
Let’s start with the hardware setup. Before connecting our board with the gate control board, we have to connect together the three node components: voltage converter, ESP32 and relay module. The first step is to connect an input cable, made by many wires: one related to GND, one to VCC and one for each relay. This input cable will be connected to your gate/door control mechanism, so I suggest to chose a strong cable with at least one meter of length, depending also on the node location.
Once we have this input cable, GND and VCC cables must be connected to the voltage converter inputs. Also, the VCC wire is connected to the relay Normally Open input. Then, we have the relay output cable, which is the third wire inside the cable connected to your gate control mechanism. Of course, if you have many relays like in my setup, you will have many outputs wire, each one for each relay.
On the 5 volt side of the voltage converter, which shall be manually adjusted by turning the built-in regulation screw, we have to connect a GND and VCC wires, which will feed both the relays and the ESP32 boards, connecting them to the right input pins. Finally, we have to connect the control wires, which connect the ESP32 control pins with the relay board input pins, designated by the label IN2 and IN2.
A complete schematic of the performed wiring is visible below:
Before soldering all the wires and cables in the right way, you have to perform two operations:
- Regulate the voltage converter through the built-in screw, in order to obtain a 5 volt output. Pay attention! Do this operation without any board connected to the voltage converter, otherwise you could burn them. Use a voltage tester to check the output voltage.
- Before hardwiring the voltage converter to the ESP32, load the sketch on it, otherwise you could have some electrical issues by USB-powering your board with the voltage converter connected.
Finally, you can place all the component inside an IP67 box, with a small hole to allow the cable passage. I placed all the component inside a 100 x 100 x 85 mm IP67 box, over a thin wood layer in order to fix them with some screws. Below you can see the final result.
Connecting the ESP32 with the gate or door automation mechanism
Here we are to the big step: connect our node to the gate or door opener. I will try to be as generic as possible, since there exist a pletora of automation mechanisms. Fortunately, they are all quite similar, even if there could be some differences in terms of wiring and ports. Technically speaking, what you have to do is to connect the VCC wire to the VCC port on the gate opener board, while the GND wire to the relative GND connector.
And then, depending on you gate automation mechanism, there are different possible connection for the signal wires. My sliding gates has four inputs port for different kind of control. There is a partial opening, a step by step opening, an open only port and a close only too. I connected the first relay signal wire to the partial open port, which open the gate just for a meter, allowing only people or bikes to pass thorough it. The second one instead, has been connected to the step by step opener, which acts as follow:
- if the gate is closed, it opens it;
- if it is opening, it stops it;
- if it is open, it closes it;
- if it is blocked, due to statement two, it resume the opening or closing procedure.
So, with a single button, you have the control of all these states. Actually, I mounted the system on three gates and two garage doors and, despite being different brand and devices, they all had the same similar inputs ports …. so I assume it should be the same thing for many other devices around the world.
I picked-up a random gate control board on Google and I noticed it has almost the same input port as mine, even if it’s a completely different brand. Looking at the image, it’s almost clear that the GND wire must be connected to the port number 5, while the VCC to 6, then the step by step control wire must be connected to the port 12, while the partial open to 14.
If you can’t find any scheme, check where your antenna receiver or keyboard inputs are connected, since there is a very high chance that’s the gate open port. And here we have the final installation of one of my nodes.
Mobile App: how to control your gates and doors through your smartphone
And finally, here we are to the final step: the mobile control app. As I told at the beginning, there are many MQTT dashboard. I picked up this one, because it’s very nice. So, let’s see what we have to do to control our gate from the app. First of all, we have to setup the connection toward our MQTT broker, so we need the same credential used by the ESP32 board to connect to the MQTT broker in order to subscribe to the target topics.
Once you setup the broker connection, you can create your custom interface, with all the tiles and buttons you want. To do this, just press on the plus button and then chose the right kind of tiles (button, label, switch, etc). In this case, since the system behaviour is like a “push and release button”, I create a button for each relay, in order to control their functions.
Once you create a button, then you have to set its behaviour, specifying the topic where to publish and the message to send. You can see an example of a button here below.
And this bring us to the end of this project.
Conclusion
I’m using this system since July 2020 and I have to say that it works very well. I also created a NODE-RED dashboard where I can see all data collected by in-house sensor and control al gates and garage doors, and I also integrated the system with Google Home, in order to control them using Google Assistant. But I will talk about it in the upcoming weeks.
All the source code of this project can be found HERE in my repository.