Sometimes it seems like the first (and sometimes only) advice you get offered for almost any problem with a Raspberry Pi is "check your power supply". You think something like:
"hey, I'm using an official power supply sold as being matched with my Pi so how can there be any problem?"
You look up the specs then stick a controlled load across your supply and confirm that it can deliver the required number of Watts.
Yet your problems persist…
The problem might be power but it might not be your "wall-wart" power supply. It's a subtle but important distinction.
I've worked in I.T. for almost 50 years but I'm a late-comer to the Raspberry Pi world, beginning my journey with a Raspberry Pi 3B+ purchased in early 2019, both to get my feet wet and to run Octopi. The thing never worked right, usually stopping part way through a print job when it seemed to lose its USB connection to my 3D printer. I gave up and went back to transporting GCODE files via "sneakernet" using an SD card.
Then I came across PiHole. I dusted off the 3B+ and gave it another whirl. Still didn't work right - random network interface freezes which are pretty much the last thing you need from a DNS server. I installed PiHole on a MacMini and the 3B+ went back on the shelf.
Sometime later I was introduced to the wonders of Docker, took the plunge with a new Raspberry Pi 4B, and never looked back. I now have four Raspberry Pi 4Bs doing different things. They are rock solid, running for months at a time between occasional reboots, and they never ever give me a single moment's trouble.
But, back to the problematic Raspberry Pi 3B+. For the purposes of this gist:
- Boots from SD and runs current 32-bit Bullseye.
- Ethernet and WiFi both enabled.
- Runs headless (SSH).
- No peripherals. No keyboard. No screen. Nothing connected to USB ports.
- Air-cooled (ie not running a fan).
According to the specs, a Raspberry Pi 3B+ needs a power supply capable of delivering 5.1 volts DC at 2.5 amps: 12.75 Watts.
I have a number of power supplies that meet this requirement. Some are "official" (with the Raspberry Pi Foundation logo), some are "third party". Here are some examples:
Symbol | Type | Sold for | Volts | Amps | Watts | Connector |
---|---|---|---|---|---|---|
A | Official | Zero2W | 5.1 | 2.5 | 12.75 | μ-USB |
B | Official | 3B+ | 5.1 | 2.5 | 12.75 | μ-USB |
C | Official | 4B | 5.1 | 3.0 | 15.30 | USB-C |
D | Third Party | 3B+ | 5.0 | 3.0 | 15.00 | μ-USB |
I connected each of those to an Atorch DL24P controlled load test unit, set to constant power mode drawing 12.8W (the DL24P only works to 1 decimal place so I rounded up to be conservative). Here are the results.
Interpretation:
- With no load, the official supplies offer 5.2V while the third party unit offers 5.0V.
- Under load, the official supplies drop to 4.9V while the third party unit drops to 4.5V.
- All PSUs can sustain a constant power test of 12.8 Watts.
I connected each of the power supplies to the Raspberry Pi 3B+, with an Atorch USB tester placed inline to measure voltage and current draw. Each test started with the Pi switched off, then waited until the boot cycle was complete. Here are the results.
Interpretation:
- The official supplies stay over 5.0 volts while the third-party supply hovers around 4.9V.
- The maximum current draw for any supply is the third-party unit: 1.01 amps (5.2 Watts max).
Whichever way you look at it, all four PSUs have demonstrated the capacity to deliver more than double the observed load presented by the Pi. There is plenty of head-room. Whatever ails the 3B+, it ain't any of these PSUs.
When I connect each of these supplies to my Raspberry Pi 3B+, the Pi seems to boot OK (I can login via SSH connecting to the Ethernet port) yet it exhibits weird problems with its WiFi interface bouncing.
Aside from connectivity issues, how do I know WiFi is misbehaving? See Do your Raspberry Pi's Network Interfaces freeze?. The isc-dhcp-fix.sh
script running on this Pi keeps logging:
mmm dd hh:mm:ss hostname root: isc-dhcp-fix resetting wlan0
Why? Well, it turns out that the Pi is actually complaining about its power. How do I know that?
Sometimes, even though your power supply is proven to be within spec, there's a power problem within the Pi itself. The Pi actually knows about the problem but it's a little hard to get the Pi to tell you about it.
Enter the vcgencmd_power_report.sh
script:
#!/usr/bin/env bash
SCRIPT=$(basename "$0")
# fetch status
STATUS=$(vcgencmd get_throttled | cut -d "=" -f 2)
# decode - https://www.raspberrypi.com/documentation/computers/os.html#get_throttled
echo "vcgencmd get_throttled ($STATUS)"
IFS=","
for BITMAP in \
00,"currently under-voltage" \
01,"ARM frequency currently capped" \
02,"currently throttled" \
03,"soft temperature limit reached" \
16,"under-voltage has occurred since last reboot" \
17,"ARM frequency capping has occurred since last reboot" \
18,"throttling has occurred since last reboot" \
19,"soft temperature reached since last reboot"
do set -- $BITMAP
if [ $(($STATUS & 1 << $1)) -ne 0 ] ; then echo " $2" ; fi
done
echo "vcgencmd measure_volts:"
for S in core sdram_c sdram_i sdram_p ; do printf '%9s %s\n' "$S" "$(vcgencmd measure_volts $S)" ; done
echo "Temperature: $(vcgencmd measure_temp)"
If you're reading this on a Windows machine, please remember to be careful when copying-and-pasting scripts. Unless you take precautions, Windows will add its CR+LF line-endings. If those extra CRs are still in the script when it gets onto your Pi, they will cause problems.
Example output:
-
The pattern when there are no voltage problems:
$ vcgencmd_power_report.sh vcgencmd get_throttled (0x0) vcgencmd measure_volts: core volt=1.3000V sdram_c volt=1.2500V sdram_i volt=1.2500V sdram_p volt=1.2250V Temperature: temp=36.5'C
-
The problem when a voltage problem is present at the moment when the script is run (quite rare to see this):
$ vcgencmd_power_report vcgencmd get_throttled (0x50005) currently under-voltage currently throttled under-voltage has occurred since last reboot throttling has occurred since last reboot vcgencmd measure_volts: core volt=1.2000V sdram_c volt=1.2500V sdram_i volt=1.2500V sdram_p volt=1.2250V Temperature: temp=35.9'C
-
The pattern when an historical voltage problem is being reported:
$ vcgencmd_power_report.sh vcgencmd get_throttled (0x50000) under-voltage has occurred since last reboot throttling has occurred since last reboot vcgencmd measure_volts: core volt=1.3000V sdram_c volt=1.2500V sdram_i volt=1.2500V sdram_p volt=1.2250V Temperature: temp=33.2'C
Either "currently under-voltage" or "under-voltage has occurred since last reboot" are the Pi complaining about its power supply.
The actual mechanism is the "currently under-voltage" flag is raised any time there's a voltage problem "now". That flag clears as soon as the voltage problem goes away. In my experience voltage problems are transient so it is quite rare to see that flag raised when you run this script.
The "under-voltage has occurred since last reboot" flag is set if the "currently under-voltage" flag has been raised at least once since the last reboot. It doesn't tell you when "currently under-voltage" was raised, nor how long the condition persisted, nor whether it was a single isolated incident or if voltage is constantly falling below the acceptable threshold.
The "currently throttled" and "throttling has occurred since last reboot" flags just seem to be a side-effects.
Power problems get logged in the system log so, once you become aware that your Pi is moaning about its power, you can drill down:
$ grep -a -e "hwmon" /var/log/syslog
Jun 13 12:04:44 octopi kernel: [ 14.890311] hwmon hwmon1: Undervoltage detected!
Jun 13 12:05:04 octopi kernel: [ 23.210275] hwmon hwmon1: Voltage normalised
Jun 13 12:06:04 octopi kernel: [ 14.880886] hwmon hwmon1: Undervoltage detected!
Jun 13 12:06:08 octopi kernel: [ 19.030895] hwmon hwmon1: Voltage normalised
Jun 13 12:06:39 octopi kernel: [ 21.111151] hwmon hwmon1: Undervoltage detected!
Jun 13 12:06:43 octopi kernel: [ 25.270833] hwmon hwmon1: Voltage normalised
Jun 13 12:15:57 octopi kernel: [ 14.870727] hwmon hwmon1: Undervoltage detected!
Jun 13 12:16:19 octopi kernel: [ 25.270719] hwmon hwmon1: Voltage normalised
Jun 13 12:23:58 octopi kernel: [ 15.190883] hwmon hwmon1: Undervoltage detected!
Jun 13 12:24:02 octopi kernel: [ 19.360622] hwmon hwmon1: Voltage normalised
Jun 13 12:32:14 octopi kernel: [ 14.950919] hwmon hwmon1: Undervoltage detected!
Jun 13 12:32:30 octopi kernel: [ 19.110952] hwmon hwmon1: Voltage normalised
Jun 13 12:32:32 octopi kernel: [ 21.191212] hwmon hwmon1: Undervoltage detected!
Jun 13 12:32:36 octopi kernel: [ 25.350996] hwmon hwmon1: Voltage normalised
Jun 13 12:40:58 octopi kernel: [ 14.800489] hwmon hwmon1: Undervoltage detected!
Jun 13 12:41:13 octopi kernel: [ 18.950614] hwmon hwmon1: Voltage normalised
Jun 13 12:41:19 octopi kernel: [ 25.190489] hwmon hwmon1: Undervoltage detected!
Jun 13 12:41:23 octopi kernel: [ 29.350686] hwmon hwmon1: Voltage normalised
Jun 13 12:51:23 octopi kernel: [ 14.810334] hwmon hwmon1: Undervoltage detected!
Jun 13 12:51:27 octopi kernel: [ 18.980349] hwmon hwmon1: Voltage normalised
Two more scripts on a similar theme:
-
A watchdog that will log any under-voltage events via MQTT. This is more a set-and-forget solution for all your Pis. With this in place, you'll be alerted to possible power problems when they occur:
-
sample
crontab
entry:*/60 * * * * under_voltage_check.sh
-
script named
under_voltage_check.sh
in PATH:#!/usr/bin/env bash SCRIPT=$(basename "$0") BROKER="mqtt.domain.com" TOPIC="/raspberrypi/status" # fetch status STATUS=$(vcgencmd get_throttled | cut -d "=" -f 2) # redirect output to a log file LOGS="$HOME/Logs" LOGFILE="$LOGS/$SCRIPT.log" mkdir -p "$LOGS" touch "$LOGFILE" exec >> "$LOGFILE" exec 2>> "$LOGFILE" # has the undervoltage condition occurred since last reboot? if [ $(($STATUS & 1 << 16)) -ne 0 ] ; then mosquitto_pub -h "$BROKER" -t "$TOPIC" -m "{\"host\": \"$HOSTNAME\", \"underVoltage\": \"historical\"}" fi
Edit the script so the
BROKER
variable points to your Mosquitto broker. If the Pi has noticed an under-voltage condition, this script will send an MQTT message to your broker. You can subscribe to the topic in Node-RED and use the event to trigger a notification.Keep in mind that the "under-voltage has occurred since last reboot" persists so, once one under-voltage condition has been noted, you'll get another MQTT message every hour (or however often you run this script from
cron
).
-
-
A "live" watchdog will help you figure out the conditions under which power is an issue:
-
add this line to
~/.profile
:watch_under_voltage.sh &
-
script named
watch_under_voltage.sh
in PATH:#!/usr/bin/env bash SCRIPT=$(basename "$0") while : ; do # fetch status STATUS=$(vcgencmd get_throttled | cut -d "=" -f 2) # is the pi sensing undervoltage right now? if [ $(($STATUS & 1 << 00)) -ne 0 ] ; then echo "reporting under-voltage NOW" fi sleep 1 done
-
example:
$ cd ~/IOTstack $ docker-compose up -d [+] Running 1/3 [+] Running 2/3tack_default Created 0.4s [+] Running 1/3tack_default Created 0.4s [+] Running 1/3tack_default Created 0.4s [+] Running 1/3tack_default Created 0.4s [+] Running 3/3tack_default Created 0.4s ⠿ Network iotstack_default Created 0.4s ⠿ Container octoprint Started 5.3s ⠿ Container portainer-ce Started 5.3s reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW reporting under-voltage NOW $ docker-compose down [+] Running 0/0 [+] Running 0/2toprint Stopping 0.1s [+] Running 1/2toprint Stopping 1.1s [+] Running 1/2toprint Stopping 2.1s [+] Running 3/3toprint Stopping 4.2s ⠿ Container octoprint Removed 4.7s ⠿ Container portainer-ce Removed 1.1s ⠿ Network iotstack_default Removed 0.4s reporting under-voltage NOW reporting under-voltage NOW
Clearly, bringing up Docker containers puts sufficient load on the 3B+ as to cause it to grizzle about lack of power.
Bottom line: This 3B+ doesn't like running OctoPi or PiHole "native", and doesn't like running a couple of containers. Other than being an excellent test vehicle while writing this gist, it's really not all that much use.
-
The conventional one-size-fits-all wisdom that "it's yer dodgy power supply" might have a grain of truth but, sometimes, there might be a bit more to it. Your PSU might be fine. It could just be that you have a dodgy Raspberry Pi with an internal regulator that isn't up to the job being asked of it.