LDR modules give you two signals: AO, an analog voltage you can measure, and DO, an on/off output from a comparator whose threshold you set with a screwdriver. The Pico W reads AO on GP27 (ADC1) and DO on any GPIO.
Power it from 3V3 and both outputs are safe for the Pico. The script prints the light level once a second and turns the on-board LED on when it gets dark.
Wiring
| Raspberry Pi Pico W | LDR light sensor module | Wire | Notes |
|---|---|---|---|
| 3V3 | VCC | red | 3V3 is pin 36. Powered from 3.3 V, AO and DO stay inside the Pico’s range. |
| GND | GND | black | |
| GP27 | AO | green | GP27 = ADC1, physical pin 32. |
| GP16 | DO | yellow | GP16 is physical pin 21. |
3.3–5 V part, 3.3 V board. AO swings up to VCC. On ESP32 and Pico, power the module from 3.3 V so AO never exceeds the ADC's 3.3 V limit; on Uno use 5 V.
Board quirks
- On most modules AO falls as light increases; the script inverts it so 100 % means bright. Check yours with a phone torch.
- DO is the LM393 comparator: turn the blue pot until its LED flips at the light level you want — that is your “dusk” threshold with no code changes.
- Do not power the module from VBUS: AO would swing to 5 V, and GP26–GP28 are not 5 V tolerant.
- The on-board LED (
Pin("LED")) lights when DO says “dark”, like a street light.
Code
# LDR light-sensor module on a Raspberry Pi Pico W (MicroPython).
# Wiring: VCC -> 3V3 (pin 36), GND -> GND, AO -> GP27 / ADC1 (pin 32), DO -> GP16 (pin 21).
# Powered from 3V3 the module's outputs never exceed 3.3 V, so no divider is needed.
from machine import ADC, Pin
import time
ao = ADC(27) # analog: lower voltage = more light on most modules
do = Pin(16, Pin.IN) # comparator output, threshold set with the blue pot
led = Pin("LED", Pin.OUT)
def light_percent():
raw = sum(ao.read_u16() for _ in range(8)) // 8
return 100 - raw * 100 // 65535, raw # invert so 100 % = bright
while True:
pct, raw = light_percent()
dark = do.value() == 1 # DO goes HIGH when it is darker than the pot setting
led.value(dark) # on-board LED = "it's dark", like a street light
print("Light {:3d} % (raw {:5d}) DO={} {}".format(pct, raw, do.value(), "dark" if dark else "bright"))
time.sleep(1)# LDR light-sensor module on a Raspberry Pi Pico W (MicroPython).
# Wiring: VCC -> 3V3 (pin 36), GND -> GND, AO -> GP27 / ADC1 (pin 32), DO -> GP16 (pin 21).
# Powered from 3V3 the module's outputs never exceed 3.3 V, so no divider is needed.
from machine import ADC, Pin
import time
ao = ADC(27) # analog: lower voltage = more light on most modules
do = Pin(16, Pin.IN) # comparator output, threshold set with the blue pot
led = Pin("LED", Pin.OUT)
def light_percent():
raw = sum(ao.read_u16() for _ in range(8)) // 8
return 100 - raw * 100 // 65535, raw # invert so 100 % = bright
while True:
pct, raw = light_percent()
dark = do.value() == 1 # DO goes HIGH when it is darker than the pot setting
led.value(dark) # on-board LED = "it's dark", like a street light
print("Light {:3d} % (raw {:5d}) DO={} {}".format(pct, raw, do.value(), "dark" if dark else "bright"))
time.sleep(1)Expected serial output
Light 82 % (raw 11796) DO=0 bright
Light 81 % (raw 12452) DO=0 bright
Light 12 % (raw 57671) DO=1 darkLight 82 % (raw 11796) DO=0 bright Light 81 % (raw 12452) DO=0 bright Light 12 % (raw 57671) DO=1 dark
Common errors
DO never changes
The threshold pot is at one end. Turn it slowly until the module’s DO LED toggles while you cover the LDR.
Percent is backwards
Some modules put the LDR on the other side of the divider. Remove the 100 - in light_percent().