Traffic Light Control System

Objective:

Understand a MicroPython system that controls a set of traffic lights using buttons and timers.

Components:

  • 3 LEDs (Red, Yellow, Green)
  • 4 Buttons (Red, Yellow, Green, Blue)
  • Dictionary comprehensions provide a concise method to generate dictionaries.
  • Debouncing is crucial for accurate button press detection.

Additional Notes:

Program Flow and Structure

Program Structure:

              Initialization        		   
                    |
                    | 
                    V            
                Mode Switch
                /         \
               /           \
          Auto Mode    Manual Mode
              |              |
              |              |                 			|
              V              V
        Switch Light    Check Button

Note: The blue button toggles between the auto and manual modes.

  Mode Switch

  Traffic Light Auto

  Traffic Light  Manual

Soution1 🔗

Button Debounce with Timer and IRQ Flag

Code Overview & Initialization

from machine import Pin, Timer
import utime

color_and_pin_list = [('red', 23), ('yellow', 22), ('green', 21)]
leds = {color: Pin(pin, Pin.OUT) for color, pin in color_and_pin_list}

button_and_pin_list = [('red_b', 32), ('yellow_b', 33), ('green_b', 25), ('blue_b', 4)]
buttons = {color: Pin(pin, Pin.IN, Pin.PULL_UP) for color, pin in button_and_pin_list}

auto_mode = True
  • Libraries machine and utime are imported.
  • LEDs and buttons are defined and initialized.
  • A variable auto_mode determines the operating mode.

Timers and Automatic Mode

def change_light(t):
    if leds['red'].value():
        leds['red'].off()
        leds['green'].on()
        auto_mode_timer.init(period=700, mode=Timer.ONE_SHOT, callback=change_light)
    elif leds['green'].value():
        leds['green'].off()
        leds['yellow'].on()
        auto_mode_timer.init(period=200, mode=Timer.ONE_SHOT, callback=change_light)
    else:
        leds['yellow'].off()
        leds['red'].on()
        auto_mode_timer.init(period=500, mode=Timer.ONE_SHOT, callback=change_light)

auto_mode_timer = Timer(0)
leds['green'].on()
auto_mode_timer.init(period=700, mode=Timer.ONE_SHOT, callback=change_light)
  • The function change_light controls the sequence of traffic light changes.
  • The timer auto_mode_timer periodically calls this function.

Manual Mode and Button Checks

def check_buttons(t):
    if not buttons['red_b'].value():
        leds['red'].on()
        leds['yellow'].off()
        leds['green'].off()
    elif not buttons['yellow_b'].value():
        leds['red'].off()
        leds['yellow'].on()
        leds['green'].off()
    elif not buttons['green_b'].value():
        leds['red'].off()
        leds['yellow'].off()
        leds['green'].on()

button_check_timer = Timer(1)
#button_check_timer.init(period=50, mode=Timer.PERIODIC, callback=check_buttons)        
  • The function check_buttons checks if any button is pressed and adjusts the LED state accordingly.
  • The timer button_check_timer is prepared to check button presses periodically in manual mode.

Toggle Mechanism and Interrupts

def toggle_auto_mode(pin):
    global auto_mode, irq_isenable
    if irq_isenable:
        auto_mode = not auto_mode
        irq_isenable = False
        Timer(-1).init(mode=Timer.ONE_SHOT, period=200, callback=enable_irq)
        if auto_mode:
           button_check_timer.deinit()
           auto_mode_timer.init(period=700, mode=Timer.ONE_SHOT, callback=change_light)
        else:
           auto_mode_timer.deinit()
           button_check_timer.init(period=50, mode=Timer.PERIODIC, callback=check_buttons)        
        print("自動模式:", auto_mode)

blue_button = buttons['blue_b']
blue_button.irq(trigger=Pin.IRQ_FALLING, handler=toggle_auto_mode)
  • The toggle_auto_mode function switches between automatic and manual modes.
  • An interrupt is attached to the blue button to activate this function when pressed.
  • Button debounce is achieved by using timer and irq_enable flag

Main Loop

print("自動模式:", auto_mode)
while True:
    utime.sleep_ms(50)
  • The main loop keeps the program running indefinitely.
  • A minor delay is added to prevent the loop from occupying the CPU excessively.

Solution2 🔗

Button Debounce with Time Tick Difference

Initialization & Configuration

from machine import Pin, Timer
import utime

color_and_pin_list = [('red', 23), ('yellow', 22), ('green', 21)]
leds = {color: Pin(pin, Pin.OUT) for color, pin in color_and_pin_list}

button_and_pin_list = [('red_b', 32), ('yellow_b', 33), ('green_b', 25), ('blue_b', 4)]
buttons = {color: Pin(pin, Pin.IN, Pin.PULL_UP) for color, pin in button_and_pin_list}
  • Import necessary modules.
  • LEDs and buttons are initialized with their respective pins.
  • Dictionary comprehensions are utilized for concise code representation.

Automated Light Change Logic

def change_light(t):
    if leds['red'].value():
        leds['red'].off()
        leds['green'].on()
        auto_mode_timer.init(period=700, mode=Timer.ONE_SHOT, callback=change_light)
    elif leds['green'].value():
        leds['green'].off()
        leds['yellow'].on()
        auto_mode_timer.init(period=200, mode=Timer.ONE_SHOT, callback=change_light)
    else:
        leds['yellow'].off()
        leds['red'].on()
        auto_mode_timer.init(period=500, mode=Timer.ONE_SHOT, callback=change_light)
  • The change_light function manages the LED transitions based on their current state.
  • Different time intervals are set for each transition to simulate realistic traffic light behavior.

Manual Mode Logic

def check_buttons(t):
    if not buttons['red_b'].value():
        leds['red'].on()
        leds['yellow'].off()
        leds['green'].off()
    elif not buttons['yellow_b'].value():
        leds['red'].off()
        leds['yellow'].on()
        leds['green'].off()
    elif not buttons['green_b'].value():
        leds['red'].off()
        leds['yellow'].off()
        leds['green'].on()
  • The check_buttons function assesses which button has been pressed.
  • Depending on the button pressed, the corresponding LED is activated.

Timer Initialization and System Start

auto_mode_timer = Timer(0)
leds['green'].on()
auto_mode_timer.init(period=700, mode=Timer.ONE_SHOT, callback=change_light)

button_check_timer = Timer(1)
  • Initialize timers for the automatic mode and button checks.
  • At startup, the green LED is turned on, and the automatic mode timer begins.

Debounce Logic and Mode Toggle

auto_mode = True
debounce_time_ms = 150
last_button_press_time = 0

def toggle_auto_mode(pin):
    global auto_mode, last_button_press_time
    current_time = utime.ticks_ms()
    press_time_diff = utime.ticks_diff(current_time, last_button_press_time)
    if  press_time_diff >= debounce_time_ms:
        last_button_press_time = current_time
        auto_mode = not auto_mode
        if auto_mode:
           button_check_timer.deinit()
           auto_mode_timer.init(period=700, mode=Timer.ONE_SHOT, callback=change_light)
        else:
           auto_mode_timer.deinit()
           button_check_timer.init(period=50, mode=Timer.PERIODIC, callback=check_buttons)        
        print("自動模式:", auto_mode)

blue_button = buttons['blue_b']
blue_button.irq(trigger=Pin.IRQ_FALLING, handler=toggle_auto_mode)
  • toggle_auto_mode function switches modes using the blue button.
  • Button Debounce with Time Tick Difference

Main Loop

print("自動模式:", auto_mode)
while True:
    utime.sleep_ms(50)
  • The main loop keeps the program running indefinitely.
  • A minor delay is added to prevent the loop from occupying the CPU excessively.

Traffic Light Control System

By wschen

Traffic Light Control System

Discover the intricacies of a Traffic Light Control System in this presentation. Explore program flow, timers, manual mode, and more. Two solutions are presented, each with unique features and benefits. Dive into the world of traffic light control and learn how these systems operate.

  • 76