任务要求:
仿真马路上的交通灯的工作状态切换,利用板上的红、黄、绿三种颜色的LED显示道路状态的切换,行人按键时,具有优先功能
实现方式:
利用板上的3个不同颜色的LED模拟交通灯,程序会轮流切换三个灯的状态,并根据按键的输入(中断或查询机制)调整交通灯的切换
一.环境配置:
1.thonny:
官方microPython开发平台,界面简洁,十分容易上手,Windows,Mac都可使用,且软件体积小,可移植于树莓派平台,具有良好兼容性
2.树莓派pico+功能扩展板:
专为嵌入式系统学习而设计,其可以通过C/C++以及MicroPython编程来学习嵌入式系统的工作原理和应用。pico采用RP2040双核处理器,运行频率133MHz
二.程序实现
程序使用microPython,由于开源程序中有许多封装的module,因此调用起来十分容易,下面介绍每个module的功能。
模块简介:
1.time:
microPython自带库,本项目中只适用了time.sleep来实现延时
2.machine:
microPython自带库,用于使用Pin,PWM, SPI等端口,值得注意的是控制端口时需要先使用Pin,PWM赋值给常量,如
pwm = PWM(Pin(pin_cfg.buzzer))
3..ws2812b:
电子森林开源模块,用于控制扩展板上12个RGB三色灯组,通过数字1~12控制每一个led的开关,且通过封装函数可以实现一键全部点亮或熄灭。
4.button:
电子森林开源模块,用于获得扩展版上的k1,k2按钮状态。
5.board:
最重要的开源模块,将每一个扩展板设备与端口号进行对应,使得使用扩展设备时可以直接使用pin.cfg+名称获得端口号并控制
g=Pin(pin_cfg.green_led,Pin.OUT)
g.value(1) #点亮绿色led
(说是最重要的,其实由于模块封装的太细致了,可以直接用其他函数控制扩展设备)
整体实现:
程序框图:
交通信号灯有红黄绿三种颜色,根据真实情景设置红,绿,黄,红...的循环,且黄灯时间较短,绿灯即将变黄前会闪烁。
green = "#00ff00"
def green_light():
ws2812b.on_all(green)
state = 1
time.sleep(3)
i=0
while i<5:
ws2812b.off_all()
time.sleep(0.2)
ws2812b.on_all(green)
time.sleep(0.2)
i=i+1
代码展示了绿灯延时并闪烁的实现,其他颜色同理
根据要求加入行人控制功能,令每一个红黄蓝为一个循环,在本轮循环任意时刻按下按钮,下一轮循环的红灯时间将增加,且即将变为绿灯时发出警报警告行人,警报结束后信号灯变绿。
while True:
red_light()
if k1.value() == True:
print("+3s")
time.sleep(3)
print("Attention_please")
for i 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()
green_light()
yellow_light()
主程序如上,每一轮循环按下按钮时k1.value将被设置为true并在下一轮循环触发红灯延时3s与蜂鸣器报警。
三.后记
电子森林开源的module十分完备,因此上手起来十分容易,笔者在跟着官方课程学习后很快便能掌握一些基础程序的编写。
在课程介绍中有提及到使用_thread来进行异步程序的实现,代码如下:
spi = SPI(1, 100000, mosi=Pin(pin_cfg.spi1_mosi), sck=Pin(pin_cfg.spi1_sck))
oled = SSD1306_SPI(128, 64, spi, Pin(pin_cfg.spi1_dc),Pin(pin_cfg.spi1_rstn), Pin(pin_cfg.spi1_cs))
# Clear the oled display in case it has junk on it.
oled.fill(0)
state = 1
def the_second_loop():
global state
x = -64
fb = [framebuf.FrameBuffer(frames[fr], 64, 64, framebuf.MONO_HLSB)
for fr in range(0, 48)]
while True:
for fr in range(0, 48):
if state == 0: continue
oled.blit(fb[fr], x, 0)
gc.collect()
utime.sleep_ms(40)
if x < 128:
x = x + 1
else:
x = -64
print(x)
oled.show()
_thread.start_new_thread(the_second_loop, ())
代码可以实现在红灯时显示宇航员穿过马路的图像,在绿灯时停止,笔者在实现功能时尝试加入第二个loop,但遇到了许多bug。
最常见的bug如图,笔者认为与格式书写有较大关系,如在print(“attention please”)中使用下划线而不是空格都会有此bug。
在未来学习更多Python的知识后,我相信能够通过其他方法而不是全部堆入单一程序能够更好地解决问题。