Project 2.10: "Intelligent Environment Control"
๐ Project 2.10 โ Intelligent Environment Control
ย
๐ฏ What Youโll Learn
- โ Goal 1: Automatically control ambient lighting with a photoresistor (light sensor).
- โ Goal 2: Change RGB colors based on light intensity.
- โ Goal 3: Switch between automatic day/night modes.
- โ Goal 4: Create smooth color transitions.
- โ Goal 5: Add custom configuration (thresholds and brightness limits).
Key Ideas
- Short definition: A photoresistor changes its reading with light, letting your robot adapt its lights.
- Realโworld link: Smart bulbs and garden lights autoโadjust brightness at dusk and dawn.
๐งฑ Blocks Glossary
- Analog input (photoresistor):
adc32 = machine.ADC(machine.Pin(32))โ Create ADC on pin 32.adc32.atten(machine.ADC.ATTN_11DB)โ Set attenuation for wider voltage range.adc32.width(machine.ADC.WIDTH_12BIT)โ 12โbit resolution (0โ4095).adc32.read()โ Read light value.
- RGB outputs (PWM):
pwm2 = machine.PWM(machine.Pin(2))โ Red channel.pwm4 = machine.PWM(machine.Pin(4))โ Green channel.pwm5 = machine.PWM(machine.Pin(5))โ Blue channel.pwmX.duty(value)โ Brightness (0โ1023 typical).pwmX.freq(2000)โ Optional PWM frequency set.
- Control:
while True:โ Continuous loop.for i in range(start, stop, step):โ Smooth stepping.if / elif / else:โ Mode logic.
- Serial:
print("...")โ Feedback messages.
๐งฐ What You Need
| Part | How many? | Pin connection |
|---|---|---|
| D1 R32 | 1 | USB |
| Photoresistor module | 1 | ADC pin 32 |
| RGB LED (common) | 1 | Red=2, Green=4, Blue=5 |
๐ Wiring tip: Connect photoresistor module output to pin 32 (ADC). Use pins 2/4/5 for RGB PWM outputs. Ensure common ground between sensor and board.
โ Before You Start
print("Ready!") # Print startup message to confirm serial monitor works
๐ฎ Microprojects (1โ5)
๐ฎ Microproject 2.10.1 โ Automatic ambient lighting
Goal: Dim or brighten a light based on sensor reading.
# Automatic ambient lighting # Title: auto brightness by light sensor
import machine, time # Import machine for ADC/PWM and time for delays
adc32 = machine.ADC(machine.Pin(32)) # Create ADC on pin 32 for photoresistor
adc32.atten(machine.ADC.ATTN_11DB) # Set 11dB attenuation for wider input range
adc32.width(machine.ADC.WIDTH_12BIT) # Use 12-bit resolution (0โ4095 values)
pwm2 = machine.PWM(machine.Pin(2)) # Setup PWM on pin 2 for Red LED channel
pwm2.freq(2000) # Optional: set PWM frequency to 2000 Hz
print("Ambient lighting ready") # Serial confirmation
while True: # Continuous loop
light = adc32.read() # Read current light intensity from sensor
duty = min(1023, max(0, 1023 - light // 4)) # Map light to duty (brighter when darker)
pwm2.duty(duty) # Apply computed duty to Red LED
print("Light:", light, "Duty:", duty) # Print readings and output for debugging
time.sleep(0.2) # Small delay for stability
- Reflection: The LED brightens in darkness and dims in bright light.
- Challenge: Invert the behavior so it gets brighter when light increases.
๐ฎ Microproject 2.10.2 โ Color change due to light intensity
Goal: Use light ranges to select colors (Blue in dark, Green medium, Red bright).
# Color change due to light intensity # Title: choose colors by light ranges
import machine, time # Import libraries
adc32 = machine.ADC(machine.Pin(32)) # ADC on pin 32 for photoresistor
adc32.atten(machine.ADC.ATTN_11DB) # Set attenuation for full-scale input
adc32.width(machine.ADC.WIDTH_12BIT) # 12-bit resolution for precise readings
pwm2 = machine.PWM(machine.Pin(2)) # Red channel PWM on pin 2
pwm4 = machine.PWM(machine.Pin(4)) # Green channel PWM on pin 4
pwm5 = machine.PWM(machine.Pin(5)) # Blue channel PWM on pin 5
pwm2.freq(2000) # Optional frequency set for Red
pwm4.freq(2000) # Optional frequency set for Green
pwm5.freq(2000) # Optional frequency set for Blue
print("Color change by light ready") # Serial confirmation
while True: # Loop forever
light = adc32.read() # Read light intensity
print("Light:", light) # Show raw light value
if light < 1200: # Dark range
pwm2.duty(0) # Red OFF
pwm4.duty(0) # Green OFF
pwm5.duty(800) # Blue ON (cool in dark)
elif light < 2800: # Medium range
pwm2.duty(0) # Red OFF
pwm4.duty(800) # Green ON (comfortable medium)
pwm5.duty(0) # Blue OFF
else: # Bright range
pwm2.duty(800) # Red ON (warm in bright light)
pwm4.duty(0) # Green OFF
pwm5.duty(0) # Blue OFF
time.sleep(0.2) # Stabilize loop
- Reflection: Color shifts clearly with light levels.
- Challenge: Add Yellow (Red+Green) for very bright conditions.
๐ฎ Microproject 2.10.3 โ Automatic day/night modes
Goal: Switch entire behavior between Night and Day modes using thresholds.
# Automatic day/night modes # Title: mode switching by thresholds
import machine, time # Import required modules
adc32 = machine.ADC(machine.Pin(32)) # ADC for light sensor
adc32.atten(machine.ADC.ATTN_11DB) # 11dB attenuation for broad range
adc32.width(machine.ADC.WIDTH_12BIT) # 12-bit ADC resolution
pwm2 = machine.PWM(machine.Pin(2)) # Red PWM output
pwm4 = machine.PWM(machine.Pin(4)) # Green PWM output
pwm5 = machine.PWM(machine.Pin(5)) # Blue PWM output
night_threshold = 1400 # Light value below this is Night
day_threshold = 2600 # Light value above this is Day
mode = "Day" # Start in Day mode
print("Day/Night modes ready") # Serial start message
while True: # Continuous check loop
light = adc32.read() # Read sensor value
print("Light:", light, "Mode:", mode) # Show current reading and mode
if light < night_threshold: # Decide Night mode
mode = "Night" # Set mode to Night
elif light > day_threshold: # Decide Day mode
mode = "Day" # Set mode to Day
if mode == "Night": # Behavior in Night mode
pwm5.duty(900) # Blue bright for calm night
pwm4.duty(200) # Green low accent
pwm2.duty(0) # Red off
else: # Behavior in Day mode
pwm2.duty(900) # Red bright for warm day
pwm4.duty(600) # Green medium
pwm5.duty(0) # Blue off
time.sleep(0.2) # Small delay
- Reflection: Modes switch cleanly with hysteresis thresholds.
- Challenge: Add a โSunsetโ intermediate mode when light is between thresholds.
๐ฎ Microproject 2.10.4 โ Smooth color transitions
Goal: Fade LED brightness smoothly up and down.
# Smooth color transitions # Title: fading with incremental steps
import machine, time # Import machine and time
pwm2 = machine.PWM(machine.Pin(2)) # Red PWM channel
pwm4 = machine.PWM(machine.Pin(4)) # Green PWM channel
pwm5 = machine.PWM(machine.Pin(5)) # Blue PWM channel
pwm2.freq(2000) # Optional frequency set
pwm4.freq(2000) # Optional frequency set
pwm5.freq(2000) # Optional frequency set
print("Smooth transition demo") # Serial confirmation
for i in range(0, 901, 30): # Fade up steps from 0 to 900
pwm2.duty(i) # Set Red brightness to i
pwm4.duty(max(0, 900 - i)) # Set Green inverse brightness
pwm5.duty(i // 2) # Set Blue half brightness
time.sleep(0.05) # Short pause to see transition
for i in range(900, -1, -30): # Fade down from 900 to 0
pwm2.duty(i) # Red down
pwm4.duty(max(0, 900 - i)) # Green inverse down
pwm5.duty(i // 2) # Blue down
time.sleep(0.05) # Pause per step
- Reflection: Gradual changes look natural and pleasing.
- Challenge: Tie the fade speed to light intensity (faster fades in bright light).
๐ฎ Microproject 2.10.5 โ Custom configuration
Goal: Set thresholds and brightness limits; show them in serial.
# Custom configuration # Title: tweakable settings for behavior
import machine, time # Import machine/time (future use)
night_threshold = 1400 # Threshold for Night detection
day_threshold = 2600 # Threshold for Day detection
max_brightness = 900 # Upper limit for PWM duty
min_brightness = 100 # Lower limit for PWM duty
fade_step = 30 # Step size for smooth transitions
print("Config loaded") # Confirm settings loaded
print("Night threshold:", night_threshold) # Show Night threshold
print("Day threshold:", day_threshold) # Show Day threshold
print("Brightness range:", min_brightness, "to", max_brightness) # Show brightness limits
print("Fade step:", fade_step) # Show fade step size
- Reflection: Clear configuration helps teachers and students calibrate easily.
- Challenge: Add a โprofileโ switch (Comfort vs Energy Saver) that changes these values.
โจ Main Project โ Intelligent Environment Control (complete)
Goal: Combine sensor reading, modes, color mapping, smooth transitions, and custom configs.
# Project 2.10 โ Intelligent Environment Control # Title: full smart lighting system
import machine, time # Import machine/time for IO and timing
adc32 = machine.ADC(machine.Pin(32)) # ADC on pin 32 for photoresistor
adc32.atten(machine.ADC.ATTN_11DB) # Use 11dB attenuation for broad input range
adc32.width(machine.ADC.WIDTH_12BIT) # Set ADC to 12-bit resolution (0โ4095)
pwm2 = machine.PWM(machine.Pin(2)) # Red PWM output on pin 2
pwm4 = machine.PWM(machine.Pin(4)) # Green PWM output on pin 4
pwm5 = machine.PWM(machine.Pin(5)) # Blue PWM output on pin 5
pwm2.freq(2000) # Optional PWM frequency (Red)
pwm4.freq(2000) # Optional PWM frequency (Green)
pwm5.freq(2000) # Optional PWM frequency (Blue)
night_threshold = 1400 # Night threshold (calibrate in classroom)
day_threshold = 2600 # Day threshold (calibrate in classroom)
max_brightness = 900 # Max duty to avoid over-bright LEDs
min_brightness = 100 # Min duty for visible dim light
fade_step = 30 # Fade step for smooth transitions
mode = "Day" # Start in Day mode
print("Intelligent Environment Control ready") # Serial start message
while True: # Main control loop
light = adc32.read() # Read current light value (0โ4095)
print("Light:", light, "Mode:", mode) # Show reading and current mode
if light < night_threshold: # If light indicates night
mode = "Night" # Switch to Night mode
elif light > day_threshold: # If light indicates day
mode = "Day" # Switch to Day mode
else: # Between thresholds
mode = "Transition" # Use Transition mode
if mode == "Night": # Night behavior (cool calm)
target_r = min_brightness # Red low
target_g = min_brightness # Green low
target_b = max_brightness # Blue high
elif mode == "Day": # Day behavior (warm bright)
target_r = max_brightness # Red high
target_g = max_brightness // 2 # Green medium
target_b = 0 # Blue off
else: # Transition behavior (balanced)
target_r = max_brightness // 2 # Red medium
target_g = max_brightness // 2 # Green medium
target_b = max_brightness // 3 # Blue low
current_r = 0 # Start current Red duty (simple demo)
current_g = 0 # Start current Green duty
current_b = 0 # Start current Blue duty
while current_r != target_r or current_g != target_g or current_b != target_b: # Fade loop until targets
current_r = current_r + fade_step if current_r < target_r else max(target_r, current_r - fade_step) # Step Red
current_g = current_g + fade_step if current_g < target_g else max(target_g, current_g - fade_step) # Step Green
current_b = current_b + fade_step if current_b < target_b else max(target_b, current_b - fade_step) # Step Blue
current_r = min(max(0, current_r), max_brightness) # Clamp Red within limits
current_g = min(max(0, current_g), max_brightness) # Clamp Green within limits
current_b = min(max(0, current_b), max_brightness) # Clamp Blue within limits
pwm2.duty(current_r) # Apply Red duty
pwm4.duty(current_g) # Apply Green duty
pwm5.duty(current_b) # Apply Blue duty
time.sleep(0.04) # Small delay for smooth fade
time.sleep(0.2) # Rest before next sensor read
๐ External Explanation
- What it teaches: Reading analog sensors, mapping values, using thresholds for modes, and PWM for color/brightness.
- Why it works: The photoresistor provides a light value; thresholds pick modes; PWM sets smooth brightness; the loop keeps adapting.
- Key concept: Sensor inputs guide outputs in real time using readable, adjustable parameters.
โจ Story Time
Imagine your room after sunset: lights gently fade cooler as darkness grows, and at dawn they warm up again. Your robot becomes a small โambience artist,โ tuning colors to the worldโs rhythm.
๐ต๏ธ Debugging (2)
๐ Debugging 2.10.A โ Sudden changes in color
- Symptom: Colors jump abruptly when light moves around thresholds.
- Cause: Target values applied instantly with no fade or narrow thresholds.
- Fix:
fade_step = 20 # Use smaller steps for smoother changes
time.sleep(0.04) # Keep short delays to see gradual transitions
๐ Debugging 2.10.B โ It does not adapt to conditions
- Symptom: Lights stay in one mode or brightness feels wrong.
- Cause: Thresholds not calibrated for classroom hardware/lighting.
- Fix:
night_threshold = 1600 # Raise/lower Night threshold after testing
day_threshold = 2400 # Adjust Day threshold for reliable switching
print("Light:", adc32.read()) # Print values and tune thresholds accordingly
โ Final Checklist
- Photoresistor reads stable values (printed in serial).
- RGB channels respond and change duty correctly.
- Modes switch between Night/Day/Transition as expected.
- Fades are smooth without sudden jumps.
- Configuration values are visible and adjustable.
๐ Extras
- ๐ง Student tip: Note typical light values in your room (morning, noon, evening) to set good thresholds.
- ๐งโ๐ซ Instructor tip: Run a threshold calibration exercise; have learners plot sensor values over time.
- ๐ Glossary: ADC, attenuation, resolution, PWM, duty, threshold, fade.
- ๐ก Mini tips:
- Keep duty under 900 to avoid LED glare.
- Add a โComfortโ profile with warmer colors in Night mode.
- Print mode changes to help students see state transitions.