制作一个交通灯控制器
基于STEP Pico的嵌入式系统学习平台
项目介绍
- 项目名称如下
2023寒假一起练平台(1)- 基于STEP Pico的嵌入式系统学习平台 - 电子森林 (eetree.cn)
- 平台包含:
- 树莓派Pico扩展板 x1
- 硬禾版本树莓派Pico核心模块 - STEP Pico x1
- Type-C 数据线 x1
- 目标:制作一个交通灯控制器
- 具体要求:仿真马路上的交通灯的工作状态切换,利用板上的红、黄、绿三种颜色的LED显示道路状态的切换,行人按键时,具有优先功能
- 实现方式:利用板上的3个不同颜色的LED模拟交通灯,程序会轮流切换三个灯的状态,并根据按键的输入(中断或查询机制)调整交通灯的切换。
设计思路
- 利用循环实现红、黄、绿三种颜色的LED显示道路状态的切换。
- 循环中查询实现行人按键时,具有优先功能。
框图
简单的硬件介绍
板卡硬件:
- 2个按键输入
- 4个单色LED
- 12个WS2812B RGB三色灯
- 1个姿态传感器
- 1个128*64 OLED显示屏
- 1个蜂鸣器
- 1个可调电位计(用于电压表)
- 1路音频信号输入(用于示波器)
- 8位R-2R电阻网络构成的DAC(用于DDS信号发生器)
RP2040芯片概述
- RP2040具有双M0+处理器核心,DMA,内部存储器和外设块通过AHB/APB总线结构连接。
- 代码可以通过专用SPI、DSPI或QSPI接口从外部内存直接执行。小型缓存可以提高典型应用程序的性能。
- 可以通过SWD接口进行调试。
- 内部SRAM可以包含代码或数据。它被定位为一个单独的264 kB区域,但物理上划分为6个库,以允许不同主机同时并行访问。
- DMA总线主机可用于从处理器卸载重复的数据传输任务。
- GPIO引脚可以直接驱动,也可以从各种专用逻辑功能驱动。
- 专用硬件实现SPI、I2C、UART等固定功能。
- 可灵活配置的PIO控制器可用于提供各种IO功能。
- 带有嵌入式PHY的USB控制器可用于在软件控制下提供FS/LS主机或设备连接。
- 四个ADC输入与GPIO引脚共享。
- 两个锁相环为USB或ADC提供固定的48MHz时钟,以及高达133MHz的灵活系统时钟。
- 内部稳压器提供核心电压,因此最终产品只需要提供IO电压。
实现的功能及图片展示
实现功能:
- 1、仿真马路上的交通灯的工作状态切换,利用板上的红、黄、绿三种颜色的LED显示道路状态的切换,行人按键时,具有优先功能。
- 2、仿真十字路口车辆交通指示灯。
图片展示:
主要代码片段及说明
import array, time
from machine import Pin
import rp2
from javion import *
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
def ws2812():
T1 = 2
T2 = 5
T3 = 3
wrap_target()
label("bitloop")
out(x, 1) .side(0) [T3 - 1]
jmp(not_x, "do_zero") .side(1) [T1 - 1]
jmp("bitloop") .side(1) [T2 - 1]
label("do_zero")
nop() .side(0) [T2 - 1]
wrap()
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(javion.Pin_LED))
sm.active(1)
tri_LED = array.array("I", [0 for _ in range(javion.NUM_LEDS)])
pin_ctrl = Pin(javion.Pin_CTRL, Pin.IN, Pin.PULL_UP)
led_g = Pin(22, Pin.OUT)
led_r = Pin(26, Pin.OUT)
led_y = Pin(20, Pin.OUT)
def Traffic_button(light1,light2,slp_t):
while (slp_t != 0):
slp_t = slp_t - 1
tri_LED[0] = light1
tri_LED[1] = light2
tri_LED[2] = light1
tri_LED[3] = light2
sm.put(tri_LED, 8)
time.sleep_ms(javion.T_query)
def traffic_ctrl():
if pin_ctrl.value() == 0 :
led_g.value(1)
led_r.value(0)
led_y.value(0)
Traffic_button(javion.green, javion.yellow, 25)
Traffic_button(javion.green, javion.dark, 25)
Traffic_button(javion.green, javion.yellow, 25)
Traffic_button(javion.green, javion.dark, 25)
Traffic_button(javion.green, javion.yellow, 25)
Traffic_button(javion.green, javion.dark, 25)
Traffic_button(javion.green, javion.red, 800)
def Traffic_lights(light1,light2,slp_t):
if(light1 == javion.red):
led_g.value(0)
led_r.value(1)
led_y.value(0)
elif(light1 == javion.yellow):
led_g.value(0)
led_r.value(0)
led_y.value(1)
elif(light1 == javion.dark):
led_g.value(0)
led_r.value(0)
led_y.value(0)
else:
led_g.value(1)
led_r.value(0)
led_y.value(0)
while (slp_t != 0):
slp_t = slp_t - 1
tri_LED[0] = light1
tri_LED[1] = light2
tri_LED[2] = light1
tri_LED[3] = light2
traffic_ctrl()
sm.put(tri_LED, 8)
time.sleep_ms(javion.T_query)
while True:
Traffic_lights(javion.yellow, javion.red, 25)
Traffic_lights(javion.dark, javion.red, 25)
Traffic_lights(javion.yellow, javion.red, 25)
Traffic_lights(javion.dark, javion.red, 25)
Traffic_lights(javion.green, javion.red, 800)
Traffic_lights(javion.yellow, javion.red, 25)
Traffic_lights(javion.dark, javion.red, 25)
Traffic_lights(javion.yellow, javion.red, 25)
Traffic_lights(javion.dark, javion.red, 25)
Traffic_lights(javion.red, javion.yellow, 25)
Traffic_lights(javion.red, javion.dark, 25)
Traffic_lights(javion.red, javion.yellow, 25)
Traffic_lights(javion.red, javion.dark, 25)
Traffic_lights(javion.red, javion.green, 800)
Traffic_lights(javion.red, javion.yellow, 25)
Traffic_lights(javion.red, javion.dark, 25)
Traffic_lights(javion.red, javion.yellow, 25)
Traffic_lights(javion.red, javion.dark, 25)
traffic_ctrl()
控制极小周期内灯的状态,pin_ctrl.value()捕捉按键状态。
Traffic_lights(light1,light2,slp_t):
控制指定周期内灯的状态
While
主循环
点亮不同颜色交通灯
light1是横向道路信号灯颜色。
light2是纵向道路信号灯颜色。
light1,light2可为红绿、绿红、黄黄闪烁、红红四种状态。
slp_t为每个交通状态的时间。
traffic_ctrl()检查是否交通管制、行人按键。
通行时间控制与交通规则
25是黄灯闪烁间隔。
800是红灯或绿灯亮灯时间。
遇到的主要难题及解决方法
笔记本不识别rp2040
解决方法:换用项目专用Type-C 数据线
未来的计划或建议等
按照实际交通规则设计时间。
附录
交通灯概述
俗称红绿灯。19世纪初,在英国中部的约克城,红、绿装分别代表女性的不同身份。其中,着红装的女人表示我已结婚,而着绿装的女人则是未婚者。后来,英国伦敦议会大厦前经常发生马车轧人的事故,于是人们受到红绿装启发,1868年12月10日,信号灯家族的第一个成员就在伦敦议会大厦的广场上诞生了,由当时英国机械师德·哈特设计、制造的灯柱高7米,身上挂着一盏红、绿两色的提灯--煤气交通信号灯,这是城市街道的第一盏信号灯。在灯的脚下,一名手持长杆的警察随心所欲地牵动皮带转换提灯的颜色。后来在信号灯的中心装上煤气灯罩 ,它的前面有两块红、绿玻璃交替遮挡。不幸的是只面世23天的煤气灯突然爆炸自灭,使一位正在值勤的警察也因此断送了性命。
这次的交通灯是二值信号灯:
最简单的信号灯形式,信号灯的值只能取0或1,类似于互斥锁。虽然二值信号灯能够实现互斥锁的功能,但两者的关注内容不同。信号灯强调共享资源,只要共享资源可用,其他进程同样可以修改信号灯的值;互斥锁更强调进程,占用资源的进程使用完资源后,必须由进程本身来解锁。
WS2812B概述
WS2812B是一种将控制电路和RGB芯片集成在5050封装中的智能控制LED光源。其内部包括智能数字端口数据锁存器和信号重塑放大驱动电路。还包括精密内部振荡器和12V电压可编程恒流控制部分,有效保证像素点光色高度一致。数据传输协议采用单NZR通信模式。像素上电复位后,DIN端口接收来自控制器的数据,第一个像素采集初始的24bit数据然后发送到内部数据锁存器,其他数据由内部信号重塑放大电路通过DO端口发送到下一个级联像素。传输后为每个像素,信号减少24bit。像素采用自动重塑传输技术,使得像素级联数不受信号传输的限制,只取决于信号传输的速度。LED具有驱动电压低、环保节能、亮度高、散射角大、一致性好、功耗低、寿命长等优点。该控制芯片集成在LED上面,电路变得更加简单,体积小,安装方便。
致谢
非常感谢硬禾团队提供的这次学习交流的活动,让我有机会也有动力去学习新的技能,培养自己的兴趣。同时,感谢群里的各位大佬分享自己的心得体会,这让我受益匪浅!谢谢!