基于STEP Pico的交通灯控制器
利用板上的3个不同颜色的LED模拟交通灯,程序通过轮流切换三个灯的状态,仿真马路上的交通灯的工作状态切换。此外,行人按键时,具有优先功能。并根据按键的输入(中断或查询机制)调整交通灯的切换
标签
树莓派
嵌入式系统
2023寒假在家练
BIT_Ming
更新2023-03-29
北京理工大学
369

一、项目需求

制作一个交通灯控制器

具体要求:仿真马路上的交通灯的工作状态切换,利用板上的红、黄、绿三种颜色的LED显示道路状态的切换,行人按键时,具有优先功能

实现方式:利用板上的3个不同颜色的LED模拟交通灯,程序会轮流切换三个灯的状态,并根据按键的输入(中断或查询机制)调整交通灯的切换

二、完成的功能及达到的性能

2.1正常交通灯颜色交替变换

程序烧录进板子后,通过代码控制板子上的12个WS2812B RGB三色灯来模拟马路上真实的交通信号灯实现红、黄、绿三种颜色的交替变换。首先红灯亮起,时间持续5秒钟,之后变成黄灯警示,时间持续2秒钟,之后变为绿灯,时间持续5秒钟,再次变为黄灯,提示可通行时间即将结束,时间持续5秒钟,最后再转变为红灯,循环往复持续进行,实现一个最基本的交通信号灯模拟。

ZRrKsCAAAAACIcUNWQbV+RzTdpPpk1Uc+

图 1 红点亮

9lGsqwIAAAAABg8hcLkrjc9BwOTBFn1Pog=

图 2 黄灯点亮

2UayrAgAAAAA4ryLpYJMajq0ShoW8yoKsA==

图 3 绿灯点亮

2.2 OLED屏幕显示

在实现了基本的红绿灯功能之后,通过板子上的128*64 OLED显示屏,显示小人在绿灯时自左向右通行的效果。当红灯亮起时,小人禁止通行,红灯与绿灯之间的黄灯警示同样禁止通行。小人只有在绿灯和即将变为红灯的黄灯警示期间才可以正常通行。

9lGsqwIAAAAAF1bENEgxPpF3cEsfgMhMzE=

图 4 OLED显示

2.3 按键控制延长绿灯时间并用蜂鸣器提示

通过板子上的K1按键控制来延长绿灯的时间,当K1键被按下时,会在下一次循环中对绿灯的持续时间延长5秒钟,并在延长的五秒钟时间里用蜂鸣器报警,模拟提示行人抓紧时间通过并警示来往车辆绿灯时间延长。

这段代码是用来控制树莓派Pico上的LED灯,蜂鸣器和OLED显示屏的,实现一个交通灯系统和一个动画效果。

三、代码及解释

3.1代码

import ws2812b
import utime, time
import _thread
from machine import SPI, Pin,PWM
from ssd1306 import SSD1306_SPI
from button import k1
import framebuf
from astronaut import frames
from board import pin_cfg
import gc

首先,导入一些需要用到的模块,如ws2812b(LED灯控制模块),utime(时间模块),_thread(多线程模块),machine(硬件控制模块),ssd1306(OLED显示屏控制模块),button(按钮模块),framebuf(帧缓冲模块),astronaut(动画帧数据模块)和board(引脚配置模块)

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))
pwm = PWM(Pin(pin_cfg.buzzer))

# Clear the oled display in case it has junk on it.
oled.fill(0)

def pitch(frequency, duration=0):
    pwm.freq(frequency)
    pwm.duty_u16(3000)
    time.sleep_ms(duration)

然后,创建一个SPI对象,用来与OLED显示屏通信。SPI是一种串行总线协议,可以实现高速数据传输。接着,创建一个SSD1306_SPI对象,用来控制OLED显示屏的参数和功能。SSD1306是一种OLED显示屏的驱动芯片。

接着,创建一个PWM对象,用来控制蜂鸣器的频率和占空比。PWM是一种调制方式,可以用来产生不同音调的声音。接着,清空OLED显示屏上的内容,以防有杂乱的数据。然后,定义一个pitch函数,用来设置蜂鸣器的频率和持续时间,并让它发出声音。

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, ())

然后,定义一个全局变量state,用来表示是否播放动画效果。初始值为1表示播放。然后,定义一个the_second_loop函数,在另一个线程中运行。

在这个循环中首先定义一个局部变量x,表示动画帧在OLED显示屏上的横向位置。初始值为-64表示在左边界外。

最后,创建一个fb列表,存储48个framebuf对象。每个framebuf对象包含了64x64像素的单色图像数据。这些图像数据来源于astronaut模块中的frames列表。

使用一个无限循环来不断重复以下步骤:

遍历fb列表中的每个framebuf对象,并将其绘制到OLED显示屏上。使用oled.blit方法来将图像数据复制到指定位置上。使用gc.collect方法来回收内存空间。暂停40毫秒以控制动画速度。如果x小于128,则将其加1以向右移动一像素;否则将其重置为-64以从左边界重新开始移动。打印x的值以便调试。使用oled.show方法来更新OLED显示屏上的内容。使用_thread.start_new_thread方法来启动the_second_loop函数在另一个线程中运行。这样可以避免阻塞主线程中的其他代码。

green = "#00ff00"
red = "#ff0000"
yellow = "#fff00"

while True:
    ws2812b.on_all(red)
    state = 0
    time.sleep(5)
    ws2812b.on_all(yellow)
    time.sleep(2)
    ws2812b.on_all(green)
    state = 1
    time.sleep(5)
    if k1.value() == True:
        ws2812b.on_all(green)
        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()
    state = 1
    ws2812b.on_all(yellow)
    time.sleep(5)

最后,在主线程中使用一个while循环来不断重复以下步骤:

将所有LED灯点亮为红色,并将state设为0表示暂停播放动画效果。等待五秒钟。将所有LED灯点亮为黄色,并等待两秒钟。将所有LED灯点亮为绿色,并将state设为1表示恢复播放动画效果。等待五秒钟。如果检测到按钮被按下,则保持所有LED灯为绿色,并使用两个for循环来产生一个上升和下降的音阶效果。关闭蜂鸣器并将state设为1表示恢复播放动画效果。

3.3 流程图

1mMhrwMTAJkAAJkIB1Alybsc6OMUmABEiABHol8P8B9SX7fu93IJMAAAAASUVORK5CYII=

图 5 程序流程图

四、感受以及心得体会

本次硬禾学堂的2023寒假在家一起练的活动收获颇丰,基于树莓派Pico的嵌入式系统学习平台专为嵌入式系统学习而设计,其可以通过C/C++以及MicroPython编程来学习嵌入式系统的工作原理和应用,对新手非常友好,上手容易,适合没有编程基础的同学进行学习,老师讲解细致,手把手带着我们写代码并且解释意义,通俗易懂,本次设计交通信号灯的项目并不是很难,在老师的带领下非常容易就可以完成,我学到了很多,本项目也存在着一些需要完善的地方,比如按键控制后绿灯时间延长,但是OLED显示屏上的小人未能及时通过就变为红灯,会造成小人不能完全通过,后续可以优化代码实现当小人完全通过时再变为红灯。

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