A Home Automation system using a Raspberry Pi 2 and Windows 10 IoT Core including an App.
Update 2: The project is still growing and a lot of new features are already implemented (like a Twitter-Client and the integration of Telegram-Bots). Please check the GitHub repository and release notes to learn more about the new features (or follow me on Twitter) . I hope I am able to update this project page as soon as possible.
Update 1: First I want to say “thank you” to everyone who has read this project page and gave me feedback (either private or at the comments). It was a lot of fun to present this project at Maker Faire Rome 2015 and Microsoft Technical Summit 2015 and future events are still waiting. I added some pictures from the events.
I am developing a home automation solution for the last 3 years. This includes the physical installation of the hardware and developing the software.
At this time, the following features are supported.
- Push button (BUSCH-JAEGER 2020US)
- Motion detector (Abus 360° BW8085)
- Room temperature (My own device based on DHT22)
- Room humidity (My own device based on DHT22)
- Window state (open or closed using Honeywell Slimline reed contact)
- Sunrise, Sunset, Temperature & Humidity (Taken from OpenWeatherMap)
- Lamp (ceiling) (driven by relay, no dimming)
- Socket (driven by relay, no dimming)
- Roller shutter (window) (driven by two relays for up and down)
- Fan (ceiling) (driven by 3 relays for every gear)
- Bathroom fan (driven by 2 relays for every gear)
- The solution contains a web app for iOS, Android, Windows, Mac OSX which can be used to control the virtual actuators. The configuration for the web app is loaded from the controller (Windows IoT instance).
- All events generated by inputs and outputs can be published to a Microsoft Azure Event Hub and/or logged to a CSV file.
- The controller (Windows IoT instance) provides UDP based tracing which can be shown using a console application. The trace is very detailed and can be used to find bugs or wrong connected actuators etc.
- Custom actuators can be added to support more hardware.
- Physical outputs can be combined to logical outputs.
- Animations (the physical outputs within a logical output can be animated).
- The whole system is designed to be as resistant to errors/hardware failures as possible. Even if multiple core components are disconnected/broken the remaining system still works as intended (e.g. some of the boards in the living room are not reachable due to a hardware failure, but the bathroom still functions as intended)
- Support for 433Mhz remote relays.
As we renovated our home 3 years ago, I decided to implement my own home automation solution. The main idea behind the implementation is to control everything from the power distributor using relays. Due to this decision every button, lamp, socket, roller shutter etc. needs to be connected by it’s own cable via the actuator to the power distributor. A bus like KNX or EIB is not required.
Note: Due to the fact that I live in Germany, every component is designed to work with the 230V power supply. Other kinds of power supplies may need further modifications. The installation of 230V cables (NYM), new power distributors etc. are done by my preferred electrician and not by myself.
The new power distributor
We installed a new power distributor which is responsible for the two floors of our home.
The I2C bus
In general, the I2C bus is not designed to work with longer cables but it is possible to increase the maximally possible length using some tricks (I do not know the reason for every optimization but these are the things I found at the WWW).
- Drive the bus at 5V. The RaspberryPi drives the bus at 3.3V, so a I2C level shifter (P82B96) is required. This is the first (and only) device which is added to the RaspberryPi 2 (called Controller in my solution). The cable for this connection should be as short as possible. The specification allows running the bus at up to 15V but the slaves like PCF8574 only support max 5V.
- Use a twisted pair cable like CAT7. It is important to use one pair for SDA&GND and another one with SCL&GND. Do not use a single twisted pair cable for SDA&SCL. Also ensure that the shielding of the cable is connected to PE (in Germany).
- Prefer a strand cable. This makes it more complex to connect everything but will boost up the length of the cable.
- Add pull-up resistors with 10k to the end of the bus for SDA and SCL.
- Limit the bus speed to 100kbits (Standard Mode) even if the slaves supporting faster speeds.
- Include a I2C buffer (P82B96). The IC can be used as a level shifter or can be used to separate the bus in physical segments. I used one of this buffers within the power distributor. The buffer should be placed at the middle of the bus.
This optimized I2C bus is used to connect every board within the power distributor.
The relay boards (outputs)
CCToolsfrom Germany sells boards with relays which can be connected to the I2C bus. It is also possible to buy the boards as individual parts or the circuit board only. This allows replacing the port expander with pin compatible alternatives. The former is required because the available addresses of the devices are limited. I added holders for the relay and ICs so I can replace them easier if one o them is broken. Another point is that I can use a PCA9555D instead of a MAX7311 because the PCA9555D is cheaper and can be ordered easier (in Germany).
The HSRel5 relay board has 5 relays and 3 GPIOs. All required ports are taken from the internal PCF8574 8bit port expander which has 8 GPIOs. The first 5 are used for the relays and the last 3 can be used for other outputs. The relays require 12V to operate which can’t be provided by the port expander (which can only drive a LED). So, a relay driver is needed. The relays are connected with the relay driver and the relay driver in return is connected to an inverter. This inverter is required because the state of all ports at the port expander is HIGH after the IC gets power. This will close all relays, which is an unintentional behavior.
Conclusion: If the first relay should be closed, it is required to send 00011110 (MSB) to the port expander using the I2C bus. This will set the first port to LOW (the other ports are also updated). The first port of the port expander is wired to the first input of the inverter. And the first output of the inverter is wired to the first input of the relay driver (ULN2803). As the last part of the chain the relay is wired to the first output of the relay driver.
Another relay board from CCTools is the HSRel8(+8) which uses a MAX7311 as the port expander and contains 8 relays and 8 GPIOs. This board does not need a hardware inverter. This means that a HIGH state for a relay at the HSRel5 means OFF and a HIGH state at the HSRel8(+8) means ON. This different behavior is handled by the driver for those devices and is part of the software.
Every lamp, socket, etc. is connected to one of these relays. At my home I currently use 8 HSRel5 and 4 HSRel8. I also use boards with solid state relays and other kinds of relays but to keep it short I won’t go into the details here. The HSRel5 is the simplest relay board. But the PCF8574 only allows 8 distinct addresses. The PCF8574Ais the same port expander but has 8 different addresses. This means that 16 HSRel5 can be wired to the I2C bus.
The port expanders (inputs)
Buttons, motion detectors and reed switches (for the windows) are wired to a board called I2C-Port16 HS from CCTools. This board contains a port expander (MAX7311), pull-up resistors (5V, 10K) for every port and ceramic capacitors (100NF). The board can be used with 12V or 5V power supply. The ceramic capacitors are used to filter out noise (glitch filter).
Every input device (button, motion detector, reed switch) has its own cable leading to the power distributor. A CAT7 cable is used for every input device since it needs to have shielding, which is connected with PE (protection ground). Spots which have more than one button like the buttons for the roller shutters can be connected using only a single CAT7 cable.
At the power distributor, every input device is wired to one port of the port expander and GND. Due to the pull-up resistors, the state at the ports is HIGHby default. Pushing the button will connect the port to GND which results in a LOW state of the port. The motion detectors and reed contacts are working that way too.
An shared interrupt cable is wired to all input boards. This cable is pulled-up by default. In the case of a changed state at any of the port expanders, the corresponding port expander will set the state of the interrupt to LOW. This behavior prevents continuous polling of all port expanders using the I2C bus. The software at the Pi2 is only polling the corresponding GPIO. If the state at the interrupt-GPIO has been changed, the current state of each input board is polled accordingly and events are fired if needed.
Raspberry Pi 2
The Raspberry Pi 2 is running Windows 10 IoT and is mounted with a custom case to the power distributor. It also has a prototyping shield with a status-LED, the interrupt port with a pull-up resistor (10K), a protection resistor (1K), and a ceramic capacitor (100NF) for glitch filtering. All cables can be wired using a screw-terminal.
Temperature & Humidity sensor
The current temperature and humidity at every room/place (currently 10) is measured using a DHT22 (AOSONG). This sensor provides the current temperature and humidity using a proprietary protocol which does not support addressing. This requires that every sensor is wired to a micro controller. For my solution I decided to add an Arduino Nano V3.0 as a slave to the I2C bus. The Arduino Nano reads the values from all attached sensors every 2.5 seconds and caches them locally. These values can be read from the Arduino Nano after sending the port id (0-10). It is the same behavior when reading data from registers using the I2C bus.
The temperature and humidity is shown at the web app using two different views.
The icon on the right side of the humidity (“Luftfeuchtigkeit”) entry indicates whether or not there is an increased risk of growing mold at the walls. A value less than 60% is green, less than 70% is yellow and above 70% is red.
The web app also provides an overview of all sensors.
The following image illustrates a hardware setup at the power distributor using input- and output-boards. The 12V/5V power supply and the N/PE connections are not shown.
433Mhz remote relay
While migrating and documenting the project in the course of this challenge I also developed the 433Mhz sender unit which is conveniently hidden inside a plain case together with the temperature and humidity sensors.
This feature makes relay boards optional. The Arduino Nano which is responsible for the DHT22 (Temperature and Humidity) sensors is also sending the 433Mhz signals. The sender (FS1000A) is mounted together with the temperature and humidity sensor within a case at a central room of the house. To increase the range of the sender even further, it is additionally powered with 12V (also working with 3.3 but short range).
One of the main problems with the remote relays is that they are not sending any state information. So it is absolutely possible for the user to introduce state changes to the system by using the original remote. To force synchronization, the software solution automatically updates the state every 5 seconds. This keeps the state which is shown on the web app as reliable as possible (but making the usage of the original remotes useless).
Remote relays can be used within every automation and providing the same features as relays from a relay board.
The 433Mhz remote’s codes can currently only be manually configured via a circuit build on a prototyping board. Those codes are then copied to the configuration. The fritzing sketch for the required circuit board is referenced below and the Arduino sketch is located at the repository at the folder CK.HomeAutomation.SensorsBridge\RemoteCodeFinder.
The digital cat litter box
The cat litter box for our cat is placed at the storage room which is sadly lacking any window to let in some fresh air after usage. Due to this problem, the box is connected to an old unused flue. In front of the tube which is connected to the flue, there is a fan wired to a relay at the power distributor. A motion detector at the storeroom detects even the cat and starts the fan for some minutes.
The cat litter box has its own icon at the web app which allows for controlling the fan remotely.
By analyzing the generated logs and filtering by the corresponding actuator changes (Azure SQL DB or CSV file) it is possible for us to track the cat’s litter box usage over time and therefore improve upon the required cleaning intervals.
Before the release of Windows 10 IoT, the software was running on a G120from GHI electronics using the .NET Micro Framework in Version 4.3. But mainly due to the lack of performance (120Mhz, 16MB RAM and interpreter) not all planned features were working as planned.
A couple of weeks ago I started migrating the code base to run as a Windows 10 IoT background task, while also adding features like the Microsoft Azure integration.
The repository which is referenced below contains the Visual Studio 2015 Solution and all depending projects. It is all that is required to use the Raspberry Pi 2 as a Home Automation Controller, while being open for extension by writing custom drivers for other relay boards or sensors.
The projects of the software solution are grouped into:
- App (Contains the web app)
- Controllers (Contains the startup project for the Pi and the home configuration)
- SDK (Contains all shared projects)
This project contains a console application which displays trace messages sent by the controller (Pi2 instance). Currently all notifications are continuously sent to a broadcast address using an UDP socket. Therefore opening a port (e.g. 19227) at the firewall is required. I use the TraceViewer mainly to find bugs and/or misconfigurations.
All classes which are required to send notifications are located at the project CK.HomeAutomation.Notifications.
This project contains the implementation of a basic HTTP server. The HTTP server is required for the web app and provides status information in JSON format and accepts requests with status changes.
The HTTP server is also able to host the web app. Due to different package names, the content of the web app must be manually uploaded to the destination folder using the administrative SMB share.
Target folder: \\[IP]\c$\Users\DefaultAccount\AppData\Local\Packages\CK.HomeAutomation.Controller-uwp_p2wxv0ry6mv8g\LocalState\app
Each project in the Controllers folder is a startup project implementing an IoT Background Task. Until a detailed documentation is provided one can use these projects (currently at use in my home) as an example.
Additionally I provide the project CK.HomeAutomation.Controller.Empty as starting point for playing around with the solution. NOTE: The controller named Cellar which is responsible for the garden and parking lot lights is not covered in this documentation.
Before testing the solution you should be familiar with the following tasks:
- Setting up a Raspberry Pi2 with Windows 10 IoT from scratch (https://ms-iot.github.io/content/en-US/win10/SetupRPI.htm)
- Connect with the Raspberry Pi2 using a Microsoft PowerShell remote session (https://ms-iot.github.io/content/en-US/win10/samples/PowerShell.htm)
- Deploying an universal windows app to the Raspberry Pi2.
The solution directory also includes a small PowerShell script called SetupRaspberryPi.ps1 to execute a common chain of commands to setup the Raspberry Pi2. It is recommended but not required that you execute the script (make sure to adjust all IP settings according to your own infrastructure).
This project provides the highest level of abstraction. The home, rooms end every actuator like push buttons, lamps, socket etc. are implemented in this project and provide special events and methods according to the features of every actuator.
Rooms can be created using a fluent API which makes the configuration easy to read and understand.
MotionDetector – Actuator
This actuator is used to detect people and motion at the rooms. I use the motion detector BW8085 360° from Abus which is mounted at the ceiling of every room.
The implementation of a motion detector actuator provides two events. The first of the two is the MotionDetected event which is fired if motion is detected. The physical motion detector keeps the output at a HIGH level until no further motion is detected, at which point the second event DetectionCompleted is fired.
The following image shows an entry for a motion detector in the web app. Every motion detector can be deactivated (in software only) using the web app. The red dot indicates that motion is currently detected.
Button – Actuator
This actuator represents a physical push button. The button has two events which are indicating that it was pressed. The event PressedShort is fired if the button was pressed for a short duration (< 1.5 seconds), while the event PressedLong is fired only if the button was pressed for a longer duration (> 1.5 seconds). The second event is also automatically fired if the duration (1.5 seconds) has exceeded and the push button is not released. This two events allowing buttons with multiple features.
The solution also contains a VirtualButton. This button implements the same interface (IButton) and can be “pressed” using the web app only.
Socket, Lamp, BinaryStateOutput – Actuator
The base class BinaryStateOutput is used for every actuator which supports a binary state (ON and OFF) only. Examples for those actuators are Socketand Lamp. The base implementation provides methods for updating (ON and OFF) or toggling the state. Buttons can interact with objects implementing the IBinaryStateOutputActuator, this allows the addition of multiple custom actuators.
The following image shows the template for every binary state outputs. The icon on the left side is different for sockets and lamps. Custom icons like the poison bottle at the “Mückenstecker” entry can be defined using the configuration file (Configuration.js) for the web app.
Every physical actuator of type BinaryStateOutput can be used to create a logical binary state actuator. One actuator must be set to “master” which is required to determine the new state if the state should be toggled. The actuator has its own ID and can be used like any other binary state output actuator (the required interface is implemented).
One important advantage of this implementation is the way state updates are handled. Usually the new state of a binary state output is directly committed to each device one by one via the I2C bus. This behavior creates short but visible delays between each actuator state update. The CombinedBinaryStateActuator prevents this delay using internal change tracking.
StateMachine – Actuator
More complex states than ON and OFF are possible to configure using the StateMachine. This actuator allows multiple states for ports (relays) or other binary output actuators.
Example with a fan:
The state machine provides methods to turn it off or moving to the next state. The state is reset to OFF if the last state of the state machine has been reached and the initial state should be applied next.
Another use case for the state machine is creating templates or “moods” for a couple of other actuators.
The method WithTurnOffIfStateIsAppliedTwice ensures that the state of the state machine will change to OFF if a particular trigger has been activated a second time as the configured state is still active (Example: Pressing the push button for “DeskOnly” will activate the “DeskOnly” mood. If the push button is pressed again while the “DeskOnly” mood is still active, the actuator applies the OFF state. A dedicated push button for the OFF state is not needed.).
The following image shows the template for state machines. The caption and image of each state can be changed using the configuration file of the web app.
Read More Detail Home Automation system using Raspberry Pi