一、任务要求
仿真马路上的交通灯的工作状态切换
利用板上的红、黄、绿三种颜色的LED显示道路状态的切换
行人按键时,具有优先功能
二、环境配置
1、thonny:
作为官方推荐的开发软件,thonny页面简洁,基础功能齐全,简单易上手,非常适合初学者(比如我)。安装的教程网上比较多,就我而言,我是按照直播课的讲解进行了安装,具体可以参考:
https://class.eetree.cn/detail/l_63acf922e4b07b05582a719d/4?fromH5=true
2、硬禾学堂树莓派pico平台:
硬禾学堂为“寒假一起练”制作了一个平台,这平台正是我视频中演示用到的板子他的原理图如下,具体可以参考:
三、功能实现、相关代码介绍与成果展示
1、模块介绍:本次模拟交通灯的制作用到了button和ws2812b的库(视频课程中提到的那几个LED灯太小的问题确实有一些,所以我也按照视频课程中所建议的那样,放弃使用板子自带的小LED灯,转而使用ws2812的那12个大号LED灯来模拟交通灯),首先我们需要将相关的库文件下载到板子上。
如上图所示,我们将本次模拟需要的board.py、button.py、ws2812.py三个库文件全部下载到了板子上。
2、代码展示
首先是初始化部分
import time
import ws2812b
from button import k1
from button import k2
from machine import PWM, Pin
from board import pin_cfg
这部分代码的格式相对固定,很明显就可以看出我们初始化了板子的延时功能、按钮、蜂鸣警报与ws2812b模块的LED灯。
随后是蜂鸣警报,这里我是直接套用的代码库中buzzer.py文件中所预先给出的蜂鸣警报的代码。
pwm = PWM(Pin(pin_cfg.buzzer))
def pitch(frequency,duration=0):
pwm.freq(frequency)
pwm.duty_u16(3000)
time.sleep_ms(duration)
接下来便是对交通灯红黄绿三种状态的设置,首先是红灯的代码,我的基本设计思路是在红灯亮起的过程中,查询状态切换按钮K1的状态,若K1被按下过,则开始进行状态切换,进行黄——绿——黄——红的变换顺序,同时Thonny下方的运行区会显示出“change”的字样,具体代码如下。
def red_light(): #红灯程序
for i in range(1, 20):
ws2812b.on_all("#ff0000")#ws2812b全部亮起为红色
time.sleep(1)
if k1.value() == True: #每秒进行一次状态查询,若k1键被按下则执行状态切换
print("change")
yellow_light()
green_light()
yellow_light()
随后是黄灯的代码,考虑到黄灯时间较短,为了能够做到一定的警示效果,我借鉴了视频课程中的思路,在黄灯亮起的5秒持续时间中持续进行响起蜂鸣警报,从而做到提示行人的效果,具体代码如下:
def yellow_light(): #黄灯程序
ws2812b.on_all("#ffff00") #ws2812b全部亮起为黄色
for k in range(10):
for freq in range(880, 1760, 16):
pitch(freq, 6)
for freq in range(1760, 880, -16):
pitch(freq, 6)
pwm.deinit() #黄灯亮起同时响警报
最后是绿灯的代码,考虑到行人优先的原则,有可能出现行人将过马路却时间不足的问题,于是在绿灯的设计思路是在绿灯亮起的过程中,查询延时按钮K2的状态,每当K2被按下过一次,绿灯时间将会延长5s,同时运行区会出现“time+5”的提示。具体代码如下:
def green_light(): #绿灯程序
for j in range(1,20):
ws2812b.on_all("#00ff00")
time.sleep(1)
if k2.value() == True: #每秒查询k2状态,若被按下则延长5s绿灯时间
print("time+5")
ws2812b.on_all("#00ff00")
time.sleep(5)
为了保证正常情形下红绿灯的正常工作状态,我设置了一个整体大循环,从而实现若无行人按键干扰,则能够实现红——黄——绿——黄的灯色顺序的循环变化,以此模拟交通灯的正常工作状态。
while True: #循环执行红黄绿灯程序
red_light()
yellow_light()
green_light()
yellow_light()
3. 成果展示
最后的结果如下:
首先在没有使用K1、K2按钮的情况下,板子能够实现预设的红灯20s、黄灯5s、绿灯20s、黄灯5s的变换顺序,从而模拟正常的工作状态。
在加入K1、K2的影响后,可以看到,在按下K1后,运行区出现了change字样
在绿灯期间连续按下三次K2后,依次出现了3次“time+5”的字样。
至此,交通灯的基本功能算是成功实现了。
以下是流程图与红黄绿灯运行状态的展示
流程图如下
红灯状态如下
黄灯状态如下
绿灯状态如下
四、不足之处与改进方案
作为一个初学者,这个交通灯代码只是能够实现查询按钮状态进行交通灯状态切换与维持常态交通灯运行的功能,但是在实现过程中依旧有许多瑕疵。
首先是查询按钮状态的思路,我的代码中是运用了每秒一次的循环查询,这无疑带给了交通灯使用者一定的延迟,同时由于这样的查询机制,如果按下了多次K1按钮,则会在执行过一次变换操作后1s立刻进行第二次状态变换操作(本质上是因为K1按钮状态的记忆能力),这与最初的想法其实是有冲突的。
另外,在绿灯延时的问题上,虽然是能够做到主观通过K2按钮进行延时,但是由于也是按秒进行查询,并在有结果后进行一次额外的绿灯量五秒的操作,故而进行绿灯时延其实是一个相对繁琐的事,并因为每秒查询的原因,事实上能够实现的绿灯延时操作的次数实际上是有限的(虽然实际上也不太可能有连续延长绿灯20多次的人吧)。
关于以上的两点问题,我设想中的解决思路就是优化相关的算法。
首先是优化查询按钮状态的机制,解除操作次数上限的问题。
随后是解决按钮次数记忆的问题,通过算法使得程序能够无视掉执行状态转换时的K1操作以及统计K2的被按下的次数,并在绿灯执行结束前延长对应次数*5s的绿灯延时效果。