Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
uc-welt:gscheiduino:11-hysterese [2016/01/06 17:55] Hannes Jochriemuc-welt:gscheiduino:11-hysterese [2024/02/06 09:43] (aktuell) – Externe Bearbeitung 127.0.0.1
Zeile 1: Zeile 1:
-[[uc-welt:gscheiduino:10-batterie|← Kapitel 10: Übungsaufgabe Batterietester]] | [[uc-welt:gscheiduino:00-uebersicht|↑ Übersicht]]  | [[uc-welt:gscheiduino:12| →]]+[[uc-welt:gscheiduino:10-batterie|← Kapitel 10: Übungsaufgabe Batterietester]] | [[uc-welt:gscheiduino:00-uebersicht|↑ Übersicht]]  | [[uc-welt:gscheiduino:12-daemmerungsschalter|Kapitel 12: Dämmerungsschalter →]]
  
-====== Hysterese ======+====== Kapitel 11: Hysterese ======
  
 ===== Was ist eine Hysterese ===== ===== Was ist eine Hysterese =====
Zeile 19: Zeile 19:
  
 Wir können erkennen, dass es zwei verschiedene Zustände für die Heizung gibt: Zwischen 18°C und 20°C kann das Thermostat ein- oder ausgeschaltet sein. Welcher Zustand gerade ausgegeben wird, ist abhängig von der Vorgeschichte, ob der Raum aufgeheizt wird oder abkühlt. Wir können erkennen, dass es zwei verschiedene Zustände für die Heizung gibt: Zwischen 18°C und 20°C kann das Thermostat ein- oder ausgeschaltet sein. Welcher Zustand gerade ausgegeben wird, ist abhängig von der Vorgeschichte, ob der Raum aufgeheizt wird oder abkühlt.
 +
 +===== Beispiel Schwellwertschalter =====
 +
 +Wir betrachten nun unser Beispiel vom [[uc-welt:gscheiduino:09-schwellwert|Schwellwertschalter]].
 +
 +Wir laden den Code auf den Controller und drehen das Poti an die Stelle, an der die grüne LED aus- und die rote LED angeht.
 +
 +Wenn wir nun ein wenig rumspielen, erhalten wir einen Zustand, an dem beide LEDs leuchten. Das liegt daran, dass wir keine Hysterese im Code haben und wir genau an der Schwelle vom eingestellten Analogwert sind.
 +
 +Angenommen wir überwachen mit diesem Schwellwertschalter eine Spannung und geben einen Alarm aus, wenn die Spannung zu hoch ist: Was passiert an der Schaltschwelle?
 +
 +Richtig! Der Alarm würde dauern ein- und ausgehen was definitiv kein gewünschtes Ergebnis ist.
 +
 +Wir müssen also eine Hysterese in unseren Code einbauen.
 +
 +Was wir dafür extra benötigen haben wir oben gelernt:
 +
 +  * Eine Variable die sich merkt, ob der Wert sinkt oder steigt
 +  * Eine Hysterese
 +
 +Bevor wir aber den Code anpacken lernen wir noch eine wichtige Funktion:
 +
 +===== Logische Verknüpfungen =====
 +
 +In den Kapiteln zuvor haben wir gelernt, wie wir anhand einer if-Abfrage entscheiden können, welche Codeteile ausgeführt werden und welche nicht. Diese Abfrage sieht vereinfacht so aus:
 +
 +<code c>
 +if(BEDINGUNG)
 +{
 +  #CODE#
 +}
 +</code>
 +
 +Das hat uns in den bisherigen Beispielen schon viel gebracht, was passiert jetzt aber, wenn wir zwei Bedingungen abfragen möchten? Angenommen BEDINGUNG1 und BEDINGUNG2 sollen zutreffen um Code auszuführen. Das können wir so lösen:
 +
 +<code c>
 +if(BEDINGUNG1)
 +{
 +  if(BEDINGUNG2)
 +  {
 +    #CODE#
 +  }
 +}
 +</code>
 +
 +Ja, das funktioniert, ist aber nicht sonderlich elegant. Um das Ganze besser zu lösen gibt es praktischerweise die so genannten **logischen Verknüpfungen**.
 +
 +Für uns sind vorerst folgende zwei wichtig:
 +
 +^ Logische Verknüpfung ^ Funktion ^
 +| && | Logisches UND |
 +| %%||%% | Logisches ODER |
 +
 +Diese Verknüpfungen machen also nichts anderes, als zwei Bedingungen zu vergleichen und entsprechend einen Wert auszugeben.
 +
 +Schnell Beispiele zum besseren Verständnis:
 +
 +^ Verknüpfung ^ Ergebnis ^
 +| false && false | false |
 +| false && true  | false |
 +| true && true   | true  |
 +| false %%||%% false | false |
 +| false %%||%% true  | true  |
 +| true  %%||%% true  | true  |
 +
 +Unser Codebeispiel von oben können wir also so lösen:
 +
 +<code c>
 +if(BEDINGUNG1 && BEDINGUNG2)
 +{
 +  #CODE#
 +}
 +</code>
 +
 +Diese Verknüpfung dürfen wir gleich für unser Hysteresbeispiel verwenden:
 +
 +===== Hysterese in Software =====
 +
 +Wie oben beschrieben benötigen wir zwei zusätzliche Werte:
 +
 +<code c>
 +int wert_steigt = 1;
 +#define HYSTERESE 20
 +#define SCHWELLWERT 613
 +</code>
 +
 +//wert_steigt// ist die Variable, die sich den Zustand des Systems merkt. Wir definieren sie hier mit 1, damit sie irgend eine Grundinitialisierung hat. Ist aber eigentlich egal, wir werden den Wert in der setup()-Routine definieren, indem wir abfragen, ob der Wandlerwert unter oder über der Schwelle liegt.
 +
 +//HYSTERESE// ist in diesem Fall ein Wert, den wir vom gewünschten Schwellwert abziehen oder addieren. Wir wollen eine Gesamthysterese von 0,2V erreichen, das heißt, der untere Schwellwert beträgt 2,9V, der obere 3,1V.
 +
 +Grafisch dargestellt sieht das so aus:
 +
 +{{:uc-welt:gscheiduino:011-schwellwerte.png?direct&500|Schwellwerte grafisch}}
 +
 +Zusätzlich definieren wir noch unseren Schwellwert, einfach weil es den Code schöner macht.
 +
 +<note tip>Wie wir auf diese Werte kommen wird [[uc-welt:gscheiduino:08-analoginputs#theorie|hier]] beschrieben.</note>
 +
 +Wer sich traut, darf jetzt gerne selber versuchen, den Code zu schreiben. Für alle anderen folgt hier die Lösung:
 +
 +<code c kapitel11_schwellwert_hysterse.ino>
 +#define LED_ROT 13
 +#define LED_GRUEN 11
 +#define ANALOGPIN A0
 +#define HYSTERESE 20
 +#define SCHWELLWERT 613
 + 
 +int wert_steigt = 1;
 +int messwert = 0;
 + 
 +void setup()
 +{
 +  pinMode(LED_ROT, OUTPUT);   // Pin auf Ausgang
 +  pinMode(LED_GRUEN, OUTPUT); // Pin auf Ausgang
 +  pinMode(ANALOGPIN, INPUT);  // Pin auf Eingang
 +  if(analogRead(ANALOGPIN)<SCHWELLWERT)
 +  {  // Der Wert ist im grünen Bereich, kann also steigen
 +    wert_steigt = 1;
 +    digitalWrite(LED_ROT, LOW);    // rote LED aus
 +    digitalWrite(LED_GRUEN, HIGH); // gruene LED an
 +  }
 +  else
 +  {  // Der Wert ist im roten Bereich, kann also fallen
 +    wert_steigt = 0;
 +    digitalWrite(LED_ROT, HIGH);  // rote LED an
 +    digitalWrite(LED_GRUEN, LOW); // gruene LED aus
 +  }
 +}
 + 
 +void loop()
 +{
 +  messwert = analogRead(ANALOGPIN);
 +  // Lieber mehr Klammern setzen als zu wenig, so ist die Reihenfolge sicher definiert:
 +  if((wert_steigt == 1) && (messwert > (SCHWELLWERT + HYSTERESE)))
 +  { // Wenn der Wert >SCHWELLWERT+HYSTERESE ist, wird folgender Code ausgeführt:
 +    digitalWrite(LED_ROT, HIGH);  // rote LED an
 +    digitalWrite(LED_GRUEN, LOW); // gruene LED aus
 +    wert_steigt = 0;
 +  }
 +  else if((wert_steigt == 0) && (messwert < (SCHWELLWERT - HYSTERESE))) 
 +  { // Ansonsten wird dieser Code hier ausgeführt:
 +    digitalWrite(LED_ROT, LOW);    // rote LED aus
 +    digitalWrite(LED_GRUEN, HIGH); // gruene LED an
 +    wert_steigt = 1;
 +  }
 +  else
 +  { // nichts tun
 +  }
 +}
 +</code>
 +
 +Wir fassen noch einmal zusammen was das Programm macht:
 +
 +  * In der setup()-Routine wird der Eingang ausgelesen um zu entscheiden, ob man unter oder ober der Schwelle ist
 +  * Entsprechend werden auch schon die LEDs ein- bzw. ausgeschaltet
 +  * In der loop()-Routine wird der Eingang ausgelesen und in eine Variable gespeichert
 +  * Abhängig von "unter" oder "über Schwelle" werden verschiedene Vergleichswerte verwendet
 +  * Dadurch entsteht eine Hysterese und es kann nicht zu zu schnell wechselnden Zuständen kommen
 +
 +Nach erfolgreichen Upload des Programms kann es sofort getestet werden:
 +
 +Wenn man nun das Poti langsam zum Schwellwert dreht, schaltet die LED um. Nun muss das Poti weiter als zuvor zurück gedreht werden, damit die LEDs wieder zurückschalten. Wie viel unterschied zwischen den zwei Umschaltpunkten ist, kann man mit #define HYSTERESE einstellen.
 +
 +Da wir uns jetzt schon sehr gut mit Analogeingängen und Hysteresen auskennen, kommt ein ganz klassisches Beispiel für beide Anwendungen:
 +
 +[[uc-welt:gscheiduino:12-daemmerungsschalter|Kapitel 12: Dämmerungsschalter]]