Read the statement by Michael Teeuw here.
{HowTo} turn on/off your monitor (Time based, PIR/Button, App)
-
Hi all ;)
Since there were several questions in the Forum for the best way to turn off and on the monitor i wrote this tutorial and try to show the mostly used options.
The meaning of this tutorial is to get the most used options at the same place :)
So i hope it is ok for the developers of the modules/scripts when i maybe write the installation guide a second time. :DPlease keep in mind, that i wrote some parts just out of my head. I tried all options listed here some time ago and all were working. Nevertheless it could be that i forget some points, but if so don’t hesitate to hit my face :P
Many thanks to all developers, who wrote these great modules and/or scripts.
@paviro (MMM-PIR)
@Jopyth (MMM-Buttons)
@cowboysdude (pir script)
@mochman (Whitelist HowTo)Oh…and i am open for any suggestion
So…
The very important thing is, that your monitor supports HDMI-CEC or ARC. Otherwise u will not be able to turn it on or off via HDMI.
To reassure you, most monitors do this ;)
To check if it works just go into terminal via ssh and type:sudo tvservice -oto turn off
sudo tvservice -pto turn onedit: for some monitors the following commands work better. Please use them if your monitor needs it:
vcgencmd display_power 0to turn off
vcgencmd display_power 1to turn onWe will define in several possibilities:
Using
-
Software handling via Cronjob (time based)
-
PIR-Sensor (HC-SR501)
1.module version
2.external version -
App
-
Button
1.module version
2.external version -
Relays (monitor will be totally shut down!)
1.button version (toggle function, on/off with every press)
2.PIR version -
Just turn monitor content black (monitor is still on, but u got a black screen)
1. Using Cronjobs
So lets start with the most easiest way. There is no optional hardware needed and u will be able to turn on or off the monitor at specific days and daytimes.
For your understanding how cronjobs works u should note the following:
* * * * * user executive_command ┬ ┬ ┬ ┬ ┬ │ │ │ │ │ │ │ │ │ └──── Weekday (0-7, Sunday is 0 or 7) │ │ │ └────── Month (1-12) │ │ └──────── Day (1-31) │ └────────── Hour (0-23) └──────────── Minute (0-59)Next steps we will do as root to be sure it works. Maybe not the best way, but i am just a simple guy, who is still learning the stuff. ^^
Lets say we want to turn on the monitor every day at 6am and turn off at 8pm:
sudo nano /etc/crontab(to open the crontab)write this into the file:
0 6 * * * root /usr/bin/tvservice -p >/dev/null 2>&1
0 20 * * * root /usr/bin/tvservice -o >/dev/null 2>&1your crontab file should look like this:
# /etc/crontab: system-wide crontab # Unlike any other crontab you don't have to run the `crontab' # command to install the new version when you edit this file # and files in /etc/cron.d. These files also have username fields, # that none of the other crontabs do. SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin # m h dom mon dow user command 17 * * * * root cd / && run-parts --report /etc/cron.hourly 25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily ) 47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly ) 52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly ) 0 6 * * * root /usr/bin/tvservice -o >/dev/null 2>&1 0 20 * * * root /usr/bin/tvservice -p >/dev/null 2>&1 #This was simple, right?
So now we want to turn on the monitor every Mo-Fr from 6-9am and from 4-10pm. On saturday and sunday it will be turned on from 8am-10pm. That would be look like this:
0 6,16 * * 1,2,3,4,5 root /usr/bin/tvservice -p >/dev/null 2>&1 0 9,22 * * 1,2,3,4,5 root /usr/bin/tvservice -o >/dev/null 2>&1 0 8 * * 6,7 root /usr/bin/tvservice -p >/dev/null 2>&1 0 22 * * 6,7 root /usr/bin/tvservice -o >/dev/null 2>&1Alright, thats it. Please keep in mind that this way is the easiest, but probably the most expensive because on at the predefined times even if you don’t look at your mirror.
2.1 Using PIR-Module
Probably the most used option is using a PIR and paviro’s MMM-PIR module.
cd MagicMirror/modules
git clone https://github.com/paviro/MMM-PIR-Sensor.git
cd MMM-PIR-Sensor
npm install
cd
sudo usermod -a -G gpio pi(the „pi“ at the end stands for your username)
sudo chmod u+s /opt/vc/bin/tvservice && sudo chmod u+s /bin/chvt
nano MagicMirror/config/config.jsAdd the following somewhere between your existing modules:
{ module: 'MMM-PIR-Sensor', config: { powerSavingDelay: 120 // (seconds) how long the monitor will be turned on } },Save the file by typing „ctrl+c“ and „y“
Connect your PIR as shown here:

We use GPIO-Pin 22 as it is used by default in the MMM-PIR module.
For all next options in this tutorial we will use pin 22, too.Please note: It can be that after you start your MM you have to move once through the PIR to make the module work.
2.2 Using PIR-Script
Why using an external script, when there is already a module for that?!
Well, in my case i use the PIR for several operations. My PIR tuns on the monitor and at the same time a LED stripe is turning on. To do this we need two shell scripts and one python script, which will be activated when booting your Pi.cd
nano monitor_on.shwrite this in this file:
sudo tvservice -pSave the file by typing „ctrl+c“ and „y“
nano monitor_off.shwrite this in this file:
sudo tvservice -oSave the file by typing „ctrl+c“ and „y“
chmod +x monitor_on.sh(to make it executable)
chmod +x monitor_off.shIf you want to do other things happen when monitor turns on or off you can simple add your commands or scripts to this file :)
So now you have two options. Write a python script to automatically start the shell scripts by using a GPIO or just put the Shell scripts into a cronjob.
Here is the first way:
nano pir.py(creates a script which executes the *.sh files via PIR or Button)write this into the file:
#!/usr/bin/env python import sys import time import RPi.GPIO as io import subprocess io.setmode(io.BCM) SHUTOFF_DELAY = 120 # in seconds, how long the monitor will be on until next button press or PIR detection PIR_PIN = 22 # 15 on the board (this needn't to be a PIR. Can be a button also) LED_PIN = 16 # optional, don't use as Relay-PIN. It just shows detection time of the PIR without delay time def main(): io.setup(PIR_PIN, io.IN) io.setup(LED_PIN, io.OUT) turned_off = False last_motion_time = time.time() while True: if io.input(PIR_PIN): last_motion_time = time.time() io.output(LED_PIN, io.LOW) print ".", sys.stdout.flush() if turned_off: turned_off = False turn_on() else: if not turned_off and time.time() > (last_motion_time + SHUTOFF_DELAY): turned_off = True turn_off() if not turned_off and time.time() > (last_motion_time + 1): io.output(LED_PIN, io.HIGH) time.sleep(.1) def turn_on(): subprocess.call("sh /home/pi/monitor_on.sh", shell=True) def turn_off(): subprocess.call("sh /home/pi/monitor_off.sh", shell=True) if __name__ == '__main__': try: main() except KeyboardInterrupt: io.cleanup()Save the file by typing „ctrl+c“ and „y“
chmod +x pir.pyYou can check if your button works by simply typing
python pir.py. Every time u move through the PIR or press the button it will show you several …
End the test with “ctrl+c”now we editing the rc.local to start the script after booting the Pi:
sudo nano /etc/rc.localwrite this in the file (above the “exit 0”):
python /home/pi/pir.py &Save the file by typing „ctrl+c“ and „y“
after all it should look like this:
#!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. # Print the IP address _IP=$(hostname -I) || true if [ "$_IP" ]; then printf "My IP address is %s\n" "$_IP" fi python /home/pi/pir.py exit 0Here comes the second way:
Next steps are nearly the same as the first option shown in this tutorial.
Lets say we want to turn on the monitor every day at 6am and turn off at 8pm:
sudo nano /etc/crontab(to open the crontab)write this into the file:
0 6 * * * root /home/pi/monitor_on.sh >/dev/null 2>&1
0 20 * * * root /home/pi/monitor_off.sh >/dev/null 2>&1Save the file by typing „ctrl+c“ and „y“
3. Using App
First i need to say that this isn’t really an App. But you can make it look a like. I just know how to do it with iPhone devices so in this example i will show you how to do it with that.
We need to install the MMM-Remote-Control module:
cd MagicMirror/modules
git clone https://github.com/Jopyth/MMM-Remote-Control.git
cd MMM-Remote-Control
npm install
cdIn the next step we will add the module to our config.js. To get access to our mirror u should notice the „Whitelist HowTo“.
nano MagicMirror/config/config.jsAdd the following somewhere between your existing modules:
{ module: 'MMM-Remote-Control' // uncomment the following line to show the URL of the remote control on the mirror // , position: 'bottom_left' // you can hide this module afterwards from the remote control itself },Save the file by typing „ctrl+c“ and „y“
and restart your MagicMirror.
I suppose that you are knowing the IP-address of your Pi, otherwise u should google how to find out ;)
Lets say your Pi has this IP: 192.168.178.240so know u should be able to get access to the Mirror by typing the following in your Safari-Browser on the iPhone:
http://192.168.178.240:8080/remote.html
You should see this:

Tap the „share button“ and tap „Add to home screen“. After that a new „app“ will appear on your home screen.
If you tap on it u will get a full screen of the Remote-Control module and will be able to turn on and off your monitor :)
4.1 Using Button module
To use the MMM-Button it is totally necessary to already get the MMM-Remote-Control module running!
cd MagicMirror/modules
git clone https://github.com/Jopyth/MMM-Buttons.git
cd MMM-Buttons
npm install(this can take a while)
cd
nano MagicMirror/config/config.jsAdd the following somewhere between your existing modules:
{ module: 'MMM-Buttons', config: { buttons: [ { pin: 22, name: "monitor_control", longPress: { notification: "REMOTE_ACTION", payload: {action: "MONITOROFF"} }, shortPress: { notification: "REMOTE_ACTION", payload: {action: "MONITORON"} } } ] } },So if you press your button shortly (0 - 0,5 seconds) the monitor will turn on. A longer press (> 3 seconds) will turn off the monitor.
Connect the button like shown in the next step.
4.2 Using Button script
Why it can be necessary to use an external script i already wrote above.
And luckily the way to use a button with an external script is the same way as using a PIR.
So turn back to point 2.2 and do it exactly like described there. Maybe u want to rename the pir.py to button.py, but then you also have to change the cronjob commands or the rc.local entry ;)Connect it like this:

5. Relay
If you want to safe money or your monitor doesn’t support HDMI-CEC you can simply breaks off the current to your monitor by using a Relay. To keep it simple i will use the srd-05vdc-sl-c relay.Keep in mind, that some monitors don’t start automatically by giving them power.
5.1 - Use Relay with a button:
Note: The script below toggles the output for the relay. If u want to use the relay with time delay u can use the scripts on point 5.2 and just replace the PIR with a button.
Note: Some relays are active low. That means, that they are active while the GPIO is set to “0” or “False”. in this case u need to turn the commands for turn_on and turn_off in the python script. So for monitor on u need to write “io.output(RELAY_PIN, False)” and for monitor off “io.output(RELAY_PIN, True)”
cd
nano relay.pyput this code into the file:
#!/usr/bin/env python import subprocess import time import RPi.GPIO as gpio import sys gpio.setwarnings(False) gpio.setmode(gpio.BCM) BUTTON_PIN = 22 RELAY_PIN = 27 def main(): gpio.setup(BUTTON_PIN, gpio.IN, pull_up_down=gpio.PUD_DOWN) gpio.setup(RELAY_PIN, gpio.OUT) gpio.output(RELAY_PIN, False) count = 0 while True: gpio.wait_for_edge(BUTTON_PIN, gpio.FALLING) t = time.time() time.sleep(.3) gpio.wait_for_edge(BUTTON_PIN, gpio.RISING) count += 1 if count > 1: count = 0 if count == 0: print "Turn screen on" gpio.output(RELAY_PIN, True) if count == 1: print "Turn screen off" gpio.output(RELAY_PIN, False) if __name__ == '__main__': try: main() except KeyboardInterrupt: gpio.cleanup()Save the file by typing „ctrl+c“ and „y“
make it executable:
chmod +x relay.pyYou can test by simply typing python relay.py. Every time you push the button your screen will toggle to go on or off.
So your first push turns off the screen content and your second push turns it on :)
Between every press, u need to wait 5 seconds.
its that simple…Connect the button and the relay like this:

5.2 - Use Relay with a PIR:
Note: Some relays are active low. That means, that they are active while the GPIO is set to “0” or “False”. in this case u need to turn the commands for turn_on and turn_off in the python script. So for monitor on u need to write “io.output(RELAY_PIN, False)” and for monitor off “io.output(RELAY_PIN, True)”
nano relayPIR.pyput in this:
#!/usr/bin/env python import sys import time import RPi.GPIO as io import subprocess io.setmode(io.BCM) SHUTOFF_DELAY = 120 # in seconds, how long the monitor will be on until next button press or PIR detection PIR_PIN = 22 # 15 on the board (this needn't to be a PIR. Can be a button also) LED_PIN = 17 # 11 on the board (optional): It just shows detection time of PIR without delay time RELAY_PIN = 27 # 13 on the board def main(): io.setup(PIR_PIN, io.IN) io.setup(LED_PIN, io.OUT) io.setup(RELAY_PIN, io.OUT) turned_off = False last_motion_time = time.time() while True: if io.input(PIR_PIN): last_motion_time = time.time() io.output(LED_PIN, io.LOW) print ".", sys.stdout.flush() if turned_off: turned_off = False turn_on() else: if not turned_off and time.time() > (last_motion_time + SHUTOFF_DELAY): turned_off = True turn_off() if not turned_off and time.time() > (last_motion_time + 1): io.output(LED_PIN, io.HIGH) time.sleep(.1) def turn_on(): io.output(RELAY_PIN, True) def turn_off(): io.output(RELAY_PIN, False) if __name__ == '__main__': try: main() except KeyboardInterrupt: io.cleanup()save with “ctrl+x” and “y”
chmod +x relay.pyYou can check if your button works by simply typing python relayPIR.py. Every time u move through the PIR or press the button it will show you several …
End the test with “ctrl+c”
The Shutoff delay in the script defines how long the relay will be turned on after last detection through the pir.Connect it like this:

now we editing the rc.local to start the script after booting the Pi:
sudo nano /etc/rc.localwrite this in the file (above the “exit 0”):
python /home/pi/relayPIR.py &Save the file by typing „ctrl+c“ and „y“
after all it should look like this:
#!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. # Print the IP address _IP=$(hostname -I) || true if [ "$_IP" ]; then printf "My IP address is %s\n" "$_IP" fi python /home/pi/relayPIR.py exit 0
6. Just turn black
Alright, for some reason you might want to be able to just set your monitor content black instead of turning it to standby.
That can be necessary, if you still want to use your monitor speaker.We can do this nearly the same way as shown with the normally used PIR/button script shown above.
cd
nano screen_on.shput this into the file:
export DISPLAY=:0 xset dpms force onSave the file by typing „ctrl+c“ and „y“
nano screen_off.shput this into the file:
export DISPLAY=:0 xset dpms force offSave the file by typing „ctrl+c“ and „y“
make them executable:
chmod +x screen_on.sh
chmod +x screen_off.shNow at this point you got three options.
- Use it with cronjob (do it like described at section 1 & 2.2 from this tutorial)
- Use a PIR (just replace the *.sh scripts from the section 2.2 and change the shell script names in the commands within the pir.py script)
- Use a single push button
For using the push button you need to connect your button the same way as shown at section 4.2.
Alright, here comes the script:
cd
nano screenbutton.pyput in the following content:
#!/usr/bin/env python import subprocess import time import RPi.GPIO as gpio import sys gpio.setwarnings(False) gpio.setmode(gpio.BCM) BUTTON_PIN = 22 #turn screen on at startup subprocess.call("sh /home/pi/screen_on.sh", shell=True) def main(): gpio.setup(BUTTON_PIN, gpio.IN, pull_up_down=gpio.PUD_DOWN) count = 0 while True: gpio.wait_for_edge(BUTTON_PIN, gpio.FALLING) t = time.time() time.sleep(.5) gpio.wait_for_edge(BUTTON_PIN, gpio.RISING) count += 1 if count > 1: count = 0 if count == 0: print "Turn screen on" subprocess.call("sh /home/pi/screen_on.sh", shell=True) if count == 1: print "Turn screen off" subprocess.call("sh /home/pi/screen_off.sh", shell=True) if __name__ == '__main__': try: main() except KeyboardInterrupt: gpio.cleanup()Save the file by typing „ctrl+c“ and „y“
make it executable:
chmod +x screenbutton.pyYou can test by simply typing
python screenbutton.py. Every time you push the button your screen will toggle to go on or off.
So your first push turns off the screen content and your second push turns it on :)
its that simple…now we editing the rc.local to start the script after booting the Pi:
sudo nano /etc/rc.localwrite this in the file (above the “exit 0”):
python /home/pi/screenbutton.py &Save the file by typing „ctrl+c“ and „y“
after all it should look like this:
#!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. # Print the IP address _IP=$(hostname -I) || true if [ "$_IP" ]; then printf "My IP address is %s\n" "$_IP" fi python /home/pi/screenbutton.py exit 0
-
-
Thanks, @cruunnerr. Very comprehensive. Can I suggest you also add how to black out but not disable the monitor? I’ve seen this question a few times. It is often important when users:
- want to still use the integrated audio out of a monitor, or
- are using a TV style display where it will turn off without signal, and then cannot be turned back on by the Pi.
I’ve seen solutions using
xset dpms force offand another usingchvtto display a blank virtual terminal, but there may be other (even better) solutions. -
is there a way to use a PIR sensor and the PIR module to make the PI load a black screen saver so that it looks like the screen went off but really didnt and then when the PIR sensor picks up motion the screen saver is “turned off” like it would normally do.?
-
yes it is.
Just use the external script from this tutorial. Change the content of the monitor_off.sh and monitor_on.sh to the following:
monitor_off:
export DISPLAY=:0 xset dpms force offmonitor_on:
export DISPLAY=:0 xset dpms force onI will add this options to the tutorial later. ;)
-
Those commands look familiar. :-)
-
Nice tutorial!
Time to connect the Pir to the Pi.
Thanks!
Peter -
Alright, i add this option to the tutorial. Hope you enjoy :)
If there are any suggestions on the scripts i am using please tell me. I am not a programmer so it could be, that the scripts aren’t as “clean” as they could be.
-
- disable the HDMI port with
vcgencmd display_power 0and enable with
vcgencmd display_power 1Most monitors then go into standby. Some also show ‘NO Signal’.
-
@OdomLinx copy paste error?
-
@E3V3A Yes copy paste error, I adjusted it
-
Most modern monitors also have a PowerSave function that completely turn off the monitor when there is no HDMI signal, after a set amount of time. So I guess experimentation will be needed as to what really happen after you have turned it off using either:
vcgencmd display_power 0sudo tvservice -oDISPLAY=:0 xset dpms force off(Notice, it’s not necessary to export!)xset -display :0 dpms force off
The first 2 turn off HDMI and most likely put your monitor into PowerSave mode, eventually.
The last 2 only blanks the screen (visible when dark), and does not disable HDMI signals. -
@E3V3A Some monitors, but almost all television displays turn off after delay (and then cannot be woken in software).
That, and some folks have complained that they can’t hear a podcast or Alexa because their integrated speakers turn off when the monitor is in powersaving.
You’re right, it takes some experimentation to tailor to a given use case/situation depending on requirements.
-
I would like to use the MMM-PIR-sensor module to trigger the relay to power off the LCD. However, whenever I set
relayPIN: 27,in the config.js, the motion detector doesn’t do anything anymore. Anyone know what else I have to change in the config? It’s working just fine without the relay.Config working without relay (switches off HDMI):
{ module: 'MMM-PIR-Sensor', config: { sensorPIN: 22, relayPIN: false, powerSaving: true, } },Not working with relay:
{ module: 'MMM-PIR-Sensor', config: { sensorPIN: 22, relayPIN: 27, relayOnState: 1, powerSaving: true, } },The problem is I am using a V59 LCD controller board which doesn’t power on again once the HDMI is re-activated.
-
- Can u turn on GPIO27 with
gpio -g write 27 1and off withgpio -g write 27 0? - Have u tried just to connect a LED on GPIO27 ?
- What relay do u use and how exactly is it connected? ?
- Can u turn on GPIO27 with
-
Hmm, I get
Unable to determine hardware version. I see: Hardware : BCM2835 , - expecting BCM2708 or BCM2709. Please report this to projects@drogon.netwhen I run
gpio -g write 27 1. -
@MadScientist said in {HowTo} turn on/off your monitor (Time based, PIR/Button, App):
Unable to determine hardware version. I see: Hardware : BCM2835
Huh… a quick google search tells, that this could be several causes. Some wrote to update or downgrade the kernel., some wrote to update wiring pi and so on.
So its not a problem of the module at all. I’m sorry but for the first u should try to google.Maybe start with this: https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=182191
However you should start a new thread if you cannot get to target :(
-
@MadScientist said in {HowTo} turn on/off your monitor (Time based, PIR/Button, App):
Hmm, I get
Unable to determine hardware version. I see: Hardware : BCM2835 , - expecting BCM2708 or BCM2709. Please report this to projects@drogon.netwhen I run
gpio -g write 27 1.I had the same issue. I just followed the instructions on the wiring pi site to install. Don’t have my notes but there was a different version depending if you use wiringpi or wiring-pi. I’ll see if I can find the right one.
-
So I think as wiring-pi is the npm specific version the reason it didn’t work was because they haven’t compiled it to work with the pi3 chip.
-
Thanks so far. I did
npm uninstall wiring-piand installed wiringpi via git. Now I don’t get the error anymore but the relay still does nothing. It’s getting late and won’t have the time today anymore to look into it. Let me know if you have other ideas and I will continue tomorrow.Thanks so far.
-
I think I kept the npm wiring-pi on there as well… There’s probably some other stuff in there that makes it work in mm.
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login