Raspberry 4 – Temperaturgesteuerte Lüfterregelung – Teil 2

(Update 07.03.2021) Ich habe mir ein Raspberry Pi 4 Komplettset (Werbung) zugelegt, da mir der Raspi 3 als NAS doch etwas zu langsam war.

Da der dazugehörige Lüfter auf Dauer doch etwas laut ist, habe ich mir eine temperaturgesteuerte Lüfterregelung eingerichtet.

In Teil 2 zeige ich das Python-Skript, das den Lüfter steuert.

Nachdem ich in Teil 1 die Hardware der Lüftersteuerung vorgestellt habe, geht es nun weiter mit der Software, die aus einem Python-Skript besteht.

2. Die Software

Bei der Software handelt es sich um ein Python-Script, das sich um die Regelung des Lüfters kümmert. Das Script ist aus verschiedenen Quellen im Netz zusammengeklaubt und von mir noch etwas angepasst worden. Um das Script zu erstellen, kann man folgendermaßen vorgehen:

– Python-Script herunterladen

– Script über ssh auf dem Raspbi installieren

Nach der Installation von Raspbian und dem Zugang zum System über SSH (was hier nicht weiter beschrieben wird, da es dazu bereits viele Anleitungen gibt), erstellen wir uns (als User pi) ein Python-Script „fancontrolpwm.py“ im Unterordner scripts in unserem Homeverzeichnis.

  1. Kommando cd (+ anschließend ENTER-Taste) in der Shell eingeben, um ins Homeverzeichnis zu wechseln:
    cd
  2. Und weiter
    mkdir scripts
    cd scripts
    nano fancontrolpwm.py
  3. Dann den Inhalt des heruntergeladenen Python-Scripts kopieren und im Editor-„Fenster“ von nano einfügen (bei Putty z.B durch Drücken der rechten Maustaste)
  4. Jetzt muss das eingegebene (reinkopierte…) Script noch gespeichert werden. Dazu die Tastenkombination STRG+x, danach y und danach ENTER drücken.

– Fehlende Libraries in Python installieren

  1. Bevor wir das Script testweise starten können, müssen wir erst noch pip und im Anschluss eine fehlende Python-Libraray installieren:
    sudo apt install python-pipy 
    und danach ENTER drücken.
  2. pip install gpiozero
    (Beim Installieren der Python-Library mit pip sind mir Warnungen wegen irgendwelcher bin-Pfade angezeigt worden, was aber hier nicht weiter stört.)

– Testen des Scripts

  1. Jetzt sollten wir das Script ausprobieren können:
    python fancontrolpwm.py
    Das Script sollte starten, dabei muss der Lüfter für drei Sekunden anlaufen und sollte danach wieder abschalten (falls der Raspi nicht schon heiß geworden ist). Das Script muss jetzt alle zwei Sekunden die aktuelle CPU-Temperatur ausgeben.
  2. Hat das soweit geklappt, stoppen wir das Script mit der Tastenkombination STRG+c.
  3. Um zu überprüfen, ob der Lüfter auch temperaturabhängig gesteuert wird, bringen wir die CPU auf Trab, sodass die Temperatur steigt:
    1. Erst wird stress-ng installiert (zum Ausführen von Stresstests):
      sudo apt install stress-ng
      y und danach ENTER drücken.
    2. Jetzt lassen wir unser Script im Hintergrund laufen:
      python fancontrolpwm.py &
      Hier auf das abschließende & achten, damit wir weitere Kommandos eingeben können. Unser Script gibt die Temperatur weiterhin auf der Konsole aus, es ist aber dennoch möglich, Eingaben zu tätigen!
    3. Danach wird die CPU „gestresst“, damit sie sich erhitzt und die Lüftersteuerung geprüft werden kann:
      stress-ng -c 4
    4. Die Temperaturausgaben, die das Script im Hintergrund immer noch ausgibt, sollten anzeigen, dass die CPU sich erhitzt und nach einiger Zeit sollte der Lüfter anlaufen.
    5. Hat das geklappt, stoppen wir den Stresstest durch Drücken von STRG+c.
    6. Die Temperatur sollte langsam sinken und der Lüfter langsamer werden und schließlich wieder stoppen.
    7. Zum Schluss bringen wir das Python-Script in den Vordergrund und beenden es:
      fg
      und danach mit STRG+c beenden.

In Teil 3 richten wir es so ein, dass das Python-Script beim Booten des Raspberry Pi automatisch startet.


Quelltext des Python-Scripts:

 
#!/usr/bin/python
 
import sys
import time
from gpiozero import PWMLED # doc: https://gpiozero.readthedocs.io/
 
# ---------------- version info ----------------
# Version 2021-03-07 (2. Release): Einrueckungsfehler in Zeilen 77/78 (Alt 74/75)
 
# ---------------- parameter -------------------
 
# GPIO fuer den Luefter
fan = PWMLED(21,True,0,20)
 
# Temperatur in Celsius, ueber der der Luefter mit pwm-wert dutycycleatmax (s.u.) einschaltet
maxt = 55.0
# Temperatur in Celsius, unter der der Luefter aus ist
mint = maxt - 10
# Temperatur in Celsius, bis zu der die pwm linear geregelt wird
pwmt = maxt - 5
# Temperatur in Celsius, ab der der luefter (wegen zu grosser hitze) mit 100 prozent laeuft
fult = maxt + 5
 
# pwm-aussteuerung bei maxt (anpassen, falls der luefter unangenehm oder laut klingt)
dutycycleatmax = 0.7
 
# pwm-aussteuerung bei mint (anpassen, falls der luefter unangenehm oder laut klingt oder
# der wert zu niedrig ist, sodass der luefter nicht anspringt)
dutycycleatmin = 0.4
 
 
# ---------------- programmcode ab hier -------------------
 
def translate(value, leftMin, leftMax, rightMin, rightMax):
    # Figure out how 'wide' each range is
    leftSpan = leftMax - leftMin
    rightSpan = rightMax - rightMin
 
    # Convert the left range into a 0-1 range (float)
    valueScaled = float(value - leftMin) / float(leftSpan)
 
    # Convert the 0-1 range into a value in the right range.
    return rightMin + (valueScaled * rightSpan)
 
def cpu_temp():
    with open("/sys/class/thermal/thermal_zone0/temp", 'r') as f:
        return float(f.read())/1000
 
 
def main():
    # luefter kurz anlaufen lassen
    is_close = True
    fan.value = 1.0
    time.sleep(3.0) # nach 3 s wieder ausschalten und regelung beginnen
    fan.off()
    while True:
 
        temp = cpu_temp()
        if is_close:
            if temp > maxt: # obergrenze, einschalten des luefters
                print time.ctime(), temp, 'Fan ON'
                fan.value = dutycycleatmax
                is_close = False
        else:
            if temp < mint: # untergrenze, ausschalten des luefters
                print time.ctime(), temp, 'Fan OFF'
                fan.value = 0.0
                is_close = True
            else:
                if temp < pwmt: # lineare pwm-steuerung
                    dc  = translate(temp, mint, maxt, dutycycleatmin, dutycycleatmax)
                    if dc > 1:
                       dc = 1
                else: # entweder max. pwm-wert oder bei zu grosser hitze vollaussteuerung
                    dc = dutycycleatmax if temp < fult else 1.0
                print time.ctime(), "FAN PWM: ", dc
                fan.value = dc
 
 
        time.sleep(2.0) # alle zwei sekunden neu messen und regeln
        print time.ctime(), temp
 
 
if __name__ == '__main__':
    main()
 

(Update 07.03.2021):
Vielen Dank an meinen Namensvetter Markus Mueller aus der Schweiz, der mich auf einen Einrückungsfehler in den Zeilen 74 und 75 im Script hingewiesen hat! 🙂