vcgencmd and checkthrottle.sh
There are two parts to this question: How is under voltage detected and how can that information be used without more hardware. The first part has already been ably addressed by @seamus's answer.
The second part can be accomplished using vcgencmd
. Here is a shell script I've written which prints out the throttle status in plain English. It also returns an error code if the problem is occurring now so that it can be used by a "watchdog" type of daemon to shutdown the Pi if problems persist.
#!/bin/bash -e
# Check whether a Raspberry Pi is currently experiencing insufficient
# power or overheating or if it has had such problems in the past.
# From vcgencmd(1)
# get_throttled
# Returns the throttled state of the system. This is a bit
# pattern - a bit being set indicates the following meanings:
# Bit Meaning
# ──── ────────────────────────────────────
# 0 Under-voltage detected
# 1 Arm frequency capped
# 2 Currently throttled
# 3 Soft temperature limit active
# 16 Under-voltage has occurred
# 17 Arm frequency capping has occurred
# 18 Throttling has occurred
# 19 Soft temperature limit has occurred
# A value of zero indicates that none of the above conditions
# is true.
A=( [ 0]="Under-voltage detected"
[ 1]="Arm frequency capped"
[ 2]="Currently throttled"
[ 3]="Soft temperature limit active"
[16]="Under-voltage has occurred"
[17]="Arm frequency capping has occurred"
[18]="Throttling has occurred"
[19]="Soft temperature limit has occurred" )
for ((i=0; i<32; i++)); do
if [[ ! ${A[i]} ]]; then
A[i]="set, but meaning is unknown. See vcgencmd(1)."
fi
done
# vcgencmd get_throttled returns a string like "throttled=0x50000"
eval $(vcgencmd get_throttled)
# If user supplied a number (e.g., 0x50005), use it instead.
if [[ "$1" ]]; then throttled="$1"; fi
if (( throttled == 0 )); then
echo "No problems with voltage or temperature since boot."
elif (( (throttled & 0xFF) == 0 )); then
echo "Problems have occurred but are not happening now."
fi
for ((i=0; i<32; i++)); do
if (( throttled & 2**i )); then
echo "bit $i: ${A[$i]}"
fi
done
# Exit with a non-zero value if problems are occurring now.
exit $(( throttled & 0xFF ))
Usage
If you run checkthrottle.sh, it'll show you a message such as:
raspberrypi:~$ checkthrottle.sh
Problems have occurred but are not happening now.
bit 16: Under-voltage has occurred
bit 18: Throttling has occurred
You can also give checkthrottle.sh a command line argument to interpret any of the cryptic numbers returned by vcgencmd get_throttled
.
raspberrypi:~$ checkthrottle.sh 0xf0005
bit 0: Under-voltage detected
bit 2: Currently throttled
bit 16: Under-voltage has occurred
bit 17: Arm frequency capping has occurred
bit 18: Throttling has occurred
bit 19: Soft temperature limit has occurred
The script returns true if no problems are currently occurring, so its result can be used in another script. For example,
declare -i count=0
while sleep 60; do
if checkthrottle.sh; then
count=0
continue
else
count=count+1
if (( count > 5 )); then
shutdown --poweroff +1 "Batteries low. Shutting down soon to avoid crashing."
exit 1
fi
fi
done
vcgenmd
not found on my pi 3B, but/opt/vc/bin/vcgencmd
found.