Raspberry Pi power saving (disable HDMI port and others) – the SystemD way

For a few year I have been playing with Raspberry Pi’s. I started off with a 1B, then moved to a a 2B and for some time am heavily using a model 3B as my monitoring (nagios) server while the 2B is being setup for other use (as well as a few Pi Zero’s being used for other things).

Since the switch to the 3B I started to have more and more issues with the SD card getting corrupt. Actually, it wasn’t the card itself but critical files tended to get corrupted, making the system unusable after a while – one of the reasons  I scripted the setup of my monitoring server using Ansible). Recently I found this discussion on stackexchange which hinted me on the root cause of my problems – the Raspberry Pi 3B really needs a 2.5A power supply to function correctly.

For sime time I had been getting (and ignoring) messages like these:

Jun 10 15:47:14 raspberrypi kernel: [ 1716.074009] Under-voltage detected! (0x00
050005)
Jun 10 15:54:53 raspberrypi kernel: [ 2175.754689] Voltage normalised (0x0000000
0)

for some time, which I now understand was a bit more than just a warning and shouldn’t be ignored. After switching the power supply of the Raspberry Pi (this was on a 2B, stil waiting for a 3A power supply for my 3B to arrive) things appear stable now and made me think how to reduce the amount of power used by the Raspberry Pi.

After a bit of searching (see this RPi forum post) I learned that it is possible to reduce the power by reducing the CPU speed / #cores used (not practical in my case) and also by:

  • Disabling HDMI port with the /opt/vc/bin/tvservice command
  • Disabling USB Bus using echo 0x0 > /sys/devices/platform/soc/3f980000.usb/buspower (use echo 0x0 to enable)
  • Disabling WiFi adapter (3B/ZeroW only) using ifdown wlan0

As already mentioned, I use Ansible to script most of the settings of my Raspberry PIs, just in case the SD card fails again (I have 2 completely unusable cards already). As I did not like patching the /etc/rc.local (as it changes over time, I decided to work out how to do this the SystemD way as it provides more flexibility. As there are plenty of good tutorials and write-ups around including the official documentation, I will not detail the structure of the systemd .service files created, but merely share my solution.

For each device / bus to disable I created a separate systemd service to allow each of them to be separately enabled and disabled. As per the documentation of systemd, locally created files should be placed in /etc/systemd/system, so I created the following files:

/etc/systemd/system/rpi_no_hdmi.service – to disable to HDMI port

[Unit]
Description=Disable Raspberry Pi HDMI port

[Service]
Type=oneshot
ExecStart=/opt/vc/bin/tvservice -o
ExecStop=/opt/vc/bin/tvservice -p
RemainAfterExit=yes

[Install]
WantedBy=default.target

/etc/systemd/system/rpi_no_usb.service – to disable to USB bus

[Unit]
Description=Disable Raspberry Pi USB bus

[Service]
Type=oneshot
ExecStart=/bin/sh -c "echo 0x0 > /sys/devices/platform/soc/3f980000.usb/buspower"
ExecStop=/bin/sh -c "echo 0x1 > /sys/devices/platform/soc/3f980000.usb/buspower"
RemainAfterExit=yes

[Install]
WantedBy=default.target

/etc/systemd/system/rpi_no_wifi.service – to disable the WiFi interface on a Raspberry Pi 3B/ZeroW

[Unit]
Description=Disable Raspberry Pi 3B/ZeroW WiFi interface

[Service]
Type=oneshot
ExecStart=/sbin/ifdown wlan0
ExecStop=/sbin/ifup wlan0
RemainAfterExit=yes

[Install]
WantedBy=default.target

To enable one of these ‘services’ (i.e. to disable the functionality upon boot) use the following command (example for disabling the HDMI port) as root:

systemctl enable service rpi_no_hdmi

The system will then respond with a message like:

Created symlink /etc/systemd/system/default.target.wants/rpi_no_hdmi.service → /etc/systemd/system/rpi_no_hdmi.service.

and from now on the HDMI port will be disabled during the boot of the Raspberry Pi. To make this change effective immediately, run the following command as root:

service rpi_no_hdmi start

This command makes clear what the advantage of this setup is. Besides no longer having to hack around in /etc/rc.local, using SystemD allows one to 1) selectively enable which items should be disable and also to re-enable the functionality again with a command as (again as root):

service rpi_no_hdmi stop 

to temporarily disable the power-saver as well as (again as root):

systemctl disable service rpi_no_hdmi

to disable it from the next boot onwards. I have now made these services part of my standard installation of a Raspberry pi and enable the ones I would like to have disabled to save power.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.