Controlling your garage doors with an ESP32 - Part 3

  • October 6, 2018
  • tuxotron
  • ESP32 - Relay - Sensor wiring

    ESP32 - Relay - Sensor wiring

    Now that we have our ESP32 ready to rock and roll it is deployment time! The first thing we need to do is to use an MQTT broker with authentication. So far we have done all our tests using the free io.eclipse.org server without any kind of authentication, this means, if somebody knows the topics you are using, could open/close your garage door. Not good!

    There are plenty of options out there you can use, but I personally roll out my own broker, so I am going to explain what I have done. I will be using a Moquitto broker, from the Eclipse foundation, and of course, inside a docker container ;)

    I have also created my own docker image based on the official one, adding some extra functionality to be able to specify an username and password when you create your container, so you don’t have to deal with user and configuration files. I am running my MQTT broker in a droplet in Digital Ocean. All you need to make sure you have Docker installed in the host and also you will need to open at least port 1883/tcp. To bring your container up, all you need to run if the following command:

    docker run -d --name mosquitto -p 1883 --restart=always -e MOSQUITTO_USER=YOUR_USERNAME -e MOSQUITTO_PASS=YOUR_PASS tuxotron/mosquitto
    

    Here we are running a container called mosquitto, with the option of restart automatically and the credentials YOUR_USERNAME and YOUR_PASS (make sure you change these values). This container will also disable the anonymous access to our server, so basically you will be able to connect using that one user.

    The next step would be to reconfigure our ESP32 to set the correct server, username and password credentials, as we explained in part 1 of this series. Make sure you update code for this project first. From inside the directory or your project’s code:

    git pull origin master
    

    After you make the configuration changes and flash the new code. You should see something like:

    I (2545) MQTT_CLIENT: Sending MQTT CONNECT message, type: 1, id: 0000
    I (3195) GARAGE: MQTT_EVENT_CONNECTED
    I (3195) GARAGE: sent subscribe successful, msg_id=63593
    I (3195) GARAGE: sent subscribe successful, msg_id=48468
    I (3205) GARAGE: sent subscribe successful, msg_id=29761
    I (3205) GARAGE: sent subscribe successful, msg_id=63161
    I (3215) GARAGE: MQTT_EVENT_SUBSCRIBED, msg_id=63593
    I (3225) GARAGE: MQTT_EVENT_SUBSCRIBED, msg_id=48468
    I (3435) GARAGE: MQTT_EVENT_SUBSCRIBED, msg_id=29761
    

    At this point we are ready to mount the device in our garage. In my case I follow the following schema to connect the relay to both garage door openers:

    Relay - Opener connections

    Relay - Opener connections

    If your door opener has different connections, just look for the wires coming from the button that opens/closes your garage door and wire your relay with it.

    The next thing will be to mount the magnetic switches, in this case you will have find the best spot to install them. I have installed this projects in 3 different houses and I had to install the switches in different places, since the doors were different. Here is a picture of how it looks like in my current garage:

    Magnetic switch

    Magnetic switch

    Once you have wired up your relay to the door openers and the magnetic sensors, you are good to go. Here is a video of my current installation:

    At this point, all you need to do in order to interact with your ESP32 is to send messages to the MQTT broker. As you have seen in the video, I was using MQTLens, but you can use practically any client. From the command line like we have seen in previous videos, a web application, mobile application, etc.

    I’m finishing up an iOS application to control the garage doors from the phone. I won’t probably publish an entry for that since I’m not going to teach iOS development, but I will make the code available in Github and I will update this entry with the link.

    The next thing to do would be to enable TLS in your broker and do all the communications through it. That’s in my to-do list, but I currently have some other priorities in my agenda, so eventually I will get it done and then I will publish a new entry to describe the changes. Until then, happy hacking!

    Previous parts:

    Controlling your garage doors with an ESP32 - Part 1

    Controlling your garage doors with an ESP32 - Part 2

Controlling your garage doors with an ESP32 - Part 2

  • September 21, 2018
  • tuxotron
  • ESP32 - Relay - Sensor wiring

    ESP32 - Relay - Sensor wiring

    In this second post of this series, we’ll see how to connect a couple of magentic switches, one for each door, that will allow us to see if a door is closed or not.

    I’m using this one in particular: https://www.adafruit.com/product/375.

    This sensor has two wires, one goes to ground (GND) and the second one to an output GPIO pin. In my case I’m using pins 25 and 26 for the left and right door respectively.

    Now our schematics will look like this:

    ESP32 - Relay - Sensor schematics

    ESP32 - Relay - Sensor schematics

    I also updated the code with the parts to interact with these sensors. All the changes were made in the main/app_main.c file. Here are the relevant snippets:

    static const char *LEFT_DOOR_STATUS_TOPIC = "garage/door/left/status";
    static const char *RIGHT_DOOR_STATUS_TOPIC = "garage/door/right/status";
    ...
    #define LEFT_DOOR_SENSOR_GPIO 25
    #define RIGHT_DOOR_SENSOR_GPIO 26
    

    We added four new constants, two to define the new topics were the sensor will be receiving/sending the traffic and another two to define the pin numbers where we are connecting the sensors.

    In the initialization code:

    gpio_set_direction(LEFT_DOOR_SENSOR_GPIO, GPIO_MODE_INPUT);
    gpio_set_direction(RIGHT_DOOR_SENSOR_GPIO, GPIO_MODE_INPUT);
    gpio_pullup_en(LEFT_DOOR_SENSOR_GPIO);
    gpio_pullup_en(RIGHT_DOOR_SENSOR_GPIO);
    

    Here we are settng the two GPIO as input mode, since in this case will be reading from them, and also we pull them up.

    case MQTT_EVENT_CONNECTED:
        ...
        msg_id = esp_mqtt_client_subscribe(client, LEFT_DOOR_STATUS_TOPIC, 0);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
    
        msg_id = esp_mqtt_client_subscribe(client, RIGHT_DOOR_STATUS_TOPIC, 0);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
    

    In this snippet, once we are connected to the MQTT server, we subscribe to the new topics. And the last thing I added was the code that handles the messages:

    if (strcmp(topic, LEFT_DOOR_TOPIC) == 0) {
      ...
    } else if (strcmp(topic, RIGHT_DOOR_TOPIC) == 0) {
      ...
    } else if (strcmp(topic, LEFT_DOOR_STATUS_TOPIC) == 0) {
        if (strcmp(data, "get") == 0) {
            if (gpio_get_level(LEFT_DOOR_SENSOR_GPIO)) {
                esp_mqtt_client_publish(client, LEFT_DOOR_STATUS_TOPIC, "status:open", 0, 0, 0);
            } else {
                esp_mqtt_client_publish(client, LEFT_DOOR_STATUS_TOPIC, "status:closed", 0, 0, 0);
            }
        }
    } else if (strcmp(topic, RIGHT_DOOR_STATUS_TOPIC) == 0) {
        if (strcmp(data, "get") == 0) {
            if (gpio_get_level(RIGHT_DOOR_SENSOR_GPIO)) {
                esp_mqtt_client_publish(client, RIGHT_DOOR_STATUS_TOPIC, "status:open", 0, 0, 0);
            } else {
                esp_mqtt_client_publish(client, RIGHT_DOOR_STATUS_TOPIC, "status:closed", 0, 0, 0);
            }
        }
    }
    

    Here as you see we are responding only when we receive the get payload or message. Then we read the sensor gpio_get_level(….), and if the result is true (not equal to 0), then we send back to the topic the message status:open or status:closed otherwise.

    Here is a little video showing this functionality with just one sensor:

    If you missed part one of this series, here you have Part 1

    Esta entrada también está disponible en español.

Controlling your garage doors with an ESP32 - Part 1

  • September 19, 2018
  • tuxotron
  • Garage

    Garage

    Four years ago, I got to wire up a Raspberry Pi to a 2 channel relay and a couple of sensors, and hook it up to my garage door openers. This allowed me to open/close any of the doors, as well as to see if the doors were open or closed. Here is blog post I wrote then explaining all I did: https://www.cyberhades.com/2014/02/04/controlando-las-puertas-del-garaje-con-un-raspberry-pi/ (Spanish). This setup suffered a couple evolutions, adding into the picture an MQTT broker (mosquitto), an Android app and even an application for my good old Pebble watch. Although I never published any of theses evolutions, here you can watch a video opening my garage door (as you can see is also a different house… military life…):

    Although the setup worked pretty nicely, during this time I had to replace the SD Card at least twice, plus sometimes due to power outages, I had some issues with network connectivity, requiring a device restart. Because of that and the fact you don’t really need much power for driving a relay this way, I decided to go with an ESP32 micro controller, in particular with this development board. Also I would like to mention, the boot up time in the micro controller is way better, since there is not operating system.

    The wiring is pretty simple. We need four wires, the power of the relay (VCC) will connect to the 5V output pin in our board, the ground (GND) to one of the GND pins in the board, and then we need to more wires for each channel, in my case I connected the left channel to GPIO 32 and the right one to GPIO 33. Here is the schema:

    ESP32-relay-wiring

    ESP32-relay wiring

    To program the micro controller, I used the ESP-IDF (Espressif IoT Development Framework).

    The way we’ll communicate with our micro controller, will be through an MQTT broker, in this case I’m using Mosquitto, but it should work with any other broker. All the source code is also published on this Github repository, and lastly, I am using this esp-mqtt component, which you will have to install separately following their installation process.

    Assuming you already have installed the ESP-IDF and the esp-mqtt component mentioned above, the first thing you need to do is to clone the repository:

    git clone https://github.com/tuxotron/garage-esp32
    

    Once you have done that, you need to configure your project by running:

    make menuconfig
    

    And you should see something like this:

    menuconfig

    make menuconfig

    The first thing you want to do here is to configure your Serial communication, device and speed (the development board I am using accepts up to 921600 baud).

    Serial

    Serial configuration

    The next you want to configure are the parameters for our project (Garage Door Opener option), in particular you need to provide an SSID and its password, and an MQTT broker, MQTT username and password (in this case, for testing purposes, I’m using mqtt://iot.eclipse.org, which doesn’t required authentication, so we can leave the the username and password blank).

    Garage Door Opener menu option

    Garage Door Opener menu option

    Once you have done that if everything is working properly, then your ESP32 will be listening (subscribed) to two topics: /garage/door/left and /garage/door/right. When a message arrives to any of these channels, we’ll check the value of such message and if the value is PUSH, then we close the relay for .5 seconds, otherwise we discard the message and do nothing.

    Let’s go through some of the important parts of the code.

    static const char *LEFT_DOOR_TOPIC = "/garage/door/left";
    static const char *RIGHT_DOOR_TOPIC = "/garage/door/right";
    
    #define LEFT_DOOR_GPIO 32
    #define RIGHT_DOOR_GPIO 33
    

    These are some of the constants where we define the topic names and the GPIO ports our relay is connected.

    During the initialization part, besides connecting to the WIFI, etc. We need to set the LEFT_DOOR_GPIO and RIGH_DOOR_GPIO as output and high.

    void app_main()
    {
        ...
    
        gpio_pad_select_gpio(LEFT_DOOR_GPIO);
        gpio_pad_select_gpio(RIGHT_DOOR_GPIO);
        /* Set the GPIO as a push/pull output */
        gpio_set_direction(LEFT_DOOR_GPIO, GPIO_MODE_OUTPUT);
        gpio_set_direction(RIGHT_DOOR_GPIO, GPIO_MODE_OUTPUT);
        /* Set these PINs high */
        gpio_set_level(LEFT_DOOR_GPIO, 1);
        gpio_set_level(RIGHT_DOOR_GPIO, 1);
    
        ...
    }
    

    Finally, inside our handling function is where we process the messages we receive to any of the channels we mentioned before:

    static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
    {
        esp_mqtt_client_handle_t client = event->client;
        int msg_id;
    
        switch (event->event_id) {
            ...
            case MQTT_EVENT_DATA:
                ...
                // Get the topic name
                char *topic = malloc(event->topic_len);
                memcpy(topic, event->topic, event->topic_len);
                topic[event->topic_len] = '\0';
    
                // Get the data
                char *data = malloc(event->data_len);
                memcpy(data, event->data, event->data_len);
                data[event->data_len] = '\0';
    
                if (strcmp(topic, LEFT_DOOR_TOPIC) == 0) {
                    if (strcmp(data, "PUSH") == 0) {
                        gpio_set_level(LEFT_DOOR_GPIO, 0);
                        vTaskDelay(500 / portTICK_PERIOD_MS);
                        gpio_set_level(LEFT_DOOR_GPIO, 1);
                    }
    
                } else if (strcmp(topic, RIGHT_DOOR_TOPIC) == 0) {
                    if (strcmp(data, "PUSH") == 0) {
                        gpio_set_level(RIGHT_DOOR_GPIO, 0);
                        vTaskDelay(500 / portTICK_PERIOD_MS);
                        gpio_set_level(RIGHT_DOOR_GPIO, 1);
                    }
                }
                ...
        }
        return ESP_OK;
    }
    

    The next step will be to test our setup. For that you can use any MQTT client, but first we need to upload our code to chip. Make sure your device is connected to your computer and run:

        make flash
    

    or if you want to see the log messages and what’s going on:

        make monitor
    

    or you can just do both in one shot:

        make flash monitor
    

    I’m using the mosquitto_pub application. Which I run the following commands:

    mosquitto_pub -h iot.eclipse.org -t "/garage/door/right" -m "PUSH"
    
    mosquitto_pub -h iot.eclipse.org -t "/garage/door/left" -m "PUSH"
    

    The first command sends the message PUSH to the right door, and second one to the left door.

    Here is short video showing these commands running:

    In the next parts of this series, we’ll add some sensors, install the device in the garage and create a mobile application to interact with it. Stay tuned!

    Esta entrada también está disponible en español.