从零玩转Micropython+ESP32(五) GPIO输入和按键操作

前面我们使用了GPIO输出高低电平, 并实现了点灯和闪灯的效果, 但GPIO引脚可不仅仅是输出这么简单, 它还可以检测信号的输入, 来实现控制效果

现在我们就来学习一下吧!

友情提示: 学完本集之后, 请不要用这种方法控制核弹发射🤣🤣🤣

hedan

一. 输入电路

1. 引脚输入

我们的引脚非常强大, 当它处于输入模式时, 如果引脚收到高低电平, 就可以获取这些电平, 并将高电平转为1, 将低电平转为0

于是, 我们明白了: 我们给引脚加高电平就相当于告诉单片机一个数字1, 给引脚加低电平就相当于告诉单片机一个数字0

输入电路可以让我们收到外部的信息和命令, 让ESP32实现更加强大的功能

2. 怎么给引脚加高低电平呢?

那么, 我们要怎么给引脚加高低电平呢?

在ESP32开发板上有多个电压来源, 根据板子的不同,可能有不同的标识, 比如3V3 VIN VCC等等

与之对应的, ESP32开发板上也有多个预留的接地点, 比如: GND G等等

image-20220303151031393

比如, 我们将3V3引脚和D5引脚连起来, D5引脚就能获得高电平, 我们将GND引脚和D5引脚连起来, D5引脚就能获得低电平

image-20220303151559738

3. 按键输入电路

上面, 我们学会了输入高低电平, 但是靠短接电源和地输入0, 1是很不方便的, 我们最好能有个按键, 按键按下输入1, 按键抬起输入0, 或者按键按下输入0, 按键抬起输入1也行

所以,根据刚才的分析, 我们可以设计出这样的电路图 (输入电路有好多种形式, 这里我们介绍一种典型了的: 外上拉)

当按键抬起时, VCC电源和引脚D5接通, 形成了高电平, 电流会流过电阻, 再流进D5引脚

当按键按下后, GND和引脚D5接通了, 形成了低电平, 电流会流过电阻, 直接流向GND, 而不流向D5, 因为D5内部是有一点阻抗的

电阻R的阻值随意1K 2K 10K都可以

不过在这里, 告诉大家一个好消息, 我们使用的开发板上已经有一个引脚已经接上了按键, 那就是0号引脚, 所以我们不用自己搭建按键电路了

0号引脚连到了哪个按键呢??? 就是开发板右边这个BOOT按键, 其接线电路就和我们刚刚描述的电路原理图一样

下面, 我们就先用这个按键进行实验

image-20220304115008034

二. MicroPython控制GPIO输入

1. 初始化GPIO为输入

key = Pin(0, Pin.IN)

2. 检测GPIO输入值

key.value()

3. 编写一个程序, 实现按键检测

这里我们要注意加一个延时, 因为不加延时的话, 由于运算太空, 终端会卡死

from machine import Pin #导入引脚模块
import time             #导入时间模块

key = Pin(0, Pin.IN)    #把0号引脚初始化为输入模式, 并取名为key     
while True:
    print("GPIO_0:", key.value()) #打印当前0号引脚输入状态
    time.sleep(0.01)                #延时0.01秒

4. 编写一个程序, 实现按灯即亮

只需要稍微改一改程序

from machine import Pin             #导入引脚模块
import time                         #导入时间模块

key = Pin(0, Pin.IN)                #把0号引脚初始化为输入模式, 并取名为key     
led = Pin(2, Pin.OUT)               #把2号引脚初始化为输出模式, 并取名为led     
while True:
    print("GPIO_0:", key.value()) #打印当前0号引脚输入状态
    led.value(not key.value())      #给led设置值, 因为按键按下时是0, 所以取一下反
    time.sleep(0.01)                #延时0.01秒

2. GPIO

from machine import Pin, PWM
import time

pwm_freq = 50 #PWM频率
duty_range = 1000 #PWM最大占空比 千分之多少
delay_rgs = 3  #延迟系数

while 1:
    for i in range(0,duty_range):
        pwm2 = PWM(Pin(5), freq=pwm_freq, duty=25)
        time.sleep_ms(delay_rgs)
    for i in range(0,duty_range):
        pwm2 = PWM(Pin(5), freq=pwm_freq, duty=50)
        time.sleep_ms(delay_rgs)
    for i in range(0,duty_range):
        pwm2 = PWM(Pin(5), freq=pwm_freq, duty=75)
        time.sleep_ms(delay_rgs)
    for i in range(0,duty_range):
        pwm2 = PWM(Pin(5), freq=pwm_freq, duty=100)
        time.sleep_ms(delay_rgs)
    for i in range(0,duty_range):
        pwm2 = PWM(Pin(5), freq=pwm_freq, duty=125)
        time.sleep_ms(delay_rgs)

三. 学会搭建按键电路

1. 搭建按键电路

根据上面的电路图, 我们可以这样搭建电路

image-20220304123711855

2. 使用大按键模块

这里推荐大家使用下面这种大按键模块, 大家做实验时可以直接用, 因为它已经焊好了电阻

image-20220303154347290

image-20220303154238527

但这种按键内部电路是这样的:

image-20220304113114252

可以看到, 此模块把电阻R放在了GND管脚一侧, 这和我们的电路图不一样了, 所以, 我们使用时应该把vcc和gnd引脚反过来接线, 如下图

image-20220304111938827

当然, 如果手头没有这种大按键模块, 用普通按键串联电阻也是可以的

搭建完电路后, 我们把上面程序中的0号引脚改为5号引脚即可进行实验

四. 小挑战

1. 按键 开/关 灯

实现这个功能: 按一下按键亮灯, 再按一下灭灯

from machine import Pin               # 导入引脚模块
import time                           # 导入时间模块

key = Pin(5, Pin.IN)                  # 把0号引脚初始化为输入模式, 并取名为key
led = Pin(2, Pin.OUT)                 # 把2号引脚初始化为输出模式, 并取名为led
light_flag = False                    # 创建一个亮灯标志位, 用于管理LED灯的开关状态

while True:
    print("GPIO_0:", key.value())     # 打印当前0号引脚输入状态
    if not key.value():               # 如果按键被按下
        while not key.value():            # 当按键没抬起之前一直死循环在这里
            pass
        light_flag = not light_flag   # 能运行到这里, 说明上面的循环已经被打破, 证明按键已经被抬起

    if light_flag:                    # 根据亮灯标志位判断灯是否亮
        led.value(1)
    else:
        led.value(0)
    time.sleep(0.01)                  # 延迟0.01秒

2. 按键 开/关 闪灯

大家再试着做一个按键闪灯效果: 按一下按键闪灯, 再按一下熄灯

from machine import Pin               # 导入引脚模块
import time                           # 导入时间模块

key = Pin(5, Pin.IN)                  # 把0号引脚初始化为输入模式, 并取名为key
led = Pin(2, Pin.OUT)                 # 把2号引脚初始化为输出模式, 并取名为led
light_flag = False                    # 创建一个亮灯标志位, 用于管理LED灯的开关状态

while True:
    print("GPIO_0:", key.value())     # 打印当前0号引脚输入状态
    if not key.value():               # 如果按键被按下
        while not key.value():            # 当按键没抬起之前一直死循环在这里
            pass
        light_flag = not light_flag   # 能运行到这里, 说明上面的循环已经被打破, 证明按键已经被抬起

    if light_flag:                    # 根据亮灯标志位判断灯是否亮
        led.value(not led.value())
        time.sleep(1)
    else:
        led.value(0)
    time.sleep(0.01)                  # 延迟0.01秒

这里大家就发现问题了, 我们发现启动闪灯很简单, 但关闭闪灯有时候不行, 得按的久一点才行, 这是为什么呢???

img

这是因为, 当程序执行time.sleep(1)的时候, 系统会睡一秒钟, 这一秒钟无论我们怎么按, 都不会执行到 if not key.value():这个分支, 导致我们按键是无效的, 这个问题我们后面会解决, 现在我就按的久一点

3. 按0键 开/关 闪灯, 按5键调整闪灯速度

效果: 按一下按键0闪灯, 再按一下熄灯, 按下按键5会加快闪灯速度(每次加快0.2秒), 最快0.2秒一闪, 最慢1秒一闪, 当到达最快速度后再按键会重置为1秒一闪, 老样子, 我们按键要按久一点

from machine import Pin               # 导入引脚模块
import time                           # 导入时间模块

key = Pin(0, Pin.IN)                  # 把0号引脚初始化为输入模式, 并取名为key
key2 = Pin(5, Pin.IN)                 # 把5号引脚初始化为输入模式, 并取名为key
led = Pin(2, Pin.OUT)                 # 把2号引脚初始化为输出模式, 并取名为led
light_flag = False                    # 创建一个亮灯标志位, 用于管理LED灯的开关状态
flash_span = 1                        # 默认间隔一秒钟

while True:
    if not key.value():               # 如果按键0被按下
        while not key.value():
            pass
        light_flag = not light_flag

    if not key2.value():              # 如果按键0被按下
        while not key2.value():
            pass
        flash_span -= 0.2               # 减少闪灯间隔
        if flash_span < 0.2:            # 当减到最少时, 重置为1秒
            flash_span = 1
        print(flash_span)               # 打印一下当前间隔

    if light_flag:                    # 根据亮灯标志位判断灯是否亮
        led.value(not led.value())
        time.sleep(flash_span)
    else:
        led.value(0)
    time.sleep(0.01)                  # 延迟0.01秒
©本文首发于 菁英编程爱好者, 转载请注明出处.
菁英编程爱好者 » 从零玩转Micropython+ESP32(五) GPIO输入和按键操作

发表评论

提供最优质的资源集合

立即查看 了解详情