ich habe folgendes Problem. Ich steuere zwei Lüfter zur Kühlung eines Serverschranks über PWM. Als Signalgeber habe ich einen NTC der mir gemeinsam mit einem Widertsand zum Nullabgleich die Temperatur liefert an A0.
Jetzt habe ich mich an einem Code Beispiel von einer Anleitung die ich im www gefunden habe entlang gehangelt.
Mein Problem ist das mein Regelbereich relativ klein ist. Ich möchte zwischen 30 und 45 grad die Lüfter Stückweise langsam hochdrehen lassen je nach Temperatur.
In dem Programm wird dies über folgendes Mapping gemacht
Wenn Du die Temperatur in Einer-Schritten mißt dann könnendie Lüfter auch nur in großen Schritten variieren.
Die Lüfter laufen unter einer gewissen Spannung/PWM nicht bzw nicht an. Das mußt Du auch bedenken.
Grüße Uwe
void temperaturberechnung()
{
// Nimmt N Abfragen in einer Reihe, mit einem kurzen delay
for (int i=0; i < abfrageZahl; i++)
{
abfrage[i] = analogRead(ntc);
delay(10);
}
// Mittelt alle Abfragen
durchschnitt = 0;
for (int i=0; i < abfrageZahl; i++)
{
durchschnitt += abfrage[i];
}
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
so kommt temp zustande @uwefed wie meinst du in einer schritten das könnte ein interessanter anzastz sein. Kannst du mir das kurz erklären wie ich das realisiere?
Satalaner: @uwefed wie meinst du in einer schritten das könnte ein interessanter anzastz sein. Kannst du mir das kurz erklären wie ich das realisiere?
Ich heiße zwar nicht Uwe, aber ich vermute, dass er auf den Datentyp der Variable temp anspielt. Wenn Du für den Bereich, den Du überblicken/messen möchtest, nur Ganzzahlwerte herausbekommst, kann map() kaum etwas Anderes machen als große Schritte.
Schaue Dir die Beispiele zur PID-Regelung an.
Damit (also mit einem Selbst-bau) läuft der Schieber meiner Öl-Heizung (und hält den Heizungsvorlauf auf Soll 55°).
Naja - fast
Da ich bei diesem sehr trägem System zu wenig Lebenszeit habe, um Das auszutesten, ist wohl P zu niedrig und I zu hoch gewählt - habe also wohl 6...8K Schwankungsbereich (also +/-4 Grad).
noiasca:
Das macht imho was, ist vollständig und kompiliert:
.
.
.
.
byte temp2pwm(float in, float tMin, float tMax)
{
if (in < tMin) return 0;
if (in > tMax) return 255;
byte pwm = 0;
pwm = in / (tMin - tMax) * 255.0;
return pwm;
}
Hallo,
Bitte um Entschuldigung für die Frage, falls ich den Wald vor lauter
Bäumen nicht sehe:
für tMin 20 und tMax 30 ergibt der Ausdruck in der Klammer (tMin - tMax) -10.
Ich bekomme beim Nachrechnen nicht die Werte wie angegeben.
Habe gerade keinen Arduino zum Probieren hier.
In welchem Bereich misst du temp? 28.0 und momentan 53.5 Grad (wollte Linear von 0-255 einen Bereich haben)
Was hast du als tMin und tMax eingetragen?
float tMin = 28.0; // Untere Grenze des
float tMax = 53.5; // Obere Grenze des Temperaturbereichs
Also mein Programm sieht folgendermaßen aus:
/*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.
*/
// 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 Widerstand 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
const int abfrageZahl = 50; // Je mehr abfragen, desto stabiler isr das Ergebnis, dauert aber länger
// Variablen
int fanSpeed = 0; // Variable für die Lüftergeschwindigkeit
int fanMin = 25; // 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
float tMin = 28.0; // Untere Grenze des Temperaturbereichs
float tMax = 53.5; // Obere Grenze des Temperaturbereichs
int abfrage[abfrageZahl]; // Array Variable für das Mitteln der Temperatur
float durchschnitt = 0; // Variable für das Mitteln der Temperatur
float temp; // Variable für die Berechnung der temperatur nach Steinhart
int index;
void setup()
{
TCCR1B = TCCR1B & 0b11111000 | 0x01; // Setzt Timer1 (Pin 9 und 10) auf 31300Hz
Serial.begin(9600); // Baudrate für die Ausgabe am Serial Monitor
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 >= 33)
{
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
// Ausgabe an den Seriellen Monitor
Serial.print("Temperatur ");
Serial.print(temp);
Serial.print(" *C ");
Serial.print("Lueftergeschwindigkeit: ");
Serial.print(fanSpeed);
Serial.print(" PWM");
Serial.println();
analogWrite(fanPin, fanSpeed); // Den Lüfter mit dem PWM Wert ansteuern
delay(1000);
}
void temperaturberechnung()
{
// Nimmt N Abfragen in einer Reihe, mit einem kurzen delay
for (int i=0; i < abfrageZahl; i++)
{
abfrage[i] = analogRead(ntc);
delay(10);
}
// Mittelt alle Abfragen
durchschnitt = 0;
for (int i=0; i < abfrageZahl; i++)
{
durchschnitt += abfrage[i];
}
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
//temp =temp*100;
delay(1000);
}
Ausgabe serieller Monitor: Temperatur 36.10 *C Lueftergeschwindigkeit: 81 PWM Temperatur 35.92 *C Lueftergeschwindigkeit: 71 PWM Temperatur 35.08 *C Lueftergeschwindigkeit: 71 PWM Temperatur 34.42 *C Lueftergeschwindigkeit: 61 PWM Temperatur 34.36 *C Lueftergeschwindigkeit: 61 PWM Temperatur 33.83 *C Lueftergeschwindigkeit: 51 PWM Temperatur 33.69 *C Lueftergeschwindigkeit: 51 PWM Temperatur 32.82 *C Lueftergeschwindigkeit: 40 PWM Temperatur 33.13 *C Lueftergeschwindigkeit: 51 PWM Temperatur 33.50 *C Lueftergeschwindigkeit: 51 PWM Temperatur 32.44 *C Lueftergeschwindigkeit: 40 PWM Temperatur 32.99 *C Lueftergeschwindigkeit: 40 PWM Temperatur 32.44 *C Lueftergeschwindigkeit: 40 PWM Temperatur 32.22 *C Lueftergeschwindigkeit: 40 PWM Temperatur 32.35 *C Lueftergeschwindigkeit: 40 PWM Temperatur 31.65 *C Lueftergeschwindigkeit: 30 PWM Temperatur 31.96 *C Lueftergeschwindigkeit: 30 PWM Temperatur 31.54 *C Lueftergeschwindigkeit: 30 PWM Temperatur 31.72 *C Lueftergeschwindigkeit: 30 PWM Temperatur 31.61 *C Lueftergeschwindigkeit: 30 PWM Temperatur 31.59 *C Lueftergeschwindigkeit: 30 PWM Temperatur 30.98 *C Lueftergeschwindigkeit: 0 PWM
Der Tipp mit float war echt super die Frage ist nur wie bekomme ich es hin das der PWM nicht in 10er schritten läuft sondern in 1er?
Und nochmal danke das ihr so schnell geantwortet habe echt Klasse Support
Zur Hilfe gekommen ist mir nur der eingeschränkte Zahlenraum vom byte pwm.
Ich wollte eigentlich die Differenz der beiden Grenzen ermitteln. Habs nun umgedreht.
Danke.
Jetzt bin ich durchgestiegen."byte pwm" wird durch das Ergebnis der Formel
mehrfach komplett überschrieben wenn der Wert z.B. 530,4 ist.
Eigentlich ein klassischer Overflow.
Habe das mal auf einem Uno laufenlassen...
Meine güte combie und ich frage mich warum du autamtisch voraussetzt das man deine Lösung nicht getestet hast und direkt ein solch kindlicher post "war wohl nicht wichtig genug" nötig ist.
Tut mir leid das ich nicht gleich aus "Warum tust du das?
Map ist bei den richtigen Eingangsdaten sehr gut für deine Zwecke geeignet."
ableiten konnte das hier der MAP Befehl, NICHT der Richtige ist aufgrund der Nachkommastellen die missachtet werden.
Ich musste mich da auch erstmal reindenken und wie du siehst habe ich die Grundsätzliche Formel des MAP Befehls auch genutzt!