Funktionsprinzip des Sensors

Der TSL2561 Helligkeitssensor ist ein digitaler Lichtsensor, der sich ideal für den Einsatz in einer Vielzahl von Lichtsituationen eignet. Der Sensor ermöglicht exakte Lux-Berechnungen und kann für verschiedene Verstärkungs- und Timing-Bereiche konfiguriert werden, um Lichtbereiche von 0,1 bis über 40.000 Lux im laufenden Betrieb zu erfassen. Darüber hinaus sind Infrarot- als auch Vollspektrum-Dioden integriert. Das bedeutet, dass Infrarot-, Vollspektrum- oder sichtbares Licht separat gemessen werden können.

Lichtsensor
Lichtsensor TSL2561 Pin-Belegung und Spezifikationsdaten

Der Sensor verfügt über 2 Messkanäle, die sowohl Infrarot- als auch Vollspektrumdioden enthalten und mit Hilfe verschiedener Verstärkungs- und Zeitbereiche konfiguriert werden. Die Konfiguration erfolgt über verschiedene Register und versetzt den Sensor in die Lage Lichtbereiche von 188 uLux bis zu 88.000 Lux im laufenden Betrieb zu erfassen. Die Stromaufnahme ist extrem niedrig, daher ist der Sensor ideal für Datenerfassungssysteme die mit geringem Stromverbrauch (ca. 0,4 mA) bei aktiver Erfassung arbeiten müssen. Im ausgeschalteten Zustand benötigt der Sensor weniger als 5 µA.

Die Steuerung und Überwachung des Sensors erfolgt über Register, auf die über die serielle I²C-Schnittstelle zugegriffen wird. Diese Register ermöglichen eine Vielzahl von Steuerfunktionen und dienen auch zur Ermittlung der Ergebnisse. Das Datenblatt bietet ausführlichere Informationen.Vereinfacht dargestellt sind in nachfolgender Tabelle die wesentlichen Register mit Ihrer Funktion aufgelistet:

Registername Adresse (Hex) Funktion
Command Register 0x80 Steuert Zugriff auf andere Register
Control Register 0x00 Sensor ein-/ausschalten
Timing Register 0x01 Integration Time und Gain
Data0 Low 0x0C Low-Byte Kanal 0 (sichtbar + IR)
Data0 High 0x0D High-Byte Kanal 0
Data1 Low 0x0E Low-Byte Kanal 1 (nur IR)
Data1 High 0x0F High-Byte Kanal 1

Eines der wichtigsten Register für die Verwendung des Sensors ist das Control-Regster. Es dient zur Konfiguration der ALS-Verstärkung sowie der Integrationszeit. Darüber hinaus ist ein System-Reset möglich. Beim Einschalten wird das CONTROL-Register auf 0x00 zurückgesetzt. Anschliessend werden die anderen Funktionen konfiguriert. Eine vereinfachte Darstellung des Control-Registers ist nachfolgend dargestellt. Diese erklärt, welche Parameter im nachfolgenden Test-Programm verwendet werden, um den Licht-Sensor in Betrieb zu nehmen:

Vereinfachtes Control-Register
Vereinfachte Darstellung des Control-Registers

Der TSL2561 arbeitet intern mit einem Timer-basierten Integrationsmechanismus, der die Lichtmenge über einen definierten Zeitraum „aufsammelt“. Dazu sind zwei Kanäle vorhanden, die jeweils über eigene Analog-Digital-Wandler verfügen:

Der Sensor integriert das Licht über eine feste Zeitspanne – vergleichbar mit der Belichtungszeit einer Kamera. Je länger die Zeit, desto höher die Genauigkeit – aber auch je langsamer erhält man das Ergebnis. Die Zeit wird über Bit0 und Bit1 im Control-Register (Adr: 0x01) eingestellt.

Neben der "Belichtungszeit wird über das Timing-Register ebenfalls der Gain-Faktor festgelegt. Der Gain-Faktor definiert die Verstärkung des Signals, das aus den Fotodioden kommt. Der TSL2561 bietet zwei Gain-Stufen:

Die Gain-Werte können wie folgt gesetzt werden:


		  //   0x02 → 402 ms, Gain 1x
		  //   0x06 → 402 ms, Gain 16x

		  Wire.beginTransmission(TSL2561_ADDR);
		  Wire.write(0x80 | 0x01); // Timing Register
		  Wire.write(0x06);        // Set Gain to 16x
		  Wire.endTransmission()

		  /*
		  Gain 1x und Integration 101 ms erfordert:
		  •  Gain-Bit = 0
		  •  Integrationszeit-Bits = 01
		  →  00000 0001→ **01**

		  Oder Gain 16x, Manual aktiv, Integration 101 ms:
		  •  Bit 3 = 1 (Manual)
		  •  Bit 2 = 1 (Gain)
		  •  Bits1 = 0
		     Bit0  = 1 damit ist das Register 0000 1101 → 0x0D
		  */
		

Programmierung des Sensors Schritt für Schritt

Programmierung des TSL2561 Sensors mit Arduino

Der TSL2561 ist ein digitaler Lichtsensor mit zwei Kanälen: CH0 (sichtbar + IR) und CH1 (nur IR). Die Messung erfolgt in drei Schritten: Initialisierung, Auslesen der Rohdaten und Berechnung der Lichtintensität in Lux.

1. Sensor initialisieren

Der Sensor wird über I²C aktiviert. Dazu setzen wir das Control-Register auf 0x03 (Power ON) und konfigurieren das Timing-Register für Integrationszeit und Verstärkung (Gain).


		writeRegister(0x00, 0x03);  // Sensor einschalten
		writeRegister(0x01, 0x02);  // 402ms Integration, Gain 1x
		

2. Rohdaten auslesen

Nach einer kurzen Wartezeit (z. B. delay(500)) können die Rohwerte aus den beiden Kanälen ausgelesen werden. Dazu verwenden wir eine Funktion, die zwei aufeinanderfolgende Register kombiniert:


		uint16_t readRegister16(uint8_t reg) {
		Wire.beginTransmission(TSL2561_ADDR);
		Wire.write(0x80 | reg);  // Command-Bit + Registeradresse
		Wire.endTransmission();
		
		Wire.requestFrom(TSL2561_ADDR, 2);
		uint8_t low = Wire.read();
		uint8_t high = Wire.read();
		return (high << 8) | low;
		}
		

3. Lux berechnen

Aus dem Verhältnis der beiden Kanäle lässt sich die Lichtintensität berechnen. Die Formel basiert auf empirischen Daten aus dem Datenblatt:


		float ratio = (float)ch1 / (float)ch0;
		float lux;
		
		if (ratio <= 0.5)
		lux = 0.0304 * ch0 - 0.062 * ch0 * pow(ratio, 1.4);
		else if (ratio <= 0.61)
		lux = 0.0224 * ch0 - 0.031 * ch1;
		else if (ratio <= 0.80)
		lux = 0.0128 * ch0 - 0.0153 * ch1;
		else if (ratio <= 1.30)
		lux = 0.00146 * ch0 - 0.00112 * ch1;
		else
		lux = 0;
		

Funktionsanalyse

Die Funktion readRegister16() arbeitet in drei Schritten:

  1. Adresse senden: Wire.write(0x80 | reg) setzt das Command-Bit und wählt das Register.
  2. Daten anfordern: Wire.requestFrom(..., 2) holt zwei Bytes vom Sensor.
  3. Bytes kombinieren: (high << 8) | low ergibt den 16-Bit-Wert.

Zusätzliche Beispiele

Gesamtes Programm

Hier ist das vollständige Arduino-Programm zur Messung der Lichtintensität mit dem TSL2561:


		#include 
		#define TSL2561_ADDR 0x39
		
		void writeRegister(uint8_t reg, uint8_t value) {
		Wire.beginTransmission(TSL2561_ADDR);
		Wire.write(0x80 | reg);
		Wire.write(value);
		Wire.endTransmission();
		}
		
		uint16_t readRegister16(uint8_t reg) {
		Wire.beginTransmission(TSL2561_ADDR);
		Wire.write(0x80 | reg);
		Wire.endTransmission();
		Wire.requestFrom(TSL2561_ADDR, 2);
		uint8_t low = Wire.read();
		uint8_t high = Wire.read();
		return (high << 8) | low;
		}
		
		void setup() {
		Serial.begin(9600);
		Wire.begin();
		writeRegister(0x00, 0x03);  // Sensor einschalten
		writeRegister(0x01, 0x02);  // 402ms, Gain 1x
		delay(500);                 // Warten auf erste Messung
		}
		
		void loop() {
		uint16_t ch0 = readRegister16(0x0C);
		uint16_t ch1 = readRegister16(0x0E);
		float ratio = (float)ch1 / (float)ch0;
		float lux;
		
		if (ratio <= 0.5)
			lux = 0.0304 * ch0 - 0.062 * ch0 * pow(ratio, 1.4);
		else if (ratio <= 0.61)
			lux = 0.0224 * ch0 - 0.031 * ch1;
		else if (ratio <= 0.80)
			lux = 0.0128 * ch0 - 0.0153 * ch1;
		else if (ratio <= 1.30)
			lux = 0.00146 * ch0 - 0.00112 * ch1;
		else
			lux = 0;
		
		Serial.print("Lux: ");
		Serial.println(lux);
		delay(1000);
		}
		

Nun stellt sich natürlich die Frage was fängt man nun damit an. Wir haben einen Sensor, der uns verschiedene Lux-Werte liefert. Um in Abhängigkeit dieser Werte weitere Aktionen starten zu können, benötigen wir eine Schwellwert Unterscheidung. Diese könnte Software-technisch so umgesetzt werden:


	float schwelle = 50.0;

	if (lux < schwelle) {
	  Serial.println("→ Dunkel genug – Licht einschalten");
	  digitalWrite(LED, HIGH); // oder Relais/MOSFET aktivieren
	} else {
	  Serial.println("→ Hell genug – Licht aus");
	  digitalWrite(LED, LOW);
	}
	

In meinem Projekt, soll eine Unterscheidung zwischen Tag und Nacht erfolgen, wobei es darum geht ab wann eine LED Leuchte angeschaltet werden soll. Experimente zeigten das ein Lux-Wert zwischen 30 und 50 ein guter Start für die genauen Tests darstellt. Folgende Schwellwerte geben eine erste Orientierung:

Erkennen der Tageszeit

Als Ergänzung hier der ein Ausschnitt bzw eine Erweiterung des Programmcodes zum Erkennen der Tageszeit anhand der Helligkeit bzw. des dabei zu erwartenden Lux-Wertes


	void loop() {
	  uint16_t ch0 = readChannel(0x0C, 0x0D);
	  uint16_t ch1 = readChannel(0x0E, 0x0F);

	  float ratio = (float)ch1 / (float)ch0;
	  float lux = 0;

	  if (ratio <= 0.5) {
	    lux = 0.0304 * ch0 - 0.062 * ch0 * pow(ratio, 1.4);
	  } else if (ratio <= 0.61) {
	    lux = 0.0224 * ch0 - 0.031 * ch1;
	  } else if (ratio <= 0.80) {
	    lux = 0.0128 * ch0 - 0.0153 * ch1;
	  } else if (ratio <= 1.30) {
	    lux = 0.00146 * ch0 - 0.00112 * ch1;
	  } else {
	    lux = 0;
	  }

	  // Tageszeit bestimmen
	  String tageszeit;

	  if (lux < 100) {
	    tageszeit = "Abend";
	  } else if (lux < 300) {
	    tageszeit = "Morgen";
	  } else {
	    tageszeit = "Mittag";
	  }

	  Serial.print("Lux: "); Serial.print(lux, 2);
	  Serial.print(" → Tageszeit: "); Serial.println(tageszeit);

	  delay(2000);
	}
    

Anhang

Architektur des Lichtsensors TSL2591

Sensor Architektur
Architektur des Lichtsensors TSL2591 [Quelle: AMS Datenblatt]

Architektur des Control-Registers des TSL2591

Control-register
Architektur des Control-Registers des TSL2591 [Quelle: AMS Datenblatt]
⬅ Zurück zur Hauptseite