Arduino Tutorial 3 - Lüfter per PWM steuern
Ich zeige euch heute wie man 3-Pin Lüfter an den Arduino anschließt und den benötigten Code dazu, mit dem wir die Geschwindigkeit der Lüfter per PWM regeln und trotzdem die Drehzahl auslesen zu können.
Ich werde dieses Tutorial in mehrere Teile aufspalten, um verschiedene Szenarien durchzuspielen.
3.0 - PWM ohne pfeifen
3.1 - Lüftergeschwindigkeit per Taster wechseln
3.2 - Temperaturgesteuerter Lüfter
3.3 - Lüftergeschwindigkeit per Drehpoti einstellen
Vorwort
3-Pin Lüfter lassen sich sehr einfach mit einem Arduino und einem N-Kanal Mosfet (Transistor) per PWM steuern. Diese Methode birgt allerdings ein paar Probleme.
Lüfter Pfeifen/Rattern
Wenn man einen Lüfter per PWM mit dem Arduino drosselt, dann kann man oft ein störendes Pfeifen oder Rattern vom Lüfter hören. Das liegt daran,
dass die PWM Ausgänge bei Arduino standardmäßig mit 490Hz oder 980Hz laufen.
Diese Frequenz liegt im für
Menschen hörbaren Bereich , daher auch die Geräusche (ganz vereinfacht gesagt
![;)](wcf/../images/smilies/wink.png)
). Um diesem Problem Herr zu werden muss man dem Arduino sagen,
er soll die PWM Ausgänge mit höherer Frequenz (über 20kHz) betreiben. Das wiederum bringt weitere Stolpersteine mit sich.
Diese Probleme und dessen Lösungen beschreibe ich unter
3.0 - PWM ohne pfeifen.
Tachosignal
Die Drehzahl eines Lüfters, der mit PWM angesteuert wird, lässt sich nicht einfach auslesen. Das liegt daran, dass die Elektronik, die das Tachosignal erzeugt, vom Lüfter mit Strom versorgt wird.
Wenn wir jetzt ein PWM Signal an den Lüfter anlegen, wird er sehr schnell an und aus geschalten und somit eine gedrosselte Geschwindigkeit erzielt. Dadurch wird aber auch die Elektronik des Tachosignals gestört und der Lüfter gibt kein saubers Signal mehr aus.
Dieses Problem und dessen Lösung beschreibe ich im nächsten Tutorial
4 - Lüfterdrehzal auslesen
Teileliste
Arduino IDE (Tutorial wurde mit 1.5.7 Beta erstellt)
Arduino UNO (Es gibt die Arduinos aber auch deutlich günstiger bei Ebay)
Breadboard
10kOhm Widerstand
Taster
Steckbrücke (oder Kabel je nach Vorliebe)
10kO Drehpoti
10kO NTC-Wiederstand (Temperatursensor)
alternativ
Wakü Thermosensor (das sind auch nur 10kO NTC-Wiederstände in einem Metallgehäuse)
N-Chanel Transistor/Mosfet
12V Netzteil (das ist nur ein Beispiel! Bitte wählt ein ausreichend starkes Netzteil je nach Leistung des Lüfters)
alternativ 12V Computer Netzteil
12V PC Lüfter
________________________________________________________________________
3.0 - PWM ohne Pfeifen
Um das Problem mit den pfeifenden/ratternden Lüftern zu lösen, muss man die Voreinstellungen der
Timer im Arduino ändern um so die PWM Frequenz zu erhöhen.
Jetzt fragt ihr euch sicherlich, was redet er jetzt von Timern
Als Timer bezeichnet man beim Arduino/ Mikrocontrollern einen auf dem Chip integriertes Funktionsmodul, welcher beim Zählen von Ereignissen, Messen von Zeitabständen und periodischen Ausführen von Programmteilen eine wichtige Hilfe darstellt. Mit einem Timer sind immer mehrere PWM Ausgänge verbunden. Das ganze sieht wie folgt aus.
Der Arduino Uno hat 3 Timer und 6 PWM Ausgänge. Sie hängen wie folgt zusammen
Diese Belegung müsste mit den meisten anderen kleinen Arduinos übereinstimmen. Ich kann dafür aber nicht die Hand ins Feuer legen.
Der Arduino Mega 2560
hat 6 Timer und 15 PWM Ausgänge. Sie hängen wie folgt zusammen
Ergänzend hier noch die
Intel Spezifikation für PWM Lüfter.
Jetzt, da wir wissen welcher Timer welche Pins steuert, kommen wir zu dem Stolperstein von dem ich vorher gesprochen habe.
Timer0 steuert nicht nur zwei PWM Pins, sondern auch die Funktionen
delay(),
millis() und
micros().
Wenn man jetzt die Frequenz dieses Timers verändert, ändern sich auch die Funktionen, wie oben in der Tabelle zu sehen ist. Zum beispiel, wenn wir die Frequenz auf 62500 Hz stellen, muss man die Funktion
delay(1000) in
delay(62500) ändern um 1 Sekunde zu warten.
Wenn ihr es etwas genauer nachlesen wollt,
Arduino Playground
Der beste Weg dieses Problem zu umgehen, ist die Pins von Timer0 einfach nicht zu benutzen, da ihr sonst im Code schnell einen Timingfehler machen könnt. Wenn es nicht anders geht, dann achtet bitte sorgfältig darauf, die betroffenen Zeitfunktionen richtig zu programmieren.
Das Umstellen der Frequenz ist ganz einfach. Es bedarf nur einer einzigen Zeile Code die unter
void setup() eingefügt werden muss.
TCCR
nB = TCCR
nB & 0b11111000 |
Befehl;
Bei diesem befehl müsst ihr nur das
n durch die Nummer des Timers und Befehl durch den Hex Code aus der Tabelle oben ersetzen. Für Timer1 und 31300Hz sähe es dann so aus.
TCCR
1B = TCCR
1B & 0b11111000 |
0x01;
Code
/*
Der Arduino hat 3 Timer und 6 PWM Ausgänge. Der Zusammenhang zwischen Timern und PWM Kanälen ist:
Pins 5 und 6: gesteuert von timer0 (ACHTUNG, dieser Timer beinflusst auch Funktionen wie "delay" und "millis")
Pins 9 und 10: gesteuert von timer1
Pins 11 und 3: gesteuert von timer2
Beim Arduino Mega gibt es 6 Zimer und 15 PWM Ausgänge:
Pins 4 und 13: gesteuert von timer0 (ACHTUNG, dieser Timer beinflusst auch Funktionen wie "delay" und "millis")
Pins 11 und 12: gesteuert von timer1
Pins 9 und 10: gesteuert von timer2
Pin 2, 3 und 5: gesteuert von timer 3
Pin 6, 7 und 8: gesteuert von timer 4
Pin 46, 45 und 44:: gesteuert von timer 5
Nachzulesen:
http://playground.arduino.cc/Main/TimerPWMCheatsheet
*/
void setup() {
TCCR1B = TCCR1B & 0b11111000 | 0x01;
// Setzt Timer1 (Pin 9 und 10) auf 31300Hz
}
void loop() {
// put your main code here, to run repeatedly:
}
Wenn ihr diese Zeile in euren Code einbaut, sollte es kein pfeifen oder rattern mehr geben. Ihr könnt jetzt ganz normal mit der
analogWrite(0 - 255) Funktion euren Lüfter ansteuern.
________________________________________________________________________
3.1 - Lüftergeschwindigkeit per Taster wechseln
In diesem Teil zeige ich euch, wie ihr die Geschwindigkeit eines Lüfters in mehreren Stufen mit zwei Tastern steuern könnt.
Anschlussplan
Code
/*
Arduino Tutorial 3.2 - Lüftergeschwindigkeit per Taster wechseln
by Scynd 2014
In diesem Tutorial geht es darum die Geschindigkeit eines Lüfters
per tastendruck um einen vordefinierten Wert zu erhöhen oder zu senken.
*/
// Konstante Variablen
const int FanPin = 9; // Pin für den Lüfter
const int Taster1Pin = 2; // Pin für Taster 1
const int Taster2Pin = 3; // Pin für Taster 2
// Variablen
int Schrittweite = 20; // Variable für die Schrittweite pro Tasterdruck des PWM Wertes
int FanSpeed = 75; // PWM Startwert des Lüfters (ca.30%)
int Taster1Status = 0; // Variable zum speichern des Tasterstatus
int Taster2Status = 0; // Variable zum speichern des Tasterstatus
void setup() {
TCCR1B = TCCR1B & 0b11111000 | 0x01; // Setzt Timer1 (Pin 9 und 10) auf 31300Hz
Serial.begin(9600); // Setzt die Baudrate für die Ausgabe am Serial Monitor auf 9600
pinMode(FanPin, OUTPUT); // Setzt den Pin des Lüfters als Ausgang
pinMode(Taster1Pin, INPUT); // Setzt den Pin des Tasters 1 als Eingang
pinMode(Taster2Pin, INPUT); // Setzt den Pin des Tasters 2 als Eingang
/* Der Lüfter bekommt 1 Sekunde einen Startimpuls und wir dann gedrosselt.
Das ist eine Sicherheitsmaßnahme, falls der Lüfter mit 30% nicht anläuft
*/
analogWrite(FanPin, 255);
delay(1000);
analogWrite(FanPin, FanSpeed);
}
void loop() {
Taster1Status = digitalRead(Taster1Pin); // TasterPin1 lesen und Status speichern
Taster2Status = digitalRead(Taster2Pin); // TasterPin2 lesen und Status speichern
// Wenn Taster 1 gedrückt ist, um den Wert von "Schrittweite" erhöhen
if(Taster1Status == HIGH) {
FanSpeed = FanSpeed + Schrittweite;
delay(500);
}
// Wenn Taster 2 gedrückt ist, um den Wert von "Schrittweite" senken
if(Taster2Status == HIGH) {
FanSpeed = FanSpeed - Schrittweite;
delay(500);
}
// Der ausgegebene PWM Wert wird auf den Bereich 75-255 begrenzt
if(FanSpeed > 255) {
FanSpeed = 255;
}
if(FanSpeed < 75) {
FanSpeed = 75;
}
analogWrite(FanPin, FanSpeed); // Gibt den PWM Wert am FanPin aus
Serial.println(FanSpeed); // Gibt den FanSpeed Wert im Seriellen Monitor aus
}
In den Variablen habe ich den Startwert des Lüfters mit
FanSpeed = 75 festgelegt. Das entspricht ca. 30% des PWM wertes, also ca. 4V. bei dieser Spannung läuft evtl. nicht jeder Lüfter los. Deshalb lasse ich den Lüfter beim Programmstart unter
void setup() für 1 Sek mit 100% laufen um das Anlaufmoment des Lüfters zu überwinden. Danach wird er wie geplant mit 75 angesteuert.
Die Hauptschleife beginnt mit dem abfragen der Taster. Ist ein Taster gedrückt, wird die Variable
FanSpeed um 20 erhöht oder gesenkt.
Wenn
FanSpeed größer als 255 wird, wird sie auf 255 zurückgesetzt. Das gleiche passiert in die andere Richtung bei 75. So wird ein Steuerbereich von 75 - 255, also 30% - 100% eingestellt.
Nun wird der Wert von
FanSpeed per
analogWrite() Befehl an den Lüfter ausgegeben und zur Kontrolle am Seriellen Monitor.
________________________________________________________________________
3.2 - Temperaturgesteuerter Lüfter mit 10kO NTC
In diesem Szenario geht es darum, die Lüftergeschwindigkeit über die Temperatur zu steuern. Bei steigender Temperatur, soll auch die Lüftergeschwindigkeit steigen, bei sinkender Temperatur fallen. Ausserdem legen wir bei niedriger Temperatur einen Bereich fest, in dem die Lüfter nicht laufen.
Die Temperatur wird mit einem 10kO NTC Widerstand gemessen. Diese NTC Widerstände werden gewöhnlich auch im Wasserkühlungsbereich verwendet, dort sind sie allerdings in Gehäusen verbaut, was aber nichts an ihrer Funktionsweise ändert.
Anschlussplan
Code
/*
Arduino Tutorial 3.2 - Temperaturgesteuerter Lüfter mit 10kO NTC
by Scynd 2014
In diesem Szenario geht es darum, die Lüftergeschwindigkeit über die Temperatur zu steuern.
Bei steigender Temperatur, soll auch die Lüftergeschwindigkeit steigen, bei sinkender Temperatur fallen.
*/
// Konstanten
const int FanPin = 9;
// Pin für den Lüfter
const int NTC = A0;
// Pin für den 10kO NTC Wiederstand
const int NTCNominal = 10000;
// Wiederstand des NTC bei Nominaltemperatur
const int TempNominal = 25;
// Temperatur bei der der NTC den angegebenen Wiederstand hat
const int BCoefficient = 3977;
// Beta Coefficient(B25 aus Datenblatt des NTC)
const int SerienWiederstand = 10000;
// Wert des Wiederstands der mit dem NTC in Serie geschalten ist
// Variablen
int FanSpeed = 0;
// Variable für die Lüftergeschwindigkeit
int FanMin = 60;
// Kleinster PWM Wert für den Lüfter befor er abschält
int FanOut = 1;
// Variable zum pürfen ob der Lüfter aus war
int TMin = 20;
// Untere Grenze des Temperaturbereichs
int TMax = 60;
// Obere Grenze des Temperaturbereichs
int AbfrageZahl = 5;
// Je mehr abfragen, desto stabiler isr das Ergebnis, dauert aber länger
int Abfrage[5];
// Array Variable für das Mitteln der Temperatur http://arduino.cc/de/pmwiki.php?n=Reference/Array
float Durchschnitt = 0;
// Variable für das Mitteln der Temperatur
float Temp;
// Variable für die Berechnung der temperatur nach Steinhart
void setup() {
TCCR1B = TCCR1B & 0b11111000 | 0x01;
// Setzt Timer1 (Pin 9 und 10) auf 31300Hz
Serial.
begin(9600);
// Setzt die Baudrate für die Ausgabe am Serial Monitor auf 9600
pinMode(FanPin,
OUTPUT);
// Setzt den Pin des Lüfters als Ausgang
pinMode(NTC,
INPUT);
// Setzt den Pin des NTC Wiederstands als Eingang
}
void loop() {
Temperaturberechnung();
// Startet die Temperaturerfassungsroutine
// Lüftergeschwindigkeit über den Temperaturbereich einstellen
// TMin->0% PWM | TMax->100% PWM
FanSpeed =
map(Temp, TMin, TMax, 0, 255);
// Wenn der PWM Wert unter den van FanMin fällt, schält der Lüfter ab
if (FanSpeed < FanMin) {
FanSpeed = 0;
FanOut = 1;
}
// Hysterese
if (FanOut == 1) {
FanSpeed = 0;
}
if(Temp >= 32) {
if(FanOut == 1) {
FanOut = 0;
analogWrite(FanPin, 255);
}
}
// PWM Wert auf 255 begerenzen
if (FanSpeed > 255) {
FanSpeed = 255;
}
// Lüftergeschwindigkeit über den Seriellen Monitor ausgeben
Serial.
print(
"Lueftergeschwindigkeit: ");
Serial.
println(FanSpeed);
analogWrite(FanPin, FanSpeed);
// Den Lüfter mit dem PWM Wert ansteuern
delay(500);
}
void Temperaturberechnung() {
// Nimmt N Abfragen in einer Reihe, mit einem kurzen delay
for (
int i=0; i < AbfrageZahl; i++) {
Abfrage =
analogRead(NTC);
delay(10);
}
// Mittelt alle Abfragen
Durchschnitt = 0;
for (
int i=0; i < AbfrageZahl; i++) {
Durchschnitt += Abfrage;
}
Durchschnitt /= AbfrageZahl;
// Umwandlung des Wertes in Wiederstand
Durchschnitt = 1023 / Durchschnitt - 1;
Durchschnitt = SerienWiederstand / Durchschnitt;
// Umrechnung aller Ergebnisse in die Temperatur mittels einer Steinhard Berechnung
Temp = Durchschnitt / NTCNominal;
// (R/Ro)
Temp =
log(Temp);
// ln(R/Ro)
Temp /= BCoefficient;
// 1/B * ln(R/Ro)
Temp += 1.0 / (TempNominal + 273.15);
// + (1/To)
Temp = 1.0 / Temp;
// Invertieren
Temp -= 273.15;
// Umwandeln in °C
// Ausgabe an den Seriellen Monitor
Serial.
print(
"Temperatur ");
Serial.
print(Temp);
Serial.
println(
" *C");
delay(500);
}
Fangen wir mit den Konstanten an. Hier haben wir diesmal ein paar für die Berechnung wichtigen Werte, die ich jetzt erläutere.
- NTCNominal = 10000 - Damit ist der Wiederstand des NTC bei Nominaltemperatur gemeint. Dieser Wert wird immer im Namen schon angegeben. Ein 10kO NTC hat einen Wiederstand von 10000 Ohm.
- TempNominal = 25 - Das ist die Nominaltemperatur. Diese ist im Normalfall 25°.
- BCoefficient = 3977 - Der Beta Coefficient ist eine Materialkonstante und ist im Datenblatt des NTC zu finden und wird mit B25 bezeichnet.
- SerienWiederstand = 10000 - Das ist der Wert in Ohm, des Wiederstand, der zusammen mit dem NTC Wiederstand verbaut wird. In unserem Fall auch ein 10kO Wiederstand.
Bei den Variablen gibt es ein paar Einstellmöglichkeiten, die je nach Geschmack oder Anwendungsfall zu wählen sind. Ich habe diese Werte nur exemplarisch gewählt.
- FanMin = 60 - Das ist der kleinste PWm Wert den der Lüfter macht. Fällt der PWM Wert durch die Temperatursteuerung darunter, schält der Lüfter ab. Wählt diesen Wert so, dass euer Lüfter damit noch läuft.
- TMin = 20 - Untere Tegeltemperaturgrenze
- TMax = 60 - Obere Regeltemperaturgrenze
Über den Temperaturbereich zwischen TMin und TMax wird im Code der PWM Wert linear verteilt. Sprich 20° (TMin) = 0 PWM und 60° (TMax) = 255 PWM. Ich habe hier mit FinMin festgelegt das der Lüfter erst bei einem PWM Wert von 60 startet. Das entspricht ca. 30°. Alles was darunter liegt resultiert in einem stehenden Lüfter.
- AbfrageZahl = 5
- Abfrage[5]
AbfrageZahl und Abfrage hängen zusammen und bestimmen mit wievielen Messwerten des NTC gemittelt wird. Je höher der Wert, desto weniger sprunghaft ist der Temperaturwert, allerdings dauert die Erfassung auch länger.
Dier Code startet mit der
Temberaturberechnung()
Hier wird als erstes der NTC so oft ausgelesen und dessen Werte gespeichert wie mit
AbfrageZahl und
Abfrage festelegt ist.
Als nächstes werden die Werte zusammengezählt und durch
AbfrageZahl geteilt um den
Durchschnitt zu bilden.
Jetzt wird der Durchschnitt in einen Wiederstandswert umgerechnet. Ist das erledigt, wird die Temperatur mittels der
Steinhart Formel berechnet.
Die Berechnete temperatur wird nun in °C im Seriellen Monitor ausgegeben.
Weier im loop geht es mit dem festlegen des PWM Wertes von
FanSpeed. Dieser wird mittels des
map Befehls linear auf den temperaturbereich verteilt.
Wenn der PWM Wert unter den Wert von FanMin (60) fällt, was in diesem fall ca. 30°C sind, schaltet der Lüfter ab und setzt die Variable
FanOut auf 1. Das mache ich, um zu registrieren, dass der Lüfter ausgegangen ist. Würde man den Lüfter bei 30°C einfach wieder anspringen lassen, könnte es passieren, dass der Lüfter ständig an und aus geht, wenn die Temperatur um 30°C pendelt. Da soetwas störend ist, Farge ich FanOut ab. Wenn
FanOut = 1 ist weiß der arduino, dass der Lüfter aus ist und ich sage ihm er soll aus bleiben, solange
FanOut auf 1 steht.
Wenn die Temperatur jetzt auf 32 °C steigt, setze ich
FanOut wieder auf 0 zurück. Jetzt kann der Lüfter wieder anlaufen. Auf diesem Weg haben wir eine Einschaltdifferenz von ca. 2°C eingebaut. Der Lüfter schaltet bei 30°C ab und erst bei 32°C wieder an.
Ausserdem lasse ich den Lüfter kurz mit 100% PWM Wert anlaufen um das Anlaufmomend des Lüfters zu überwinden.
Zu guterletzt wird noch
FanSpeed am Seriellen Monitor, und dann per analogWrite an den Lüfter ausgegeben.
Hier ist eine neuere Version des Codes , da in der alten ein Fehler war.
________________________________________________________________________
3.3 - Lüftergeschwindigkeit per Drehpoti einstellen
Hier zeige ich euch, wie man den Lüfter mit einem 10kO Drehpoti steuern kann. Das funktioniert genauso wie die günstigen Lüftersteuerungen, allerdings realisieren wir es über den Microkontroller und nicht über einen IC.
Anschlussplan
CODE
/*
Arduino Tutorial 3.3 - Lüftergeschwindigkeit per Drehpoti einstellen
by Scynd 2014
In diesem Tutorial geht es darum, die Lüftergeschwindigkeit mit Hilfe eines Drehpotenzometers einzustellen.
*/
//Konstante Variablen
const int FanPin = 9; // Lüfter an Pin 9 angeschlossen
const int PotiPin = A0 ; // Potenzometer am analogen Eingang Pin 0 angeschlossen
// Variablen
int FanSpeed = 0; // Variable für die Lüftergeschwindigkeit
int PotiVar = 0 ; // Variable zum speichern des Potentiometereingangs
void setup() {
TCCR1B = TCCR1B & 0b11111000 | 0x01; // Setzt Timer1 (Pin 9 und 10) auf 31000Hz
Serial.begin(9600);
pinMode(FanPin, OUTPUT) ; //Setzt den Lüfter Pin als Ausgang
pinMode(PotiPin, INPUT) ; //Setzt den LEDPin als Ausgang
}
void loop() {
PotiVar = analogRead(PotiPin) ; // Liest das Potentiometer aus
FanSpeed = map(PotiVar, 51, 1023, 60, 255); // Verteilt den PWM Wert über den Messbereich des Potis
// Unterer Potenziometerbereichs (0-50) = Lüfter aus
if(PotiVar < 50) {
FanSpeed = 0;
}
Serial.println(FanSpeed); // Gibt die Variable im Seriellen Monitor aus
analogWrite(FanPin, FanSpeed); // Gibt die Variable mit PWM aus
}
Am Anfang des
Loops, lesen wir das Potentiometer am
PotiPin aus und speicher den Wert, der sich zwischen 0 - 1023 bewegt in der Variable
PotiVar ab.
Jetzt verteilen wir per
map Befehl über den Bereich des Potentiometer von 51 - 1023 den PWM Wert von 60 - 255 und speichern den PWM Wert dann in der Variable
FanSpeed.
Um den Lüfter auch abschalten zu können, lege ich im Bereich des Potis von 0 - 50 einen PWM Wert von 0 fest.
Zum Schluss lassen wir uns den PWM Wert zu Kontrolle noch am Seriellen Monitor ausgeben und geben den Wert dann per
analogWrite an den Lüfter aus.
Hier noch der Download der Arduino Sketche. Viel Spaß beim Nachbauen
Arduino Tutorial 3 - Lüfter steuern.zip