用树莓派控制交通红绿灯(简洁版)

前面我们通过控制led灯和读取按钮状态,简单演示了树莓派如何通过gpio来与外部世界沟通。今天我们要用树莓派模拟一个控制交通的红绿灯,让大家进一步学习如何通过程序和计算机的i/o来解决实际问题。
今天要做的红绿灯是简洁版,我们今后还会讲它的进阶版(高级版)。简洁版的红绿灯有一个开关控制按钮和红黄绿三色交通控制灯。当程序启动时,只有黄灯处于闪烁状态,提醒来往车辆注意其他路口的车辆,当第一次按下按钮后,则进入红绿灯交替开关的状态,和大家日常在路口看到的类似,再次按下按钮,则重新恢复到黄灯闪烁状态。这是大部分路口自动控制红绿灯的逻辑。(如果大家不明白红绿灯相关的交规,可以咨询父母或者上网搜索,这里不说了)。
需要的元器件
本次的红绿灯需要如下的元器件
开关按钮一个跳线若干,元器件连接方式不同,需要的跳线数不同,约6-10个。发光二极管(led)三个,如果没有红黄绿三色,可以用同色led,用led位置表示红黄绿。1k欧姆的电阻三个面包板(可选)树莓派gpio扩展组件(可选)红绿灯电路
在前面控制发光二极管时,我们知道发光二极管需要连接一个1k欧姆的电阻来起到限制电流的保护作用。所以电路如下图。
从电路可以看到,控制按钮连接了gpio17,红色led连接了gpio26,黄色led连接了gpio5,绿色led连接了gpio27。
最终的元器件连接如下图:
python控制程序
在我们实际进行电路或程序设计时,一般都会采取循序渐进的方式,先从简单的设计开始,然后一步一步加入更复杂的逻辑,直到最终实现我们需要的效果。这在电路或程序较复杂时尤其重要。
首先,我们需要确保电路连接都是正确的,有一个简单的验证方法,在前面的发光二极管控制一讲也提到过,就是在发光二极管连接到gpio之前,先直接连接gpio的第一引脚,也就是3.3v的电源,此时led会亮,则说明连接正确无误。
其次,我们要确保各器件连接了正确的gpio引脚,因为有些gpio引脚紧挨着(如gpio17,27,22),如果连接错了,也是没法成功控制电路的。按我的电路,先用下面的程序运行一下看,3个led都应该亮1秒,灭1秒,同时按钮按下超过1秒,可以看到打印输出pressed。
from gpiozero import ledfrom time import sleepred = led(26) #红灯链接了gpio26yellow= led(5) #黄灯链接了gpio5green = led(22) #绿灯连接了gpio22control = button(17) #按钮连接了gpio17while true: red.on() yellow.on() green.on() if control.is_pressed: print(pressed) #保持按钮按下超过1秒,可以看到打印输出 sleep(1) #先让led亮1秒 red.off() yellow.off() green.off() sleep(1) #再让led灭1秒接下来我们加入更多的逻辑。只让黄灯闪烁,还是红绿灯交替控制,需要有一个变量来进行判断,因为非此即彼,所以可以把这个变量设置为布尔型(true或false),我们把它命名为kaiguan。代码先改为如下:
from gpiozero import led,buttonfrom time import sleepkaiguan = false #控制变量默认设置为false,此时黄灯闪烁red = led(26) #红灯链接了gpio26yellow= led(5) #黄灯链接了gpio5green = led(22) #绿灯连接了gpio22control = button(17) #按钮连接了gpio17while true: if kaiguan == false: #当kaiguan变量为false时,黄灯闪烁 yellow.on() sleep(0.5) yellow.off() sleep(0.5) else: red.on() yellow.on() green.on() if control.is_pressed: print(pressed) sleep(1) red.off() yellow.off() green.off() sleep(1)运行上面的程序,可以看到黄灯闪烁,按按钮没有任何效果,因为else部分的代码永远执行不到。
接着我们加入按钮是否按下的判断逻辑,代码改为:
from gpiozero import led,buttonfrom time import sleepkaiguan = false red = led(26) #红灯链接了gpio26yellow= led(5) #黄灯链接了gpio5green = led(22) #绿灯连接了gpio22control = button(17) #按钮连接了gpio17while true: if kaiguan == false: #当kaiguan变量为false时,黄灯闪烁 yellow.on() sleep(0.5) yellow.off() sleep(0.5) else: #当kaiguan变量为true时,和原来逻辑一样 red.on() yellow.on() green.on() sleep(1) red.off() yellow.off() green.off() sleep(1) if control.is_pressed: #判断按钮是否被按下 print(pressed) kaiguan = bool(1-kaiguan) #取反。运行上面的程序,可以看到,一开始只有黄灯闪烁,当我们按下按钮时(保持按下状态直到看到pressed被打印出来),会变成所有灯亮1秒灭1秒,再次按按钮,又会变成黄灯闪烁,如此反复。
现在看来,我们需要修改else部分的逻辑,使它实现绿灯亮3秒,然后熄灭,同时黄灯亮1秒,然后熄灭,同时红灯亮,3秒后红灯熄灭,绿灯亮,如此反复。大家也可以按自己喜好调整红绿灯的时间。最新的代码如下:
from gpiozero import led,buttonfrom time import sleepkaiguan = false red = led(26) #红灯链接了gpio26yellow= led(5) #黄灯链接了gpio5green = led(22) #绿灯连接了gpio22control = button(17) #按钮连接了gpio17while true: if kaiguan == false: #当kaiguan变量为false时,黄灯闪烁 yellow.on() sleep(0.5) yellow.off() sleep(0.5) else: #当kaiguan变量为true时 green.on() sleep(3) #绿灯亮3秒 green.off() yellow.on() #黄灯亮1秒 sleep(1) yellow.off() red.on() #红灯亮3秒 sleep(3) red.off() if control.is_pressed: ##判断按钮是否被按下 print(pressed) kaiguan = bool(1-kaiguan)上面代码中 bool(1-kaiguan)可以实现取反的效果,也就是当kaiguan现在是true时,运算后会被改为false,如果kaiguan现在是false,则会被改为true。
运行上面的代码基本可以实现我们需要的逻辑,但是存在以下不足:
按钮不是按下后就会触发改变,而是需要多按一会,尤其是在红绿灯交替亮灭时,需要多按一会,直到屏幕输出pressed后才会变化为黄灯闪烁。这是因为在红绿灯交替亮灭时,约7秒的时间没有检测按钮是否按下,只有这7秒的程序执行完毕后才能进入按钮检测部分的代码,可以在红灯亮了后再按,会减少按下的时间。
大家可以看看我的红绿灯电路运行起来的样子。
如何才能让按钮更灵敏,同时加入更高级的控制逻辑呢?下一次我们将在红绿灯高阶版进行介绍。

荣耀NOTE8、荣耀畅玩6X升级EMUI 5.0:终生不卡顿!
美国泛林宣布与ASML、IMEC合作开发出新的EUV光刻技术 成本大幅降低
Maxim Integrated推出可安全、快速充电的智能枚举电池充电器
外媒曝三星正打造一款Odyssey+头显设备
LTC6752,200MHz时钟恢复/电平移位
用树莓派控制交通红绿灯(简洁版)
无线传感器网络(WSN)定位系统设计
什么叫偏移地址_偏移地址怎么计算
全新RedmiBook Pro下月即将首发
PCB布局时去耦电容安装在哪里比较好
国内电视企业推ULED和QLED叫板OLED电视
分析能源之星影像设备产品的前景以及用途
Lenovo xCloud的破局之道 推开混合云市场大门
SK Innovation将积极开拓柔性材料事业
不虚AMD EPYC处理器:Intel 56核心服务器首秀
realme将成为国内首批推出5G商用手机的厂商
SIMATIC S7-1500 PLC IEC计数器简述
FPGA和多DSP的高速视觉测量系统
如何买到心仪的吹风机呢?追觅吹风机入手体验分享
“新基建”的东风已到来,国产IP将振翅高飞