from machine import ADC, Pin, PWM, I2C, SPI, Timer
from ssd1306 import SSD1306_I2C
from time import sleep, ticks_ms
# ================= INPUT SUBROUTINES =================
# Initialize hardware components
BUZZER = PWM(Pin(15)) # Buzzer for feedback when button is pressed
BUZZER.freq(2000) # Set buzzer frequency to 2000Hz
BUZZER.duty(0) # Start with buzzer off
LED = PWM(Pin(2)) # LED with PWM for brightness control
LED.freq(1000) # Set PWM frequency for LED to ensure smooth dimming
BUTTON = Pin(12, Pin.IN, Pin.PULL_DOWN) # Button with pull-down resistor
POT = ADC(Pin(34)) # Potentiometer for manual brightness control
LIGHT_SENSOR = ADC(Pin(14)) # Light sensor for ambient light measurement
i2c = I2C(0, scl=Pin(22), sda=Pin(21)) # I2C communication for OLED display
# Setup OLED display
spi = SPI(1, baudrate=5000000, polarity=0, phase=0)
oled_width = 128
oled_height = 64
oled = SSD1306_I2C(oled_width, oled_height, i2c)
# Define lamp operating modes
modes = ["off", "on", "auto"] # Modes: Off, Manual On, Auto (sensor-based)
mode = [0] # Start in "off" mode
last_press_time = [0] # Track last button press time for debouncing
# Function to debounce and toggle lamp mode when button is pressed
def debounce_toggle_lamp(pin):
current_time = ticks_ms() # Get current time in milliseconds
if current_time - last_press_time[0] > 300: # Check if 300ms has passed since last press
last_press_time[0] = current_time # Update last press time
mode[0] = (mode[0] + 1) % len(modes) # Cycle through modes
BUZZER.duty(512) # Activate buzzer for feedback
sleep(0.01) # Short delay for beep
BUZZER.duty(0) # Turn off buzzer
# Function to read light sensor value and convert it to 0-99 range
def read_light():
raw_adc = LIGHT_SENSOR.read() # Read ADC value (0-4095)
lux = 100 - (raw_adc / 4095) * 100 # Invert the mapping
return int(lux) # Return scaled lux value
# Function to read potentiometer value and scale it to 0-1023 range
def read_pot():
return POT.read() // 4 # Scale ADC (0-4095) to 0-1023
# ================= OUTPUT SUBROUTINES =================
# Function to update OLED display periodically
def update_display(timer):
oled.fill(0) # Clear display
oled.text(f"Light: {read_light()} lux", 0, 0) # Display light level
oled.text(f"Lamp: {modes[mode[0]]}", 0, 10) # Display current mode
oled.show() # Refresh display
# Configure button interrupt to switch modes with debounce
BUTTON.irq(trigger=Pin.IRQ_FALLING, handler=debounce_toggle_lamp)
# Setup periodic OLED display update
timer = Timer(0)
timer.init(period=500, mode=Timer.PERIODIC, callback=update_display)
# Define brightness levels for different light sensor values
lux_levels = [0, 10, 25, 40, 60, 80, 99] # ADC lux values from 0 to 99
brightness_levels = [1023, 900, 700, 300, 100, 50, 0] # Corresponding brightness levels (0-1023)
# Function to interpolate brightness based on measured lux
def interpolate_brightness(lux):
for i in range(len(lux_levels) - 1): # Iterate through defined brightness levels
if lux_levels[i] <= lux <= lux_levels[i + 1]: # Find range where lux fits
ratio = (lux - lux_levels[i]) / (lux_levels[i + 1] - lux_levels[i]) # Compute ratio
return int(brightness_levels[i] + ratio * (brightness_levels[i + 1] - brightness_levels[i])) # Linear interpolation
return brightness_levels[-1] # Default to max brightness if out of range
# Define LED brightness functions for different modes
def mode_off():
return 0 # LED off in "off" mode
def mode_on(pot_value):
return pot_value # Use potentiometer value in "on" mode
def mode_auto(lux):
return interpolate_brightness(lux) # Adjust brightness based on ambient light in "auto" mode
# ================= MAIN ROUTINE =================
# Main loop
while True:
pot_value = read_pot() * (mode[0] == 1) # Read potentiometer only in "on" mode
lux = read_light() * (mode[0] == 2) # Read light sensor only in "auto" mode
brightness = [mode_off(), mode_on(pot_value), mode_auto(lux)][mode[0]] # Select brightness based on mode
print(f"Mode: {modes[mode[0]]}, Lux: {lux}, Potentiometer: {pot_value}, Brightness: {brightness}") # Debug output
LED.duty(brightness) # Set LED brightness
sleep(0.1) # Small delay to prevent flickering