When interfacing a light detection sensor with a microcontroller, the most critical distinction is whether the module outputs a digital I2C stream or a raw analog voltage. The TEMT6000 is a precision analog phototransistor module that outputs a continuous voltage (0V to 3.3V) proportional to ambient illuminance. Unlike digital sensors that handle math internally, the TEMT6000 requires you to convert raw ADC readings into physical lux values using specific mathematical scaling and calibration.
The Sensing Principle: Photons to Voltage
Unlike a basic Light Dependent Resistor (LDR) like the GL5528 which changes bulk resistance based on light, the TEMT6000 is an NPN phototransistor. When photons strike the silicon base region, they generate electron-hole pairs that act as base current. This allows collector-emitter current to flow, and the magnitude of this current is strictly proportional to the light intensity hitting the semiconductor die.
On a standard breakout board, this current passes through an integrated 10kΩ pull-down resistor, converting the current into a measurable analog voltage. This makes the output strictly an analog voltage, entirely distinct from digital sensors like the BH1750 which output pre-calculated lux values over a serial bus. You must read this voltage with an Analog-to-Digital Converter (ADC) and apply scaling math to determine the actual physical lux.
Wiring the Sensor to an ESP32
The TEMT6000 breakout operates safely on a supply range of 2.5V to 5.5V. However, because the ESP32's GPIO pins are strictly 3.3V tolerant, you must power the sensor from the 3.3V rail. Powering it with 5V will result in a 5V analog output, which will permanently damage the ESP32's ADC pin.
| Pin | Function | ESP32 Connection | Notes |
|---|---|---|---|
| VCC | Power Supply (2.5V - 5.5V) | 3V3 | Do not use 5V (VIN) to protect ESP32 ADC |
| GND | Circuit Ground | GND | Must share common ground with ESP32 |
| SIG / OUT | Analog Voltage Output | GPIO 34 (ADC1_CH6) | ADC1 only; ADC2 is disabled during WiFi use |
- Connect the sensor VCC pin to the ESP32 3V3 pin.
- Connect the sensor GND pin to any ESP32 GND pin.
- Connect the sensor SIG pin to ESP32 GPIO 34. (GPIO 34 is input-only and routed to ADC1, which remains active even when the WiFi radio is transmitting).
- Add a 0.1µF ceramic capacitor between the SIG and GND pins on the breadboard to filter high-frequency ADC noise.
Output Signal Math: Converting Raw ADC to Lux
To get a physical lux reading, we must map the ESP32's 12-bit raw ADC value (0–4095) to voltage, and then map that voltage to illuminance based on the TEMT6000 datasheet specifications.
Step 1: Raw ADC to Voltage
The ESP32 ADC maps 0V–3.3V to 0–4095.
Voltage = (Raw_ADC / 4095.0) * 3.3
Step 2: Voltage to Collector Current
The breakout board uses a 10,000Ω (10k) pull-down resistor. Using Ohm's Law (I = V / R):
Current (Amps) = Voltage / 10000
Step 3: Current to Lux
According to the Vishay TEMT6000 datasheet, the typical sensitivity is 2 µA per lux (0.000002 Amps/lux).
Lux = Current / 0.000002
Combined Formula:
Substituting the variables, the math simplifies beautifully. For a 10k resistor, every 20mV (0.02V) equals 1 Lux. Therefore:
Lux = Voltage * 50
With a 10k resistor and a 3.3V max ADC limit, the maximum measurable lux is roughly 165 lux (3.3V * 50). Direct sunlight is >10,000 lux and will saturate the sensor. If you need to measure outdoor light, desolder the 10k resistor on the breakout and replace it with a 1k resistor. This changes your multiplier from 50 to 500, allowing readings up to ~1,650 lux, or use a 200Ω resistor for full sunlight ranges.
ESP32 Arduino Implementation
The following code samples the ADC multiple times to average out noise and applies the exact mathematical scaling derived above. For deeper understanding of ESP32 analog-to-digital conversion limits, refer to the official Espressif ADC documentation.
const int lightPin = 34; // GPIO 34 (ADC1_CH6)
const int sampleCount = 20; // Multi-sample to defeat 60Hz flicker
void setup() {
Serial.begin(115200);
analogReadResolution(12); // Ensure 12-bit resolution (0-4095)
}
void loop() {
long totalRaw = 0;
// Multi-sampling to smooth out AC mains lighting flicker
for (int i = 0; i < sampleCount; i++) {
totalRaw += analogRead(lightPin);
delayMicroseconds(500); // Small delay between reads
}
float avgRaw = totalRaw / (float)sampleCount;
// Convert raw ADC to Voltage
float voltage = (avgRaw / 4095.0) * 3.3;
// Convert Voltage to Lux (assuming standard 10k pull-down resistor)
float lux = voltage * 50.0;
Serial.print("Raw ADC: ");
Serial.print(avgRaw, 1);
Serial.print(" | Voltage: ");
Serial.print(voltage, 3);
Serial.print("V | Lux: ");
Serial.println(lux, 1);
delay(500);
}
Calibration, Scaling, and Interference Mitigation
While the theoretical math is exact, real-world physics and microcontroller quirks require calibration and interference management.
ESP32 ADC Non-Linearity
The ESP32's internal ADC is notoriously non-linear at the extremes of its range. Readings below 0.1V (approx. 120 raw) and above 2.9V (approx. 3600 raw) will deviate from true voltage. If your application requires high precision in very dark or very bright environments, you must implement a polynomial correction curve or use an external I2C ADC like the ADS1115. For general indoor automation, the internal ADC with multi-sampling is sufficient.
Common Interference Sources
- 50/60Hz Mains Flicker: Incandescent, fluorescent, and cheap LED drivers pulse at twice the AC mains frequency (100Hz or 120Hz). Because the TEMT6000 is incredibly fast (response time in microseconds), it will read these pulses as wild fluctuations. Fix: Always use multi-sampling (as shown in the code) over a window of at least 20ms to integrate a full AC cycle.
- Infrared (IR) Heat Contamination: The TEMT6000 peaks in the visible spectrum (570nm, green-yellow) but has a sensitivity tail that extends into the near-infrared. Placing the sensor near an incandescent bulb, a space heater, or direct hot sunlight will yield artificially high lux readings because the sensor is counting IR radiation as visible light. Fix: Mount an IR-cut optical filter over the sensor if measuring strictly visible light in high-heat environments.
Frequently Asked Questions
Why is my analog light detection sensor reading fluctuating wildly indoors?
This is almost always caused by 50Hz or 60Hz AC mains flicker from your room's lighting. The TEMT6000 reacts in microseconds, easily capturing the rapid on/off pulsing of LED drivers and fluorescent ballasts that human eyes filter out. To fix this, do not rely on a single analogRead(). Instead, take 20 to 50 rapid readings and average them, ensuring the sampling window spans at least one full AC cycle (approx. 16.6ms for 60Hz grids).
Can I use a 5V light detection sensor module on a 3.3V ESP32 pin?
It depends on the module's output type. If the module is a digital I2C sensor (like a BH1750) powered by 5V, its SDA/SCL lines will output 5V logic, which will fry the ESP32's 3.3V GPIOs; you must use a logic level shifter. However, if you are using an analog TEMT6000 module, simply wire the module's VCC pin to the ESP32's 3.3V pin. The TEMT6000 operates perfectly down to 2.5V, and powering it with 3.3V ensures the analog output never exceeds the ESP32's safe 3.3V ADC limit.
How do I calibrate a light detection sensor for outdoor sunlight measurements?
Standard TEMT6000 breakouts include a 10kΩ pull-down resistor, which maxes out the 3.3V ADC at roughly 165 lux. Direct sunlight exceeds 10,000 lux, meaning the sensor will simply read a flat 4095 (saturation). To calibrate for outdoor use, you must physically modify the board: desolder the 10k surface-mount resistor and replace it with a 1kΩ or 470Ω resistor. If you use a 470Ω resistor, your math multiplier changes from 50 to roughly 1063, allowing you to accurately measure up to 3,500 lux before ADC saturation.






