Garage Raspi Overview

Smart garages are the next big thing in home automation, and with the help of a Raspberry Pi, Home-Assistant and Room-Assistant, you can easily convert your garage into a smart garage that provides full control of your garage door, temperature and door status monitoring, and advanced automations.

In this post, we’ll be covering the complete guide to building a smart garage control system using a Raspberry Pi and Room-Assistant, including the wiring, hardware, and network and power requirements.

We’ll also be discussing the various garage functions that you can add, such as relay for garage door opener, reed switch for manual doors open/closed status, PIR motion for occupancy sensor, and DHT11 temperature and humidity sensor.

This garage controller was one of the first devices I built and integrated into Home Assistant. Using the Raspberry pi I already had on hand and some amazon sensors and relays I’ve successfully converted my garage into a Smart Garage!

Garage Functions

The main goal to the automation was to get full control of the garage door opener as the 2 that came with the rental home never worked. Could we have asked the homeowners to fix or replace the units, sure but where the innovation in that?

On top of the door control, I also added some devices to allow some advanced automatons to happen through Home Assistant.

  • Relay for Garage door opener (5v relay)
  • Relay for 120v outlet control (5v relay)
  • Reed Switch for Man doors open/closed status
  • PIR Motion for Occupancy sensor
  • DHT11 Temp/Humid sensor

Wiring

Everything wires to the GPIO pins of the Raspberry Pi as seen in the photo below. Nothing too complex going on here, just don’t forget the resistor for the LED.

garage raspi wiring diagram

Undocumented Change! I ended up needing to add a capacitor to the PIR motion sensor as the power was not consistent at the device. Small little 4.7UF capacitor did the trick! (Change not shown in diagram below)

Hardware

Using on old Raspberry Pi Model B v1 that was a dumpster find, I built the controller with (2) 5v relay boards, PIR motion senor, Reed Switches for the doors, and a DHT11 temp sensor mounted to the top of the controller.

  • Raspberry Pi Model B v1
  • (2) 5v relay boards
  • DHT11 Temperature and Humidity Sensor
  • PIR Motion Sensor
  • (3) Reed Switches
  • Case LED (5v blue)

Network and Power

I have a network switch in the garage for devices like this that is within 20’ of the controller. Easy cable run for hardwired connectivity.

Power is fed from the outlet that also feeds the garage door opener. It’s conveniently located directly next to the opener in the ceiling.

Garage Door Controls

Using the N/O (normally open) relay contacts I’ve wired the wall switch in parallel. This gives both automated functionality through the home assistant app, it also allows the wall switch to function as intended.

This has an issue where the door controller is looking for a momentary switch, press the wall switch to initiate and release once door moves. As I have a latching relay with this setup, some trickery was needed.

In home assistant I’ve created an automation that watches for state change on the relay switch, and if seen turns it back off. Less than 1 sec of delay between initiation and deactivation.

This works like a charm for this application, turning the relay into a momentary switch.

Automation excerpt:

automation:
  # If the garage latching relay has been activated,
  # turn the garage relay off immediately, creating a momentary relay
  - alias: "Turn off garage door relay"
    trigger:
        platform: state
        entity_id: switch.garage_door
        to: 'on'
    action:
        service: switch.turn_off
        entity_id: switch.garage_door

Room-Assistant config excerpt:

switches:
    # Relay 1 - Garage door open/close
    - name: Garage Door
      pin: 17
      icon: mdi:garage-variant

Electrical Outlet Control

Using the other relay to control an outlet in the garage for things like fans and lights. Setup the relay in Room-Assistant and then automate things in Home Assistant to control the outlet.

Room-Assistant config excerpt

    # Relay 2 - FAN
    - name: Garage Fan
      pin: 18
      icon: mdi:fan

Door Status

Door status is attained using some reed switches mounted to the door frames, magnets mounted adjacent on the doors with wires running back to the controller.

Room-Assistant config excerpt:

From Garage room-assistant config

gpio:
  binarySensors:
    # Garage Back Door position reed switch
    - name: Garage Back Door
      pin: 15
      deviceClass: door
    
    # Garage House Door position reed switch
    - name: Garage House Door
      pin: 4
      deviceClass: door

Temperature

Using the DHT11 sensor and a script to report the temp every min (cron job through room-assistant script.

I’m using the old depreciated Adafruit_Python_DHT library due to issues with the new circuit python version and already having this working.

The sensor is mounted to the controller which is up in the unfinished rafters of the garage. This gives a skewed reading as the air up there is way hotter than below at head height.

Room-Assistant config excerpt:

From Garage room-assistant config

shell:
  sensors:
     # DHT11 Sensor reporting the temp °F result
    - name: Garage Temperature
      command: 'python3.7 /home/pi/room-assistant/script/myDHT.py'
      regex: '(-?[0-9.]+)F'
      cron: '*/2 * * * *'
      icon: mdi:temperature-fahrenheit
      unitOfMeasurement: '°F'
      deviceClass: temperature

     # DHT11 Sensor reporting the humid % result
    - name: Garage Humidity
      command: 'python3.7 /home/pi/room-assistant/script/myDHT.py'
      regex: '(-?[0-9.]+)%'
      cron: '*/5 * * * *'
      icon: mdi:water-percent
      unitOfMeasurement: '%'
      deviceClass: humidity

Motion

PIR sensor connected to the controller and mounted using a few standoffs to give it *better placement. The controller is mounted upside down putting the sensor on the ceiling next to the garage door opener. It is blocked by some obstructions but overall covers the doors.

No additional scripting was required as this is supported in room-assistant. Just give the pin number and name the sensor.

Room-Assistant config excerpt:

From Garage room-assistant config

gpio:
  binarySensors:
    # PIR motion sensor
    - name: Garage Motion 1
      pin: 14
      deviceClass: motion

Additional debounce configuration added for motion sensor using the Room-assistant entities configuration. This clears up any bouncy input from the device, giving a stable reading to the front end.

entities:
  behaviors:
    garage_motion_sensor:
      debounce:
        wait: 0.75
        maxWait: 2

Software

Everything is controlled and mapped to the home assistant dashboard over MQTT via the room-assistant system.

Room Assistant Config

This config file is the meat and potatoes of the program. Find it in the /home/$USER/room-assistant/config/local.yml

# ########################
# Raspi Config
#   hass-raspi6
#   Garage Ceiling
#   Garage control and monitoring
#   10.10.10.73
# ########################

# ############
# GPIO Pin-Out
# ############
#
# Inputs:
# Pin: {GPIO NUMBER} Use: {Pin function} ConnectPin: {DB9 PIN}
# Pin: 04 Use: Garage door CLOSED position sensor (reed sw) ConnectPin: 1
# Pin: 23 Use: Garage door partial OPEN position sensor (reed sw) ConnectPin: 2
# Pin: 24 Use: Garage door OPEN position sensor (reed sw) ConnectPin: 3
# Pin: 25 Use: Garage Back Door Sensor (reed sw) ConnectPin: 4 
# Pin: 15 Use: Garage House Door Sensor (reed sw) ConnectPin: 5
# Pin: 14 Use: Garage Motion Sensor (PIR) ConnectPin: 6
#
# Outputs:
# Pin: 17 Use: Garage door control (relay 1)
# Pin: 18 Use: Garage Fan Control (relay 2)
# Pin: 22 Use: Garage CPU Case LED (blue)
# Pin: 27  Use: humidity/temp DHT11 sensor using the shell functions below

# #######################
# Global Config settings
# #######################
global:
  instanceName: garage
  integrations:
    - homeAssistant
    - gpio
    - shell

# #######################
# Cluster settings
# #######################
# Config options for clustering multiple Room-Assistant
# Give leader more weight
cluster:
  weight: 1
  networkInterface: eth0
  port: 6425
  timeout: 60
  peerAddresses:
    # raspi1 patio
    - 10.10.10.70:6425
    # raspi2 office
    - 10.10.10.71:6425
    # raspi3 sprinkler
    - 10.10.10.72:6425
    #raspi4 kitchen
    - 192.168.1.75:6425 
    #raspi5 crawlspace
    - 10.0.0.74:6425
    # raspi6 garage <-- this cpu
#   - 10.10.10.73:6425

# #######################
# home assistant settings
# #######################
homeAssistant:
  mqttUrl: mqtt://10.10.10.21:1883
  mqttOptions:
    username: homeassistant
    password: {LONG_RANDOM_STRING}

# #######################
# GPIO settings
# #######################
gpio:
  binarySensors:
##########################
# NON-FUNCTIONING
#
# Connection issue at controller requiring tinkering
#######################################################

    # Closed garage door position switch
    # GPIO-23:DB9-2?
    - name: Garage Door Closed
      pin: 23
      deviceClass: garage_door
    # Partial open garage door position switch
    # GPIO-25:DB9-?
    - name: Garage Door Partial Open
      pin: 25
      deviceClass: garage_door
    # Full open garage door position switch
    # GPIO-24:DB9-?
    - name: Garage Door Open
      pin: 24
      deviceClass: garage_door 

########################################################

    # Garage Back Door position reed switch
    # GPIO-15:DB9-5
    - name: Garage Back Door
      pin: 15
      deviceClass: door
    
    # Garage House Door position reed switch
    # GPIO-4:DB9-1
    - name: Garage House Door
      pin: 4
      deviceClass: door
    
    # PIR motion sensor
    - name: Garage Motion 1
      pin: 14
      deviceClass: motion

# #######################
# Switches settings
# #######################
  switches:

    # Relay 1 - Garage door open/close
    - name: Garage Door
      pin: 17
      icon: mdi:garage-variant
    
    # Relay 2 - FAN
    - name: Garage Fan
      pin: 18
      icon: mdi:fan
    
    # blue RasPi case LED
    - name: Garage LED
      pin: 22
      icon: mdi:led-on
# #######################
# Shell settings
# #######################
shell:
  sensors:

     # DHT11 Sensor reporting the temp °F result
    - name: Garage Temperature
      command: 'python3.7 /home/pi/room-assistant/script/myDHT.py'
      regex: '(-?[0-9.]+)F'
      cron: '*/2 * * * *'
      icon: mdi:temperature-fahrenheit
      unitOfMeasurement: '°F'
      deviceClass: temperature

     # DHT11 Sensor reporting the humid % result
    - name: Garage Humidity
      command: 'python3.7 /home/pi/room-assistant/script/myDHT.py'
      regex: '(-?[0-9.]+)%'
      cron: '*/5 * * * *'
      icon: mdi:water-percent
      unitOfMeasurement: '%'
      deviceClass: humidity

#    - name: Garage CPU Temp
#      command: '/home/pi/room-assistant/script/cpuTemp.sh'
#      cron: '*/1 * * * *'
#      unitOfMeasurement: '°F'
#      deviceClass: temperature
#      icon: mdi:thermometer-lines

    # Script to check onboard temp sensor reading
    - name: Garage CPU Temp
      command: '/home/pi/room-assistant/script/cpuTemp.sh'
      cron: '*/2 * * * *'
      unitOfMeasurement: '°F'
      deviceClass: temperature

    # Script to check voltage and return boolean if no errors seen. 
    # See the script for more
    - name: Garage CPU Voltage
      command: '/home/pi/room-assistant/script/cpuVolt.sh'
      cron: '1 */1 * * *'
      deviceClass: power

    # Report CPU uptime in sec
    - name: Garage CPU Up Time
      command: '/home/pi/room-assistant/script/cpuUp.sh'
      cron: '* * * * *'
      unitOfMeasurement: 's'

    # Free memory `free -h` results
    - name: Garage CPU Free Memory
      command: '/home/pi/room-assistant/script/freeMem.sh'
      cron: '*/10 * * * *'
      unitOfMeasurement: 'MB'

#    - name: Garage Wifi Strength
#      command: 'iwconfig wlan0 | grep -i quality'
#      regex: 'Signal level=(-?[0-9]+) dBm'
#      cron: '*/30 * * * *'
#      icon: mdi:wifi
#      unitOfMeasurement: dBm
#      deviceClass: signal_strength

#    - name: Garage CPU Free Storage
#      command: '/home/pi/room-assistant/script/cpuStorage.sh'
#      cron: '1 * */1 * *'
#      unitOfMeasurement: 'GB'
#      deviceClass: timestamp

# #######################
# Entity settings
# #######################
entities:
  behaviors:
    garage_motion_sensor:
      debounce:
        wait: 0.75
        maxWait: 2

Scripts

Some additional helper scripts were also developed to return some info on the device for integrations and status’s over in home assistant.

Add these to room assistant using the shell.sensors function like this:

shell:
  sensors:

     # DHT11 Sensor reporting the temp °F result
    - name: Garage Temperature
      command: 'python3.7 /home/pi/room-assistant/script/myDHT.py'
      regex: '(-?[0-9.]+)F'
      cron: '*/2 * * * *'
      icon: mdi:temperature-fahrenheit
      unitOfMeasurement: '°F'
      deviceClass: temperature

cpuUp.sh

return the uptime in seconds formatted as int

#!/bin/bash

echo `cat /proc/uptime |awk '{print $1}' |cut -d '.' -f1`

cpuTemp.sh

return the CPU reported temp

#!/bin/bash

cpuTemp=`vcgencmd measure_temp |cut -d "=" -f2 |cut -d "'" -f1 | awk '{print ($1 *9/5) + 32}'`
echo $cpuTemp


freeMem.sh

returns the remaining RAM on the pi

#!/bin/bash

memfree=`cat /proc/meminfo | grep MemFree | awk '{print $2}'`; 
memtotal=`cat /proc/meminfo | grep MemTotal | awk '{print $2}'`; 


awk '/MemFree/{free=$2} /MemTotal/{total=$2} END{print (free*100)/total}' /proc/meminfo

#echo $(($memfree * 100 / $memtotal))

myDHT.py

adapted DHT11 temp sensor reading temp and humid

import Adafruit_DHT
import time

DHT_SENSOR = Adafruit_DHT.DHT11
DHT_PIN = 27

while True:
    humidity, temperature = Adafruit_DHT.read_retry(DHT_SENSOR, DHT_PIN)
    if humidity is not None and temperature is not None:
        temperature_f = temperature * (9 / 5) + 32
        print("Temp={0:0.1f}F Humidity={1:0.1f}%".format(temperature_f, humidity))
        exit()
    else:
        time.sleep(.05);

temperature_sensor_code.py

read DS18B20 sensor, report value in F


# Temp DS180b20 reading into F result on raspi
#
# https://pimylifeup.com/raspberry-pi-temperature-sensor/
# Modified from
#   - git clone https://github.com/pimylifeup/temperature_sensor.git

import os
import glob
import time

os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')

base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'

def read_temp_raw():
    lines = []
    i = 0
    # try to read the file 20 times, return the result
    while not lines and (i < 19):
        try:
            f = open(device_file, 'r')
            lines = f.readlines()
            i += 1
        except NameError:
            time.sleep(1)
        else:
            if not lines:
                f.close()
            else:
                f.close()
                return lines

def read_temp():
    lines = read_temp_raw()
    if lines[0].strip()[-3:] != 'YES':
        lines = read_temp_raw()
    equals_pos = lines[1].find('t=')
    if equals_pos != -1:
        temp_string = lines[1][equals_pos+2:]
        temp_c = float(temp_string) / 1000.0
        temp_f = temp_c * 9.0 / 5.0 + 32.0
        return temp_f

# print to reduced decimal place
print('{0:06.3f}'.format(read_temp()))



cpuVolt.sh

return boolean if no issues with voltage (power supply failure)

#!/bin/bash

THROTTLED=`/opt/vc/bin/vcgencmd get_throttled |cut -d "=" -f2`
RESULTS=0

if [[ "$THROTTLED" != *"0x0"*  ]];then
	RESULTS=1
fi

echo $RESULTS