Lüfter Steuerung (mit Arduino)

Wie im Logic Analyzer beschrieben, brauchte ich eine Lüftersteuerung für meinen neuen Fileserver, da ich unter Debian, genauer mit lm-sensors, nicht auf die Daten der Lüfter zugreifen kann.

Anforderungen

Die Anforderungen an die Lüftersteuerung waren übersichtlich:

  • Bei Steuerungsausfall müssen die Lüfter mit voller Geschwindigkeit laufen.
  • Die Lüfter sollen immer mit einer Mindestdrehzahl laufen.
  • Die Temperatur der Festplatten soll um die 40 °C gehalten werden.
  • Je ein Sensor soll je eine Festplattentemperatur messen.
  • Bis zu vier Lüfter sollen individuell gesteuert werden.
  • Die Steuerung soll die Lüfter und deren ideale Drehzahl selbst ermitteln.
  • Eine Schnittstelle zum Steuerungsdaten abfragen soll bereitgestellt werden.
  • Die Drehgeschwindigkeit der Lüfter soll messbar sein.

Prototypen

Die Anforderungen an die Messbarkeit sprechen für einen 3-Pin oder 4-Pin Lüfter. Die Steuerung von 4-Pin Lüftern ist allerdings sehr viel einfacher und preislich ist da kein großer Unterschied. 4-Pin Lüfter für PCs funktionieren nach einer Intel Spezifikation. Die Lüfter haben 4 Anschlüsse: GND, 12V, Tacho, PWM. Der Pin für das PWM Signal nimmt 0V als Low und 5V als High entgegen, kann also direkt am Arduino betrieben werden. Das Tacho-Signal wird meist mit einem Hall-Sensor realisiert, pro Umdrehung liefert Sensor 2 Impulse. Der Arduino muss also Impulse über Zeit zählen und kann daraus die Drehzahl errechnen. Um die Impulse sauber zu erkennen, wird die Verbindung zwischen Tacho-Signal und Arduino mit einem Widerstand auf 5V gezogen. Als Temperatursensoren verwende ich Dallas DS18B20 OneWire Sensoren, dies ermöglicht es mehrere Sensoren an einem Bus zu betreiben. Den OneWire-Bus zieht man ebenfalls über einen Widerstand auf 5V. Daraus ergibt sich folgende Schaltung.


FanControll v1.0 Schaltung

Wie ich im Logic Analyzer schon erklärte, hat der Arduino Uno bzw. sein Mikroprozessor der ATmega328P leider zu wenig 16-Bit Timer. Ich verwende deshalb den Arduino Leonardo, dessen Mikroprozessor hat einen 16-Bit mehr und damit genug für die Ansteuerung von 4 Lüftern.

Wenn man die PWM-Signale nicht vom Arduino erzeugen lässt, geht natürlich auch ein Arduino Uno. Ich habe einen Prototypen gebaut, der ein PWM-Generator-Board via UART (also serieler Ansteuererung) zur Erzeugung der PWM-Signale benutzt.


Prototyp mit externen PWM-Generator

Leider hat das Board, welches die PWM-Signale erzeugt, auch nur drei Ausgänge, ich hatte da noch die Hoffnung ein ähnliches Board mit vier oder mehr Ausgängen zu finden, leider erfolglos.

Die ursprüngliche Schaltung habe ich auf einem Arduino Prototyp-Shield aufgebaut, um sie zu testen und mit der Softwareentwicklung anfangen zu können.


Prototyp mit Arduino-Shield

Eigene Platine (PCB)

Eigentlich hätte ich jeden Pin des Arduinos fest verdrahten können, also in der Software festlegen können an welchen Pin das PWM-Signal ausgegeben werden muss und an welchem Pin das dazugehörige Tacho-Signal anliegt. Bei meinem Prototyp-Shield sieht man eher schlecht was an welchen Pin geführt wird. Ich habe in der Software nur die Pins festgelegt, welche für Tacho bzw. PWM verwendet werden. Im Setup testet die Software dann selbständig welche Lüfter angeschlossen sind und an welchen Pins die dazugeöhrigen Tacho-Signale anliegen. Das finde ich sehr komfortabel und verhindert auch Fehlverdrahtungen auf dem Breadboard, auch wenn es beim Erstellen eines PCB nicht mehr nötig wäre.

Fritzing ermöglicht es aus dem Breadboard-Aufbau ein PCB zu erstellen. Nach dem händischen Optimieren der auto-gerouteten Leiterbahnen erhält man produktionsfähiges Layout. 2-Layer, also unten und oben, reichen hier aus. Manche Leiterbahnen müssen ab und an die Seite wechseln, damit es keine ungewollten Verbindungen gibt. Eigentlich wollte ich mir das dann von irgendwem ätzen lassen, aber das Durchkontaktieren der zwei Layer ist relativ umständlich.


Layout des PCBs

Aus Fritzing heraus kann man mit wenigen Klicks direkt bei aisler.net das PCB in Auftrag geben. Die Mindestbestellmenge lag bei mir bei drei Stück und die sollten etwa 25€ kosten. Das ist im Prinzip recht günstig, verglichen mit den anderen deutschen Herstellern, dass liegt an der geringen Stückzahl.

Direkt in China stellt man deutlich günstiger her. Ich hatte das vorher noch nie gemacht. Ich habe hier PCBWay getestet, dort war die Mindestmenge fünf Stück für $1 das Stück, der Express-Versand hat $6 gekostet und als Neukunde habe ich $5 Rabatt bekommen.

Für 5 PCBs habe ich etwa 5€ gezahlt. Die Dateien die man zur Produktion braucht, können direkt aus Fritzing exportiert werden. Die Produktion kann man auf der Webseite gut verfolgen und dauerte knapp drei Tage. Der Versand hat dann etwa eine Woche gedauert, ich hatte also nach 10 Tagen die PCBs zu Hause.


fertiges PCB

Für die Sensoren hatte ich zuerst 2,54mm Pin-Header verwendet. Leider sind die nicht verdrehsicher, es hat mich einen Arduino gekostet dies herauszufinden. OK bei dem Arduino ist nur die Spannungsversorgung durchgebrannt, der Mikroprozessor selbst funktioniert noch. Ich habe dann für den zweiten Anlauf Steckerbuchsen von Molex verwendet, die kosten bei Segor pro Sensor (Wanne, Stecker & Crimkontakte) etwas unter 1€, dafür geht aber kein Arduino mehr kaputt.

Im ersten Versuch waren alle Widerstände 4,7kΩ, leider konnte ich dann nur noch vier Temperatursensoren anschließen, einer mehr und es wurde keiner mehr gefunden. Ich habe den Widerstand der zwischen 5V und dem OneWire-Bus durch einen 2,7kΩ ersetzt, damit ging es dann ohne weitere Probleme.

Die 4-Pin PWM Lüfter Buchsen sind etwas speziell. Der Teil der beim zusammenstecken für das Einrasten sorgt, ist nur drei Pin breit. Das ermöglicht im PC 3-Pin und 4-Pin Lüfter zu verwenden und sorgt dafür das 4-Pin Lüfter nicht falsch aufgesteckt werden können. Bei Segor habe ich die leider nicht bekommen. Aufgebaut sieht das Arduino-Shield dann so aus:


fertiges Arduino-Shield

Für die Stromversorgung benötigt man 12V für die Lüfter und irgendetwas zwischen 7-12V für den Arduino. Man könnte auch direkt 5V nehmen und den Arduino über die Pins mit Strom versorgen. Das würde vermutlich sogar etwas Strom sparen, da der Spannungswandler auf dem Arduino nicht verwendet wird. Ich habe einfach die 12V genommen mit denen ich auch die Lüfter versorge und einen kleiner Y-Adapter gebastelt.


Stromversorgungskabel

Softwareentwicklung

Beim Testaufbau für die Softwareentwicklung habe ich die Anzahl und Art der Lüfter und Anzahl der Sensoren variiert. Mit maximaler Bestückung sieht das dann so aus:


Versuchsaufbau für die Softwareentwicklung

Die Software habe ich so geschrieben, dass beim Einschalten oder Reset des Arduinos im Setup erst einmal alle Parameter ermittelt werden, die für die Steuerung benötigt werden. Ich beschreiber hier nur die grobe Funktionsweise.

Als erstes wird geschaut wieviele Temperatursensoren angeschlossen sind. Es muss mindestens ein Sensor angeschlossen sein, sonst verharrt der Arduino hier bis der erste Sensor angeschlossen wird. Das Vorhandensein von Sensoren wird später regelmäßig überprüft, sodass man auch im Betrieb welche hinzufügen oder entfernen kann. Sollte die Software allerdings keine Sensoren mehr finden, werden die Lüfter voll aufgedreht.

Im nächsten Schritt werden die vier möglichen PWM Signale den vier möglichen Tachosignalen zugeordnet. Dabei wird auch ermittelt wieviele Lüfter angeschlossen sind. Es muss mindestens ein Lüfter angeschlossen sein, damit dieser Schritt abgeschlossen wird, sonst wartet der Arduino hier wieder. Jede Änderung an der Lüfterkonfiguration bedarf eines Neustarts bzw. Resets.

Im letzten Schritt werden die Lüfter ausgemessen. Es wird pro Lüfter der höhste PWM-Wert ermittelt, bei dem der Lüfter eine minimale Drehzahl größer als 0 hat.

Die Spanne zwischen welcher der Lüfter geregelt wird, befindet sich dann zwischen PWM-Wert 100 und dem gemessenen minimalen PWM-Wert. Es werden zwei Temperaturpunkte definiert. Punkt A, unter dem die Lüfter mit minimaler Drehzahl laufen soll, und Punkt B, bei welcher der Lüfter mit voller Drehzahl laufen soll.


Temperatur-Drehzahl-Kurve

Die Spanne zwischen den beiden Temperaturen wird gleichmäßig auf die Spanne der möglichen PWM-Werte aufgeteilt. So kann man für jede Temperatur den passenden PWM-Wert berechnen.

Betrieb

Die Steuerung selbst ist recht einfach. Es werden alle Temperaturen gemessen und die Höhste wird zur Regelung verwendet. Für jeden Lüfter wird der PWM-Wert passend berechnet und der Lüfter entsprechend angesteuert.

Um mit Arduino zu kommunizieren, wird er an einen internen USB-Anschluss angeschlossen. Ich habe mir dafür so ein kleines Kabel gebaut.


InternesUSB zu MicroUSB Kabel

Mit dem internen USB verbunden, verhält sich der Arduino wie eine über USB verbundene serielle Schnittstelle. Man kann an die serielle Schnittstelle ein beliebiges Byte schicken (ausser das kleine ‘r’) und er antwortet mit den aktuellen Parametern. Sendet man das kleine ‘r’, wird ein Reset durchgeführt. Ich verwende zum Auslesen und der Weitergabe an check_mk folgendes kleines Python-Skript:


#!/usr/bin/python

import serial
import time
import sys

connected = False
tries = 0

while not connected:
    try:
        arduino = serial.Serial('/dev/fancontrol', 9600, timeout=2)
        connected = True
    except:
        if tries > 10:
            sys.stdout.write("FanControl Failed - Not connectable. |")
            sys.stdout.flush()
            sys.exit(2)
        pass
    time.sleep(1)
    tries = tries + 1

arduino.write("x")

sys.stdout.write("FanControl OK - Running and readable. |")
sys.stdout.write(arduino.readline())
sys.stdout.flush()
sys.exit(0)


Fazit und Verbesserungen

Nach ausgiebigen Tests läuft die Steuerung nun seit drei Wochen zuverlässig in meinem Fileserver. Ich bin insgesamt zufrieden. Für Version 1.1 würde ich ein paar Sachen verbessern:

  • Mehr Änschlüsse für den OneWire-Bus und den Abstand dazwischen vergrößern.
  • Die Widersände leicht versetzen, damit der 12V auch 90° zum Shield zeigen kann.
  • Eine Diode oder so einbauen, damit ein verdrehter Sensor nichts beschädigt.
  • Statt des Arduinos, eine eigene Platine mit dem ATmega32u4 entwerfen.
  • Ein richtiges Gehäuse zb. 3D gedruckt, vielleicht als 3,5 Zoll Laufwerk.
  • Vielleicht ein Display oder Kontroll-Leds.
  • Temperaturpunkte A und B via serieller Kommunikation ändern.
  • Der ExitCode für check_mk sollte vom Arduino kommen.


Lüftersteuerung im Einsatz

Hier nochmal alle Teile die ich verwendet habe:

Hier alle benötigten Dateien:

Bei Fragen, Anregungen, Kommentaren oder Verbesserungsvorschlägen schickt mir einfach eine E-Mail, ich baue das hier dann ein.