在本系列的前几篇博客中,咱们使用桌面软件控制过红绿灯,也编程点亮过炫彩的3色LED 灯。在这些实验的过程当中,相信你对树莓派GPIO引脚如何输出高低电平,以及如何使用PWM技术来控制电压输出等都有了了解。本篇博客,咱们将再探索一些树莓派编程更多新鲜好玩的领域,来尝试使用硬件来控制硬件。python
如今,咱们将尝试完成这样一个实验,使用按压开关控制蜂鸣器的发声。将开关元件和蜂鸣器都链接到树莓派,当按下开关时,让蜂鸣器发声,当松开开关时,蜂鸣器中止发声。编程
开始动手实验前,咱们先来认识一下将要出场的主角们,固然,不管什么实验,树莓派都是当之无愧的第一主角,但我相信你已经对它已经有了足够的了解(若是没有,能够查看本系列的前几篇博客),所以咱们将介绍的重点放在两个新登场的“角色”上:蜂鸣器与按压开关。markdown
蜂鸣器,顾名思义,其是一种发声元件。普遍应用于计算机、打印机、电话、玩具等电子设备中。ide
蜂鸣器能够分为“有源蜂鸣器”和“无源蜂鸣器”。其中的源并不是指电源,而是指蜂鸣器内部是否有震荡源。有源蜂鸣器自带一个震荡源模块,其使用起来很是简单,只要接通直流电,其就会自动发出声音。而无源蜂鸣器内部没有震荡源,须要外接使用必定频率的方波来驱动其发声。关于无源蜂鸣器更多深刻的用法,咱们后续博客再专门介绍。这里,咱们先着重理解有源蜂鸣器的工做原理。函数
本实验中,咱们采用的是低电平触发的有源蜂鸣器,元件以下图所示:学习
其有3个引脚,GND引脚用来接地,VCC引脚用来接3.3V的电源,I/O引脚用来进行蜂鸣器是否播放声音的控制。你可能有些疑惑,为何低电平也能够触发元件的“开”状态,这要归功于PNP型三极管的功劳,对于PNP型三极光,当输入管脚为低电平时,三极管处于导通状态,使得蜂鸣器被加电压,当输入管脚为高电平时,三极管处于截止状态,蜂鸣器无电压。原理以下图所示:编码
如今,咱们先来编写一段简单的Python程序,来使蜂鸣器发出声音。3d
咱们使用的蜂鸣器的3个引脚,其中VCC接电源,GND接地,I/O引脚咱们能够选择树莓派BCM编码为27的GPIO引脚,经过查表,能够获得其物理编码为13。连线示意以下:code
编写Python程序代码以下:blog
#coding:utf-8 # 导入GPIO控制薄块 import RPi.GPIO as GPIO # 导入time模块 import time # 定义引脚 fm = 13 # 设置使用的引脚编码模式 GPIO.setmode(GPIO.BOARD) # 进行引脚的初始化,由于是低电平触发,初始时设置为高电平 GPIO.setup(fm,GPIO.OUT, initial=GPIO.HIGH) # 进行一长两短的声音播放 # 播放1秒声音 GPIO.output(fm, GPIO.LOW) time.sleep(1) GPIO.output(fm, GPIO.HIGH) time.sleep(0.1) # 播放0.5秒声音 GPIO.output(fm, GPIO.LOW) time.sleep(0.5) GPIO.output(fm, GPIO.HIGH) time.sleep(0.1) # 播放0.5秒声音 GPIO.output(fm, GPIO.LOW) time.sleep(0.5) # 中止蜂鸣器播放 GPIO.output(fm, GPIO.HIGH) GPIO.cleanup()
在树莓派上运行代码,你应该已经能够听到蜂鸣器发出一长两短的鸣叫声了。
按压开关是电子设备中最为经常使用的一种元件,关于按压开关自己的结构和原理,其实很是简单,其按键内部会有弹簧进行控制,当没有外力做用时,弹簧会将开关自动顶起,接触器上升。当外力将按键按下时,接触器降低。经过接触器的上升和降低来控制电路的导通。以下图所示:
本次实验,咱们使用的按压开关元件以下图所示:
咱们使用的此开关当按键按下式,会向引脚输入低电平,当按键松开时,会向引脚输入低电平。在连线时,按压开关的“-”引脚接地,中间引脚节3.3V电压,“S”引脚接GPIO信号引脚,咱们能够将其接BCM编码为GPIO5的引脚,其物理编码为29。连线以下图所示:
下面,咱们要来学习点新东西了,如何获取到GPIO引脚的输入。
以前,咱们都是将GPIO做为输出引脚进行使用,即让GPIO输出高电平或低电平从而控制元件。其实还有不少场景,须要读取GPIO的输入信号,例如各类传感器和开关元件。一般,咱们能够采用两种方式来获取GPIO的输入信号:轮询式或中断式。
轮询式很好理解,即咱们不停的询问当前GPIO引脚:输入的信号是什么啊?以后GPIO会将当前的输入信息告诉咱们,这种不停的读取某个GPIO引脚的值的方式就是轮询式获取输入信号。更多时候,咱们会采起中断式,中断式是指在程序运行过程当中,若是出现外部事件,则中断当前程序运行来处理外部事件。在本实验中,开关的按下和松开就能够理解为中断事件。
须要注意,对于做为输入使用的GPIO引脚来讲,当咱们未接任何输入源时,其值多是任意的,即其值是浮动且不可控的,所以咱们须要为其配置一个默认值,硬件上,咱们一般使用下拉电阻或上拉电阻。软件上咱们也能够经过GPIO库的相关接口来实现一样的功能,例如使用下面的方式初始化引脚:
# 将引脚初始化为输入引脚,同时设置默认值为高电平 GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_UP) # 将引脚初始化为输入引脚,同时设置默认值为低电平 GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
若要获取到某个输入引脚当前的电平状况,可使用以下方法:
# 1表示高电平 0表示低电平 GPIO.input(channel)
例如能够经过以下的方式轮训检查某个引脚的输入:
while GPIO.input(channel) == GPIO.LOW: time.sleep(0.01)
咱们一般只须要关心电平的变化,以及变化方向,以本实验为例,当按下开关时,电平由低变高,当松开开关时,电平由高到低。下面方法能够中断当前程序的运行,等待电平变化的信号:
# 当channel引脚由低电平变到高电平时会触发向后执行, timeout设置超时时间 GPIO.wait_for_edge(channel, GPIO.RISING, timeout=5000)
GPIO.RISING表示要等待的是由低到高的电平变化,与之对应的还有GPIO.FALLING表示由高到低的电平变化,GPIO.BOTH表示两个方向的电平变化都会触发。
对于本实验的场景,GPIO.wait_for_edge方法并不实用,若是咱们要采用轮询的方式获取GPIO输入信号,则能够实用下面的方法:
# 为channel输入引脚添加[从低到高]的电平变化监听 GPIO.add_event_detect(channel, GPIO.RISING) # 下面的判断能够放在轮询中,只要有[从低到高]的电平变化,即会命中if判断 if GPIO.event_detected(channel): print('从低到高变化')
须要注意,GPIO.add_event_detect方法比直接轮询经过GPIO.input方法获取信号要可靠的多,直接轮询可能会错过某些电平变化事件,而GPIO.add_event_detect 不会。在使用GPIO.add_event_detect方法时,咱们也能够直接设置回调函数,当有变化发生时,即会执行到回调函数,例如:
# 定义回调函数 def my_callback(channel): pass # 注册回调函数 bouncetime参数用来进行防抖 GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback, bouncetime=200)
上面示例代码中,bouncetime参数可以提供软件防抖的功能,其单位为毫秒,200毫秒内的屡次电平变化来回将被忽略。
最后,若是你再也不须要监听,可使用以下方法移除:
GPIO.remove_event_detect(channel)
如今,咱们能够尝试使用树莓派读取按压开关元件的开关状态了。示例代码以下:
#coding:utf-8 # 导入GPIO控制薄块 import RPi.GPIO as GPIO # 导入time模块 import time # 设置使用的引脚编码模式 GPIO.setmode(GPIO.BOARD) # 定义开关引脚 swi = 29 # 进行开关引脚的初始化,设置为输入引脚,且默认为高电平 GPIO.setup(swi, GPIO.IN, pull_up_down=GPIO.PUD_PU) # 定义状态变化的回调函数 def switch(channel): # 高电平的开关松开 if GPOI.input(channel): print("开关松开") # 低电平为开关按下 else: print("开关按下") # 添加输入引脚电平变化的回调函数 GPIO.add_event_detect(swi, GPIO.BOTH, callback=switch, bouncetime=200) # 开启循环 while True: pass
在树莓派运行上面代码,经过按压和松开开关,观察控制台的输出是否正确。
若是你成功作完了前面的工做,那么好了,本节的内容将很是简单,只须要将上面编写的蜂鸣器程序和开关程序进行结合,你就可使用开关来控制蜂鸣器了。示例代码以下:
#coding:utf-8 # 导入GPIO控制薄块 import RPi.GPIO as GPIO # 导入time模块 import time # 设置使用的引脚编码模式 GPIO.setmode(GPIO.BOARD) # 定义开关引脚 swi = 29 # 定义蜂鸣器引脚 fm = 13 # 进行开关引脚的初始化,设置为输入引脚,且默认为高电平 GPIO.setup(swi, GPIO.IN, pull_up_down=GPIO.PUD_UP) # 进行蜂鸣器引脚的初始化,由于是低电平触发,初始时设置为高电平 GPIO.setup(fm,GPIO.OUT, initial=GPIO.HIGH) # 定义状态变化的回调函数 def switch(channel): # 高电平的开关松开 if GPI0.input(channel): GPIO.output(fm, GPIO.HIGH) # 低电平为开关按下 else: GPIO.output(fm, GPIO.LOW) # 添加输入引脚电平变化的回调函数 GPIO.add_event_detect(swi, GPIO.BOTH, callback=switch, bouncetime=200) # 开启循环 while True: pass
如今,运行程序,用开关来控制蜂鸣器的声音播放吧。恭喜!你已经可以使用硬件来控制硬件了!
经过本篇博客,你应该收获了GPIO输入信号的编程方法,以及经过GPIO读取有输入功能的传感器数据的方法。本篇博客涉及的内容不少,重点在于GPIO输入引脚中断的相关用法,须要你多多练习。说了这么多,你有没有发现此次咱们完成的实验很像生活中的一种东西?没错,就是门铃,你已经可使用树莓派实现一个简单的门铃器件啦。
专一技术,懂的热爱,愿意分享,作个朋友
QQ:316045346