1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 树莓派c语言按键开关 树莓派 GPIO按钮开关 原理与实现

树莓派c语言按键开关 树莓派 GPIO按钮开关 原理与实现

时间:2020-07-26 18:37:30

相关推荐

树莓派c语言按键开关 树莓派 GPIO按钮开关 原理与实现

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。