I purchased some Klipsch AW-400 outdoor speakers for a good price and mounted them on my garage (which is a separate building.) To drive them, I bought a HifiBerry AMP+ and a Raspberry Pi 3B+. I’d been using Max2Play for music streaming but came across Volumio and I prefer it. The web interface is so much better. Also, it makes it really easy to share the USB hard drive I use as a media server on another Raspberry Pi.
Volumio works fine right out of the box and the set up instructions on their site are very easy to follow. The problem I have is that since I live in the desert and have my Raspberry Pi on a shelf high in my garage, it overheats occasionally. I bought heat sinks for it but that didn’t solve the heat problem.
My solution was that I bought a USB powered fan on a goose neck. I got this one but any USB-powered fan, NOT one that charges a battery via USB, will work. I suppose I could just let the fan blow in the Raspberry Pi constantly, but where’s the fun in that? I figured that if I can read the temp, I turn the fan on and off as needed. Yes I can. Yes I did and here’s how.
I found that the CPU temperature is stored in /sys/class/thermal/thermal_zone0/temp as milidegrees Celsius, which means 45000 is 45° C.
I found uhubctl at GitHub which allows Linux in some applications to control some smart USB hubs. Fortunately, a RPi 3B+ is the right application and its USB ports are the right kind of smart USB hubs. To get it to work, it has to be download and compile first.
Volumio ships as a fairly stripped down version of Debian. To add the missing standard software, run:
sudo apt-get update && sudo apt-get -y upgrade
Next, install gcc, make, and a USB library:
sudo apt-get install gcc sudo apt-get install make sudo apt-get install libusb-1.0
To download the uhubctl command, we need to install git:
sudo apt-get install git
At this point we should be able to download and compile uhubctl:
git clone git://github.com/mvp/uhubctl cd uhubctl make
uhubctl is now ready to use. Next we need to find which port the fan is plugged in to. To list the ports run:
sudo ./uhubctl
You should see an output something like:
Current status for hub 1-1.1 Port 1: 0503 power highspeed enable connect [0424:7800] Port 2: 0100 power Port 3: 0100 power Current status for hub 1-1 [0424:2514] Port 1: 0503 power highspeed enable connect [0424:2514] Port 2: 0100 power Port 3: 0100 power Port 4: 0100 power Current status for hub 1 [1d6b:0002 Linux 4.19.118-v7+ dwc_otg_hcd DWC OTG Controller 3f980000.usb]
In this case, my fan is plugged into hub 1-1 port 2 but it doesn’t show up.
To turn the right port off, you need to be specific about which hub and which port. Plug in the fan, and hunt for it by turning ports off one at a time till the fan stops.
The command to turn off my fan is:
sudo ./uhubctl -l 1-1 -p 2 -a off
To turn it back on:
sudo ./uhubctl -l 1-1 -p 2 -a on
And to get the current status:
sudo ./uhubctl -l 1-1 -p 2
Experiment with it and make sure you can control your fan. Next, we’ll create a script to switch the port on or off depending on the temperature of the CPU:
sudo nano coolme.sh
Copy and paste this code:
#!/bin/bash # This is where the raw cpu temp is stored # Could use vcgencmd measure_temp but it returns # a formatted string. Messy. cpu=$(</sys/class/thermal/thermal_zone0/temp) # This is the limit I set. Change as necessary limit=70000 # To find which port your fan is plugged in run: # sudo ./uhubctl May need to experiment turning # them off to find it. port_state=$(sudo /home/volumio/uhubctl/uhubctl -l 1-1 -p 2) if [ $cpu -gt $limit ]; then # We're overtemp. Turn on fan if necessary if [ $(expr substr + "$port_state" 79 6) == "off" ] then # Port was off, turn it on echo "Overtemp: CPU raw temp is $cpu 'C at $(date)" /home/volumio/uhubctl/uhubctl -l 1-1 -p 2 -a on printf " -----\n" fi else # We're undertemp. Turn fan off if necessary if [ $(expr substr + "$port_state" 79 6) == "power" ] # Fan is on, turn that baby off then echo "Undertemp: CPU raw temp is $cpu 'C at $(date)" /home/volumio/uhubctl/uhubctl -l 1-1 -p 2 -a off printf " -----\n" fi fi
If you’re using a different hub, you may need to change
if [ $(expr substr + "$port_state" 55 6) == "off" ]
What it is saying is to start at character 55 and read the following 6 characters. If you use hub 1-1.1, that will throw that number off. To find it, I used the following command and adjusted the first number till I got “power” or “off” with no space in front of it.
port_state=$(sudo /home/volumio/uhubctl/uhubctl -l 1-1 -p 2) && echo $(expr substr + "$port_state" 55 6)
I set the limit to 70° C because the overtemp warning happens at 80° C. Adjust the limit as you see fit.
To make the script executable, run
sudo chmod 755 coolme.sh
Now test the script. Change the limit to make it turn on the fan and then change it back to turn it off. Make sure it works. To run the script:
sudo ./coolme.sh
If you don’t use sudo, uhubctl won’t work correctly. Once you’re satisfied with the script, we need to add a cron job to execute it every five minutes. Like I said, Volumio is pretty stripped down, so we need to install cron:
sudo apt-get install cron
Add the script to the cron jobs:
sudo crontab -e
If you don’t use sudo, you’ll only add the script for the user and we need root access for this thing to work.
Add the following line to the bottom of the file:
*/5 * * * * /home/volumio/uhubctl/coolme.sh >> /home/volumio/log.txt
I included the log file because I want to see that it works. The way the script is written, it will only produce output when it turns the fan on or off so the log file won’t fill up too quickly.
If you want to make sure the cron jobs are working, you can also add:
* * * * * echo “crontest $(date) $(whoami)” >> /tmp/crontest.txt
Don’t forget to remove it or it will create a pretty big log file in a few days.
That should do it. My experience has been that the fan cools the RPI down pretty quickly. Here’s an example of my log file:
Overtemp: CPU raw temp is 70370 'C at Sun Jun 24 22:45:01 PDT 2018 Current status for hub 1-1 [0424:2514, USB 2.00, 4 ports] Port 2: 0000 off Sent power on request New status for hub 1-1 [0424:2514, USB 2.00, 4 ports] Port 2: 0100 power ----- Undertemp: CPU raw temp is 49388 'C at Sun Jun 24 22:50:01 PDT 2018 Current status for hub 1-1 [0424:2514, USB 2.00, 4 ports] Port 2: 0100 power Sent power off request New status for hub 1-1 [0424:2514, USB 2.00, 4 ports] Port 2: 0000 off ------ Overtemp: CPU raw temp is 70370 'C at Mon Jun 25 15:40:01 PDT 2018 Current status for hub 1-1 [0424:2514, USB 2.00, 4 ports] Port 2: 0000 off Sent power on request New status for hub 1-1 [0424:2514, USB 2.00, 4 ports] Port 2: 0100 power ----- Undertemp: CPU raw temp is 52616 'C at Mon Jun 25 15:45:01 PDT 2018 Current status for hub 1-1 [0424:2514, USB 2.00, 4 ports] Port 2: 0100 power Sent power off request New status for hub 1-1 [0424:2514, USB 2.00, 4 ports] Port 2: 0000 off -----
You can see that it overheated at 70.3° C, kicked the fan on and in 5 minutes when it ran again, the temperature was down to 49.3° C so it turned it back off. While the outside temp remains high, it does oscillate on and off but we’re doing that well below the overheat limit so we should be good.