I’ve had a desire to learn to work with Raspberry Pi since, like, forever. What better way to learn it than by trying out some DIY project? One of the most popular ones I’ve found around is brilliant Magic Mirror by Michael Teeuw: it’s a mirror that displays some useful info (in.e. time, forecast, news etc.) in a very stylish-looking way and gives your home a classy appeal. The only issue I had with it is that it is always on, even when there is noone around – which can be quite troublesome for your electricity bill. That’s why I decided to incorporate a simple motion detector to turn the mirror on and off, depending on whether there is somebody in the house.
R Pi and Magic Mirror set-up
There are plenty of tutorials on how to set up a Raspberry Pi, install Linux a system and get it started. Michael Teeuw also provided a step-by-step tutorial on how to set-up his Magic Mirror and gave his code for everybody to use. Perhaps the most useful tutorial for beginners is the one I found on reddit, by user The-Bent that shows an ultimate how-to guide on Michael’s mirror. So, let’s get started! The things I needed:
- Raspberry Pi (any version), accompanying SD card and a WiFi dongle
- An old LCD monitor
- Two-way mirror and a wooden frame for it
- PIR motion sensor, like one of these.
The Magic Mirror software is basically a web-browser displaying a delightfully designed php page on a local server running on R Pi. Here comes the fast run-through on how to set up Michael’s mirror.
- Set up a Raspbian (Jessie) on your R Pi, enable SSH, WiFi auto connect, and boot in Desktop mode (may the Google be with you).
- Set up an apache2 server on your R Pi and install php5 (if any of these doesn’t go smoothly, try some
sudo apt-get update
sudo apt-get upgrade.
- Download Michael’s code from github repository into /var/www/html folder (
sudo git clone https://github.com/MichMich/MagicMirror). At this point, you might check the website he made by opening http://”R Pi IP”/MagicMirror. Looks neat, isn’t it?
- Now adapt his code to match your private settings:
- open MagicMirror/calendar.php and put a calendar of your choice (change the URL in 4th row to your own iCal address)
- open MagicMirror/js/config.js and change the following lines:
var lang = 'nl'to the language of your choice (
var langn = 'en'makes it english)
- APPID to the open weather map api key of your choice
'q':'<city>,<state>'to city and country where you live.
var feed = 'http://feeds.nos.nl/nosjournaal?format=rss';to RSS feed of your choice
- List of the compliments
- Set R Pi to boot to a fullscreen web-browser. I used Midori as web-browser, and I edit /home/pi/.config/lxsession/LXDE-pi/autostart to include commands like
@xset s off @xset -dpms @xset s noblank @midori -e Fullscreen -a http://localhost/MagicMirror/index.php
that will ensure that R Pi opens a Midori browser on your homepage in fullscreen mode right after it boots up. This is so called kiosk mode. It will also disable the screen going off eventually. You can also disable the cursor showing in the middle of your screen by installing unclutter (
sudo apt-get install unclutter). If needed, you can rotate your screen (if you use it in vertical mode) by adding
"DISPLAY_ROTATE=1"in /boot/config.txt (I didn’t need it).
At this point you should have the R Pi running the Michael’s code with your private settings. Well done!
Adding a motion detector
There are many options of motion detection, and the most popular one is arguably a PIR sensor which is basically an IR sensitive JFET. So it senses your body heat when you move around. It usually comes on a board with a regulation circuitry, BISS0001 motion detector IC, and plastic cap that focuses the radiation. It has only one output pin that is logic high (3.3V) when the motion is detected and low (0 V) otherwise. Adafruit has a pretty helpful tutorial on these thingies.
You can use R Pi’s general purpose input/output pins (GPIO) to connect the sensor. I connected mine to 26th pin of the header which corresponds to the 7th GPIO port. Simple Python script can easily access those pins and read out the PIR sensor’s state. Here’s the script that I used:
#!/usr/bin/env python import sys import time import RPi.GPIO as io import subprocess io.setmode(io.BCM) SHUTOFF_DELAY = 60 # seconds PIR_PIN = 7 # Pin 26 on the board def main(): io.setup(PIR_PIN, io.IN) turned_off = False last_motion_time = time.time() while True: if io.input(PIR_PIN): last_motion_time = time.time() sys.stdout.flush() if turned_off: turned_off = False turn_on() else: if not turned_off and time.time() &amp;amp;gt; (last_motion_time + SHUTOFF_DELAY): turned_off = True turn_off() time.sleep(.1) def turn_on(): subprocess.call(&amp;amp;quot;sh /home/pi/Documents/PIR/monitor_on.sh&amp;amp;quot;, shell=True) def turn_off(): subprocess.call(&amp;amp;quot;sh /home/pi/Documents/PIR/monitor_off.sh&amp;amp;quot;, shell=True) if __name__ == '__main__': try: main() except KeyboardInterrupt: io.cleanup()
The script basically reads the sensor state from the 7th GPIO pin and depending on its state and the time since the last activity it turns on or off the monitors. Now, this is an interesting part: monitor is turned on/off by calling a shell scripts
monitor_off.sh. Each of these contains simple
tvservice command and everything would be easy-peasy if there wasn’t that HDMI/VGA babble. More on that a bit later.
When I tested the PIR sensor for the first time it worked like a charm. But when I built it in a mirror there was a problem – a sensor output was always in high state! I’ve lost a lots of nerves trying to find what was the reason for malfunction. At some point I noticed that sensor works normally again when the WiFi dongle is switched off. I realized that the cables connecting sensor with the Pi are picking up some WiFi interference as they are placed quite close to the dongle. The cables behave like some freaking antennas! Aaargh!
How to solve it then? One convenient way is a ferrite bead – a ring of ferritic material around the cable that absorbs most of the high-frequency radiation. Where to find one? It’s Sunday afternoon, ferrite bead stores are all closed. Look around the house, find a smartphone charging cable…what’s that bump next to the connector (that cylindrical widening on the cable)? Cut it out, strip it off, OMG it’s a ferrite bead!! Woohoo! Put my cable through it, just like on the photo on the right, and what – interference is gone and sensor is read normally again! If it doesn’t work try: multiple windings around the bead, different material type or maybe some ceramic capacitors to the ground next to the connectors.
Configuring the HDMI interface
Back to turning the monitor on and off. So, the Pi has a HDMI port while the monitor I got has a VGA. In normal operation HDMI-to-VGA adapter would be enough, but here we need to take a special care on few things. First, open the /boot/config.txt and edit few things, like set
hdmi_force_unplug=1 that will force the HDMI output on R Pi even though there is no HDMI device on the other end. You may want to change few other options to define desired resolution or audio output. Other cool HDMI settings are listed here and don’t forget to set the resolution (
hdmi_mode) that your monitor supports.
One additional thing is turning monitor back on after it’s been shut down. Simple
sudo tvservice -p won’t do the job – you have to re-enable the frame buffer and add the following code
fbset -depth 8 && fbset -depth 16. Finally,
monitor_on.sh script should look something like this
#! /bin/bash sudo tvservice -p && fbset -depth 8 && fbset -depth 16
The only thing left is making the python script started as soon as Pi is turned on. To make this, I included a command
@reboot python /home/pi/Documents/PIR/pir.py &
cronetab (& at the end means it will be background process).Reboot the Pi and if everything’s done right you should have your mirror working in something like on this video: