基于STEP Pico的嵌入式系统学习平台模拟交通灯系统
利用板上的3个不同颜色的LED模拟交通灯,程序会轮流切换三个灯的状态,并根据按键的输入调整交通灯的切换
标签
显示
MicroPython
PICO
2023寒假一起练
模拟红绿灯
cardry
更新2023-03-29
中国矿业大学(北京)
421

硬件介绍:

该平台采用Raspberry Pi官方自助研发的RP2040微控制器芯片,搭载ARM Cortex M0+双核处理器,内置有264KB SRAM和2MB内存,还板载有多达26个多功能的GPIO引脚。软件上可采用MicroPython进行开发。

 

项目要求:

利用板上的3个不同颜色的LED模拟交通灯,程序会轮流切换三个灯的状态,并根据按键的输入调整交通灯的切换。

 

设计思路:

我想要模拟我国实际红绿灯逻辑,即红灯亮完绿灯亮,绿灯亮完黄灯亮,黄灯亮完红灯亮。另外,对于行人优先按键的加入,我决定设置为:

若在红灯期间按下按键,将会在基础红灯时间后额外加一个延长时间;若在绿灯期间按下按键,将会立即结束绿灯流程并跳转到黄灯流程,进而转换为红灯,之所以没有设置为立即转为红灯,是为了给司机一个缓冲的反应时间,防止发生交通事故。

当上电系统启动后,首先执行红灯亮5秒的程序,并利用线程检测是否有按键按下:若按下按键,在红灯亮5秒后执行红灯延长4秒程序;若没有按下按键,接着执行主循环。红灯以及延长的红灯结束后,执行绿灯亮5秒程序。下图为本系统程序流程图:

FszCZBWxFFmiYgyTpdwUKTg52F3A

 

代码介绍:

首先在主循环的程序开头加入确保所有灯处于关闭状态的语句:

    red.off()                
    yellow.off()
    green.off()

然后执行红灯亮5秒程序stop():

def stop():                  #执行红灯亮5秒后灭
    red.on()
    for i in range(5):
        oled.fill(0)
        oled.text("Please wait", 0, 0)
        oled.text(str(5-i), 55, 20)
        oled.show()
        time.sleep(1)
    red.off()

并且利用线程检测红灯亮的过程中按键是否按下,需要在主循环程序之前创建一个全局变量,并给他一个默认值False,意思是当程序开始时按键还没有按下:

global button_pressed        #设置一个全局变量
button_pressed = False       #并赋一个初始值False

下一步是定义线程,直接在下面添加以下几行,第一行定义了线程名称,下一行让MicroPython知道我即将更改全局变量的值,接着设置一个新的循环,这个循环也是线程的一部分:

def button_reader_thread(): 
     global button_pressed 
     while True:
        if button.value() == 0: 
            button_pressed = True
        utime.sleep(0.01)

在上面这个循环中,第一行是一个条件语句,用于检查按键的值是否为1, Pico使用一个内部的上拉电阻,当按键没有被按下时,读取的值是1,这意味着在此条件下代码永远不会运行, 只有当按键被按下时,读取的值才为0,线程的最后一行才会运行,这一行将button_pressed变量设置为True,让程序的其余部分知道按键已经被按下。最后,我们添加了一个非常短(0.01秒)的延迟,以防止while循环运行过快。

在线程下面创建一个新行,如下所示:

_thread.start_new_thread(button_reader_thread, ())

这告诉_thread库启动前面定义的线程。在这一点上,线程将开始运行并快速进入它的循环, 每秒检查按键数千次,看看它是否被按下。与此同时,主线程将继续执行程序的主要部分。

红灯或红灯延长程序执行完毕后,进入亮绿灯程序:

    green.on()                       #绿灯亮
    for k in range(5):           
        if button_pressed == True:   #在亮绿灯程序中检测案件是否被按下,若按下立即跳出亮绿灯的读秒循环程序
            global button_pressed
            button_pressed = False
            break
        oled.fill(0)
        oled.text("Permit passage", 0, 0)
        oled.text(str(5-k), 90, 20)
        oled.show()
        time.sleep(1)
    green.off()                      #绿灯灭

从上面这个程序可以看出,我在绿灯每次读秒时检测按键是否按下,若按下,将执行break语句直接跳出for循环,即接着执行green.off()以及接下来的亮黄灯程序。若没有检测到按键按下,那程序将在执行亮绿灯5秒完毕后才会执行亮黄灯程序。

以下是亮黄灯程序:

def wait():                  #执行黄灯亮3秒后熄灭
    yellow.on()
    for j in range(2):
        oled.fill(0)
        oled.text("Attention please", 0, 0)
        oled.text(str(2-j), 0, 20)
        oled.show()
        time.sleep(1)
    yellow.off()

 

功能展示:

上电后,红灯亮,正常读秒:

FihoulG61YH_dRpOupA0hHrW085j

然后绿灯亮,正常读秒:

FnqjFNE0pL87IlwKU8wCKrhESagO

随后黄灯亮,正常读秒:

FgRW43ck9M6XqEpv1nf9Mx7qvnvF

若在红灯期间按下按键,将进入延长时间:

FsqoY2G91NuDyxVgqfh2cDxVgd7D

若在绿灯期间按下按键,将会立即转入黄灯流程。具体展示请看视频介绍。

 

存在不足:

1、可以为该系统加入行车以及停止的动画,丰富显示效果;

2、还可以引入汉字字符库,使得屏幕显示汉字,便捷本地化应用。

附件下载
traffic_light.py
团队介绍
机电学院
团队成员
cardry
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号