For a couple of years the Raspberry Pi I running OSMC was housed in an old settopbox I bought at a secondhand shop in my town. There was no power brick with it which droped the price a lot. There was no airflow at all which resulted in an system that got a bit warm. So started looking for a beter case but never found a appealing replacement that also had a FAF (Family Approval Factor). Until a couple of months ago while browsing Thingiverse.com for 3 Printable cases and among the standaard box there was a case based on the Mac Pro I liked the looks of it. And do have an 3d printer so way not. I started printing and after a couple of long prints talking some 24+ hours of printing I had the parts ready.
Cooler but not much
The first tests did show a lower base temperature was lower but playing a movie stil resulted in a temperature warning so more work was needed. Sinds the case has room for a fan at the top to pull air though the case I went on a fan hunt. At first the plan was to buy a simple 12v fan and power it From the same 5v powersupply that powers the Pi but knowing that not all 12v fans can start at 5v the search included 5v. I came across a 5v 80mm fan from Noctua that also was PWM-enabled. Noctua is known for making silent fans and being PWM-enabled gave me an idea would it possible to create the PWM signal with the Pi itself and control the speed based on de temperature. In my search I came stumbled on this blogpost which was what I needed. So order placed and the script downloaded. I knew I had to look for another PWM pin the pin 18 was occupied by my IR reciever looking at the pinout I saw that pin 19 which was free to use was also an PWM output.
import RPi.GPIO as GPIO
import time
import signal
import sys
import os
# Configuration
FAN_PIN = 18 # BCM pin used to drive PWM fan
WAIT_TIME = 1 # [s] Time to wait between each refresh
PWM_FREQ = 25000 # [Hz] 25kHz for Noctua PWM control
# Configurable temperature and fan speed
MIN_TEMP = 40
MAX_TEMP = 70
FAN_LOW = 40
FAN_HIGH = 100
FAN_OFF = 0
FAN_MAX = 100
# Get CPU's temperature
def getCpuTemperature():
res = os.popen('vcgencmd measure_temp').readline()
temp =(res.replace("temp=","").replace("'C\n",""))
#print("temp is {0}".format(temp)) # Uncomment for testing
return temp
# Set fan speed
def setFanSpeed(speed):
fan.start(speed)
return()
# Handle fan speed
def handleFanSpeed():
temp = float(getCpuTemperature())
# Turn off the fan if temperature is below MIN_TEMP
if temp < MIN_TEMP:
setFanSpeed(FAN_OFF)
#print("Fan OFF") # Uncomment for testing
# Set fan speed to MAXIMUM if the temperature is above MAX_TEMP
elif temp > MAX_TEMP:
setFanSpeed(FAN_MAX)
#print("Fan MAX") # Uncomment for testing
# Caculate dynamic fan speed
else:
step = (FAN_HIGH - FAN_LOW)/(MAX_TEMP - MIN_TEMP)
temp -= MIN_TEMP
setFanSpeed(FAN_LOW + ( round(temp) * step ))
#print(FAN_LOW + ( round(temp) * step )) # Uncomment for testing
return ()
try:
# Setup GPIO pin
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(FAN_PIN, GPIO.OUT, initial=GPIO.LOW)
fan = GPIO.PWM(FAN_PIN,PWM_FREQ)
setFanSpeed(FAN_OFF)
# Handle fan speed every WAIT_TIME sec
while True:
handleFanSpeed()
time.sleep(WAIT_TIME)
except KeyboardInterrupt: # trap a CTRL+C keyboard interrupt
setFanSpeed(FAN_HIGH)
#GPIO.cleanup() # resets all GPIO ports used by this function
To start the script after a restart whithout the need for manual intervention I created a file fan_control.service in /lib/systemd/system/
whit the following contents:
[Unit]
Description=Fan control
After=multi-user.target
Conflicts=getty@tty1.service
[Service]
Type=idle
ExecStart= /usr/bin/python /home/osmc/Scripts/fan_control.py
[Install]
WantedBy=multi-user.target
Then I had to issue the command sudo systemctl enable fan_control.service
to start the script at boot. Now whenever the Raspberry is powered down the fan spins at 100% and is audible as soon as the script kicks in the sound levels go down to an slight hum which you can just about hear in a silent room. There is a good airflow out the top of the case and the temperatures stay below 70°C.