Hi,
ich versuche gerade eine kleine Temperatursteuerung zu realisieren.
Soweit so gut. Also das Grundprinzip läuft. Im Arduino ist eine
Temperatur von 28°C voreingetellt (veränderbar)
1
intSetPoint=28;
Bis zu dieser Temperatur schaltet ein Relay, ist die Temperatur
erreicht, dann schaltet das Relay ab.
Nun ist es so, dass bei nur kleinen Veränderungen das Relay permanent
nacheinander in kürzester Zeit auf und zu geht.
Wie kann ich das nun im Code so anpassen, dass nur alle 5 Minuten
geprüft wird?
Ich habe da zwar eine Prüfung die nur alle Minuten durchgeführt wird,
allerdings wird jetzt bis zur nächsten Prüfung (5 Minuten)
1
constlonginterval=300000;
durchgeheizt... Also gerne dann mal eben auch auf weit über die
eingestellte Temperatur....
https://pastebin.com/nkHbhUCy
Maik schrieb:> Wie kann ich das nun im Code so anpassen, dass nur alle 5 Minuten> geprüft wird?
Du solltest lesen was ein PID Regler ist und wie man den mit autotune
auf einem uC umsetzt.
Ich weiss, ein sehr weiter Weg noch, aber er hilft, damit du nicht von
1 Sackgasse in die nächste läufst.
Das Stichwort ist "Hysterese". Du musst mit zwei Schwellen statt einer
arbeiten: Deine Einschalttemperatur muss etwas höher liegen als Deine
Ausschalttemperatur.
Maik schrieb:> schaltet ein Relay
Schreib doch einfach Relais, das versteht auch jeder und es hört sich
nicht so unkundig an.
> Wie kann ich das nun im Code so anpassen, dass nur alle 5 Minuten> geprüft wird?
Bastle nicht an Symptomen herum. Sondern behebe das Problem.
> Ich habe da zwar eine Prüfung die nur alle Minuten durchgeführt wird,> allerdings wird jetzt bis zur nächsten Prüfung (5 Minuten)const long> interval = 300000;> durchgeheizt...> Also gerne dann mal eben auch auf weit über die eingestellte Temperatur
Also Programmfehler. Dein Regler (egal ob Zweipunkt mit oder ohne
Hysterese oder auch PID) muss immer schneller abtasten als dein
Regelstrecke sich ändern kann. Sonst bist du halt einfach immer zu spät
dran.
> Nun ist es so, dass bei nur kleinen Veränderungen das Relay permanent> nacheinander in kürzester Zeit auf und zu geht.
Dann taste einfach dauernd ab und schalt das Relais bei 27°C ein und bei
29°C aus. Also so, dass du im Mittel deine gewünschten 28°C hast.
So hoch mit PID-Regler muß man es aber auch nicht aufhängen... ist ja
eigentlich eine Zweipunkt-Regelung.
Wenn ich den Code beim Überfliegen richtig verstanden habe, hast Du
ursprünglich in einer Schleife alle 100ms die aktuelle Temperatur
angezeigt, die Taster abgefragt und das Relais gesteuert.
Temperatur kommt von einem A/D-Wandler-Anschluß. Der Wert ist natürlich
wackelig. Und so war er alle 100ms mal zu hoch und mal zu niedrig.
Jetzt hast Du die Reaktion des Relais auf 5min verlangsamt, unter
Verwendung eines Timestamps oder wie auch immer man das nennt... finde
ich persönlich ok, hätte ich auch so gemacht.
Dazu aber noch meine Ideen:
1. Müssen es jetzt gleich 5min statt der 100ms sein? Ein Kompromiß bei
30s?
2. Nutze die schnelle Schleife, um den A/D-Wandlerwert zu mitteln. Dann
tanzt er weniger.
3. Bau eine Hysterese ein. Abschalten bei X + 0,2°C, wieder Einschalten
bei X - 0,2°C
4. Nutze die Zeit, die das delay(100) braucht, zum Mitteln des
A/D-Wandlerwertes.
Gruß
Tom.
TomH schrieb:> 3. Bau eine Hysterese ein. Abschalten bei X + 0,2°C, wieder Einschalten> bei X - 0,2°C
Ok, ja dass macht natürlich Sinn... Warum kommt man selber nicht auf
solche Gendanken.
Also Grob vereinfacht:
Wenn IST Temperatur kleiner SOLL Temperatur, dann schalte Relais ein.
Sonst, Wenn IST Temperatur größer als (Soll Temperatur +1 Grad), dann
schalte Relais aus.
Trifft beides nicht zu, warte 100ms und prüfe erneut
Maik schrieb:> Trifft beides nicht zu, warte 100ms und prüfe erneut
Warte N Sekunden und mittle währenddessen die gemessenen Temperaturwerte
- und prüfe dann erneut.
Statt (Soll Temperatur +1 Grad) würde ich (Soll Temperatur +X Grad)
schreiben, das X parametrisierbar machen.
N und X sind abhängig von deinem Aufbau.
Maik schrieb:> Wenn IST Temperatur kleiner SOLL Temperatur, dann schalte Relais ein.>> Sonst, Wenn IST Temperatur größer als (Soll Temperatur +1 Grad), dann> schalte Relais aus.
Dann dürfte deine Ist-Temperatur im Mittel 0.5K höher als deine
Soll-Temperatur sein.
Forist schrieb:> Maik schrieb:>> https://pastebin.com/nkHbhUCy>> Wichtige Regeln - erst lesen, dann posten!> ...> Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
Dann hat er doch alles richtig gemacht, oder?
Warum meckert hier der "Forist"?
Paul schrieb:> Dann hat er doch alles richtig gemacht, oder?
Den Unterschied zwischen Dateianhang und Link kennst du?
Mit Verfallsdatum des Links wird dieser Thread unbrauchbar - du
verstehen?
Forist schrieb:> Paul schrieb:>> Dann hat er doch alles richtig gemacht, oder?>> Den Unterschied zwischen Dateianhang und Link kennst du?> Mit Verfallsdatum des Links wird dieser Thread unbrauchbar - du> verstehen?
Das Hauptaugenmerk liegt bei "Längeren Sourcecode nicht im Text
einfügen", und genau das tat er. Lediglich du ziehst dich an dem Link
hoch...
Paul schrieb:> Das Hauptaugenmerk liegt bei "Längeren Sourcecode nicht im Text> einfügen", und genau das tat er.
Nein, da gibt es zwei "Hauptaugenmerker":
1. Posts kompakt halten (soweit hast du das richtig verstanden)
UND
2. die Dateien beim Post und hier auf dem Server speichern und eben
nicht auf einem morgen toten Link
> Lediglich du ziehst dich an dem Link hoch...
Nein, ich klicke auch nicht unnötigerweise auf Links, wo ich nicht weiß
was sich dahinter versteckt. Was wenn einer übermorgen die Domain kauft
und Blödsinn damit anstellt?
Maik schrieb:>> 3. Bau eine Hysterese ein.> Ok, ja dass macht natürlich Sinn...
Ja.
> Warum kommt man selber nicht auf solche Gendanken.
Weil Internet denkfaul macht.
Paul schrieb:> Warum meckert hier der "Forist"?
Weil er sonst nichts weiter beitragen kann.
Jester schrieb:> Warte N Sekunden und mittle währenddessen die gemessenen Temperaturwerte> - und prüfe dann erneut.
Genau, durch Mittelung mehrerer Meßwerte wird er den 1-Bit-Wackler der
A/D weitestgehend los. Ob der überhaupt relevant ist, hängt natürlich
von der Auflösung ab. Egal, wenn der Arduino sonst nichts zu tun hat,
tut eine Mittelwertbildung nicht weh.
> Statt (Soll Temperatur +1 Grad) würde ich (Soll Temperatur +X Grad)> schreiben, das X parametrisierbar machen.
"Warte N Sekunden" habe ich bei meiner Lötstation dynamisch gestaltet:
Ich habe einen Wert "Temperaturanstieg pro Zeit" ausgeguckt und heize
unterschiedlich lange, abhängig von der Differenz zwischen Ist und Soll.
Manfred schrieb:> delay(100); //Update at every 100mSeconds
Ich habe den Programmfehler gefunden!
Ich frage mich: warum um alles in der Welt verwendet man ein delay()
OBWOHL man die Zeiten ja soweiso mit millis() kontrolliert?
Und ich antworte mir: weil man wieder mal nicht so weit mitgedacht hat,
dass man versteht, was das eine und was das andere macht. Und vor allen
WIE es das macht.
Mein Ansatz wären jetzt ein paar Änderungen:
1
constlonginterval=100;// 100 ms
2
:
3
:
4
// double Temperature = ((5.0/1024.0) * analogRead(A0)) * 10;
5
intTemperature=(50*analogRead(A0))/1024;
6
:
7
:
8
if(Temperature>SetPoint)
9
{
10
:
11
:
12
Serial.print("Turn off heater \n");
13
}
14
15
// else
16
if(Temperature<SetPoint)
17
{
18
:
19
:
20
Serial.print("Turn on heater \n");
21
}
22
:
23
// delay(100); //Update at every 100mSeconds
Weil ich das Ganze nicht unnötigerweise mit einer Temperatur im
Fließkommaformat mache, muss ich auch keine explizite Hysterese
einbauen, weil ich die +-1°C Hysterese durch die Abfrage if-kleiner und
if-größer automatisch bekomme.
Dass die Berechnung des Temperaturwerts dazuhin noch Rechenzeit spart,
ist ein netter Nebeneffekt.
Ich habe vor Jahren mal einen PID Regler für eine Temperatursteuerung
implementiert.
Eine gute Beschreibung ist auf
https://rn-wissen.de/wiki/index.php/Regelungstechnik#PID-Regler
Und lässt man die Theorie mal weg, dann ist der Regler ein 3-Zeiler.
Man muss etwas spielen, das P I und D für seine Anwendung zu ermitteln,
und das wars.
Ich würde mit 2 Temperaturen arbeiten.
Min_temp + Max_temp.
Dann nur noch
if milli() > alt_milli + Laufzeit_in_milli then
Wert = Lese_temperatur
if wert < min_temp then heizung = an
if Wert > max_temp then Heizung = aus
alt_milli = milli()
end if
Dann spart man sich den ganzen Theater und muss nur 2 Variablen
eingeben.
Das ganze in einer Ewigkeitsschleife.
Bei Dauerbetrieb muss noch eine Überlauf_zeile eingefügt werden für
Milli()
Schlaumaier schrieb:> Bei Dauerbetrieb muss noch eine Überlauf_zeile eingefügt werden für> Milli()
Nein, bei korrekter Anwendung von milli() braucht man das nicht (wenn
man davon ausgeht, dass deine milli() Funktion in etwa das tut und
zurückgibt wie die Arduino millis() Funktion).
Und das hier ist eben einfach falsch und macht beim Überlauf Probleme:
1
ifmilli()>alt_milli+Laufzeit_in_millithen
Mit einer kleinen Umformung dieser Ungleichung geht es problemlos auch
beim Überlauf:
Lothar M. schrieb:> Weil ich das Ganze nicht unnötigerweise mit einer Temperatur im> Fließkommaformat mache, muss ich auch keine explizite Hysterese> einbauen, weil ich die durch die Abfrage if-kleiner und if-größer> automatisch bekomme.
statt dessen brauchst du dann zusätzliche Code für die Ausgaben von Soll
und Isttemperatur. Je nach dem wie geschickt du dich anstellst vieleicht
sogar Division und/oder ein Modulo.
Wenn man mit aller Gewalt etwas Speicher sparen will, würde ich das
special character eliminieren und das Grad Zeichen von Position 0xDF aus
dem LCD Character ROM nehmen.
Wobei bei all diesen "guten Ratschlägen" soll der Thread Owner
überlegen, was er mit den "gewonnen" Resourcen machen soll. Das Programm
muss ja eh fast nichts machen und ob da im loop 100ms für nichts
verbraten werden ist dann auch schon egal.
Lothar M. schrieb:> if milli() - alt_milli > Laufzeit_in_milli then> Einfach mal drüber nachgrübeln...
hihi hab ich sogar. Aber meine Lösung ist nit so Fein wie deine. ALSO
DANKE DAFÜR. !!!
Aber der Code ist aus den Bauch raus geschrieben .
Und er funktioniert bei einer Steuerung von mir ausgezeichnet die auch
mit IR-Befehlen arbeitet. Allerdings ist die nicht für Dauerbetrieb
gemacht, weshalb ich bei den Tippen des Code an meine Steuerung gedacht
habe.
Aber wie oben erwähnt wäre meine Code-Zeile ne extra Zeile und nicht so
fein wie deine.
Und JA ich dachte auch an Arduinos. Wobei ich denke das so eine einfache
Sache, mehr oder weniger auf allen anderen Systemen läuft.
Ich habe allerdings in den Code noch eine Key-Board-Abfrage und ein
Display-Anzeige drin.
Da kann ich die Variable Laufzeit_in_milli während der Laufzeit des
Codes ändern, und die Änderung in den kleinen Permanentspeicher des
Arduinos ablegen.
Wäre vielleicht für den TO auch ein Idee. Dann bracht er den Chip nicht
neu zu Flashen wenn er andere Zeiten braucht.
Sind nur ca. 20-30 Zeilen mehr .
ps. : ich hasse Delay und setze es nur ein wenn irgend ein Teil nicht in
die Hose kommt.
noiasca schrieb:> Das Programm muss ja eh fast nichts machen
Schon, aber man lernt an kleinen Projekten für große Projekte.
Und wenn man bei kleinen Projekten Murks lernt, dann beherrscht man den
bei großen Projekten ganz besonders gut.
Hallo,
so könnte ein Zweipunktregeler mit Hysterese aussehen.
values.abschalt = untere Schwelle
values.zuschalt = oberer Schwelle
values.batterie_spg -> deine Temperatur
hmm schrieb:> values.abschalt = untere Schwelle>> values.zuschalt = oberer Schwelle
Das war nicht unbedingt das glücklichste Händchen bei der Vergabe der
Variablennamen für eine Heizung...
Denn wenn die aktuelle Temperatur über der oberen Schwelle ist, dann
muss die Heizung nicht zugeschaltet sondern vielmehr abgeschaltet
werden.
Und genausowenig muss sie abgeschaltet, sondern zugeschaltet werden,
wenn die Temperatur unter der unteren Schwelle ist.
Abgesehen davon gibt es hier eben keine untere und keine obere Schwelle,
sondern nur eine Solltemperatur und eine Hysterese.
PittyJ schrieb:> für seine Anwendung zu ermitteln,> und das wars.
Blöd nur, wenn man zwar aktiv heizen, aber nicht kühlen kann. Dann
brauchts zwei Parameter-Sätze.
Ich musste eine 400V/4KW (quadratisch 40cm Kantenlänge) Herdplatte
befeuern und dort stehen 35Liter 'Destillat' im passend großen Topf
drauf. "Halten Sie die Temperatur auf 78°C". Da kommt man schon ins
Grübeln. schon die Zeiten für den Regler zu ermitteln, dauern "Tage",
weil das schon gefühlt ne Ewigkeit dauert, bis es dann mal warn ist.. ;)
die fertigen China-Regler, die man ja so als Einschub kaufen kann, sind
garnicht für solch lange Regelzeiten ausgelegt.
Aber wahrscheinlich hab ich mich /wir uns auch einfach nur zu doof
angestellt. Na jedenfalls: rein hardwaretechnisch ging das am Ende, aber
die Reglerparameter haben wir schlussendlich über den Haufen geworfen
und am Anfang einen fetten Überschwinger in Kauf genommen.
Was ich sagen wollte: Elektronik und Reglungstechnik sind zwei komplette
paar unterschiedliche Schuhe.
Viel Erfolg aber weiterhin, ich lese interessiert mit.
Lieben Gruß,
Äxl, DG1RTO
Schon klar, dass sollte nur ein Beispiel für ein Zweipunkt regeler mit
Hysterse sein. Den kann er ja leicht anpassen.
Bau gerade ein Tiefenentladeschutz für ne Batterie.
Gru0
Axel R. schrieb:> PittyJ schrieb:>> für seine Anwendung zu ermitteln,>> und das wars.>> Blöd nur, wenn man zwar aktiv heizen, aber nicht kühlen kann. Dann> brauchts zwei Parameter-Sätze.
Doch das geht. Für eine Anwendung habe ich ein Peltierelement benutzt.
Das kann kühlen oder heizen.
Je nach Vorzeichen im PID-Regler habe ich dann auf Heizen oder Kühlen
gestellt.
Lothar M. schrieb:> // double Temperature = ((5.0/1024.0) * analogRead(A0)) * 10;
Das hat den Vorteil, dass es wenigstens Funktioniert.
double Temperature = ((5.0*10/1024.0) * analogRead(A0));
Zudem ist er nicht (ganz) so teuer, wie es aussieht, da (5.0*10/1024.0)
zur Kompilezeit aufgelöst werden kann
Lothar M. schrieb:> int Temperature = (50*analogRead(A0))/1024;
Das führt hingegen (auf 8Bit AVR) schnurstracks ins Versagen
Etwas besser:
int Temperature = (50L*analogRead(A0))/1024;
EAF schrieb:> Lothar M. schrieb:>> int Temperature = (50*analogRead(A0))/1024;> Das führt hingegen (auf 8Bit AVR) schnurstracks ins Versagen
Ist alles eine Frage was der Sensor zurück-Liefert.
Und DAS steht im Datenblatt.