Skip to content

9. Input devices

Group assignment:

  • Probe an input device(s)'s analog and digital signals
  • Document your work on the group work page and reflect on your individual page what you learned

To see our group assignment click here

Individual assignment:

  • add a sensor to a microcontroller board that you have designed and read it.

Threshold

A threshold value is defined in the code to distinguish between "light ON" and "light OFF" states.


How the LDR Sensor Works

What is an LDR?

A Light Dependent Resistor (LDR), also called a photoresistor, is a component whose electrical resistance decreases as light intensity increases it can measure a few hundred ohms in bright light and several hundred kilo-ohms in darkness.

Since the ESP32 can only measure voltage, not resistance directly, the LDR is paired with a fixed resistor to form a voltage divider: the LDR sits between 3.3V and the analog input pin, while the fixed resistor pulls the same pin down to GND. As ambient light changes, the LDR's resistance changes, which shifts the voltage at this midpoint a value the ESP32 converts into a digital reading between 0 and 4095 using analogRead().

In this wiring, more light , lower LDR resistance , more voltage across the fixed resistor, a higher analogRead() value. Conversely, darkness produces a lower reading which is exactly the logic behind the THRESHOLD comparison in the code below.

GPIO choice matters on the ESP32

The ESP32 has two ADC blocks: ADC1 (GPIO32–39) and ADC2 (GPIO0, 2, 4, 12–15, 25–27). ADC2 cannot be reliably read while Wi-Fi is active, because the Wi-Fi driver uses it internally. Since this project runs a Wi-Fi access point continuously, the LDR must be read on an ADC1 pin (e.g. GPIO 34) to avoid unstable readings — not on an ADC2 pin like GPIO 2.

Sizing the Fixed Resistor & Voltage Divider Calculation

The voltage divider formula

The voltage divider formula

Vout = Vin × R_fixed / (R_LDR + R_fixed)

Where Vin = 3.3V (ESP32 supply rail).

Where Vin = 3.3V (ESP32 supply rail).

How to choose the fixed resistor

The goal is to place the fixed resistor close to the LDR's own resistance at the light level you want to detect most sensitively. At that point R_LDR ≈ R_fixed, which puts Vout near Vin / 2 — the region where the divider is most sensitive to small changes in light.

For a typical 5mm LDR (e.g. GL5528-type), resistance behaves roughly like this:

Light condition Approx. R_LDR
Bright daylight ~1 kΩ
Lit indoor room ~5–10 kΩ
Dusk / twilight ~10–20 kΩ
Dark room ~200 kΩ
Total darkness ~1 MΩ

A 5 kΩ fixed resistor was chosen here, centering the divider's sensitivity around the lit indoor room condition.

Resulting output voltage and ADC reading

Light condition R_LDR Vout analogRead() (approx., 12-bit)
Bright daylight 1 kΩ 2.75 V ~3412
Lit indoor room 5 kΩ 1.65 V ~2048
Dusk / twilight 10 kΩ 1.10 V ~1365
Dark room 200 kΩ 0.08 V ~100
Total darkness 1 MΩ 0.02 V ~20

(ADC value ≈ Vout / 3.3 × 4095, assuming 11dB attenuation, required on the ESP32 to read the full 0–3.3V range.)

Practical takeaway

With THRESHOLD = 2000 in the code, the switch to Visitor Mode only happens once the room is genuinely lit (readings above ~2048), not merely at dusk (~1365) — matching the intended day/night behavior.


My Custom PCB

The sensor is connected to the custom PCB I designed during Week 06 — Electronics Design, based on an ESP32-WROOM microcontroller.

Custom ESP32-WROOM PCB with LDR circuit

Custom ESP32-WROOM PCB with the LDR voltage divider circuit (J2 + fixed resistor) integrated on-board.


Wiring Diagram

LDR voltage divider schematic

LDR Pin ESP32 Pin
One leg 3.3V
Other leg GPIO 34 (analog, ADC1) + 5kΩ to GND

LDR voltage divider schematic

Schematic of the LDR voltage divider: 3.3V - LDR analog pin - 5kΩ resistor - GND.

Physical wiring of the LDR sensor

Physical wiring of the LDR sensor on the assembled board, matching the schematic above.


Code

The following code reads the LDR analog value and switches between the two modes:

#define LDR_PIN 34        // Analog pin connected to LDR (ADC1 — safe to use with Wi-Fi active)
#define THRESHOLD 2000    // Adjust based on your environment

void setup() {
  Serial.begin(115200);
  pinMode(LDR_PIN, INPUT);
}

void loop() {
  int ldrValue = analogRead(LDR_PIN);
  Serial.print("LDR Value: ");
  Serial.println(ldrValue);

  if (ldrValue < THRESHOLD) {
    // Room light is OFF → Night light mode
    Serial.println("Mode: Night Light");
    // Add your night light logic here
  } else {
    // Room light is ON → Visitor mode
    Serial.println("Mode: Visitor");
    // Add your visitor mode logic here
  }

  delay(500);
}

Calibration

Run the Serial Monitor first with the room light ON then OFF to read the actual LDR values and adjust THRESHOLD accordingly.


Serial Monitor

The video below shows the Serial Monitor output as the light condition changes in real time:

Live Serial Monitor output as the room light is switched on and off, showing the LDR value and resulting mode.


Final Project Development: Smart Mode Management via LDR Sensor

This section details the development and implementation of the LDR (Light Dependent Resistor) sensor within the final project architecture.

System Dynamic Adaptation

The integration of this sensor enables the system to dynamically adapt its behavior based on ambient light level variations. By continuously monitoring the environment, the system automatically triggers seamless transitions between distinct operating modes.

Operational Modes

  • Trigger: Activated during optimal ambient light conditions.
  • Objective: Ensures full system responsiveness, maximum performance, and fluid user interaction.
  • Trigger: Activated automatically when darkness is detected.
  • Objective: Optimizes energy consumption by transitioning the system into a low-power state.

Demo of the system transitioning between Visitor Mode and Sleep Mode as ambient light changes.

LDR sensor integrated in the final enclosure The LDR sensor integrated into the final enclosure, positioned to sense ambient room light.


Sensor Evolution: From LDR to Phototransistor

LDR sensor integrated in the final enclosure

While the LDR-based system worked reliably for basic day/night detection, I wanted a more precise and repeatable sensor for the final version of this feature CdS-based LDRs age over time, respond slowly, and vary significantly from one unit to another.

TEMT6000 Phototransistor

Instead of adding correction filters to a photodiode, I switched to the Vishay TEMT6000, a phototransistor purpose-built as an ambient light sensor, with a spectral response close to the human eye and internal gain that removes the need for an op-amp entirely.

Parameter Value
Type Silicon NPN phototransistor
Peak sensitivity 570 nm (green, close to human eye response)
Spectral range 440 – 800 nm
Dark current (ICEO) 3 – 50 nA (VCE = 5V)
Light current @ 100 lx ~50 µA (typ., VCE = 5V)
Light current @ 20 lx 3.5 – 16 µA
Package 1206 SMD (or TO-92 leaded variants)

Circuit Design

Same simple voltage-divider topology as the original LDR :

LDR sensor integrated in the final enclosure


Component sizing

Component Value Purpose
Phototransistor TEMT6000 Ambient light sensor
R (pull-down) 10 kΩ Sets the sensitivity / output swing
C (filter) 100 nF Reduces electrical noise on the reading
ESP32 pin GPIO34 (ADC1) Safe to read with Wi-Fi active

With R = 10kΩ, the expected output swing is:

Condition Approx. current Vout analogRead() (12-bit)
Dark room (<10 lx) ~5 µA 50 mV ~62
Lit room (100–300 lx) 50–150 µA 0.5–1.5 V ~620–1860
Bright light (>1000 lx) >500 µA saturates ~3.2V ~3970 (clamped)

This gives a clean, well-separated range for the day/night threshold — with much better consistency across different light sources than either the LDR or the BPW34.

Preventing light contamination from the on-board RGB LEDs

Since the phototransistor sits on the same PCB as the 14 district RGB LEDs, unshielded placement risks the sensor picking up light from the board's own LEDs (especially during Auto or Walkthrough mode), falsely reporting "daylight" conditions. To prevent this, the TEMT6000 is mounted inside a small opaque light pipe / sleeve, facing only outward through the enclosure, isolated from the on-board LEDs.

Comparison: LDR vs. TEMT6000

LDR (original) TEMT6000 (final)
Spectral match to human eye Approximate Purpose-built match (570nm)
Response speed Slow (ms range) Fast
Unit-to-unit consistency Variable (analog CdS cell) Consistent (semiconductor)
Aging / drift over time Yes Minimal
Sensitivity to light source type Moderate Low

Files

File Description
LDR Code Arduino sketch for the LDR sensor