DIY Motion Sensor with Raspberry Pi Zero W and MQTT

I've been really getting in to Home Automation lately. I don't own a home, but there is a surprisingly large pool of things you can implement when living in an apartment. Most recently I've been playing with automating lights, starting first with the humble bathroom! I'm one of those people who needs a light to use the bathroom. Even if it's the middle of the day, the sun is shining, I have to turn on a light. This has been an experiment to relieve my brain of that pressure, as well as make any late night excursions a little more pleasant.

This whole project can be done for around $20 to just make the sensor. For a DIY approach, it's not bad! The nice thing is that it's also a great platform to add more sensors too down the line for a small investment.

Things you'll need

  • Raspberry Pi Zero W (RPiZW for short)

  • 8GB+ Class 10+ Micro SD Card

  • PIR Motion Sensor with headers

  • A few jumper wires (or loose wire to solder)

I decided to start with the hardware as this made the most sense. I picked up a RPiZW from my local Micro Center for $13 with header pins. I'm still relatively new to soldering, so it didn't make sense to purchase the headers separately if I might screw it up. The price of headers with a bare computer also happened to be slightly more expensive. Win win for me! I also grabbed a cheap plastic case for around $5.

The next thing I needed was the motion sensor. I also picked this up from Micro Center, but at what I later found out was a steep premium. A 3 pack of these sensors can be found on Amazon for $5, whereas I paid $6 for one. If you want your homemade sensor to be multi-functional, a temperature/humidity sensor is a great addition for just a few more dollars.

Follow the directions to hook up your sensor to the Pi. In my case, the PIR needed 5V, a ground, and a data pin. I used GPIO 14, but feel free to use any open GPIO if you are adding this to an existing board. Using some extra female to female jumper wires I had laying around, it took all of 30 seconds to hook everything up. Now onto the software.

I used Etcher to mount Raspbian Stretch to the SD card. While I have the hardware necessary to setup the Pi using the GUI, it didn't make sense considering I will likely never need to use it again, except to tweak a few values in a script file occasionally.  I followed a setup guide for installing the OS headless, got it connected to my network and SSH'd in. Once logged in, I needed to install pip using the apt package manager then I needed to install paho-mqttusing the newly installed Python package manager. I did run into an issue here with the library being detected, so I recommend doing a reboot just to refresh everything. Since the computer is basically empty, it takes maybe 30 seconds even on the low spec hardware.

After that, I adapted a simple Python script I found online to access the GPIO pins, and constantly read the data for the motion sensor. When the pin is pulled high (1 in my case), then motion has been detected. Whenever motion is detected, I fire off a very simple MQTT event using paho.mqtt.publish. While it's technically not the most efficient way to send  data, it is much easier to read and the bathroom is such a low traffic area, the extra overhead to connect to the MQTT broker is not an issue. If you are potentially sending constant updates for temperature and humidity, it may be worth looking into the client method in paho.

To run the script on startup, I added a cron task on @reboot to start the Python script. I'm not an expert on the Linux startup processes enough to know when the network kicks in, so at the top of my Python script, it sleeps for a minute while the computer finishes booting and connects to my network. So far, this has worked fine and should continue to work even in the case of an ISP failure, since the Pi is connecting a MQTT broker on my local network.

With that working, I subscribe to the MQTT topic from within my Home Automation software, OpenHAB at the moment, and then everything else is connected there. For my own purposes I have a few simple rules. The bathroom light is controlled with wireless smart bulbs (IKEA Tradfri). Upon entering the bathroom, motion triggers the light to turn on. From there a timer starts for 2 minutes. If motion is sensed before that timer expires, it is reset back to 2 full minutes. This is fine for most bathroom tasks. Brushing your teeth or hair are very animated tasks that constantly trigger the sensor, which is positioned in the corner of the vanity, facing the door and whoever is standing in front of the sink. For other more, private rituals, two minutes can be a little too short if you like to read Reddit on your phone. Luckily a quick swipe of the arm or shake of the head will trigger the sensor again and turn on the lights.

For showering, I placed an IKEA Tradfri remote near the shower that can be used to manually turn on the light so poking an arm out is not required every few minutes. Upon exiting the shower, motion is sensed and the 2 minute timer is started. Unfortunately, there is no way to re-purpose the Tradfri remotes yet for custom events, otherwise I would have it be a manual override at all times. This way, one could press the button before getting in the shower and then press it again after they are done. Or perhaps manually overriding the timer for 45 minutes instead of 2. Plenty of time for a long shower or bath.

At Midnight, the bathroom light automatically changes to a very dim, but solid red. This is to help preserve night vision for those late night trips to the loo. At 6AM, the lights are changed back to a bright white, the preferred color of my wife and I for our lights.

Since it's just the two of us, the 2 minute timer is fine to deal with. We've had it running successfully for 3 days now and haven't minded the occasional shut-off. If anything it's a reminder to hurry up since we only have one bathroom in our apartment! When guests come over, I plan to change the timer to a much more generous amount, most likely 10-15 minutes. I also plan to have the manually override ironed out by then.

In the future I may add a temp/humidity sensor to effect the timer, since even a moderately warm shower will raise the overall humidity in the bathroom. Adapting the script to read an extra GPIO pin or two should be straightforward as well.

Below is a short demo I recorded the night I got everything working. Over time I hope to add the script as well as some more in depth assembly photos. If that's something that interests you, leave a comment or tweet me @DaronSpence and I'd love to hear your thoughts. I'm also happen to answer any questions about my setup.

Posted in:

Home Automation