Ein Quantisierer mit Hysterese für meinen LoRaWAN Bodenfeuchtesensor

Wie in diesem Artikel vorgestellt, habe ich einen LoRaWAN Sensor entwickelt, der mich über kritische Bodenfeuchtigkeit z.B. einer Zimmerpflanze benachrichtigt. Auf ein Modul meines selbst entwickelten Backends zur Auswertung will ich in diesem Beitrag näher eingehen: Den Quantisierer mit Hysterese.

Damit das Plantmonitor-Backend bei kritischen Bodenzuständen (zu wenig Feuchtigkeit, zu viel Feuchtigkeit) Alarm schlagen kann, müssen die Sensordaten korrekt eingeordnet werden. Dazu nutze ich einen Quantisierer, der Messwerte anhand einer vorher festgelegten Konfiguration in unterschiedliche “Level” bzw. Zustände einteilt. So werden Feuchtigkeitswerte von 0-64 beispielsweise dem Zustand “low” zugeordnet. Höhere Werte zwischen 65 und 92 sorgen hingegen für den Zustand “normal”.

Das funktioniert soweit - doch in der Praxis kann so ein einfacher Quantisierer schnell für Frust sorgen. Denn nicht alle Sensoren liefern streng monoton verlaufende Wertereihen bzw. kurzfristig aussagekräftige Daten - so auch mein kapazitiver Feuchtigkeitssensor. In so einem Fall kann eine Hysterese Abhilfe schaffen.

Wozu eine Hysterese?

Eine Hysterese sorgt dafür, dass für einen ansteigenden Wert ein anderer Schwellwert für den Übertritt in einen anderen Zustand gilt, als für einen sinkenden. Veranschaulichen lässt sich das am besten an einem Beispiel:

Beispielgrafik: Zustandsübergänge ohne Hysterese

Hier ist ein einfacher Quantisierer ohne Hysterese zu sehen. Für alle Werte kann einer der Zustände “low”, “normal” oder “high” zugeordnet werden. Befindet man sich mit dem Sensorwert nahe eines Zustandsübergangs, kann es durch leichte Veränderungen des Sensorwerts zum “flapping” kommen. Liegt der aktuelle Sensorwert bei 65, würde ein weiteres Absinken der Feuchtigkeit auf 64 einen Zustandswechsel auf “low” bedeuten. Meldet der Sensor bei der nächsten Messung durch seine leichte Toleranz wieder eine 65, würde erneut ein Zugangswechsel registriert und eine weitere Benachrichtigung gesendet. Durch die Austrocknung der Erde wird der Sensor im Laufe der Zeit erneut einen Zustandswechsel richtung “low” auslösen - erneut würde eine Benachrichtigung gesendet.

Dieses störende Verhalten lässt sich durch eine Hysterese in gewissem Rahmen eliminieren. Kennt man die Fehlertoleranz des Sensors in etwa und wählt die Übergangsbereiche der Hysterese groß genug, sind Zustandsübergänge “robuster” und tendieren weniger dazu, zu “wackeln”.

Beispielgrafik: Hysterese Schema

Hier wird der Zustandsübergang durch aufsteigende (rot) und absteigende (grün) Sensorwerte veranschaulicht: Während der Schwellwert zum nächsthöheren Zustand nach oben verschoben wird, wird der Schwellwert für einen Wechsel zu einem niedrigeren Zustand nach unten bewegt. Die Zustandsübergänge werden “sticky”. Erst, wenn ein Sensorwert in verlässlichen Wertebereichen eines Zustands liegt, wird ein erneuter Zustandswechsel ermöglicht. Bis es soweit ist, wird der alte Zustand beibehalten - auch, wenn rein rechnerisch bereits der nächstgelegene Zustand erreicht wurde.

Im Beispiel von oben würde also ein Absinken des Sensorwertes von 65 auf 64 noch keinen Zustandswechsel bedeuten. Erst bei einem Wert unter 63 würde ein Zustandswechsel auf “low” ausgelöst werden. Steigt der Wert durch Messtoleranzen erneut auf 65, bedeuten kleine Steigerungen ebenso noch keinen Zustandswechsel: Erst, wenn der Wert 66 übertroffen ist, wird der Wechsel auf den Zustand “normal” vollzogen. Für aufsteigende und absteigende Werte gelten also unterschiedliche Schwellwerte - je nach Richtung.

Implementierung der Hysterese

Für eine einfache Implementierung einer solchen Hysterese genügt es, die Grafik von oben leicht verändert darzustellen und sich Folgendes bewusst zu machen:

Grafik: Vereinfachung Hysterese

  • Die Wertebereiche der Zustände überlappen an den Schnittstellen
  • Wo es keine Überlappung gibt, kann ein eindeutiger Zustand zugeordnet werden.
  • Liegt ein Sensorwert in einem überlappenden Bereich (“ambivalence”), kommen prinzipiell zwei Zustände für eine Zustandszuordnung infrage. Hier gelten dann folgende Regeln:
    • Entspricht einer der Zustände dem vorherigen Zustand des Systems, soll das System in diesem Zustand verharren (=> “stickyness” der Hysterese)
    • Entspricht keiner der beiden Zustände dem vorherigen Zustand des Systems (beispielsweise durch eine sehr starke Wertänderung oder weil das System noch keine Historie hat und es keinen vorherigen Wert gibt), sollen die Überlappungen entfernt werden und eine Einstufung aufgrund eines herkömmlichen Modells ohne Hysterese stattfinden (siehe erste Grafik).

Diese Regeln lassen sich ohne viel Aufwand direkt in Code übertragen. Abschließende Unit-Tests sorgen in meinem Fall dafür, dass das korrekte Verhalten auch in Grenzbereichen und bei untypischen Wertentwicklungen sichergestellt ist.

Nutzen

Mithilfe meine Hysterese-Implementierung konnte ich die Zahl der unnützen Fehlalarme drastisch reduzieren, denn der von mir verwendete Sensor schwankt durchaus ein paar mal hin- und her, bevor ein Wert für eine Weile stabil bleibt. Wer will, kann sich die Implementierung im quantifier Modul meines Plantmonitors hier ansehen:

https://github.com/ThomasLeister/plantmonitor/tree/master/quantifier