Helligkeitssensor TSL2591 auslesen

@mois: Die spikes bei Deinem Helligkeitssensor sehen mit ‘256’ schwer nach einem 8bit-Überlaufproblem mit type casting auf einen größeren Typ aus. Hast Du schon eine Idee, was das sein könnte, wo das clipping herkommt?

1 Like

ich schrumpfe die kurve auf die quadratwurzel.
die tatsächlich gemessenen werte der spikes liegen zwischen 65530 und 65540.
ich hab keine ahnung wo die herkommen.
wollte in den nächsten tagen mit den verschiedenen einstellmöglichkeiten für gain und timing der adafruit-library für den sensor spielen. meinst du damit bin ich auf dem richtigen weg?

für die schöne kurve hier hab ich die spikes jetzt erst mal rauszensiert:

if ($l >= 65530 && $l <= 65540)	# auf ausreißer prüfen
	{  $lux = $oldlux;	}               # vorherigen wert verwenden
	else
	{
//	   $lux = $l * 0.1;			# darstellungsgruende: lux-kurve um faktor 10 gestaucht
	   $lux = round(sqrt($l), 2);		# darstellungsgruende: lux-kurve in quadratwurzel gestaucht
	}

in meiner unzensierten kurve sind sie nach wie vor voll zu sehen.

Wirklich 65540? Das paßt nicht mehr in die 16bit, die aus dem Sensor kommen (max. 65535).
Egal, wie die Integrationszeit und Verstärkung eingestellt sind, kommen da nie mehr als 2^16-1 heraus. 65540 paßt da irgendwie nicht, mehr als clippen kann der auch nicht…

Ist Dein Grund, den 16bit-Sensorwert auf halbe Auflösung zu bringen, die payload size um ein Byte zu verringern? Oder ist Dir nur der gerechnete Lux-Wert egal und Du nutzt den lediglich ‘normalisiert’ ?

Deine Quadratwurzel begrenzt zwar auf 9bit, aber sie bringt eben eine (erwünschte?) invertiert quadratische Abhängigkeit mit herein (die dunkelblaue):

Wenn Du wirklich nur 8bit von dem Sensor willst, dann ist binäres Bitshift auf jeder CPU und MCU das Billigste: input >>8 schiebt das unterste Byte raus und ersetzt es mit dem oberen Byte eines 16bit-Wortes (im Bild mit der entsprechenden spreadsheet-Funktion nachgebaut).
In Deinem Fall hast Du noch eine andere Möglichkeit: das 16bit-Wort liegt im Sensor in zwei Byte-Registern vor. Du könntest lediglich das high byte auslesen - mit gleichem Effekt wie mit bitshift right 8 , nämlich schnelle integer division by 256.

Mit gain und integration time mußt Du auf jeden Fall herumspielen: Helligkkeitssensoren müssen mit einer Dynamik von sechs Größenordnungen umgehen können, Dein gewählter (TSL2591) angeblich in der höchsten Verstärkung sogar mit fast neun (600M:1). Aber weder paßt das in ein 16bit-Wort, noch bekommt so ein Ding die automatische Umschaltung seiner Arbeitsbereiche selbst hin, wir müssen denen also mit Software helfen. Um eine echte AGC dafür zu bauen, bräuchte es eine eigene state machine… Fragst Du den INT des Sensors ab?

Unser Anwendungsszenario (helle Sonne, Sensor eher zur Sonne oder Zenit) paßt also also zur kleinsten oder nächst höheren Verstärkung und eher einer kleinen ‘Verschlußzeit’ (200 oder 300 ms) - damit kommen erstmal Werte für Helligkeiten, bei denen die Bienen auch draußen sind; die Frevler-Taschenlampe in der Nacht zu erkennen, klappt mit dieser fixen Einstellung natürlich nicht. Es könnte aber ein setting preamp vs. integration time geben, mit welchem das geht - wenn Du die 16bit des Sensors auch verwendest! ;)

Ein Grund für die spikes bei Dir könnte sein, daß aus irgendeinem Grund bei dem transfer der zwei bytes das high byte als 0xFF aus der lib zu kommen scheint. Durch das round kann ich es nicht sehen, aber ich möchte fast wetten, daß das low byte der vorhergehenden Messung identisch wäre…

Der Helligkeitsgraph ist so ein Kandidat für logarithmische Y-Teilung im Grafana.

fast komplett OT, wieder btw:

… ist teurer als dieser Vergleich:

$l > 65529 && $l < 65541

1 Like

ja, aber auch nur ein einziger spike (2017/03/17 23:43:41) geht über die 65535. zu sehen in graph_pure.php.

nee, ich habe keinen grund außer dass das die adafruit-lib für den TSL2591 so vorschlägt, weil auf den anderen 8 bit die infrarot-werte sitzen, wenn ich das richtig verstanden habe.

ja, hohe werte werden mehr gestaucht. ich schaue immer noch in erster linie auf meinen alten graphen will dort eine nicht zu steile tageslichtkurve erreichen.

das verstehe ich nicht. wie wären die gain und integration time-werte kombiniert für eine preamp vs. integration time einstellung? und: kann ich die 16 überhaupt komplett fürs sichtbare licht verwenden? da müsste ich wohl mal sorgfältig in die beschreibung des sensors schauen, wenn du das nicht aus der hohlen hand sagen kannst.

was mir zu den spikes noch auffällt: einige kommen unmittelbar beim ausschalten einer relativ starken lichtquelle zustande: z.b. wenn ich bei dunkelheit die zimmerbeleuchtung ausschalte. als ob da durch den krassen unterschied was “überschwappt”. ist es das was du mit eher technischen begriffen hier beschreibst? oder meinst du was ganz anderes?

und schließlich:

danke für den tip. schon geändert.

Siehe auch:

und:

Ich sehe in der lib noch nicht, wo die das vorschlagen… klar gibt’s primitives wie read8(), aber die wirst Du doch nicht direkt benutzen?
In jedem Fall haben aber beide Sensoren (Kanäle des Sensors) eigene 16bit-Register.

Register Address Bits Description C0DATAL 0x14 7:0 ALS CH0 data low byte C0DATAH 0x15 7:0 ALS CH0 data high byte C1DATAL 0x16 7:0 ALS CH1 data low byte C1DATAH 0x17 7:0 ALS CH1 data high byte

Nutzt Du die Adafruit unified lib oder direkt deren API für diesen IC (getLuminosity(), getFullLuminosity ()... ) ?

Was ich meinte, war: zwischen den vielen möglichen Kombinationen aus Integrationszeit * Empfindlichkeit will man ja (bei unserer Anwendung) nicht hin- und herschalten.
Bei 100ms schafft er gute 2^5 max count in die 16bit, also sollte es wenigstens 200ms werden. - Der max gain mode taugt fast zum Zählen einzelner Photonen, also braucht der schonmal nicht betrachtet zu werden. Da uns bei den Bienen eher der sonnige Sommertag interessiert als die Helligkeit einer Kerze in der Nacht, werden tendenziell eher kurze Integrationszeiten und kleine Vertärkungen die ‘nutzbaren’ Tageshelligkeiten am besten abbilden.

Ja.

;) Datenblatt-Lesen ist nötig und macht schlau! (oder so…)

Nö, die kleinen und mittleren werden betont, das ist wie das ‘Knie’, welches Gamma in der Bildverarbeitung darstellt.

Verstehe. OK, bei Grafana könntest Du (wie schon geschrieben) die logarithmische Y-Skalierung dafür anmachen, das ist genau für solche Fälle. Aber ich verstehe die Intention wg. ‘altem’ Graphen.

1 Like

Achja, und noch keine Erklärung habe ich für diesen max-Wert von 88k, den sie festlegen:

Noch was:

Da gibt es im code einen Hinweis auf ein zumindest ähnliches Verhalten (ohne jetzt weitere code-Details von Dir zu kennen):

ich mache lux = tsl.getLuminosity(TSL2591_VISIBLE);

das mit den 8bit mache ich nicht bewußt und kann dir auch nicht erklären, wo es passiert. ich vermutete lib, weil ich nicht wirklich verstanden habe, wie die das aufteilen mit dem sichtbaren und dem unsichtbaren licht. wenn du sagst, die haben beide theoretisch 16bit zur verfügung… wie gesagt: hab mich da noch nicht systematisch hintergeklemmt. dass die kurve jetzt halbwegs vernünftig aussieht, ist ergebnis von try&error und der tatsache, dass sie jetzt nicht mehr im zimmer unter der deckenleuchte steht sondern auf dem balkon (keine plötzlichen helligkeitsänderungen mehr!).

mein sketch ist ja jetzt auch im offiziellen repo, ab zeile 118 ist das setup für diesen sensor:
https://github.com/bee-mois/arduino/blob/master/node-yun-http/node-yun-http.ino#L118-L132
und zeile 139 wird er ausgelesen:
https://github.com/bee-mois/arduino/blob/master/node-yun-http/node-yun-http.ino#L134-L142

kurz nachgedacht, mein datenverarbeitungsskript hat ja beide variablen.
ich habe also die sendezeile (54) so geändert, dass hiveeyes mit dem “echten” messwert $l beschickt wird und mein alter graph nach wie vor mit dem prozessierten $lux. wo ich die logarithmische y-skalierung anschalten kann, werd ich sicher leicht finden, oder?

Hier mal kurz nachgehakt…

…nur interessehalber: Sind wir hier aus den Kinderschuhen raus oder gibt es auch beim Auslesen dieses Sensors noch sporadische Probleme im beschriebenen Kontext?


P.S.: Schön, dass https://www.euse.de/wp/blog/2019/05/es-rappelt-wieder/ ansonsten gut klappt und dass Du wieder dabei bist.

Bzgl. der hier angesprochenen Themen könnte man noch einmal einen Blick auf den Beispielcode von Upstream (by Ladyada et al.) werfen, also die jeweiligen Details von simpleRead vs. advancedRead vs. unifiedSensorAPIRead betrachten.


Also interesting:

The example tsl2591_interrupt.ino shows how the interrupt system on the TLS2591 can be used to detect a meaningful change in light levels.

Dazu müßte der INT out des TLS an einem interruptfähigen GPIO des Prozessors angeschlossen sein (und natürlich eine ISR das serven).

‘meaningful change in light’ - es geht hier nur um Helligkeit resp. Sonne. Schnellere Änderungen, für die der INT gebraucht werden könnte, wären lediglich, wenn des Nachts der Bienenfrevler mit der Taschenlampe drüberfunzelt, ansonsten sehe ich nicht, warum der TLS einen INT input am MCU bekommen sollte.

1 Like

nee, an der stelle seh ich gerade keine probleme. danke der nachfrage!