Raspberry Pi 2 W power saving configuration. - Digital-Waters/WaterMonitorDevice GitHub Wiki
Many of these techniques are paraphrased from Jean-Luc Afranc's writeup.
By disabling unused services and turning off unused features of the chip via the overlays, it seems possible to reduce the power consumption of the Rpi. Jean Luc's numbers suggest that he was able to get the unit down to an idle current of around 74mA. His best numbers had energy consumption of around 468 mWh but our use case is different and his setup was a little unclear to me. I've seen lower numbers quoted in other places, especially with the USB turned off. Wifi also seems to consume about 19mA. There are some notes as well that suggest powering the unit from 3.3V may also save power.
- Navigate to /boot/firmware
cd /boot/firmware
- Edit the config file with your choice of editors (you'll have to use sudo):
sudo vi config.txt
- Turn off audio:
dtparam=audio=off
- Turn off display autodetect:
display_auto_detect=0
- Turn off composite video
# disable composite video output enable_tvout=0
- Turn off HDMI support by commenting out the
dtoverlay
line (this is necessary for disabling the real power hog later):
# Enable DRM VC4 V3D driver #dtoverlay=vc4-kms-v3d max_framebuffers=2
- Turn off boost mode:
arm_boost=0
- and reduce the CPU clock speed:
arm_freq=600
- Disable bluetooth
dtoverlay=disable-bt
- Turn off power LED
[all] dtparam=act_led_trigger=default-off
- Turn off the console UART:
[all] dtparam=act_led_trigger=default-off enable_uart=0
- Script-based LED turn off:
$ echo none | sudo tee /sys/class/leds/ACT/trigger
These can (should) be added as a systemd service. Details to follow.
Turn off the HDMI drivers. This depends on using the Bullseye release of the OS. It will not work with Bookworm. Note that you'll have to comment out the dtoverlay in the config.txt file as explained above in the HDMI section.
$ tvservice -o
Turn off USB port power (note the register address may differ according to the board family)
$ echo 0 | sudo tee /sys/devices/platform/soc/3f980000.usb/buspower >/dev/null
The Wifi radio seems to use about 10 - 20mA average for a decent Wifi signal. Probably more when the signal is weak (TBC).
Turn off the Wifi for 30 seconds, attempt to connect for 5 seconds, turn off again. Note that this should be tweaked
depending on how long it takes to connect to the phone app. 5 seconds is a long time power-wise. If we can get away
with less, that would be better.
This can be accomplished many ways but the "Linux-y" way to do it is to create a system service or run a cron job.
I used the info here
to write this example. The script file is wifi_probe.sh
which will be copied to /usr/bin with the appropriate permissions set (prob 755 root:root)
/usr/bin/wifi_scan.sh ------------------------------- #!/bin/bash # # This script is meant to be run either as a cron job or from a systemd timer. # If there is an existing, active connection then there is no change to that connection. # If the radio was off, it is turned on and we wait NUM_SEC_FOR_CONNECTION seconds # If there is a connection after that time then we are done. # If there is no connection then we assume that there is no AP in range, and turn # off the radio to save power. # NUM_SEC_FOR_CONNECTION=5 radio_on () { if [[ $(nmcli radio wifi) == "enabled" ]]; then echo 1 else echo 0 fi } connected () { nmcli device | awk '{if ($2 == "wifi") { if ($3 !~ "dis") {print 1;} else {print 0;}}}' } # Check the radio status if [[ $( radio_on ) == "0" ]]; then # if the radio is off, turn it on and wait a bit for a connection nmcli radio wifi on sleep $NUM_SEC_FOR_CONNECTION fi # Check to see if we are connected if [[ $( connected ) == "0" ]]; then # There is no connction so turn the radio off unti the next cycle nmcli radio wifi off fi # Else there is a connection and we quit silently until the next cycle
/etc/systemd/system/wifi_scan.service -------------------------------------------- [Unit] Description=Wifi connection power saver [Service] ExecStart=/usr/bin/wifi_scan.sh
/etc/systemd/system/wifi_scan.timer ------------------------------------------ [Unit] Description=Run wifi_scan Every 30 Seconds [Timer] # First run after boot OnBootSec=30 # Interval to run OnUnitActiveSec=30 [Install] WantedBy=timers.target
$ systemctl daemon-reload
Then, enable the timer to start it automatically at boot:
$ systemctl enable wifi_scan.timer
Finally, start the timer manually for the first time (optional):
$ systemctl start wifi_scan.timer
To verify that your timer is running correctly, you can check its status with:
$ systemctl status wifi_scan.timer
This one is a little weird. I got some power savings by removing alsa-utils, however, it removed a bunch of stuff we want like libcamera, raspi-config, and others.