Digitale Filter in FHEM-Devices einbauen

Begonnen von crusader, 13 Februar 2016, 15:50:11

Vorheriges Thema - Nächstes Thema

crusader

Zur Filterung rauschender bzw. fluktuierender Messwerte gibt es in FHEM bereits diverse Möglichkeiten, wie z.B. event-aggregator , gleitender Mittelwert etc.

Eine andere Möglichkeit ist der Einsatz digitaler Filter.
Diese können entweder ohne (FIR) oder mit (IIR) Rückkopplung definiert werden.
Im Netz gibt es eine Vielzahl von Seiten, auf denen sich entsprechende Filter konstruieren bzw. abrufen lassen.

Zur Einbindung eines solchen Filters in beliebige FHEM-Devices habe ich beigefügtes Perl-Script geschrieben, welches wie folgt verwendet werden kann:

VORAUSSETZUNGEN:
Im Gegensatz zur Mittelwertbildung, bei der man eine Zeitgewichtung verwenden kann (s. event-aggregator->mean), sind IR-Filter nur sinnvoll einsetzbar, wenn die Messdaten zu äquidistanten Zeitpunkten vorliegen.
Das ist nicht bei allen Modulen der Fall (z.B. FBDECT). In diesem Fall müssen über geeignete Mechanismen äquidistante Events erzeugt werden und das Filter event-gesteuert eingesetzt werden.

In vielen Fällen (z.B. DS18B20/GPIO4,Revolt,I2C_BMP180 etc. ) liefern die Devices aber von sich aus äquidistante Messwertreihen. Das Filter kann dann über ein userreading direkt ins Device eingebunden werden.


VORGEHENSWEISE:

A.
Perl-Script in 99_MyUtils.pm kopieren und mit 'reload 99_MyUtils' neu laden.

B.
Für jedes zu filternde reading im jeweiligen Devicefolgende folgende user-Attribute (mit 'attr <device> userattr ...') anlegen:
<reading>.filter
<reading>.numerator
<reading>.denominator.

C.
Das Attribut <reading>.filter je nach gewünschtem Filtertyp mit 'FIR' oder 'IIR' beschreiben.

Die Filterkonstanten für Numerator und Denominator eintragen. Die Koeffizienten dabei durch ein Leerzeichen trennen.

Bei FIR-Filtern ist kein Denominator notwendig, falls er gesetzt ist, wird er ignoriert.

Bei IIR-Filtern muss der vollständige Koeffizienten-Term (beginnend mit einer 1) eingetragen werden.
Vorsicht:
Auf vielen Webseiten werden nicht normgerechte Vorzeichen für die Koeffizienten verwendet. Diese müssen u.U. negiert werden, damit das Filter korrekt funktioniert.
Korrekte Filter-Koeffizienten bekommt man z.B. von dieser Seite: http://engineerjs.com/?sidebar=docs/iir.html.

D.
Filter aktivieren z.B. mit 'attr <device> userReadings <userreading>:<trigger> { DigitalFilter($name,"<readingsname>") }'
Dabei muss gewährleistet sein, dass der Trigger bei jedem Reading-Update ausgelöst wird.
Also entweder das triggernde reading mit 'event-on-update' freischalten oder keine event-Bedingungen setzen.

E.
Zur Überprüfung der Funktion sollten Original-Messwerte und Filterwerte geloggt und dargestellt werden.

F.
Beim Ändern von Filterkoeffizienten ist es sinnvoll, das Filter durch Eingabe eines ungültigen Filtertyps zu stoppen und nach Eingabe der neuen Koeffizienten neu zu starten.
Auch beim Entfernen eines Filters sollte zunächst der Filtertyp ungültig gemacht werden und mindestens ein Aufruf der Filter-Routine abgewartet werden, damit der Puffer, der innerhalb des Devices angelegt wurde, wieder entfernt wird.

BEISPIEL:

1.
Binominal-Filterung der Messwerte eines DS18B20-Sensors (Modul:GPIO4):


attr DS18B20_1234 userattr temperature.filter temperature.numerator
attr DS18B20_1234 temperature.filter FIR
attr DS18B20_1234 temperature.numerator 1 2 1
attr DS18B20_1234 event-on-update-reading temperature
attr DS18B20_1234 pollingInterval 30
attr DS18B20_1234 userReadings filtered_temperature:temperature {DigitalFilter($name,"temperature")}



2.
Filterung der Messwerte eines BMP180-Sensors mit Butterworth-Filter 1.Ordnung (Modul:I2C_BMP180):


attr BMP180 userattr pressure.filter pressure.numerator pressure.denominator
attr BMP180 pressure.filter IIR
attr BMP180 pressure.numerator 0.1376 0.1376
attr BMP180 pressure.denominator 1 -0.7265
attr BMP180 event-on-update-reading pressure
attr BMP180 poll_interval 1
attr BMP180 userReadings filtered_pressure:pressure {DigitalFilter($name,"pressure")}



NÜTZLICHE WEBSEITEN:

Mittelwert-Filter:
https://de.wikipedia.org/wiki/Gleitender_Mittelwert
Binominal-Filter:
https://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwj4qsS29fTKAhXBRg8KHQOZBeQQFggfMAA&url=http%3A%2F%2Fpublic.beuth-hochschule.de%2F~marganit%2FBinomiale%2520digitale%2520Filter.pdf&usg=AFQjCNFPemZBlCu1zCQ7UXNh8zSQEUUIvg&bvm=bv.114195076,d.ZWU&cad=rja
FIR/IIR-Filterdesign:
http://engineerjs.com/?sidebar=docs/iir.html

Edit:
Neue Version: Bug bei Hochpassfiltern beseitigt

crusader

Anbei zwei Beispiele für den Einsatz des vorgestellten Digitalfilters.


Erstes Beispiel zeigt die Filterung eines DHT22-Sensors mit einem FIR-Filter (Binominal).
Gefiltert wird dabei nur sensorbedingtes 'Rauschen' des Ausgangssignals. Schwankungen der Meßgröße bleiben erhalten. Störungen werden nur gering bedämpft.

Um eine bessere Unterdrückung von kurzzeitigen Schwankungen zu erzielen, empfiehlt sich der Einsatz von IIR-Filtern. Beispiel 2 zeigt eine solche Filterung (Butterworth Tiefpass) angewendet auf das 'pressure'-Signal eines BMP180-Sensors.

Damit ist natürlich ein signifikante Signalverzögerung verbunden.


lemon

Hi crusader,
vielen Dank für den Beitrag und das Filter-Tool.
Läuft bei mir momentan als FIR-Filter zur Mittelung über ein paar Werte. Ist mir so lieber als die event-aggregation vom fhem.
Das Tools hat natürlich mehr Potential, was ich evtl. später auch mal brauchen werde :-)

Gruß,
lemon