哇奥,今天才发现上一次建造的红绿灯居然不对,绿灯一般在下方,当红灯变绿灯时黄灯闪烁,我做的是绿灯变红灯时黄灯闪烁!。这在我们开发时也会碰到,就像找bug一样,对于发现的问题要及时修正。在修正问题之前,我们还是先看看如何让红绿灯更快的响应按钮操作,然后修正红绿灯问题。
要想更快的响应按钮,则需要找出原因,上一讲提到因为程序运行时没有及时检测按钮是不是被按下了,那么我们第一反应可能是在程序中加上更多的检测语句,但这样程序将变得特别臃肿,也不容易被别人理解。其实,计算机设计者早就考虑到了这个问题,他们利用一个叫做“中断”的概念来对需要及时响应的事情进行处理。
什么是中断
中断是指计算机运行过程中,出现某些需要及时处理时,计算机能自动暂停正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。中断发生时运行的程序叫做中断程序。
在我们的红绿灯程序中,当按钮被按下时,我们希望计算机可以把它作为一个中断,然后运行中断程序,及时修改运行状态。
研究gpiozero的文档,我们发现button类有一个when_pressed的方法,说明如下
意思是说当按钮按下时将调用一个函数(function)。那么什么是函数呢?
函数是什么
函数是可以完成某些任务的代码块,而且这些代码块可以被重复使用,就像我们玩具里的积木块一样。在python中,用def来定义或者说创建函数,其语法如下
def 函数名(参数): #注意最后的冒号 函数代码(完成工作需要的代码) return 返回值 #不是必须的,当需要向调用函数的程序返回数值或对象时使用函数是编程语言非常重要的一部分内容,参数有形参和实参,参数也可以是多个,返回值可以是各种数据类型,有了函数后,变量也就分为全局 变量和局部变量了,这些内容我们会逐步涉及到。今天我们先从最简单的无参数函数开始,顾名思义,这样的函数没有参数。
创建参数
回过头来看我们的红绿灯程序,只闪烁黄灯还是正常工作取决于其中的一个变量kaiguan。
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)所以,利用中断,我们的需要在按钮按下时及时改变kaiguan这个变量的数值,然后在程序中及时判断这个值是否已经变化了,从而作出正确的逻辑控制。
现在我们创建一个叫做changekaiguan的函数:
def changekaiguan(): #创建无参数函数:修改kaiguan变量,从而控制红绿灯 print(pressed) global kaiguan #kaiguan是全局变量,在主程序中已经声明 kaiguan = bool(1 - kaiguan) #取反操作 print(kaiguan) #打印kaiguan的数值,true或false因为kaiguan变量是在主函数声明的,函数如果要使用它,需要用global关键字,表示它是一个全局变量 。
当控制按钮按下时,调用changekaiguan函数,通过如下代码实现:
control.when_pressed = changekaiguan #按下按钮时调用changekaiguan函数注意: 这一个语句应该在changekaiguan函数创建之后才行,否则就会报变量没有定义的错误。
验证中断程序
通过上面的代码,我们创建了一个中断函数,当按钮按下时,每次都调用changekaiguan函数。让我们来测试一下,完整代码如下:
from gpiozero import led,buttonfrom time import sleepkaiguan = false green = led(26) #green灯链接了gpio26yellow= led(5) #黄灯链接了gpio5red = led(22) #red灯连接了gpio22control = button(17) #按钮连接了gpio17def changekaiguan(): #创建无参数函数:修改kaiguan变量,从而控制红绿灯 print(pressed) global kaiguan #kaiguan是全局变量,在主程序中已经声明 kaiguan = bool(1 - kaiguan) #取反操作 print(kaiguan) #打印kaiguan的数值,true或falsecontrol.when_pressed = changekaiguan #按钮按下时调用changekaiguan函数while true: if kaiguan == false: #当kaiguan变量为false时,黄灯闪烁 yellow.on() sleep(0.5) yellow.off() sleep(0.5) else: #当kaiguan变量为true时, red.on() sleep(3) #绿灯亮3秒 red.off() yellow.on() #黄灯亮1秒 sleep(1) yellow.off() green.on() #红灯亮3秒 sleep(3) green.off()运行上面的程序,可以发现,无论程序运行在那个阶段,当按下按钮时,都可以马上在shell界面看到打印“pressed以及最新的kaiguan参数数值。
我们发现每次按钮按下,都马上进入了中断程序changekaiguan,在程序中修改了kaiguan变量的值并打印了出来,当前程序运行在sleep还是其他语句都没有影响。
进阶版红绿灯程序
现在,是时候完成我们的进阶版程序,让红绿灯可以在按钮按下后及时切换工作状态。在此之前,我们需要调整红绿灯连接线,把红灯和绿灯互换位置,同时修改程序。最新的电路图:
电路实物照片:
要修改程序,需要考虑在什么时候探测kaiguan变量值,然后作出逻辑调整,原程序红绿灯正常工作时不能及时探测kaiguan变量才造成对按钮的反应迟钝,所以需要修改这部分代码,为了保证控制操作的完整性,我们不能在某个灯还亮着时进行切换,需要在灯灭后进行,所以修改如下:
from gpiozero import led,buttonfrom time import sleepkaiguan = false green = led(26) #green灯链接了gpio26yellow= led(5) #黄灯链接了gpio5red = led(22) #red灯连接了gpio22control = button(17) #按钮连接了gpio17def changekaiguan(): print(pressed) global kaiguan kaiguan = bool(1 - kaiguan) print(kaiguan)control.when_pressed = changekaiguanwhile true: if kaiguan == false: #当kaiguan变量为false时,黄灯闪烁 yellow.on() sleep(0.5) yellow.off() sleep(0.5) else: #当kaiguan变量为true时, red.on() sleep(3) #绿灯亮3秒 red.off() if kaiguan == false: #判断kaiguan是否已经变为false,如果是,则跳出当前操作,继续下一个循环 continue #跳过下面的代码,开始下一个循环 yellow.on() #黄灯亮1秒 sleep(1) yellow.off() if kaiguan == false: #判断kaiguan是否已经变为false,如果是,则跳出当前操作,继续下一个循环 continue green.on() #红灯亮3秒 sleep(3) green.off()运行程序,看看是不是按我们期望的正常运作了呢?
是的,现在只要我们按下按钮,程序都可以及时切换,即使在红灯或绿灯亮时按下按钮,当灯灭时也会判断出kaiguan值变为false,从而中止当前循环,进入下一个循环中。如此,进阶版的红绿灯大功告成!
嵌入式Linux操作系统的网络存储设备
DIY一个电磁悬浮装置
MIT研发RoadTracer,它能够将地图绘制精度提高45%
14种电机启动电路图及电路分析
如何使用仿真和测试进行BGA的射频和高速传输的性能研究
用树莓派控制交通红绿灯(进阶版)
虹科新品 | 什么是虹科weeve边缘计算软件平台?
为什么焊接机器人需要焊缝跟踪寻位
使用模块化、OpenUSD的Omniverse加速3D工作流程
MWC上厂商火拼 LTE与四核成看点
AI在疫情期间起到了哪些作用
电子狗和导航仪有什么区别
一种SiCl4电解液添加剂驱动的原位交联策略研究
巴西或允许华为参加5G网络拍卖会
三星电子旗舰新机Galaxy S21系列将提前至下月发布
紫光展锐联合中国联通、通则康威、广和通重磅发布两大新品
Brave成全球首个支持IPFS的浏览器
芯片短缺到底什么时候是个头?
高颜值读卡器 专为线下零售公司设计
人工智能在疫情期间对经济社会发展的影响