[patch] I2C_TSL2561 mit IODev

Begonnen von jensb, 21 März 2015, 21:23:31

Vorheriges Thema - Nächstes Thema

jensb

      Hallo,

      das Modul I2C_TSL2561 hat bisher noch keine Unterstützung für IODev. Da HiPi auf meinem RPi 2 nicht läuft, habe ich mir die Änderungen von klausw am Modul I2C_BMP180 angesehen und analog für das Modul I2C_TSL2561 umgesetzt.

      Bei der Gelegenheit habe ich noch folgende Funktionserweiterungen durchgeführt:


      • I2C-Fehlererkennung beim Lesen und Schreiben mit Hotplug-Support (derzeit nur für den IODev Modus nutzbar)
      • alternative Lux-Berechnung mit Floatingpoint-Arithmetik statt Integer-Approximation für besser Auflösung bei IR-Anteil unter 50% und unter 10 lux
      • Unterdrückung der Aktualisierung der Readings 'luminosity', 'broadband' und 'ir' im Zustand 'I2C Error' und 'Saturated', damit am Reading der Zeitstempel des letzten gültigen Werts stehen bleibt
      • Skalierung der Readings 'broadband' und 'ir' mit dem gleichen Faktor wie in der Lux-Berechnung, damit man sie "sprungfrei" z.B. in einem Plot verwenden kann
      • Fix für Invertierung von Attribut 'autoGain' in sub I2C_TSL2561_GetLuminosity
      • Fix für fehlende Rückschaltung des Reading 'state' aus den Zuständen 'Saturated' und 'Error' in den Zustand 'Initialized'

      Im Quellcode werden unterschiedliche Einrückvarianten (Tab und 2 und 4 Spaces) verwendet. Habe versucht, dies etwas zu vereinheitlichen. U.a. dadurch ist der Diff etwas umfangreicher als die Nettoänderungen.

      Da wie gesagt HiPi bei mir nicht läuft, konnte ich leider nicht testen, ob der aus I2C_BMP180 übernommene Code auch mit HiPi noch funktioniert. Insbesonder die Prüfung

sub I2C_TSL2561_Define($$)
...
if ($main::init_done || $hash->{HiPi_used}) { ... }


      habe ich nicht übernommen, da dies im IODev Modus bei reload, rereadcfg und shutdown restart mehr geschadet als genutzt hat. Möglicherweise wird dies aber im HiPi Modus benötigt. Daher habe ich die Bitte, dass jemand mit einem TSL2561 und HiPi den Patch ausprobiert, so dass eventuelle Fehler aufgedeckt werden können. Außerdem könnte man möglicherweise auch für den HiPi Modus die I2C Fehlererkennung in den subs I2C_TSL2561_i2cread und I2C_TSL2561_i2cwrite durch Auswertung des Rückgabewerts oder der Exception nachrüsten. Die vorhandene Modul-Dokumentation zu HiPi habe ich durch die Variante aus I2C_BMP180 ersetzt. Welche der beiden Varianten die bessere Beschreibung ist, kann ich nicht beurteilen.

      Dies ist mein erster Beitrag zu FHEM. Daher bitte ich um Verständnis, falls ich etwas Grundsätzliches übersehen habe.

      Hoffe, dass der Patch für eine eventuelle Aufnahme in FHEM interessant ist.

      Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

locutus

Hallo Jens,

von deiner Arbeit werden sehr viele Besitzer meines Add-On Boards profitieren. Dafür schon mal vielen Dank!
Ich teste das Modul (ohne HiPi) seit heute Morgen auf dem Banana Pro. Gleich als erstes sind mir die Nachkommastellen aufgefallen. Dazu habe ich eine Frage: ist es möglich die Dezimalstellen zu reduzieren? Ein entsprechendes roundDecimal Attribut, wie beim I2C_BMP180 könnte nützlich sein.

jensb

#2
Hallo locutus,

danke für die Rückmeldung.

Die Nachkommastellen gab es mit der Integer-Approximation vorher nicht. Die könnte man natürlich innerhalb des Moduls reduzieren, z.B. so wie du vorgeschlagen hast. Das Hauptproblem ist der sehr große Wertebereich bei der Beleuchtungsmessung von über 5 Zehnerpotenzen. Nur bei Lux-Werten unter 10 ist die Nachkommastelle überhaupt von Interesse.

Momentan löse ich das so:


attr stateFormat { if (ReadingsVal($name, "state", "") eq 'Initialized')  { sprintf("%.1f lux", ReadingsVal($name, "luminosity", 0)); } else { ReadingsVal($name, "state", ""); } }


und


attr userReadings logLine:luminosity { sprintf("Ev: %.1f", ReadingsVal("Sonne", "luminosity", 0)).sprintf(" IR: %d", ReadingsVal("Sonne", "ir", 0)).sprintf(" BB: %d", ReadingsVal("Sonne", "broadband", 0)); }


Bei ir und broadband sollte man nach dem Skalieren generell auf Ganzzahl runden. Das werde ich so einbauen. Bitte gib mir Rückmeldung, ob du für die luminosity ein Rundung wirklich brauchst bzw. was du von dem stateFormat-Ansatz hältst.

Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

jensb

Hallo locutus,

habe mir das mit den Nachkommastellen noch einmal durch den Kopf gehen lassen. In Anbetracht der Messgenauigkeit des Sensors könnte man generell auf 3 signifikante Stellen runden. Damit wäre der kleinste Messwert 0,01 lux (eigentlich schon kleiner als sinnvoll), ab 100 lux wäre der Wert ganzzahlig, ab 1000 wären die Einer Null, usw. Dadurch würde auch das Messwertrauschen leicht reduziert und entsprechend eine eventuelle on-change Weiterverarbeitung etwas ruhiger (und man braucht nichts zu konfigurieren).

Jens.
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

jensb

Habe die Nachkommastellen bei 'broadband' und 'ir' ausgeblendet und mit dem Sonnenuntergang vom 22.03. auch die Nachkommastellen des Lux-Wertes optimiert. Es gibt jetzt unter 100 lux genau eine und über 100 lux keine Nachkommastelle und es wird auf 3 signifikante Stellen gerundet. Alles unter 0,1 lux mach selbst bei 402 Millisekunden Integrationszeit keinen Sinn. Der TSL2561 kennt auch einen manuellen Timingmodus. Damit könnte man versuchen, auf stabile 0,01 lux zu kommen. Wer es braucht kann sich melden.
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

kaihs

Hallo Jens,

auch von mir erstmal vielen Dank, dass du die Umstellung gemacht hast.

Ich habe zwar selbst schon eine komplette Neuentwicklung angefangen die bei mir auch funktioniert, aber ich habe sie nie so weit gebracht, dass sie auslieferungsfähig wäre.

Daher würde ich jetzt erstmal deine Version übernehmen wenn du damit einverstanden bist.

Das Modul hat aber als 'Geburtsfehler' immer noch das Problem, dass bis zu 400ms geschlafen wird während der Sensor wandelt. Während der Zeit ist fhem blockiert was nicht gut ist.
In meiner neuen Version habe ich das schon auf eine asynchrone Verarbeitung mittels Timer umgestellt.

Magst du dich daran auch noch versuchen?
Falls nicht würde ich deine jetzige Version erstmal einchecken und dann meinen neuen Code portieren.

Gruß,

Kai

Banana Pi, Add-On Board mit 1.8" TFT LCD und IR-Sender, CULFW V1.61, div. Homematic Komponenten, Pollin Funksteckdosen, Selbstbau CUL433 MHz, Jeelink Clone, EC3000
Selbstbau CUL868MHz für Wireless M-Bus, SIGNALduino mit Logilink Temp.-sensoren und Auriol Wetterstation

jensb

Hallo Kai,

selbstverständlich kannst Du die Version übernehmen und ggf. einchecken. Es fehlt allerdings nach wie vor ein HiPi-Test.

Die Blockierung von FHEM ist mir erst heute selbst bewusst geworden, als ich das 433 MHz Software-Radio-Projekt rtl_433 in ein FHEM-Modul integrieren wollte. Die Lösung war hier ein Thread, da rtl_433 dauerhaft viel Rechenzeit benötigt. Beim TSL2561 dürft es mit einem Timer leichter sein.

Wenn du nichts dagegen hast, werde ich es mit dem Timer versuchen.

Gruß,

Jens

FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

kaihs

Hallo Jens,

den HiPI Test kann ich machen, ich habe noch einen RPi auf dem das läuft.
Banana Pi, Add-On Board mit 1.8" TFT LCD und IR-Sender, CULFW V1.61, div. Homematic Komponenten, Pollin Funksteckdosen, Selbstbau CUL433 MHz, Jeelink Clone, EC3000
Selbstbau CUL868MHz für Wireless M-Bus, SIGNALduino mit Logilink Temp.-sensoren und Auriol Wetterstation

kaihs

Sieht gut aus, funktioniert auch mit HiPI.

Lässt sich auch nachträglich auf RPII2C umstellen in dem IODev gesetzt und das Devicefile aus der Definition des Moduls entfernt wird.
Sehr schön.

Ich habe deine letzte Version jetzt eingecheckt.
Banana Pi, Add-On Board mit 1.8" TFT LCD und IR-Sender, CULFW V1.61, div. Homematic Komponenten, Pollin Funksteckdosen, Selbstbau CUL433 MHz, Jeelink Clone, EC3000
Selbstbau CUL868MHz für Wireless M-Bus, SIGNALduino mit Logilink Temp.-sensoren und Auriol Wetterstation

jensb

Hallo Kai,

danke für die schnelle Rückmeldung. Es freut mich, dass es sofort auch mit HiPi läuft.

Habe mir das mit dem Timer mal angesehen. Die I2C-Abfrage aus _Get nach _Poll zu verschieben dürfte nichts bringen, denn FHEM hängt dann weiter bei der Abarbeitung des InternalTimer.

Mein Vorschlag ohne Threads besteht darin, beim 1. Poll die Messung anzustoßen und bei einem 2. Poll 1 Sekunde später das Ergebnis einzusammeln.

Jens
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

kaihs

Ja, dass muss asynchron passieren.

Schau dir mal meine Version aus dem Post oben an.

Da starte ich im Get einen Timer entsprechend der Sensorwandelzeit und im Callback I2C_TSL2561_ADCReady wird das Ergebnis dann abgeholt.
Vielleicht ist das ein Ansatz den du übernehmen kannst.

Ich halte es eigentlich auch für sinnvoll ein explizites Get Kommando im Device zu haben, um unabhängig vom Pollintervall eine Wandlung anstossen zu können.

Das musst du aber nicht alles machen, da kann ich dann auch mal wieder Zeit investieren.
Banana Pi, Add-On Board mit 1.8" TFT LCD und IR-Sender, CULFW V1.61, div. Homematic Komponenten, Pollin Funksteckdosen, Selbstbau CUL433 MHz, Jeelink Clone, EC3000
Selbstbau CUL868MHz für Wireless M-Bus, SIGNALduino mit Logilink Temp.-sensoren und Auriol Wetterstation

jensb

Das zweistufige Pollen funktioniert nur bei autoGain=0. Die Regelschleife für autoGain=1 braucht aber eine synchrone Antwort vom TSL2561 - also muss die ganze Regelschleife asynchron werden. Dafür braucht man aber Threads (SONOS, OWX_ASYNC) oder gibt es einen asynchronen Timer in FHEM?

FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

kaihs

Da haben sich unsere Posts überschnitten.

Lehne ich mich zu weit aus dem Fenster wenn ich behaupte, dass die Timer in Form von InternalTimer immer asynchron sind? So habe ich es zumindest verstanden.
Banana Pi, Add-On Board mit 1.8" TFT LCD und IR-Sender, CULFW V1.61, div. Homematic Komponenten, Pollin Funksteckdosen, Selbstbau CUL433 MHz, Jeelink Clone, EC3000
Selbstbau CUL868MHz für Wireless M-Bus, SIGNALduino mit Logilink Temp.-sensoren und Auriol Wetterstation

jensb

Ich habe zwar schon ein paar mal in fhem.pl nachgesehen, wie der Kern arbeitet, aber ich möchte nicht behauten, dass ich alle Möglichkeiten verstanden haben.

Meiner Ansicht nach arbeitet HandleTimeout in einer Schleife alle InternalTimer nacheinander ab. Da HandleTimeout ein Teil der Hauptschleife in MAIN ist, gewinnt man dadurch nichts bzgl. Parallelität. Ein InternalTimer ermöglicht nur eine zeitliche Streuung der Last. Das ist in I2C_TSL2561 schon so umgesetzt: _Poll triggert _Get und _Get kann man bei Bedarf auch so aufrufen. Wahrscheinlich kommt man nur mit Threads, die ja lt. Styleguide nicht erwünscht sind, zu einer echten Entlastung des Kerns ohne auf AGC verzichten zu müssen.
FHEM 6.1 - RPi 4 Raspbian 12 + PiTFT - OPi Zero Armbian 5.35
EnOcean - (W)LAN/Firmata: BMP180, TSL2561, SHT21, Heatronic 3, OBIS - WLAN/ESP8266: Gardena 1251, Zirkulationspumpe - RTL433: Oregon - Bluetooth - MQTT
Contributions: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/jensb

kaihs

Aber parallele Ausführung muss doch auch nicht unbedingt sein.
Es reicht doch, dass fhem während des Wartens auf den Sensor nicht blockiert und statt dessen z. B. andere Timer abarbeitet.
Die eigentliche Berechnung auch Basis der ausgelesenen Sensorwerte dauert ja im Vergleich nicht lange.

Wenn im AGN Fall die Einstellungen des Sensors geändert werden geht das Spiel dann wieder von vorne los, d.h. wieder Timer starten und Kontrolle an die Hauptschleife abgeben.
Macht das ganze Prozedere aber sicherlich komplizierter, ein Grund warum ich mich lange nicht zu der Änderung aufraffen konnte ;-)
Banana Pi, Add-On Board mit 1.8" TFT LCD und IR-Sender, CULFW V1.61, div. Homematic Komponenten, Pollin Funksteckdosen, Selbstbau CUL433 MHz, Jeelink Clone, EC3000
Selbstbau CUL868MHz für Wireless M-Bus, SIGNALduino mit Logilink Temp.-sensoren und Auriol Wetterstation