ESP32 UNO - LDR Module

Need your project to know when the lights go off? Hook an ESP32 Uno LDR module to the ESP32 Uno form board and it can tell day from night in a few lines of Arduino code. The board on the module, often sold as a photoresistor module or photocell module, sends out a light/dark signal and a light level you can turn into a number.

By the end, you can:

  1. Connect a photoresistor light sensor module to the ESP32 Uno
  2. Sense light or darkness with the DO pin and digitalRead()
  3. Measure brightness as a 0–4095 number with the AO pin and analogRead()
  4. Set the dark/light switch point with the small trimmer on the module
ESP32 Uno LDR module

Components You Need

1×ESP32 Uno-form Board
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)
1×LDR Light Sensor Module
1×Jumper Wires

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

Meet the LDR Light Sensor Module

After this part, you know what each pin and LED on the module is for.

The module carries a light-dependent resistor (LDR), a comparator chip and a trimmer potentiometer. Its resistance drops as more light hits it. The board turns that change into two signals at once.

Output Type Best For
DO Digital, HIGH or LOW Simple "is it dark?" checks, night lights, alarms
AO Analog voltage Light level readings, smooth dimming, logging

Pinout

Four pins sit on the header. Two give power, two give the light signal.

Pin Role Notes
VCC Power in Accepts 3.3V to 5V; wire it to 3.3V here
GND Ground 0V
DO Digital out Goes HIGH in the dark and LOW in the light
AO Analog out Voltage falls with more light and rises with less light
LDR Light Sensor Module Pinout
image source: diyables.io

Two tiny LEDs help you debug:

LED When It Is On
PWR-LED The module gets power
DO-LED The sensor sees more light than the set threshold

How It Works

Here you learn how the trimmer and the two outputs depend on each other.

DO output

The comparator checks the LDR signal against the level set by the trimmer.

Room Light DO Pin DO-LED
Brighter than the threshold LOW Off
Darker than the threshold HIGH On

AO output

The AO pin follows the light level all the time. A bright spot gives a small reading. A dark spot gives a large reading. Turning the trimmer does not change AO at all; it only moves the DO switch point.

Good to know: you can tune DO for a yes/no check and still read the exact brightness from AO in the same sketch.

ESP32 Uno Pinout

Your code talks to GPIO numbers, while the board prints Uno labels like D2 and A0 on the headers. Look at the diagram below to find the matching GPIO for every header pin before you plug in any wire.

ESP32 Uno pinout diagram

How to Connect

When you finish this step, both module outputs reach the board, so you can run either sketch without moving a wire.

The wiring diagram between ESP32 Uno LDR Light Sensor Module

This image is created using Fritzing. Click to enlarge image

Module Pin ESP32 Uno Header (GPIO)
VCC 3.3V
GND GND
DO D2 (GPIO26)
AO A0 (GPIO2)

WARNING

A0 is GPIO2, a boot strapping pin of the ESP32 Uno. The chip reads it at startup to choose the boot mode. The LDR module normally leaves it alone, but if the board will not boot or will not take new code, pull the AO wire out while you upload, then put it back. Also, GPIO2 is an ADC2 pin: analogRead() on it stops working when WiFi is on.

WARNING

The ESP32 Uno is NOT 5V tolerant; every pin expects 3.3V at most. With VCC on 5V, the DO and AO outputs can reach 5V and harm the board. Keep the module on the 3.3V pin; it runs well there.

Good to know: you only need one output for each sketch, but wiring both now saves time later.

ESP32 Uno Code - Light or Dark from the DO Pin

This sketch checks D2 (GPIO26) again and again and prints if light is there or not.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-ldr-module */ #define DO_PIN 26 // D2 (GPIO26) reads the DO output of the LDR module void setup() { // open the USB serial link to the computer Serial.begin(9600); // make the DO pin an input so the board can read it pinMode(DO_PIN, INPUT); } void loop() { int light_state = digitalRead(DO_PIN); if (light_state == HIGH) Serial.println("The light is NOT present"); else Serial.println("The light is present"); }
Code Part What It Does
#define DO_PIN 26 Names the GPIO wired to the DO pin
pinMode(DO_PIN, INPUT) Makes GPIO26 an input
digitalRead(DO_PIN) Gets HIGH (dark) or LOW (light)
Serial.println(...) Prints the light state to the Serial Monitor

The result is a light detector that reports its state many times per second.

Upload and Test

  1. First time with this board? Set it up with ESP32 Uno - Getting Started before you continue.
  2. Build the circuit by following the wiring table above.
  3. Plug in the USB Type-C cable between the ESP32 Uno and your computer.
  4. Select the board in Arduino IDE: pick ESP32 Dev Module and the COM port of the board (CH340).
  5. Paste the code into a new sketch in Arduino IDE.
  6. Press Upload (Upload button) and wait for "Done uploading".
  7. Open the Serial Monitor at 9600 baud.
  8. Shade the sensor with a piece of paper, then remove it.
  9. Pro tip: Shine a phone flashlight on the LDR from about 20 cm. If the message does not flip, the trimmer is set too far one way.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32 Dev Module' on 'COM15')
New Line
9600 baud
The light is present The light is present The light is present The light is NOT present The light is NOT present The light is present The light is NOT present The light is NOT present
Ln 11, Col 1
ESP32 Dev Module on COM15
2

If the DO-LED stays lit all the time, or never lights in the dark, turn the trimmer a little at a time until it changes right at the light level you want. From here, you can switch an LED, a relay lamp or a servo based on the light state. The tutorials linked at the end show how.

ESP32 Uno Code - Light Level from the AO Pin

This sketch reads A0 (GPIO2) and prints the raw brightness value.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-ldr-module */ #define AO_PIN 2 // A0 (GPIO2) reads the AO output of the LDR module void setup() { // open the USB serial link to the computer Serial.begin(9600); // set the ADC attenuation to 11 dB (up to ~3.3V input) analogSetAttenuation(ADC_11db); } void loop() { // read a 12-bit value, 0 (bright) to 4095 (dark) int light_value = analogRead(AO_PIN); Serial.println(light_value); }
Code Part What It Does
#define AO_PIN 2 Names the GPIO wired to the AO pin
analogSetAttenuation(ADC_11db) Widens the ADC input range to about 3.3V
analogRead(AO_PIN) Returns 0 (very bright) to 4095 (very dark)
Serial.println(light_value) Prints the number on its own line

Good to know: the 11 dB attenuation lets the ESP32 Uno analog pin read the full range, from 0V up to about 3.3V. Without it, the value hits 4095 in normal room light and the readings look wrong.

Upload and Test

  1. Paste the code into Arduino IDE.
  2. Click Upload and wait until the IDE says it is done.
  3. Open the Serial Monitor at 9600 baud.
  4. Cover the LDR slowly with your palm, then open your hand again.
  5. Pro tip: Note the number at your desk and the number with the sensor fully covered. The middle of the two is a good starting threshold for your own code.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32 Dev Module' on 'COM15')
New Line
9600 baud
612 618 1034 1987 2841 3502 3896 3961 3958 3420 2266 1415 803 627
Ln 11, Col 1
ESP32 Dev Module on COM15
2

Video Tutorial

See the ESP32 Uno build in action in the video below.

The demo uses the sketch below. It reads AO, smooths the value with an EMA filter, and fades an extra LED on D9 (GPIO13) up as the room gets darker. Its limits (2000, 2200, 2400) fit the 12-bit range.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-ldr-module */ const int LDR_PIN = 2; // A0 (GPIO2) takes the AO signal from the LDR module const int LED_PIN = 13; // D9 (GPIO13) drives the dimmable LED const float ALPHA = 0.1; float emaValue = 0; int currentPWM = 0; int targetPWM = 0; void setup() { Serial.begin(115200); // set the ADC attenuation to 11 dB (up to ~3.3V input) analogSetAttenuation(ADC_11db); pinMode(LED_PIN, OUTPUT); // start the filter from one real reading emaValue = analogRead(LDR_PIN); } void loop() { // ======================================== // 1. Get a fresh light reading (0 - 4095) // ======================================== int rawValue = analogRead(LDR_PIN); // ======================================== // 2. Smooth the reading (moving average) // ======================================== emaValue = ALPHA * rawValue + (1.0 - ALPHA) * emaValue; // ======================================== // 3. Pick a brightness level (12-bit limits) // ======================================== if (emaValue < 2000) { // bright room targetPWM = 0; } else if (emaValue < 2200) { // dim room targetPWM = 70; } else if (emaValue < 2400) { // dusk targetPWM = 150; } else { // night targetPWM = 255; } // ======================================== // 4. Move one step toward the target // ======================================== if (currentPWM < targetPWM) { currentPWM++; } else if (currentPWM > targetPWM) { currentPWM--; } // ======================================== // 5. Send the PWM level to the LED // ======================================== analogWrite(LED_PIN, currentPWM); // ======================================== // 6. Show the values for debugging // ======================================== Serial.print("Raw: "); Serial.print(rawValue); Serial.print(" | EMA: "); Serial.print(emaValue); Serial.print(" | Target PWM: "); Serial.print(targetPWM); Serial.print(" | Current PWM: "); Serial.println(currentPWM); // ======================================== // 7. Short pause between samples // ======================================== delay(20); }

Code Explanation

This table sums up the demo sketch so you can change it with confidence.

Code Part What It Does
ALPHA = 0.1 Sets how strong the smoothing is. Smaller means slower and calmer
emaValue = ALPHA * rawValue + ... Mixes the new reading into the running average
if (emaValue < 2000) ... Maps the average to four brightness levels
currentPWM++ / currentPWM-- Fades one step per loop, so the LED never jumps
analogWrite(LED_PIN, currentPWM) Sends the PWM level to D9 (GPIO13)

With a 20 ms delay, a full fade from off to full takes about 5 seconds.

ESP32 Uno vs UNO R4 for This Project

This shows what changes when the same LDR project moves from the UNO R4 to the ESP32 Uno.

Item Arduino UNO R4 ESP32 Uno
Logic voltage 5V 3.3V
Module VCC 5V or 3.3V 3.3V only
DO pin D2 D2 (GPIO26)
AO pin A0 A0 (GPIO2)
ADC range 0 to 1023 0 to 4095
Extra code line none analogSetAttenuation(ADC_11db)
Arduino IDE board Arduino UNO R4 WiFi ESP32 Dev Module

The wiring stays on the same header pins, so the same diagram works. Just move VCC to 3.3V and multiply any old analog thresholds by about 4.

Go Wireless: Light Meter on Your Phone

Here is one way to put the light level on your phone.

The ESP32 Uno has WiFi and Bluetooth on board. Send the AO value to a phone page and you get a live light meter or a graph of the day turning into night. Note that A0 is an ADC2 pin, so for a WiFi version, move the AO wire to A2 (GPIO35) and change AO_PIN to 35. Bluetooth works with A0 as it is.

Troubleshooting

Problem Possible Cause Solution
Arduino IDE lists no COM port CH340 driver missing or a charge-only cable Install the CH340 driver and try a USB cable that carries data
Upload stops at "Failed to connect" or "Waiting for download" Board did not enter download mode Hold the BOOT button when the upload starts, release it once writing begins
Board does not boot or upload with the module connected A0 (GPIO2) is a boot strapping pin and is pulled the wrong way Unplug the AO wire while uploading, then plug it back in
PWR-LED on the module is dark VCC or GND wire is loose Push both wires in firmly and check they go to 3.3V and GND
Serial Monitor always shows "The light is NOT present" Trimmer set for too much light Turn the trimmer slowly while the sensor sits in normal light
AO reading sits at 4095 in a lit room Attenuation line removed or AO on a wrong pin Keep analogSetAttenuation(ADC_11db) and check that AO goes to A0
AO reading freezes after you add WiFi GPIO2 is ADC2 and WiFi blocks it Move AO to A2 (GPIO35) and set AO_PIN to 35
Serial Monitor prints random symbols Baud rate mismatch Use 9600 baud for the DO and AO sketches and 115200 for the demo
Values jump up and down under a lamp Mains flicker or a noisy LED bulb Average several readings, or use the EMA filter from the demo

FAQ

What does an LDR light sensor module actually measure?

It measures how much light falls on its light-dependent resistor. It gives a relative value, not lux. The reading depends on the part, its temperature and the supply voltage.

Do I need a resistor to wire this module to the ESP32 Uno?

No. The module already has the resistor divider and the comparator on board. Just connect VCC, GND, DO and AO with jumper wires.

Is it safe to run the module from the 5V pin?

Not with the ESP32 Uno. At 5V, the DO and AO pins can output up to 5V, and the board pins are 3.3V only. Run the module from 3.3V and both outputs stay safe.

How do I use two LDR modules in one sketch?

Give each one its own pins and its own #define. For example, put the second DO on D3 (GPIO25) and the second AO on A2 (GPIO35). Then read both inside loop().

My old sketch used 1023 as the top value. What do I change?

The ESP32 Uno ADC is 12-bit, so analogRead() returns 0 to 4095 instead of 0 to 1023. Multiply your old thresholds by about 4, and add analogSetAttenuation(ADC_11db) in setup().

What is the analogSetAttenuation(ADC_11db) line in setup() for?

The line tells the ESP32 Uno ADC to accept inputs from 0V up to roughly 3.3V, so every AO voltage gets its own number between 0 and 4095. With a smaller range, the reading saturates early and dim and bright rooms look the same. The UNO R4 has no such setting, so this line is only needed on the ESP32 Uno. Never let the AO signal go above 3.3V.

Can I read the AO pin while the ESP32 Uno is on WiFi?

Not on A0. A0 (GPIO2) and A1 (GPIO4) are ADC2 pins, and ADC2 cannot be read while WiFi is on. For a WiFi project, move the AO wire to A2–A5 (GPIO35, 34, 36, 39) or GPIO32/33, and change the pin number in the code.

Why does the board refuse to start when the sensor is plugged in?

A0 is GPIO2, one of the pins the chip checks at power-on. If something pulls it the wrong way, the board can fail to boot or upload. Unplug AO during the upload, or move it to A2 (GPIO35) and change the code.

I ran out of Uno header pins. Where can I find more?

The ESP32 Uno has a few extra holes near the power header: GPIO32 and GPIO33 (I/O, PWM, analog on ADC1, so they work while WiFi is on) and GPIO15 (I/O, PWM, analog on ADC2). Add pin headers with a soldering iron, then put the bare GPIO number in your sketch. For a second LDR in a WiFi project, GPIO32 or GPIO33 is the best AO pin. Two warnings: (1) GPIO15 and GPIO0 (the IO0 pin at the unused Uno NC position) are boot strapping pins, and a wrong connection can stop the board from booting or uploading code, so use GPIO32/33 first. (2) Never use the six holes under the digital header (SD0–SD3, CMD, CLK = GPIO6–GPIO11); they go to the flash chip and using them crashes the board.

Should I pick this module or a BH1750 sensor?

Pick the LDR module for cheap light/dark detection and rough light levels. Pick a BH1750 when you need real lux values over I2C. The BH1750 connects to the SDA (GPIO21) and SCL (GPIO22) pins.

Can I build an automatic night light with it?

Yes. Use the DO pin to switch an LED or a relay when it gets dark, or use the demo sketch to fade an LED as the light drops. The trimmer sets when the night light turns on.

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!