from machine import Pin, PWM, Timer
import time
LED_PIN = 33
RED_PIN = 25
GREEN_PIN = 26
BLUE_PIN = 27
BUTTON_PIN = 15
FREQ_HZ = 1000 # PWM frequency: 1 kHz
DEBOUNCE_MS = 300 # Thoi gian chong nhieu nut nhan (ms)
MODE_NAMES = {
1: "LED Blinking",
2: "PWM Brightness Control",
3: "RGB Color Cycling"
}
COLORS = [
(100, 0, 0, "Red"),
( 0, 100, 0, "Green"),
( 0, 0, 100, "Blue"),
(100, 100, 0, "Yellow"),
( 0, 100, 100, "Cyan"),
(100, 0, 100, "Magenta"),
(100, 100, 100, "White"),
]
current_mode = 1
mode_changed = True # True de khoi tao Mode 1 khi bat dau
last_press_time = 0
led_state = 0 # Trang thai LED cho Mode 1
led_pwm = None
red_pwm = None
green_pwm = None
blue_pwm = None
timer0 = Timer(0)
button = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
def percent_to_duty(pct):
"""Chuyen % (0-100) sang gia tri duty 10-bit (0-1023)."""
return int(pct / 100 * 1023)
def button_isr(pin):
"""ISR: Doi che do khi nhan nut, co chong nhieu bang phan mem."""
global current_mode, mode_changed, last_press_time
now = time.ticks_ms()
if time.ticks_diff(now, last_press_time) > DEBOUNCE_MS:
last_press_time = now
# Chuyen sang mode tiep theo: 1 -> 2 -> 3 -> 1 ...
current_mode = current_mode % 3 + 1
mode_changed = True
def timer_callback(t):
"""Timer callback: Toggle LED moi 1 giay (chi hoat dong o Mode 1)."""
global led_state
if current_mode == 1 and led_pwm is not None:
led_state = not led_state
try:
led_pwm.duty(1023 if led_state else 0)
except:
pass
# Don dep tai nguyen
def cleanup_all():
"""Dung timer va tat tat ca LED/PWM."""
global led_pwm, red_pwm, green_pwm, blue_pwm
# Dung timer truoc de tranh callback truy cap PWM da bi huy
try:
timer0.deinit()
except:
pass
# Tat va huy PWM LED don
if led_pwm is not None:
try:
led_pwm.duty(0)
led_pwm.deinit()
except:
pass
led_pwm = None
# Tat va huy PWM RGB
for pwm_ref in ['red_pwm', 'green_pwm', 'blue_pwm']:
obj = globals().get(pwm_ref)
if obj is not None:
try:
obj.duty(0)
obj.deinit()
except:
pass
globals()[pwm_ref] = None
red_pwm = None
green_pwm = None
blue_pwm = None
# Chuyen che do
def enter_mode(mode):
"""Chuyen sang che do moi: don dep cu, khoi tao moi, in thong bao."""
global led_pwm, red_pwm, green_pwm, blue_pwm, led_state
# Don dep che do truoc
cleanup_all()
print(f"Current Mode: {MODE_NAMES[mode]}")
if mode == 1:
# Mode 1: Timer toggle LED
led_state = 0
led_pwm = PWM(Pin(LED_PIN), freq=FREQ_HZ, duty=0)
timer0.init(period=1000, mode=Timer.PERIODIC, callback=timer_callback)
elif mode == 2:
# Mode 2: PWM fading (xu ly trong main loop)
led_pwm = PWM(Pin(LED_PIN), freq=FREQ_HZ, duty=0)
elif mode == 3:
# Mode 3: RGB cycling (xu ly trong main loop)
red_pwm = PWM(Pin(RED_PIN), freq=FREQ_HZ, duty=0)
green_pwm = PWM(Pin(GREEN_PIN), freq=FREQ_HZ, duty=0)
blue_pwm = PWM(Pin(BLUE_PIN), freq=FREQ_HZ, duty=0)
# Dieu khien PWM cho Mode 2 va Mode 3
def pwm_fade():
"""Mode 2: Tang dan do sang 0% -> 100% roi giam 100% -> 0%."""
STEP = 5
DELAY_MS = 20
# Fade up: 0% -> 100%
for brightness in range(0, 101, STEP):
if current_mode != 2:
return
led_pwm.duty(percent_to_duty(brightness))
time.sleep_ms(DELAY_MS)
# Fade down: 100% -> 0%
for brightness in range(100, -1, -STEP):
if current_mode != 2:
return
led_pwm.duty(percent_to_duty(brightness))
time.sleep_ms(DELAY_MS)
def rgb_cycle():
HOLD_MS = 50 # Kiem tra mode moi 50 ms
HOLD_STEPS = 20 # 20 x 50 ms = 1 giay moi mau
for r, g, b, name in COLORS:
if current_mode != 3:
return
red_pwm.duty(percent_to_duty(r))
green_pwm.duty(percent_to_duty(g))
blue_pwm.duty(percent_to_duty(b))
for _ in range(HOLD_STEPS):
if current_mode != 3:
return
time.sleep_ms(HOLD_MS)
print()
print("*" * 50)
print(" Lab 3 - Exercise 3: Mini Project")
print(" Event-Driven LED Controller")
print("*" * 50)
print()
print(f" LED : GPIO {LED_PIN}")
print(f" RGB LED : GPIO {RED_PIN} (R), {GREEN_PIN} (G), {BLUE_PIN} (B)")
print(f" Button : GPIO {BUTTON_PIN} (PULL_UP)")
print(f" Debounce : {DEBOUNCE_MS} ms")
print()
print(" Mode 1: LED Blinking (Timer 1s)")
print(" Mode 2: PWM Brightness Control")
print(" Mode 3: RGB Color Cycling")
print()
print(" Press button to switch mode.")
print()
# Gan ISR cho nut nhan (canh xuong = nhan nut)
button.irq(trigger=Pin.IRQ_FALLING, handler=button_isr)
try:
while True:
# Kiem tra co chuyen mode khong
if mode_changed:
mode_changed = False
enter_mode(current_mode)
# Thuc thi hanh vi cua mode hien tai
if current_mode == 1:
# Mode 1: Timer xu ly het, main loop chi doi
time.sleep_ms(100)
elif current_mode == 2:
# Mode 2: Fading lien tuc
pwm_fade()
elif current_mode == 3:
# Mode 3: Doi mau RGB lien tuc
rgb_cycle()
except KeyboardInterrupt:
cleanup_all()
button.irq(handler=None)
print("\nProgram stopped by user.")