#!/usr/bin/python3 # -*- coding: utf-8 -*- import RPi.GPIO as GPIO from datetime import date from os import path from os import getenv import time import sys # Configuration FAN_PIN = getenv('RPI_FAN_PIN', 21) # BCM pin used to drive transistor's base WAIT_TIME = getenv('RPI_FAN_WAITTIME', 10) # [s] Time to wait between each refresh FAN_MIN = getenv('RPI_FAN_MIN', 80) # [%] Fan minimum speed. PWM_FREQ = getenv('RPI_FAN_PWMFREQ', 25000) # [Hz] Change this value if fan has strange behavior # Fan speed will change only of the difference of temperature is higher than hysteresis hyst = getenv('RPI_FAN_HYST', 1) debug = bool(getenv('RPI_FAN_DEBUG', 'False')) prom_collect_dir = getenv('RPI_PROM_COLLECTDIR','/tmp/textfile-collector') prom_collect_file = prom_collect_dir + '/rpi_fan.prom' # Configurable temperature and fan speed steps tempSteps = [60, 70, 75, 80] # [°C] speedSteps = [0, 80, 90, 100] # [%] # tempSteps = [40, 45] # speedSteps = [0, 100] # Setup GPIO pin GPIO.setmode(GPIO.BCM) GPIO.setup(FAN_PIN, GPIO.OUT, initial=GPIO.LOW) fan = GPIO.PWM(FAN_PIN, PWM_FREQ) fan.start(0) i = 0 cpuTemp = 0 fanSpeed = 0 cpuTempOld = 0 fanSpeedOld = 0 if debug: print('%s Temp: %s, Fan: %s' % (date.today(), cpuTemp, fanSpeed)) # We must set a speed value for each temperature step if len(speedSteps) != len(tempSteps): print('Numbers of temp steps and speed steps are different') exit(0) try: while 1: # Read CPU temperature cpuTempFile = open('/sys/class/thermal/thermal_zone0/temp', 'r') cpuTemp = float(cpuTempFile.read()) / 1000 cpuTempFile.close() if debug: print('%s Temp: %s, Fan: %s' % (date.today(), cpuTemp, fanSpeed)) # Calculate desired fan speed if abs(cpuTemp - cpuTempOld) > hyst: # Below first value, fan will run at min speed. if cpuTemp < tempSteps[0]: fanSpeed = speedSteps[0] # Above last value, fan will run at max speed elif cpuTemp >= tempSteps[len(tempSteps) - 1]: fanSpeed = speedSteps[len(tempSteps) - 1] # If temperature is between 2 steps, fan speed is calculated by linear interpolation else: for i in range(0, len(tempSteps) - 1): if (cpuTemp >= tempSteps[i]) and (cpuTemp < tempSteps[i + 1]): fanSpeed = round((speedSteps[i + 1] - speedSteps[i]) / (tempSteps[i + 1] - tempSteps[i]) * (cpuTemp - tempSteps[i]) +speedSteps[i], 1) if fanSpeed != fanSpeedOld: if (fanSpeed != fanSpeedOld and (fanSpeed >= FAN_MIN or fanSpeed == 0)): fan.ChangeDutyCycle(fanSpeed) fanSpeedOld = fanSpeed if path.isdir(prom_collect_dir): with open(prom_collect_file, 'w') as f: str = '#HELP rpi_fan fan running at percent duty cycle\n' str += '#TYPE rpi_fan gauge\n' str += 'rpi_fan{component="sys"} %s\n' % fanSpeed f.write(str) if debug: print('%s Temp: %s, Fan: %s' % (date.today(), cpuTemp, fanSpeed)) cpuTempOld = cpuTemp # Wait until next refresh time.sleep(WAIT_TIME) except Exception as exception: print('Exception: {}'.format(type(exception).__name__)) print('Exception message: {}'.format(exception)) GPIO.cleanup() sys.exit()