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.
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:
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
*/
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.
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
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;
}
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;
Die Funktion readRegister16()
arbeitet in drei Schritten:
Wire.write(0x80 | reg)
setzt das Command-Bit und wählt das Register.Wire.requestFrom(..., 2)
holt zwei Bytes vom Sensor.(high << 8) | low
ergibt den 16-Bit-Wert.writeRegister(0x00, 0x03)
→ Sensor einschaltenwriteRegister(0x01, 0x02)
→ Timing: 402 ms, Gain 1×readRegister16(0x0C)
→ Kanal 0 (sichtbar + IR)readRegister16(0x0E)
→ Kanal 1 (nur IR)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:
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);
}