树莓派 GPIO按钮开关 原理与实现

栏目: 软件资讯 · 发布时间: 5年前

内容简介:本以为GPIO接一个开关是很简单的事情,但实际上需要学会很多前置的知识才能搞得下去,所以我把整个事情的原理和实现流程全部记录下来,希望帮助到像我一样的电路小白。给大家看一下我的按钮,是那种4个脚的:

本以为GPIO接一个开关是很简单的事情,但实际上需要学会很多前置的知识才能搞得下去,所以我把整个事情的原理和实现流程全部记录下来,希望帮助到像我一样的电路小白。

硬件

  • 树莓派 * 1(我的是1B型号)
  • 杜邦线(母对母) * 2
  • 按钮 * 1

给大家看一下我的按钮,是那种4个脚的:

树莓派 GPIO按钮开关 原理与实现

开关有4个脚,红框内的2根脚是互相联通,电会从这俩脚里流过,我们任意选一组用就可以了!

大家买到的按钮的4个脚的联通关系可能与图中不同,自己研究一下或者问一下商家到底哪两个脚是联通的就行。

按钮的作用就是按下去电路就联通了,否则就断开了,没什么特别的。

电路

GPIO有个input模式,如果输入电流到GPIO口,那么编程读取GPIO返回HIGH,如果没有输入电流则返回LOW,从而我们可以检测到按钮的状态变化。

GPIO输入安全电压应该是3.3V,因此我们会使用树莓派的3.3V供电口而不是5v(大家有兴趣可以试试5.5v会发生什么)。

错误的电路

所以很直接的,我就想把电路连成这样:

树莓派 GPIO按钮开关 原理与实现

从树莓派引出3.3V的电压,经过开关,接到某个出于输入状态的GPIO针脚。

开关闭合的时候,电流流入GPIO,可以读到HIGH。

开关断开的时候,电路不通,可以读到LOW。

然而问题就在红色字体的情况:开关断开时,GPIO引脚是悬空的,受周遭环境干扰可能产生微弱电流,导致GPIO输入时高时低。

用程序检测GPIO的输入变化,会发现按钮不停的在断开与闭合:

pi@raspberrypi:~/pi-switch $ python floating.py
open
open
open

测试代码后面我们再看,这里主要是为了告诉大家这种悬空浮动问题是客观存在的,必须解决。

此时,实际接线如下:

树莓派 GPIO按钮开关 原理与实现

左侧3.3V的电压 ,流经按钮 ,输入到GPIO 18口。

按钮没有按下的情况,出现floating问题,因此这个电路是错误的,我们接下来看一下如何修正。

下拉电阻

我们现在只要解决开关断开情况下的输入浮动问题即可,如何解决呢?

我们把电路改成这样:

树莓派 GPIO按钮开关 原理与实现

电路的变更:在开关右侧,拉了一根线出来,接了一个电阻,然后接到GND地线。

在开关断开的情况下,GPIO和GND相连,可以把GND相当于一个0v的电源,整个电路没有电流输入,所以GPIO稳定为LOW。

在开关闭合的情况下,电流经过开关后出现分叉位置(相当于水流要分叉了),因为下拉电阻存在导致电流(理解成流动的电子)并没有全部涌入,所以剩余电流得以进入GPIO,所以是HIGH。

红圈内的电路其实树莓派都封装在GPIO针脚内部,我们可以视作黑盒使用,只需要编程时控制切换到下拉模式即可。

此时,我们要做的硬件工作如下:

树莓派 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按钮开关 原理与实现

同样的,红圈都是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毫秒内的重复变化。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Linux内核设计与实现(原书第3版)

Linux内核设计与实现(原书第3版)

Robert Love / 陈莉君、康华 / 机械工业出版社华章公司 / 2011-4-30 / 69.00元

《Linux内核设计与实现(原书第3版)》详细描述了Linux内核的设计与实现。内核代码的编写者、开发者以及程序开发人员都可以通过阅读本书受益,他们可以更好理解操作系统原理,并将其应用在自己的编码中以提高效率和生产率。 《Linux内核设计与实现(原书第3版)》详细描述了Linux内核的主要子系统和特点,包括Linux内核的设计、实现和接口。从理论到实践涵盖了Linux内核的方方面面,可以满......一起来看看 《Linux内核设计与实现(原书第3版)》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

随机密码生成器
随机密码生成器

多种字符组合密码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码