For a couple of years, the Raspberry Pi I was running OSMC on was housed in an old settop box I bought at a secondhand shop in my town. There was no power brick with it, which dropped the price a lot. There was no airflow at all, which resulted in a system that got a bit warm. So started looking for a better case, but never found an 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 standard boxes there was a case based on the Mac Pro I liked the looks of it. And do have a 3d printer, so why not. I started printing and after a couple of long prints talking some 24+ hours of printing I had the parts ready.

the printed framePi MountedWiht the shell

Cooler but not much

The first tests did show a lower base temperature was lower, but playing a movie still resulted in a temperature warning, so more work was needed. Since 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 power supply that powers the Pi, but knowing that not all 12v fans can start at 5v I added ‘5v’ to my search string. That way I came across a 5v 80 mm 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 be possible to create the PWM signal with the Pi itself and control the speed based on the temperature. In my search I came stumbled on this blog post 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 receiver 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 a slight hum which you can just about notice in a silent room. There is a good airflow out the top of the case and the temperatures stay below 70 °C.

the for now completed case