from machine import Pin, I2C, PWM, Timer, time_pulse_us
import machine
import time
from time import sleep
from lcd_api import LcdApi
from i2c_lcd import I2cLcd
from ILI9341 import Display, color565
from xglcd_font import XglcdFont
print("ETC613 Mini Project: Pedestrian Traffic Light Simulator")
# Ultrasonic setup
trig = Pin(14, Pin.OUT)
echo = Pin(36, Pin.IN)
# LCD Setup
i2c = I2C(scl=Pin(22), sda=Pin(21), freq=400000)
AddressOfLcd = 0x27
lcd = I2cLcd(i2c, AddressOfLcd, 2, 16)
# SPI setup for display
sck = machine.Pin(18)
mosi = machine.Pin(23)
miso = machine.Pin(19)
spi = machine.SPI(1, baudrate=32000000, sck=sck, mosi=mosi, miso=miso)
rst = machine.Pin(2)
dc = machine.Pin(4)
cs = machine.Pin(5)
display = Display(spi, dc=dc, cs=cs, rst=rst)
arcadepix = XglcdFont('ArcadePix9x11.c', 9, 11)
# Input Pins
pin_pb = Pin(34, Pin.IN) # Pushbutton to trigger crossing
pin_pir = Pin(35, Pin.IN) # PIR (optional, not used in this example)
# Output Pins (Traffic Light LEDs)
rgbr = Pin(1, Pin.OUT) # Red light
rgbg = Pin(3, Pin.OUT) # Green light
rgbb = Pin(17, Pin.OUT) # Blue light (not used here, but can be added for other states)
buzzer = PWM(Pin(6), freq=1) # Buzzer
# Global variable for distance
distance = 0
# Function to measure distance from Ultrasonic sensor
def get_distance():
trig.off()
time.sleep_us(2)
trig.on()
time.sleep_us(10)
trig.off()
# Measure the pulse width on echo pin
duration = time_pulse_us(echo, 1, 1000000) # Timeout after 1 second
distance = (duration / 2) / 29.1 # Calculate in cm
return distance
# Function to display a walking human figure (Green)
def walking_human():
display.fill_circle(120, 260, 40, color565(0, 255, 0)) # Head
display.draw_vline(120, 100, 120, color565(0, 255, 0)) # Body
display.draw_line(120, 100, 60, 30, color565(0, 255, 0)) # Right leg
display.draw_line(120, 100, 150, 50, color565(0, 255, 0)) # Left leg 1
display.draw_line(150, 50, 180, 80, color565(0, 255, 0)) # Left leg 2
display.draw_line(120, 180, 170, 200, color565(0, 255, 0)) # Left arm 1
display.draw_line(120, 180, 70, 150, color565(0, 255, 0)) # Right arm 1
# Function to display a stopped human figure (Red)
def stop_human():
display.fill_circle(120, 260, 40, color565(255, 0, 0)) # Head
display.draw_vline(120, 100, 120, color565(255, 0, 0)) # Body
display.draw_line(120, 100, 60, 30, color565(255, 0, 0)) # Right leg
display.draw_line(120, 100, 150, 30, color565(255, 0, 0)) # Left leg 1
display.draw_line(120, 180, 170, 150, color565(255, 0, 0)) # Left arm 1
display.draw_line(120, 180, 70, 150, color565(255, 0, 0)) # Right arm 1
# Display function to indicate "Do Not Cross"
def DONOTCROSS():
display.clear()
rgbg.value(1) # Turn Green LED off
rgbr.value(1) # Turn Red LED on
lcd.clear()
lcd.move_to(0, 0)
lcd.putstr("Car Approaching!")
lcd.move_to(0, 1)
lcd.putstr("Do Not Cross!")
stop_human() # Stop the walking human figure
# Display function to indicate "Allow Crossing"
def CROSS():
display.clear()
lcd.clear()
lcd.move_to(0, 0)
lcd.putstr("No car! Cross!")
rgbr.value(0) # Turn Red LED off
rgbg.value(1) # Turn Green LED on
walking_human() # Show walking human figure
# Button interrupt handler
def PB_CROSS(pin):
global distance # Make sure we're using the global 'distance' variable
if distance < 202 and pin_pir.value() == 1 :
lcd.clear()
lcd.putstr("Button Pressed!")
sleep(1)
CROSS() # Allow crossing
# Countdown timer for crossing
for i in range(10, -1, -1):
lcd.clear()
lcd.move_to(0, 0)
lcd.putstr("Cross now!")
lcd.move_to(0, 1)
lcd.putstr(f"{i} sec")
sleep(1)
DONOTCROSS() # After countdown, stop crossing
elif distance > 202 and pin_pir.value() == 1:
lcd.clear()
DONOTCROSS()
lcd.clear()
lcd.putstr("Button Pressed!")
sleep(1)
lcd.clear()
lcd.putstr("Please Wait!")
sleep(3)
CROSS()
# Countdown timer for crossing
for i in range(10, -1, -1):
lcd.clear()
lcd.move_to(0, 0)
lcd.putstr("Cross now!")
lcd.move_to(0, 1)
lcd.putstr(f"{i} sec")
sleep(1)
DONOTCROSS() # After countdown, stop crossing
# Main function to run the traffic light system
def main():
global distance # Ensure we're using the global 'distance' variable
print('system ready')
# Set up the interrupt for the pushbutton (PB)
pin_pb.irq(trigger=Pin.IRQ_RISING, handler=PB_CROSS)
#initial state
DONOTCROSS()
while True:
sleep(1)
# Run the main function
main()