Arduino Zeitschaltung von werten.
-
const byte ledPins[7] = {A0, A1, A2, A3, A4, A5, A7}; ... pinMode (A0, OUTPUT);// für Anzeige Temperatursteuerung rot pinMode (A1, OUTPUT);// für Anzeige Temperatursteuerung gelb pinMode (A2, OUTPUT);// für Anzeige Temperatursteuerung grün pinMode (A3, OUTPUT);// für Anzeige Temperatursteuerung grün pinMode (A4, OUTPUT);// für Anzeige Temperatursteuerung grün pinMode (A5, OUTPUT);// für Anzeige Temperatursteuerung gelb pinMode (A6, OUTPUT);// für Anzeige Temperatursteuerung rot
Du hast da 1x A7 und 1x A6 als letzten Ausgang - Absicht oder Fehler?
Was Schalten mit Hysterese angeht:
static const int HYSTERESE = 2; // 2 = +- 1 Grad void HeizungRegeln(void) { int temp = TempSensorLesen(); int sollTemp = ...; int heizungEinSchwelle = sollTemp - HYSTERESE / 2; int heizungAusSchwelle = sollTemp + (HYSTERESE + 1) / 2; if (temp < heizungEinSchwelle) HeizungEinschalten(); if (temp > heizungAusSchwelle) HeizungAusschalten(); }
Was verschiedene Temperatur für Tag/Nacht angeht:
void HeizungRegeln(void) { // ... int sollTempTag = ...; int sollTempNacht = ...; int sollTemp = IstEsTag() ? sollTempTag : sollTempNacht; // ... }
Falls
hour()
die aktuelle Stunde zurückgibt kannst duIstEsTag
dann z.B. einfach so implementieren:bool IstEsTag(void) { int h = hour(); return h >= 8 && h < 20; // bzw. welche an/aus Zeiten du auch haben willst }
-
@Ben Wenn die Schaltzeiten nicht auf ganze Stunden fallen können, solltest du komplett in Minuten (oder Sekunden) seit Mitternacht rechnen
Das
delay(5000);
in der Loop solltest du vermeiden.
Da kannst du z.B. mitmillis()
arbeiten.unsigned long akt_millis, last_millis = 0; void loop() { akt_millis = millis(); if (akt_millis -last_millis >= 5000) { ZeitundDatumSchreiben(); Tempsteuerung(); Luftfeuchtigkeitsteuerung(); last_millis = akt_millis; } }
Die Regelung (du hast eine Regelung, keine Steuerung) sollte auch nur regeln und keine Ausgabe machen.
Die Ausgabe macht dann eine andere Funktion und kann auch seltener erfolgen.
-
@DirkB sagte in Arduino Zeitschaltung von werten.:
Das delay(5000); in der Loop solltest du vermeiden.
Hm. Wieso?
Geht's dir darum dass das Intervall nicht "5s + Ausführungsdauer der Regelfunktionen" sein sollte sondern möglichst genau 5s? Ich denke in diesem Fall wird das ziemlich egal sein, oder?Ist das so eine "best practice" in der Regeltechnik weil's halt viele (andere) Fälle gibt wo das
delay(5000)
problematisch wäre, umgekehrt aber kaum welche gibt wo die von dir gezeigte Variante problematisch wäre?
-
@hustbaer Arduino schreibt selber, dass man
delay()
vermeiden sollte.
https://www.arduino.cc/reference/de/language/functions/time/delay/Hier mag es jetzt keine Probleme geben, aber wenn die Ansprüche steigen, ist der Weg eine Sackgasse.
-
@DirkB
Naja, da stehtErfahrene Programmierer vermeiden normalerweise die Verwendung von delay() für das Timing von Ereignissen, die länger als 10 Millisekunden sind, es sei denn, der Arduino-Sketch ist sehr einfach.
Ich bin ein erfahrener Programmierer (nicht speziell mit Arduino, aber generell), und der Sketch (WTF?) ist sehr einfach
Ich finde auch dass die Empfehlung in der Art wie sie dort formuliert ist schlecht ist. Weil sie nicht wirklich beschreibt was das Problem ist/welches Problem man versucht damit zu lösen. Im Code des verlinkten Beispiels https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay gibt es IMO keinen nennenswerten Vorteil durch die Verwendung eines busy-loops.
In der Beschreibung steht schon worum es geht:
Sometimes you need to do two things at once. For example you might want to blink an LED while reading a button press.
Aber im Beispielcode sieht man das nicht. Und in der Doku zu
delay
steht es auch nicht. Und Empfehlungen etwas nicht zu tun ohne zu zeigen warum man es nicht tun soll, ist irgendwie doof.
-
Ich hätte jetzt außerdem erwartet, dass delay energieeffizient ist, während eine Loop, die ständig die Zeit abfragt, das sicherlich nicht ist. Ich weiß allerdings nicht, was es bei dieser Hardware alles zu beachten gilt.
-
@wob Auf den meisten Systemen ist es sicher energieeffizienter. Bei einem Arduino weiss ich nicht. Wüsste ich es, und wäre es so, dann hätte ich lauter protestiert
-
Hallo @all,
erstmal vielen lieben Dank für eure Hilfe. Ich werde nun versuchen auf euer Antworten einzugehen.@hustbaer
ja da hast du recht, mein Fehler. Da bin ich mit der 0 wohl durcheinander gekommen. DankeDeinen code werde ich erstmal so versuchen wie du ihn geschrieben hast. Vielen lieben Dank
Was ich nicht so recht verstehe ist hinten bei
int heizungEinSchwelle = sollTemp - HYSTERESE / 2; warum steht da bitte /2? Ich bezweifle nicht dass es so funktioniert, möchte nur auch verstehen was es da macht.Bei der Zeit bekomme ich über den Seriellen Monitor alles angezeigt, kann ich evtl. mit diesen Daten Arbeiten?
Ein Traum wäre alles über einen helligkeitssensor zu steuern, da ich aber bereits hier überfordert war, lass ich das lieber noch sein.
@DirkB
Das delay habe ich drin, da ich momentan alles über den seriellen Monitor konntrolliere und ich sonnst nicht mehr durchblicke bei den daten die er dann schreibt.Zu den Ausgabezeiten habe ich bis jetzt noch keinen blassen Schimmer. Ziel ist es die Daten über ein Nextion auszulesen und zu ändern. Da bin ich aber noch weit von entfernt.
Vielen Dank erstmal für euer echt freundliche Hilfe, das bekommt man leider eher selten so. Ich habe mir das alles sehr viel leiter vorgestellt, aber ich werde es schon irgendwie und mit netter Hilfe hinbekommen.
Danke euch nochmal und schönes Wochenende.
Grüße
Ben
-
@Ben sagte in Arduino Zeitschaltung von werten.:
warum steht da bitte /2?
Das steht bei der Definition der Hysterese:
static const int HYSTERESE = 2; // 2 = +- 1 Grad
Du kannst auch HYSTERESE auf 1 setzen und das /2 weg lassen. Definitionssache@Ben sagte in Arduino Zeitschaltung von werten.:
und ich sonnst nicht mehr durchblicke bei den daten die er dann schreibt.
Das Warten ist schon ok, nur das
delay()
ist da etwas unglücklich.
Für dieses kurze Programm und für eine Temperaturregelung spielt diese
(für einen Computer) lange Wartezeit keine Rolle.
-
@Ben sagte in Arduino Zeitschaltung von werten.:
int heizungEinSchwelle = sollTemp - HYSTERESE / 2; warum steht da bitte /2? Ich bezweifle nicht dass es so funktioniert, möchte nur auch verstehen was es da macht.
Naja... ich dachte mir bloss... ganze °C sind schon etwas grob. Wenn man die dann auch noch verdoppelt (x-HYSTERESE bis x-HYSTERESE), dann ist das noch gröber. Also wäre es wohl besser wenn ich die HYSTERESE so mache dass der Bereich insgesamt nur HYSTERESE+1 ist statt 2*HYSTERESE+1.
Und dann muss ich natürlich von der Mittleren Temperatur die halbe HYSTERESE abziehen bzw. die halbe HYSTERESE draufzählen. Und beim Halbieren einma auf- und einmal abrunden.Die einfachere Variante wäre natürlich zu sagen die eingestellte Temperatur ist das Maximum, und das Minimum ist eben Maximum-HYSTERESE.
Also
int sollTemp = ...; int heizungEinSchwelle = sollTemp - HYSTERESE; int heizungAusSchwelle = sollTemp;
Bei der Zeit bekomme ich über den Seriellen Monitor alles angezeigt, kann ich evtl. mit diesen Daten Arbeiten?
Da wird ja die selbe Funktion wie in meinem Beispiel verwendet. Also
hour()
.
Du kannst es natürlich auch in Minuten seit Mitternacht umrechnen wenn du es feiner haben willst.Also quasi
int MinutenSeitMitternacht() { return hour() * 60 + minute(); }
Blöd dabei ist bloss dass es passieren kann dass zwischen der Ausführung von
hour()
undminute()
die Stunde wechselt. Dann bekommst du einen falschen Wert zurück. Da ich mich mit der Plattform mit der du da arbeitest nicht auskenne, kann ich dir aber leider nicht sagen ob es einen einfachen Weg gibt das zu verhindern. (Also wenn dann müsste es eine Funktion geben die dir direkt die Tageszeit zurückgibt - nicht zwei verschiedene für Stunden und Minuten.)
-
@DirkB sagte in Arduino Zeitschaltung von werten.:
Das steht bei der Definition der Hysterese:
static const int HYSTERESE = 2; // 2 = +- 1 Grad
Du kannst auch HYSTERESE auf 1 setzen und das /2 weg lassen. DefinitionssacheGenau. Nur 3 kann er dann nicht machen
-
Guten Morgen,
ihr beiden seit SUPER, echt toll dass ich euch die zeit nehmt und auch alles gut erläutert.
Vielen Lieben Dank
-
@Ben
Bitte Das liegt nebenbei auch daran wie du die Frage hier gestellt hast. Also ein Beitrag mit- dem Code dabei den du schon hast
- einer Beschreibung was er aktuell tut
- einer Beschreibung was du anders haben möchtest
- klar formulierten Fragen
Und alles freundlich und nicht fordernd bzw. anmassend formuliert. Das hilft sehr freundliche und oft auch hilfreiche Antworten zu bekommen. Andere, speziell neue Forennutzer machen das z.T. sehr anders, und bekommen dann entsprechend auch sehr andere Antworten
Ich hätte noch mal ne doofe Frage...
Du hast in deinem Beitrag hier geschriebenBei der Temperatursteuerung habe ich festgestellt, wenn diese erreicht wird, fängt die Heizung an sich ständig an und aus zu schallten
Das impliziert dass du die Temperatursteuerung (Regelung) schon programmiert hast. Ich sehe in dem Code den du gepostet hast aber nix davon. Der scheint nur LEDs zu schalten. Oder ist die mittlere "LED" etwa ein Ausgang der die Heizung steuert?
-
Servus @hustbaer,
da ich alles noch auf einem Steckbrett habe und ich später die Heizung über 230V steuern muss ( werden Heizmatten und Lampen), muss ich ja nach meinem wissen mit optokoppler Relais arbeiten. Statt den Relays habe ich einfach die LED eingebaut um eine optische Rückmeldung zu bekommen. Nach dem anstöpseln gefällt es mir aber nun so gut, dass ich wohl auch eine LED Anzeige realisieren werde. Dann sehe ich auf einen Blick was gerade passiert. Das selbe kommt dann noch mit der Luftfeuchtigkeit.Im Aufbau habe ich es so:
LED Rot = zu warm = 2 Lüfter geht an
LED Gelb = noch ok = 1 Lüfter geht an
LED Grün = leicht erhöhte Temperater = keine Heizung, kein Lüfter
LED Grün = Alles im soll = Normale Tagbeleuchtung ohne Heizung und Lüfter
LED Grün = leicht zu niedrige Temperatur = 1 Wärmequelle geht an
LED Gelb = noch kälter als bei grün = 2. Wärmequelle geht mit an Lüfter ist gesperrt
LED Rot = zu kalt = Alle Wärmequellen gehen an und Lüfter sind gesperrtIch hoffe du kannst mir so folgen und ich habe keinen kollosalen Denkfehler mit drin.
Grüße
Ben
-
@Ben
Ja, ich kann dir folgen.
Du musst dann entweder auch die LEDs mit Hysterese schalten. Was aber bei einer reinen Visualisierung unüblich ist.Oder du musst die LEDs getrennt von der Heizung/den Lüftern steuern.
Dann brauchst du mehr Ausgänge. Und wenn du die Ausgänge in jedem Durchlauf schreiben willst wie in deinem Beispiel, dann musst du dir den aktuellen Zustand merken. Weil sonst das Schalten mit Hysterese eben nicht funktioniert.da ich alles noch auf einem Steckbrett habe und ich später die Heizung über 230V steuern muss ( werden Heizmatten und Lampen), muss ich ja nach meinem wissen mit optokoppler Relais arbeiten.
Ob du das musst weiss ich nicht. Galvanische Trennung wäre angesagt, ja. Aber die solltest du auch mit einem normalen Relais bekommen. Optokoppler ist da glaube nicht muss. Allerdings wirst du ein normales Relais vermutlich nicht mit dem Arduino schalten können. Die Dinger ziehen ja ordentlich Strom.
Gibt aber genügend Möglichkeiten. Optokoppler-Relais wie du schreibst oder Opto-Triac oder irgendsowas.Wobei ich dir da keine konkreten Tips geben kann. Da geht's um Strom und Heizung. Also Stromschlag und Haus abbrennen und so... das ist mir zu heikel, da hab ich zu wenig Plan von dem Thema
Also diesbezüglich hol dir lieber Rat oder besser sogar Hilfe (vor Ort) von jemandem der sich damit wirklich auskennt.
-
Hallo @hustbaer,
wollte euch gerade fragen ob ich da richtig liege dass dann so meine Steuerung nicht funktioniert. Also werde ich die Steuerung unterteilen in "Anzeige" und "Steuerung" dann müsste es ja klappen.Das Elektrische mache ich selber und lasse von einem Elektromeister drüberschauen. Bin auch am Überlegen Rauchmelder und eine temperaturabhängige Sicherung mit einzubauen, dass kommt aber erst später dran.
Vielen Dank für deine Rückmeldung
Grüße BenPS: Noch eine Frage, kann ich bei der Hysterese auch angeben z.B. +2 == -1?
-
@Ben sagte in Arduino Zeitschaltung von werten.:
PS: Noch eine Frage, kann ich bei der Hysterese auch angeben z.B. +2 == -1?
Hä? Versteh ich nicht
Aber egal was du damit meinst...
Das kannst du dir doch ganz einfach selbst durchdenken bzw. auch selbst aussuchen wie du es genau angeben/einstellen willst.Du brauchst einen Schwellwert für's Ein- und einen Schwellwert für's Ausschalten.
Du kannst beide Werte direkt angeben.
Oder du kannst die Temperatur dazwischen und ein Delta angeben und dann die eine Schwelle ausrechnen mitx = temp + delta
und die andere mity = temp - delta
.
Oder du kannst eine der beiden Temperaturen angeben (z.B. die höhere) und dazu die Breite des Bereichs. Und die 2. Temperatur rechnest du dann z.B. mity = x - width
.Im Endeffekt muss ein unterer Schwellwert rauskommen bei dessen Unterschreitung du die Heizung einschaltest und ein oberer Schwellwert bei dessen Überschreitung du die Heizung ausschaltest.
-
Stimmt, danke. Da hat wohl was ausgesetzt bei mir.
Schönes Wochenende noch
Grüße
Ben
-
So,
muss mich bei euch mal wieder melden.
@hustbaer : Dein Code mit der Hysterese funktioniert, leider verstehe ich ihn nicht wirklich. Daher habe ich mal was versucht was mir klar erschien. Hoffe es geht so auch.Schaut euch doch bitte mal Zeile an, dort steht alles drin.
Den nächsten Schritt den ich versuchen werde (hoffe ohne fremde Hilfe) verschiedene Heizungen (4Stk.) nach Temperaturunterschieden zu steuern. Mal sehen ob das klappt.int Tempsteuerung() { // Temperatursensoren lesen int Temperatur1 = Sensor1.readTemperature();//Temperatur Sensor1 auslesen int Temperatur2 = Sensor2.readTemperature();//Temperatur sensor2 auslesen int Durchschnitttemp = ( Temperatur1 + Temperatur2 ) / 2; // Durchscnittstemperatur berechnen // Solltemperatur ueber Potentiometer einstellen fuer Tag int einstellungtemptag = analogRead(15); //lesen des Potis mit der Solltemperatur für Tag int solltemptag = map(einstellungtemptag, 0, 1022, 10, 30); // festlegung des Regelbereiches der Temperatur Tag // Solltemperatur ueber Potentiometer einstellen fuer Nacht int einstellungtempnacht = analogRead(14); //lesen des Potis mit der Solltemperatur für Nacht int solltempnacht = map(einstellungtempnacht, 0, 1022, 10, 25); // festlegen des Reglerbereiches der Temperatur Nacht Serial.println(); // Zeilenumbruch Serial.print("Solltemperatur Tag: "); Serial.print(solltemptag); //diesen Wert möchte ich einstellen können und er soll sich zu einer bestimmten (einstellbaren Zeit) auf "solltempnacht" umstellen z.B. 20:00Uhr. Serial.println(" Grad Celsius"); //Einheit nach dem Wert Serial.print("Solltemperatur Nacht: "); Serial.print(solltempnacht); //diesen Wert möchte ich einstellen können und er soll sich zu einer bestimmten (einstellbaren Zeit) auf "solltemptag" umstellen z.B. 07:00Ihr. Serial.println(" Grad Celsius"); Serial.println(); // Zeilenumbruch Serial.print("Temperatur 1: "); //Text Sensor1 Serial.print(Temperatur1); //Sensor1 Wert Temperatur Serial.println(" Grad Celsius"); //Einheit nach dem Wert Serial.print("Temperatur 2: "); //Text für Sensor2 Serial.print(Temperatur2); //Sensor2 Wert Temperatur Serial.println(" Grad Celsius"); //Einheit nach dem Wert Serial.println(); // Zeilenumbruch Serial.print("Durchschnittstemperatur: "); //Text Durchschnittstemperatur Serial.print(Durchschnitttemp); // Schreiben des Wertes Serial.println(" Grad Celsius"); //Einheit nach dem Wert Serial.println(); // Zeilenumbruch if (Durchschnitttemp == solltemptag) leuchte(0); //startet Ausführung 0 aus dem Array else if (Durchschnitttemp == solltemptag - 1) leuchte(-1); //startet Ausführung 1 aus dem Array else if (Durchschnitttemp == solltemptag + 1) leuchte(1); //startet Ausführung 2 aus dem Array else if (Durchschnitttemp == solltemptag - 2) leuchte(-2); //startet Ausführung 3 aus dem Array else if (Durchschnitttemp == solltemptag + 2) leuchte(2); //startet Ausführung 4 aus dem Array else if (Durchschnitttemp <= solltemptag - 3) leuchte(-3); //startet Ausführung 5 aus dem Array else if (Durchschnitttemp >= solltemptag + 3) leuchte(3); //startet Ausführung 6 aus dem Array boolean Heizungon; boolean Heizungoff; { if (Durchschnitttemp < solltemptag-2) Heizungon = true; if (Durchschnitttemp > solltemptag+2) Heizungoff = true; if (Durchschnitttemp < solltemptag-2) Heizungoff = false; if (Durchschnitttemp > solltemptag+2) Heizungon =false; if (Heizungon) { digitalWrite(A10, HIGH); digitalWrite(A9, LOW); } if (Heizungoff) { digitalWrite(A10, LOW); digitalWrite(A9, HIGH); }}
Vielen Dank nochmal, die nächsten Fragen kommen bestimmt. Freue mich schon darauf.
Grüße
Ben
-
@Ben sagte in Arduino Zeitschaltung von werten.:
boolean Heizungon; boolean Heizungoff; { if (Durchschnitttemp < solltemptag-2) Heizungon = true; if (Durchschnitttemp > solltemptag+2) Heizungoff = true; if (Durchschnitttemp < solltemptag-2) Heizungoff = false; if (Durchschnitttemp > solltemptag+2) Heizungon =false; if (Heizungon) { digitalWrite(A10, HIGH); digitalWrite(A9, LOW); } if (Heizungoff) { digitalWrite(A10, LOW); digitalWrite(A9, HIGH); }}
Und bei
solltemptag -2 <= Durchschnitttemp && Durchnitttemp <= solltemptag + 2
? Da sind dannHeitzungon
undHeizungoff
undefiniert. Bumm.
Heizungoff
ist doch auch einfach nur!Heizungon
!?
Was istboolean
?