Aktiv-Passiv-Kühlung mit Arduino und Noctua NHL 9i
Guten Abend,
es ist soweit: Ich kühle meinen Xeon 1240 (ich glaube 80 Watt TDP) nun passiv bzw. bei Bedarf aktiv mit einem Noctua NHL 9i.
Bei mir läuft der Server meist im Idle, wenn aber Last kommt dann in Form einer oder mehrerer VM's oder via Plex.
Das Szenario ist also in aller Regel "keine bis minimale Last" oder "hohe Last bis Vollast".
Da der Server bei mir im Büro steht sollte die Lösung erst dann Laut werden, wenn auch aktiver Kühlbedarf besteht.
Kurzbeschreibung der Lösung:
Ein Arduino, ein LC-Display, ein Relais das 12 V schaltet, ein Temperaturfühler, der o.g. Kühler, eine Fräse und ein bisschen Programmcode.
Der Temperaturfühler misst sekündlich die Temperatur und gibt diese an den Arduino aus. Wenn die Temperatur größer als 55°C ist, dann wird über einen Pin ein Relais angesteuert und der Lüfter bekommt vom Server 12V. Sobald die Temperatur wieder unter 55°C ist, schließt der Pin das Relais.
Ausführliche Beschreibung der Lösung:
1.) Fräsen des Kühlkörpers:
Die Idee war zunächst, den Temperatursensor (DS18b20) zwischen die beiden außenliegenden Kühlrippen zu stecken (dort passte er ideal). Ergebnis war aber, dass der Sensor eine deutlich niedrigere Temperatur anzeigte als die CPU tatsächlich hatte (wobei man sich auf iLO nicht verlassen kann, siehe weiter unten). Zweite Idee war dann, in die Platte des Kühlkörpers einen 6-8mm Schlitz einzufräsen in dem der kleine Temperatursensor ausreichend Platz hat. Direkter kann man die Temperatur eigentlich ja nicht messen. Also ab zu Papa und das Problem erklären. Etwas darüber nachdenken, ran an die Fräsbank und einen Schlitz einfräsen. Wir haben die Zuleitung des Kabels auch noch mit eingefräst, da es um den Sockel ja ziemlich eng ist (kleine Stufe in der Fräsbahn für das Kabel, wir wussten nicht wie dick die eigentliche Platte ist und wollten nichts riskieren).
(Die schlechte Trennung der Lüfterklammern bitte ich zu entschuldigen, war made in eile).
Den Sensor mussten wir mit einer Pfeile noch etwas abflachen, damit er bündig in die Platte passt. Im Anschluss haben wir den Sensor mit Epoxid eingeklebt und den Kleber aushärten lassen.
Zudem habe ich beim Einbau des Kühlkörpers etwas zusätzliche Wärmeleitpaste auf den Sensor getan.
2.) Schaltung:
Die Schaltung werde ich noch einmal mit dem Arduino-Tool darstellen. Am Ende ist der Aufbau aber wie folgt:
- LCD Display gemäß Arduino Guide (Pins exakt wie im Guide) - Das Display kann man auch gut weglassen
- Temperatursensoren DS18b20 gemäß Arduino Guide (Pins etwas angepasst, da bereits durch das Display belegt)
- Relaisansteuerung über einen freien Pin (Relais war ein 5V Finder 30.22.7)
3.) Programmcode:
Der Programmcode für den Arduino ist aus den oben genannten Guides zusammenkopiert und etwas angepasst.
Ziel war es, dass die Temperatur und der Status des Lüfters an ein LCD ausgegeben wird. Ebenso wollte ich die Werte via USB an den Server ausgeben.
Ich bin nicht der große Programmierer, aber es funktioniert alles so wie es soll.
Code:
// include the library code:
#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
float temp;
#define ONE_WIRE_BUS 13 /* Digitalport Pin 13 definieren */
OneWire ourWire(ONE_WIRE_BUS); /* Ini oneWire instance */
DallasTemperature sensors(&ourWire);/* Dallas Temperature Library für Nutzung der oneWire Library vorbereiten */
void setup() {
// set up the LCD's number of columns and rows:
delay(1000);
Serial.begin(9600);
delay(1000);
pinMode(8, OUTPUT);
sensors.begin();/* Inizialisieren der Dallas Temperature library */
adresseAusgeben(); /* Adresse der Devices ausgeben */
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("Temperatur:");
lcd.setCursor(0, 1);
lcd.print("Luefter:");
}
void loop() {
Serial.println();
sensors.requestTemperatures(); // Temp abfragen
Serial.print(sensors.getTempCByIndex(0) );
Serial.print(" Grad C");
temp = sensors.getTempCByIndex(0);
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(11, 0);
lcd.print(temp);
lcd.setCursor(11, 1);
if (temp <= 55 )
{
lcd.print("Aus ");
digitalWrite(8, LOW);
}
else
{
lcd.print("An ");
digitalWrite(8, HIGH);
}
}
void adresseAusgeben(void) {
byte i;
byte present = 0;
byte data[12];
byte addr[8];
Serial.print("Suche 1-Wire-Devices...\n\r");// "\n\r" is NewLine
while(ourWire.search(addr)) {
Serial.print("\n\r\n\r1-Wire-Device gefunden mit Adresse:\n\r");
for( i = 0; i < 8; i++) {
Serial.print("0x");
if (addr[i] < 16) {
Serial.print('0');
}
Serial.print(addr[i], HEX);
if (i < 7) {
Serial.print(", ");
}
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.print("CRC is not valid!\n\r");
return;
}
}
Serial.println();
ourWire.reset_search();
return;
}
4.) Ergebnisse:
Die Ergebnisse sind hervorragend. Der Prozessor ist bei mir wie beschrieben meist im Idle, sodass der Lüfter nicht laufen muss. Im Idle werden bei aktuellen Temperaturen um 22,6°C Messwerte um die 37,5°C durch den Arduino ausgegeben. In der Startphase geht die Temperatur etwas hoch, danach pendelt sie sich beim o.g. Wert ein.
Sobald Last auf das System kommt schaltet sich der CPU-Lüfter ab 55°C ein. Bei mir läuft seit ca. 30 Minuten eine VM (unter XPenology) mit Prime 95. Der VM werden alle Kerne zur Verfügung gestellt, HT ist aktiviert. Die gemessene Temperatur liegt dabei unter Vollast bei exakt 57,8°C - 57,9°C, hat aber bisher nie die 60°C Marke erreicht.
LC-Display
Ausgabe via Serial-Monitor
5.) Abweichungen zwischen iLO und der "echten Temperatur":
Das man iLO bei der Temperatur nicht so ganz trauen kann (Schwellenwert ab 40°C) ist ja bekannt. Mir ist jedoch zusätzlich aufgefallen, dass die Temperaturen zwischen iLO und Arduino um mehrere Grad Celsius ausseinander gehen - ich traue dem Arduino deutlich mehr. Aktuell meldet iLO 54°C, der Arduino gibt 56,8°C (im Vergleich zur o.g. Angabe von 57,8°C - 57,9°C läuft der Gehäuselüfter nun anscheinend schneller, vergangen sind ca. 40 Minuten Vollast). Aufgefallen ist mir das auch im Übergang zwischen Idle --> Volllast. iLO hat stets 2-3°C weniger angezeigt, als der Arduino (auf F5 habe ich gedrückt). Ich wüsste nicht, warum der eingesetzte Sensor einen verkehrten Wert ausgeben sollte - Tests mit heißen Wasser haben die Temperaturgenauigkeit exakt bestätigt (99,89°C bei kochendem Wasser).
6.) Warum das alles?
Tjah, die Frage werde ich nicht beantworten können. Bei den ganzen positiv-verrückten hier im Forum wird das aber sicher auch nicht erwartet.
Schön finde ich, dass der Kühler keinen Lärm erzeugt wenn er nicht benötigt wird. Wird er dann doch mal benötigt, weiß ich das mit einer Temperatur unter 60°C alles im grünen Bereich ist.
7.) Ausblick:
Mein Ziel ist es, das ganze integriert im Microserver zu betreiben, sodass das Arduino-Board im Microserver Platz findet. Die fliegende Schaltung soll dann durch eine geätzte Schaltung ersetzt werden.
Ebenso möchte ich das LC-Display in die Fronttür integrieren, damit ich den Status prüfen kann. Als letzter Entwicklungsschritt wäre es dann toll, wenn ich die seriellen Informationen via VM oder XPenology auslesen kann.
Bei Fragen gerne Fragen
Liebe Grüße,
Moritz