Smart Garage Door Opener with Environmental Sensors
Written on August 10th, 2023 by Kevin AhrendtIntroduction
This project’s goal is to connect my garage door opener to Home Assistant while also collecting environmental data. My garage door opener uses the Chamberlain Security+ 2.0 protocol, so, unfortunately, a simple relay for the door button wires does not work. Fortunately, Paul Wieland has developed and sells ratgdo shields that allow you to use an ESP8266 or ESP32 to control the garage door opener. Finally, I use the esphome-ratgdo custom component to use ESPHome to control the Garage Door Opener functions while also collecting data from various sensors.
The main focus of this post is to show how I used off-the-shelf components to collect environmental data in my garage rather than the ratgdo project, though I highly recommend the ratgdo shields! The air temperature, humidity, and pressure are all measured. The distance from the ceiling to below is collected. This distance determines whether or not the car is in the garage. The motion sensor automatically turns on the door opener lights when someone enters the garage. All the sensor modules use I2C communication and have Adafruit’s Stemma/SparkFun’s Qwiic connectors for easy development. To use only I2C sensors, I contributed implementations to the ESPHome project for the BMP581, Qwiic PIR (not accepted into the project yet), and Zio Ultrasonic sensors. Instead, I could have used the existing components for the PIR sensor and the ultrasonic distance sensor. However, this would require two more GPIOs on the ESP32. Using I2C sensors allow me to keep my wiring minimal, especially since the ESP32 and ratgdo shield are next to the garage door opener, and I wanted to mount the sensors in a more optimal position.
Sensors mounted on garage ceiling with an RJ11 cable leading to the garage door opener and the ESP32 on a ratgdo shield.
Components
- Controller
- I2C Components/Sensors
- Adafruit LTC4311 I2C Extender - Allows for a long I2C cable so that sensors in a more suitable location.
- Adafruit SHT45 Precision Temperature and Humidity Sensor - Typically measures temperature with ±0.1°C accuracy and humidity with ±1.0% accuracy.
- SparkFun BMP581 Pressure Sensor - A pressure sensor with high accuracy, ± 0.5hPa max.
- SparkFun Qwiic Ultrasonic Distance Sensor - Used to determine whether the car is parked in the garage. This sensor uses I2C communications for simplified wiring.
- SparkFun Qwiic PIR Motion Sensor - A motion sensor that communicates over I2C for simplified wiring.
- Wiring
- Right Angle RJ11 Breakout - Used on the sensor end of the phone cord connecting the sensors to the ESP32 board.
- RJ11 Breakout - Used on the ESP32 end of the cord.
- RJ 11 Cord
- SparkFun Qwiic Cable Kit - Used to connect sensors to one another.
- Hardware
- Adafruit Swirly Aluminum Mounting Grid - Easy way to mount components with varying dimensions.
- Nylon Standoff Screw Set - Used to mount the components while not being electrically conductive.
Sensors
The sensors are attached to the Swirly Mounting Grid using hex standoffs. The right-angle RJ11 breakout is similarly attached, with right-angle pins soldered into place. I used a female jump to Qwiic cable to connect to the first sensor. I then used regular Qwiic cables to connect each sensor to the next in a daisy chain. The cables pass through the mounting grid holes with care.
I used a heavy-duty wire cutter to cut off the excess mounting grid. I then placed the cut-off portion on the bottom of the other grid and used M3 screws to connect the two. This extension allowed me to use a 3M Medium Command Strip to attach the sensors to the garage ceiling. Without the extension, the screws from the standoffs extended too far for the Command strip to connect with the one on the ceiling.
Sensors mounted on Adafruit Swirly before cutting.
Underneath view of sensors mounted on Adafruit Swirly before cutting.
Sensors on Adafruit Swirly after cutting excess.
Excess Swirly material mounted to sensor board with M3 screws.
Medium command strip applied to bottom of sensors mounted on Adafruit Swirly.
ESP32 on ratgdo
I soldered an RJ11 breakout directly to the LTC4311 I2C extender board. I used a Qwiic Cable to male jumper adapter to connect it to the ESP32. I soldered some headers on the ESP32 specifically for the I2C connection, as the ratgdo shield seems to have additional circuitry for the broken-out pins. The ratgdo shield is attached to the Garage door opener following the original instructions.
RJ11 breakout board soldered directly to LTC4311 module.
Another view of RJ11 breakout board soldered directly to LTC4311 module.
ESP32 D1 mini on ratgdo shield, with wiring for I2C sensors.
LTC4311 I2C extender connected to ESP32 D1 mini on ratgdo shield.
Wires on garage door opener for ratgdo control.
ESPHome Configuration Highlights
I used the basic configuration from the ESPHome-Ratgdo project as a basis. I do not have any reed switches connected to the ratgdo shield, so I removed them from the configuration. Here are some of the highlights of my ESPHome configuration file.
Ultrasonic Sensor to Detect If Car is Present
The ultrasonic sensor measures the distance from the ceiling to whatever is below it. When the car is in the garage, the distance is much less than if not. The sensor measures distance in mm, but this measurement is noisy. This noise does not affect the car presence detection, so I convert mm to m using the multiply filter and keep only one decimal of accuracy. The sensor only updates the distance to HA every minute or if the distance changes by 0.1 m using the or
, delta
, and throttle
filters.
A template binary sensor determines the car’s presence state. If the distance is more than 2m, then nothing is below the ceiling; i.e., the car is not in the garage. I use the invert
filter to get the correct logic and the delayed_on_off
filter to debounce any noise.
sensor:
- platform: zio_ultrasonic # included in ESPHome 2023.7
name: "Distance"
id: ultrasonic_distance
update_interval: 1s
unit_of_measurement: "m"
accuracy_decimals: 1
filters:
- multiply: 0.001 # convert mm to m
- or:
- delta: 0.1 # publish if distance changes more than 0.1 meters
- throttle: 60s # publish every 60s
binary_sensor:
# Car Presence from Distance Sensor
- platform: analog_threshold
name: "Car"
sensor_id: ultrasonic_distance
device_class: presence
icon: mdi:car
threshold: 2 # if the distance is more than 2m, then no car is present
filters:
- invert
- delayed_on_off: 5s
Motion Sensor to Turn On/Off Lights
The Qwiic PIR Motion sensor is an internal component in ESPHome. If it detects motion, it turns on the garage door opener light using the ratgdo component. A copy
sensor turns off the light after not observing any motion for 2.5 minutes. Finally, another copy
sensor sends the motion sensor state to Home Assistant, with the delayed_on_off
filter debouncing the signal.
external_components:
- source: github://pr#5194
components: [ qwiic_pir ]
binary_sensor:
# Qwiic PIR Motion Sensor
- platform: qwiic_pir
id: qwiic_pir_motion
on_press:
then:
- light.turn_on: ${id_prefix}_light
# Motion sensor filtered for internally turning light off
- platform: copy
source_id: qwiic_pir_motion
id: motion_light_off_delay_filter
filters:
- delayed_off: 2.5min
on_release:
then:
- light.turn_off: ratgdo_light
# Motion sensor filtered for HA
- platform: copy
source_id: qwiic_pir_motion
name: "Motion"
filters:
- delayed_on_off: # debounce the motion state
time_on: 50ms
time_off: 15s
Environmental Sensors
The SHT45 is a very accurate temperature and humidity sensor. The BMP581 is a very accurate pressure sensor. The raw measurements are internal sensors. These measurements determine the absolute humidity and dew point in the garage. Copy
sensors send the average value to Home Assistant every 15 seconds using the throttle_average
filter.
external_components:
- source: github://pr#4657 # included in ESPHome 2023.8 beta
components: [ bmp581 ]
sensor:
# SHT45 Temperature and Humidity Sensor
- platform: sht4x
update_interval: 0.25s
temperature:
id: sht45_temperature
humidity:
id: sht45_humidity
# BMP581 Pressure and Temperature Sensor
- platform: bmp581
update_interval: 0.25s
address: 0x47
temperature:
id: bmp581_temperature
oversampling: 8x
pressure:
id: bmp581_pressure
oversampling: 128x
# Absolute Humidity Sensor derived from temperature and humidity
- platform: absolute_humidity
temperature: sht45_temperature
humidity: sht45_humidity
id: absolute_humidity_sensor
# Dew point Sensor computed using Magnus-Tetens formula (uncertain up to 0.35 degrees C)
- platform: template
id: dew_point
update_interval: 1s
device_class: temperature
unit_of_measurement: "°C"
accuracy_decimals: 1 # formula is uncertain up to 0.35 degrees C = 0.63 degrees F for usual indoor temperatures
lambda: |-
const float alpha = 6.112; // (hPa)
const float beta = 17.62;
const float lambda = 243.12; // (degrees C)
float RH = id(sht45_humidity).state; // Relative Humidity
float T = id(sht45_temperature).state; // Temperature in (degrees C)
float H = log( RH/100 ) + beta*T/(lambda+T);
return (lambda)*H/(beta - H);
# SHT45 Sensor
- platform: copy
source_id: sht45_temperature
name: "Temperature"
accuracy_decimals: 1
filters:
- throttle_average: 15s
- platform: copy
source_id: sht45_humidity
name: "Humidity"
accuracy_decimals: 1
filters:
- throttle_average: 15s
# BMP581 Pressure Sensor
- platform: copy
source_id: bmp581_pressure
name: "Pressure"
filters:
- throttle_average: 15s
- platform: copy
source_id: bmp581_temperature
name: "BMP581 Temperature"
entity_category: diagnostic
filters:
- throttle_average: 15s
# Humidity Derived Sensors
- platform: copy
source_id: absolute_humidity_sensor
name: "Absolute Humidity"
filters:
- throttle_average: 15s
- platform: copy
source_id: dew_point
name: "Dew Point"
filters:
- throttle_average: 15s