内容简介:本以为GPIO接一个开关是很简单的事情,但实际上需要学会很多前置的知识才能搞得下去,所以我把整个事情的原理和实现流程全部记录下来,希望帮助到像我一样的电路小白。给大家看一下我的按钮,是那种4个脚的:
本以为GPIO接一个开关是很简单的事情,但实际上需要学会很多前置的知识才能搞得下去,所以我把整个事情的原理和实现流程全部记录下来,希望帮助到像我一样的电路小白。
硬件
- 树莓派 * 1(我的是1B型号)
- 杜邦线(母对母) * 2
- 按钮 * 1
给大家看一下我的按钮,是那种4个脚的:
开关有4个脚,红框内的2根脚是互相联通,电会从这俩脚里流过,我们任意选一组用就可以了!
大家买到的按钮的4个脚的联通关系可能与图中不同,自己研究一下或者问一下商家到底哪两个脚是联通的就行。
按钮的作用就是按下去电路就联通了,否则就断开了,没什么特别的。
电路
GPIO有个input模式,如果输入电流到GPIO口,那么编程读取GPIO返回HIGH,如果没有输入电流则返回LOW,从而我们可以检测到按钮的状态变化。
GPIO输入安全电压应该是3.3V,因此我们会使用树莓派的3.3V供电口而不是5v(大家有兴趣可以试试5.5v会发生什么)。
错误的电路
所以很直接的,我就想把电路连成这样:
从树莓派引出3.3V的电压,经过开关,接到某个出于输入状态的GPIO针脚。
开关闭合的时候,电流流入GPIO,可以读到HIGH。
开关断开的时候,电路不通,可以读到LOW。
然而问题就在红色字体的情况:开关断开时,GPIO引脚是悬空的,受周遭环境干扰可能产生微弱电流,导致GPIO输入时高时低。
用程序检测GPIO的输入变化,会发现按钮不停的在断开与闭合:
pi@raspberrypi:~/pi-switch $ python floating.py open open open
测试代码后面我们再看,这里主要是为了告诉大家这种悬空浮动问题是客观存在的,必须解决。
此时,实际接线如下:
左侧3.3V的电压 ,流经按钮 ,输入到GPIO 18口。
按钮没有按下的情况,出现floating问题,因此这个电路是错误的,我们接下来看一下如何修正。
下拉电阻
我们现在只要解决开关断开情况下的输入浮动问题即可,如何解决呢?
我们把电路改成这样:
电路的变更:在开关右侧,拉了一根线出来,接了一个电阻,然后接到GND地线。
在开关断开的情况下,GPIO和GND相连,可以把GND相当于一个0v的电源,整个电路没有电流输入,所以GPIO稳定为LOW。
在开关闭合的情况下,电流经过开关后出现分叉位置(相当于水流要分叉了),因为下拉电阻存在导致电流(理解成流动的电子)并没有全部涌入,所以剩余电流得以进入GPIO,所以是HIGH。
红圈内的电路其实树莓派都封装在GPIO针脚内部,我们可以视作黑盒使用,只需要编程时控制切换到下拉模式即可。
此时,我们要做的硬件工作如下:
- 从3.3v连到开关
- 从开关连到gpio引脚
程序需要开启GPIO口的下拉模式,开关断开时是LOW、闭合时是HIGH,所以我们监听输入的RISING(升高)即可获知按钮按下的事件:
# -*- coding: utf-8 -*- from RPi import GPIO import time # 采用BCM引脚编号 GPIO.setmode(GPIO.BCM) # 关闭警告 GPIO.setwarnings(False) # 输入引脚 channel = 18 # 设置GPIO输入模式, 使用GPIO内置的下拉电阻, 即开关断开情况下输入为LOW GPIO.setup(channel, GPIO.IN, pull_up_down = GPIO.PUD_DOWN) # 检测LOW -> HIGH的变化 GPIO.add_event_detect(channel, GPIO.RISING, bouncetime = 200) # 开关闭合的处理 def on_switch_pressed(): print('open') try: while True: # 如果检测到电平RISING, 说明开关闭合 if GPIO.event_detected(channel): on_switch_pressed() # 可以在循环中做其他检测 time.sleep(0.01) # 10毫秒的检测间隔 except Exception as e: print(e) # 清理占用的GPIO资源 GPIO.cleanup()
上拉电阻
与下拉电阻类似,同样可以解决浮动问题。
电路图如下:
同样的,红圈都是GPIO内部的电路,可以通过编程控制切换到上拉模式。
我们要做的就是从树莓派的GND接到开关,开关接到GPIO针脚即可。
在开关断开情况下,电流经过上拉电阻,虽然电流小一点但也流向了GPIO,所以是HIGH。
在开关闭合情况下,电流经过上拉电阻后遇到分叉,接着电流(理解成流动的电子)会全部走向GND,可以理解成一个并联电路的短路分支。
代码需要设置GPIO为上拉模式:
# -*- coding: utf-8 -*- from RPi import GPIO import time # 采用BCM引脚编号 GPIO.setmode(GPIO.BCM) # 关闭警告 GPIO.setwarnings(False) # 输入引脚 channel = 18 # 设置GPIO输入模式, 使用GPIO内置的上拉电阻, 即开关断开情况下输入为HIGH GPIO.setup(channel, GPIO.IN, pull_up_down = GPIO.PUD_UP) # 检测HIGH -> LOW的变化 GPIO.add_event_detect(channel, GPIO.FALLING, bouncetime = 200) # 开关闭合的处理 def on_switch_pressed(): print('open') try: while True: # 如果检测到电平FALLING, 说明开关闭合 if GPIO.event_detected(channel): on_switch_pressed() # 可以在循环中做其他检测 time.sleep(0.01) # 10毫秒的检测间隔 except Exception as e: print(e) # 清理占用的GPIO资源 GPIO.cleanup()
我们刚才说了,断开时为HIGH,闭合时为LOW,所以要监听的是从HIGH变为LOW的事件,所以是检测FALLING变化。
我们一律加了bouncetime = 200,这是为了防抖用的,因为如果不加的话按下1次开关会发现事件触发了N次,可能是因为电路多次连续抖动的原因导致,所以忽略在200毫秒内的重复变化。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
ES6 标准入门(第2版)
阮一峰 / 电子工业出版社 / 2016-1 / 69.00元
ES6(又名 ES2105)是 JavaScript 语言的新标准,2015 年 6 月正式发布后,得到了迅速推广,是目前业界超级活跃的计算机语言。《ES6标准入门(第2版)》是国内仅有的一本 ES6 教程,在前版基础上增补了大量内容——对标准进行了彻底的解读,所有新增的语法知识(包括即将发布的 ES7)都给予了详细介绍,并且紧扣业界开发实践,给出了大量简洁易懂、可以即学即用的示例代码。 《......一起来看看 《ES6 标准入门(第2版)》 这本书的介绍吧!