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

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

内容简介:本以为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毫秒内的重复变化。


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

查看所有标签

猜你喜欢:

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

Introduction to Tornado

Introduction to Tornado

Michael Dory、Adam Parrish、Brendan Berg / O'Reilly Media / 2012-3-28 / USD 23.99

Tornado is a scalable, non-blocking web server and web application framework written in Python. It is also light-weight to deploy, fun to write for, and incredibly powerful. Tornado was written with p......一起来看看 《Introduction to Tornado》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换