Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Raspberry Pi CPU temperature and throttling test script
#!/bin/bash
# Raspberry Pi stress CPU temperature measurement script.
#
# Download this script (e.g. with wget) and give it execute permissions (chmod +x).
# Then run it with ./pi-cpu-stress.sh
# Variables.
test_run=1
test_results_file="${HOME}/cpu_temp_$test_run.log"
stress_length="10m"
# Verify stress-ng is installed.
if ! [ -x "$(command -v stress-ng)" ]; then
printf "Error: stress-ng not installed.\n"
printf "To install: sudo apt install -y stress-ng\n" >&2
exit 1
fi
printf "Logging temperature and throttling data to: $test_results_file\n"
# Start logging temperature data in the background.
while /bin/true; do
# Print the date (e.g. "Wed 13 Nov 18:24:45 GMT 2019") and a tab.
date | tr '\n' '\t' >> $test_results_file;
# Print the temperature (e.g. "39.0") and a tab.
vcgencmd measure_temp | tr -d "temp=" | tr -d "'C" | tr '\n' '\t' >> $test_results_file;
# Print the throttle status (e.g. "0x0") and a tab.
vcgencmd get_throttled | tr -d "throttled=" | tr '\n' '\t' >> $test_results_file;
# Print the current CPU frequency.
vcgencmd measure_clock arm | sed 's/^.*=//' >> $test_results_file;
sleep 5;
done &
# Store the logging pid.
PROC_ID=$!
# Stop the logging loop if script is interrupted or when it ends.
trap "kill $PROC_ID" EXIT
# After 5 minutes, run stress.
printf "Waiting 5 minutes for stable idle temperature...\n"
sleep 300
printf "Beginning $stress_length stress test...\n"
stress-ng -c 4 --timeout $stress_length
# Keep logging for 5 more minutes.
printf "Waiting 5 minutes to return to idle temperature...\n"
sleep 300
printf "Test complete.\n"
@alwynallan

This comment has been minimized.

Copy link

@alwynallan alwynallan commented Dec 7, 2020

On Ubuntu for pi I changed
test_results_file="/home/pi/cpu_temp_$test_run.log"
to
test_results_file="/home/${USER}/cpu_temp_$test_run.log"
and it ran fine. It should work with Raspbian and with a different username but I didn't test it.

@geerlingguy

This comment has been minimized.

Copy link
Owner Author

@geerlingguy geerlingguy commented Dec 7, 2020

@alwynallan - Ah, good idea to just use the var there instead. Didn't think about the fact that many people run non-Pi-OS distros too!

@alwynallan

This comment has been minimized.

Copy link

@alwynallan alwynallan commented Dec 7, 2020

I got the Pi 4 Fan working with real PWM control today. It's quieter, more efficient, but still prevents throttling. It also reduces the amount of thermal cycling which generally increases life. The boot option has to be disabled. It uses 12% of one core, all due to the pigpio library, which could probably be improved. Systemd will make it easy to install as a daemon once its stable.

https://gist.github.com/alwynallan/68b6a9405de3ea493bbf53d2b0e9d52b

Let me know if you get a chance to try it.

@geerlingguy

This comment has been minimized.

Copy link
Owner Author

@geerlingguy geerlingguy commented Dec 7, 2020

It uses 12% of one core, all due to the pigpio library, which could probably be improved.

That's the difficult thing with these types of libraries! But that does look promising. I don't have time to test today, but I hope to soon—I have a couple other Pi projects on my bench right now.

Would you be able to also post the same thing as a comment on my blog post over at https://www.jeffgeerling.com/blog/2020/raspberry-pi-4-has-fan-now-case-fan (for more visibility)?

@alwynallan

This comment has been minimized.

Copy link

@alwynallan alwynallan commented Dec 8, 2020

@geerlingguy

This comment has been minimized.

Copy link
Owner Author

@geerlingguy geerlingguy commented Dec 8, 2020

@alwynallan — thanks for the post—the email doesn't make it through GitHub's filters, but if you log into GitHub and drag the image into a comment field, it should upload and be attached for all to see!

@jemaltz

This comment has been minimized.

Copy link

@jemaltz jemaltz commented Dec 30, 2020

The vcgencmd commands would probably benefit from a sudo. Attempting to run the script as a regular user causes those commands to fail, while running the whole script under sudo fails due to the hardcoded path (it resolves to /home/root/, which does not exist). Running the modified script with sudo on the three necessary lines works as expected, in my limited testing.

In addition, attempting to exit the script early with ctrl-c leaves the logging process running - I killed it with killall. Not sure if there's an easy fix for that! (I had to exit this way a few times due to the issue above)

Thanks!

@geerlingguy

This comment has been minimized.

Copy link
Owner Author

@geerlingguy geerlingguy commented Jan 11, 2021

@jemaltz - Interesting—I haven't had issues running the commands under the pi user on Raspberry Pi OS. Were you running a different OS perhaps?

@jemaltz

This comment has been minimized.

Copy link

@jemaltz jemaltz commented Jan 11, 2021

@geerlingguy - Not a different OS, but a different user. A new/regular user with sudo permissions via the sudoers file. Thanks!

@geerlingguy

This comment has been minimized.

Copy link
Owner Author

@geerlingguy geerlingguy commented Jan 11, 2021

Ah, that makes sense. The script can probably be modified to test for whether sudo permissions are required or not, too, with a check near the top to see if vcgencmd works.

@MestreLion

This comment has been minimized.

Copy link

@MestreLion MestreLion commented Apr 16, 2021

@alwynallan - Ah, good idea to just use the var there instead. Didn't think about the fact that many people run non-Pi-OS distros too!

Better than a /home/${USER} "half-solution", why not use the standard (and simpler) ${HOME}?

It would make the script work for any distro and any user, including root and other service accounts

@MestreLion

This comment has been minimized.

Copy link

@MestreLion MestreLion commented Apr 16, 2021

In addition, attempting to exit the script early with ctrl-c leaves the logging process running - I killed it with killall. Not sure if there's an easy fix for that! (I had to exit this way a few times due to the issue above)

This can be solved by setting a trap right after grabbing the pid:

...
# Store the logging pid.
PROC_ID=$!

# Stop the logging loop if script is interrupted or ends
trap "kill $PROC_ID" EXIT
...

With that you don't even need to manually kill it near end of script, the trap will automatically kill for you when the script ends.

@MestreLion

This comment has been minimized.

Copy link

@MestreLion MestreLion commented Apr 16, 2021

Question: how did you generated the images from the logging data? Is there any nice script for that?

@geerlingguy

This comment has been minimized.

Copy link
Owner Author

@geerlingguy geerlingguy commented Apr 16, 2021

@MestreLion - I think for that I just dumped the CSV into Google Sheets and generated graphs there. Something I'd like to automate more in the future though.

@geerlingguy

This comment has been minimized.

Copy link
Owner Author

@geerlingguy geerlingguy commented Apr 16, 2021

@MestreLion - Also, updated the script to use ${HOME} and trap. Thanks for the suggestions!

@geerlingguy

This comment has been minimized.

Copy link
Owner Author

@geerlingguy geerlingguy commented Jun 9, 2021

I also wanted to get the current value from the new PoE+ HAT during a run today, so I added the following above the 'throttle status' section:

  # Print the current current (e.g. 536000) and a tab.
  cat /sys/devices/platform/rpi-poe-power-supply@0/power_supply/rpi-poe/current_now | tr '\n' '\t' >> $test_results_file;

This outputs a value in microamps.

@pyro12

This comment has been minimized.

Copy link

@pyro12 pyro12 commented Jul 23, 2021

Great little script! I'm trying to figure out why HTML5 streaming is disappointing on my Pi4b and I thought maybe throttling was the issue. I ran this and temps never report above 71 so I think I'm good, but I also found this: and I'm unclear on whether your script is logging CPU or GPU temps.... or if we can expect them to be pretty much the same...

If that link is correct, you're logging GPU temps and to also log CPU temp

echo temp=$((cat /sys/class/thermal/thermal_zone0/temp/1000)).0\'C | tr -d "temp=" | tr -d "'C" | tr '\n' '\t' >> $test_results_file;

needs to be added.

@geerlingguy

This comment has been minimized.

Copy link
Owner Author

@geerlingguy geerlingguy commented Jul 27, 2021

@pyro12 - According to the Pi's documentation, measure_temp "Returns the temperature of the SoC as measured by the on-board temperature sensor." — that seems to be the only reading that really matters for throttling (it's the SoC temp). Are you seeing different numbers when checking thermal_zone0?

@pyro12

This comment has been minimized.

Copy link

@pyro12 pyro12 commented Jul 31, 2021

@geerlingguy - Nope. I ran

#!/bin/bash
while true 
do
vcgencmd measure_temp | tr -d "temp=" | tr -d "'C" | tr '\n' '\t'
echo temp=$((`cat /sys/class/thermal/thermal_zone0/temp`/1000)).0\'C
sleep 10
done

via SSH and tried various uses of stress-ng and glxgears and the biggest difference I saw was 1.4 C. A curiousity, but I don't think relevant...

Thanks for helping me understand!

@geerlingguy

This comment has been minimized.

Copy link
Owner Author

@geerlingguy geerlingguy commented Aug 2, 2021

Weird! I'm surprised there would be that much of a difference. And now I'm wondering if there are multiple temperature sensors in the SoC :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment