Project 2.2: "Ambient Light Sensor"
🚀 Project 2.2 – Ambient Light Sensor
🎯 What You’ll Learn
- ✅ Goal 1: Read ambient light levels with a photoresistor.
- ✅ Goal 2: Use thresholds to trigger LEDs.
- ✅ Goal 3: Control motors based on light intensity.
- ✅ Goal 4: Build a mini light station.
Key Ideas
- Analog input: Read sensor values.
- Logic: Compare values with thresholds.
- Outputs: LEDs or motors respond.
- Serial print: Monitor sensor readings.
🧱 Blocks Glossary (used in this project)
adcX = machine.ADC(machine.Pin(X))→ Setup analog input.adcX.atten(machine.ADC.ATTN_11DB)→ Configure attenuation.adcX.width(machine.ADC.WIDTH_12BIT)→ Configure resolution.adcX.read()→ Read sensor value.pinX = machine.Pin(X, machine.Pin.OUT)→ LED or motor output.pinX.value(1)→ Turn ON output.pinX.value(0)→ Turn OFF output.time.sleep()→ Delay.
🧰 What You Need
| Part | How many? | Pin connection |
|---|---|---|
| D1 R32 | 1 | USB cable |
| Photoresistor KY‑018 | 1 | Pin 32 (analog input) |
| LED | 1 | Pin 5 |
| Motor (optional) | 1 | Pin 12, Pin 13, Pin 14 |
✅ Before You Start
- USB cable connected
- Sensor wired correctly
- Test print shows:
print("Ready!") # Confirm serial is working
🎮 Microprojects (5 Mini Missions)
🎮 Microproject 2.2.1 – Ambient light reading
Blocks used: Analog input, Serial print
Block sequence:
- Setup photoresistor
- Read value
- Print reading
MicroPython Code:
import machine, time # Import modules
adc32 = machine.ADC(machine.Pin(32)) # Photoresistor on pin 32
adc32.atten(machine.ADC.ATTN_11DB) # Configure attenuation
adc32.width(machine.ADC.WIDTH_12BIT) # Configure resolution
while True: # Infinite loop
value = adc32.read() # Read sensor value
print("Light level:", value) # Serial log
time.sleep(0.5) # Delay
Reflection: Sensor values show ambient light intensity.
Challenge: Try faster refresh (0.2s).
🎮 Microproject 2.2.2 – Automatic night light LED
Blocks used: Analog input, Digital output, Logic
Block sequence:
- Setup sensor + LED
- If light < threshold → LED ON
MicroPython Code:
import machine, time # Import modules
adc32 = machine.ADC(machine.Pin(32)) # Photoresistor input
adc32.atten(machine.ADC.ATTN_11DB)
adc32.width(machine.ADC.WIDTH_12BIT)
pin5 = machine.Pin(5, machine.Pin.OUT) # LED output
while True:
value = adc32.read() # Read sensor value
print("Light level:", value) # Serial log
if value < 1000: # Threshold for darkness
pin5.value(1) # LED ON
print("Night detected: LED ON")
else:
pin5.value(0) # LED OFF
print("Day detected: LED OFF")
time.sleep(0.5)
Reflection: LED turns ON automatically in darkness.
Challenge: Adjust threshold for your environment.
🎮 Microproject 2.2.3 – Configurable light thresholds
Blocks used: Analog input, Logic, Serial input
Block sequence:
- Setup sensor
- Read threshold from user
- Compare values
MicroPython Code:
import machine, time # Import modules
adc32 = machine.ADC(machine.Pin(32)) # Photoresistor input
adc32.atten(machine.ADC.ATTN_11DB)
adc32.width(machine.ADC.WIDTH_12BIT)
pin5 = machine.Pin(5, machine.Pin.OUT) # LED output
threshold = int(input("Enter threshold: ")) # User sets threshold
while True:
value = adc32.read() # Read sensor value
print("Light level:", value)
if value < threshold: # Compare with threshold
pin5.value(1) # LED ON
print("LED ON")
else:
pin5.value(0) # LED OFF
print("LED OFF")
time.sleep(0.5)
Reflection: Threshold configurable by user.
Challenge: Try different thresholds.
🎮 Microproject 2.2.4 – Motor control by light intensity
Blocks used: Analog input, PWM, Logic
Block sequence:
- Setup sensor + motor
- Map light intensity to motor speed
MicroPython Code:
import machine, time # Import modules
adc32 = machine.ADC(machine.Pin(32)) # Photoresistor input
adc32.atten(machine.ADC.ATTN_11DB)
adc32.width(machine.ADC.WIDTH_12BIT)
pin12 = machine.Pin(12, machine.Pin.OUT) # Motor IN3
pin13 = machine.Pin(13, machine.Pin.OUT) # Motor IN4
pwm14 = machine.PWM(machine.Pin(14)) # Motor ENB PWM
pwm14.freq(2000) # Motor frequency
pin12.value(1); pin13.value(0) # Motor forward
while True:
value = adc32.read() # Read sensor value
speed = int(value / 4) # Map 0–4095 to 0–1023
pwm14.duty(speed) # Set motor speed
print("Light:", value, "Speed:", speed) # Serial log
time.sleep(0.5)
Reflection: Motor speed changes with light intensity.
Challenge: Try different mapping formulas.
🎮 Microproject 2.2.5 – Ambient light station
Blocks used: Analog input, Serial print, Digital output
Block sequence:
- Setup sensor + LED
- Print readings continuously
- LED indicates low light
MicroPython Code:
import machine, time # Import modules
adc32 = machine.ADC(machine.Pin(32)) # Photoresistor input
adc32.atten(machine.ADC.ATTN_11DB)
adc32.width(machine.ADC.WIDTH_12BIT)
pin5 = machine.Pin(5, machine.Pin.OUT) # LED output
while True:
value = adc32.read() # Read sensor value
print("Ambient light station:", value) # Serial log
if value < 800: # Threshold
pin5.value(1) # LED ON
print("Low light alert: LED ON")
else:
pin5.value(0) # LED OFF
print("Light OK: LED OFF")
time.sleep(1)
Reflection: Station monitors light and alerts with LED.
Challenge: Add buzzer for stronger alert.
✨ Main project – Ambient light sensor
🔧 Blocks steps (with glossary)
- Analog input: Read photoresistor with
adc32.read(). - Logic: Compare readings with thresholds.
- Digital output: LED ON/OFF with
pin5.value(1/0). - PWM output: Motor speed with
pwm14.duty(value). - Serial print: Monitor values in terminal.
🐍 MicroPython code (mirroring blocks, comentarios línea por línea)
# Project 2.2 – Ambient Light Sensor
import machine, time # Importa módulos: machine para pines/ADC, time para delays
adc32 = machine.ADC(machine.Pin(32)) # Configura ADC en pin 32 para el fotoresistor
adc32.atten(machine.ADC.ATTN_11DB) # Atenuación 11 dB para rango amplio de voltaje
adc32.width(machine.ADC.WIDTH_12BIT) # Resolución a 12 bits (0–4095)
pin5 = machine.Pin(5, machine.Pin.OUT) # LED en pin 5 como salida digital
pin12 = machine.Pin(12, machine.Pin.OUT) # Motor IN3 (dirección) como salida
pin13 = machine.Pin(13, machine.Pin.OUT) # Motor IN4 (dirección) como salida
pwm14 = machine.PWM(machine.Pin(14)) # Motor ENB (velocidad) con PWM en pin 14
pwm14.freq(2000) # Fija frecuencia PWM a 2000 Hz
pin12.value(1) # Configura motor hacia adelante: IN3 HIGH
pin13.value(0) # Configura motor hacia adelante: IN4 LOW
dark_threshold = 900 # Umbral para “poca luz” (ajustable)
print("Ambient Light Main Project Ready") # Mensaje de inicio por serial
while True: # Bucle infinito
value = adc32.read() # Lee nivel de luz (0–4095)
print("Light:", value) # Muestra el valor por serial
if value < dark_threshold: # Si hay poca luz según umbral
pin5.value(1) # Enciende LED (luz nocturna)
print("LED ON (night)") # Mensaje por serial
else: # Si hay suficiente luz
pin5.value(0) # Apaga LED
print("LED OFF (day)") # Mensaje por serial
speed = int(value / 4) # Mapea 0–4095 a 0–1023 para PWM
pwm14.duty(speed) # Ajusta velocidad del motor con PWM
print("Motor speed (duty):", speed) # Muestra velocidad por serial
time.sleep(0.5) # Pequeño delay para estabilidad
📖 External explanation
Este proyecto integra lectura analógica, comparación con umbrales y control de salidas. El fotoresistor mide brillo, el LED indica noche/día y el motor ajusta su velocidad según la intensidad de luz. Con impresiones por serial, los estudiantes observan el ciclo completo de percepción y acción.
🕵️ Debugging (2 common problems)
🐞 Debugging 2.2.A – Out-of-range values
- Problema: Lecturas solo 0 o 4095.
- Causas: Cableado incorrecto o atenuación inadecuada.
- Arreglo:
adc32 = machine.ADC(machine.Pin(32)) # Verifica pin correcto adc32.atten(machine.ADC.ATTN_11DB) # Usa 11 dB para rango amplio adc32.width(machine.ADC.WIDTH_12BIT) # Asegura 12 bits - Por qué funciona: Rango y resolución correctos estabilizan la lectura.
🐞 Debugging 2.2.B – Slow response
- Problema: Cambios de luz tardan en reflejarse.
- Causas: Delay demasiado largo.
- Arreglo:
time.sleep(0.2) # Reduce el delay para refresco más rápido - Por qué funciona: Mayor frecuencia de lectura mejora la sensibilidad percibida.
✅ Final checklist
- Wiring verificado: Fotoresistor a pin 32 (ADC), LED a pin 5, motor a 12/13/14.
- Atenuación y resolución configuradas:
ATTN_11DB,WIDTH_12BIT. - Umbral funcional: LED responde a luz ambiental.
- PWM activo: Motor ajusta velocidad según luz.
- Serial útil: Lecturas y estados visibles.
📚 Extras
- Tip estudiante: Cambia
dark_thresholdpara adaptar el sistema a tu aula. - Tip docente: Muestra cómo el mapeo
value/4convierte 0–4095 a 0–1023. - Glosario: Analog input, threshold, PWM, duty cycle.
- Mini tip: Prueba primero solo el ADC y
print(value)antes de añadir LED/motor.