前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >树莓派基础实验8:振动开关实验

树莓派基础实验8:振动开关实验

作者头像
张国平
发布2020-09-27 10:08:47
1.6K0
发布2020-09-27 10:08:47
举报

一、介绍

   振动开关也称为弹簧开关或振动传感器,是一种电子开关。它会产生振动力,并将结果传送给电路装置,从而触发其工作。它包含以下部分:导电振动弹簧,开关主体,触发销和包装壳。


二、组件

★Raspberry Pi 3主板*1

★树莓派电源*1

★40P软排线*1

★振动开关传感器模块*1

★双色LED模块*1

★面包板*1

★跳线若干

三、实验原理

振动开关

振动传感器实验原理图

  在震动开关模块中,导电的振动弹簧和触发销被精确地放置在开关体中,并且通过粘合剂结合到固化位置。通常,弹簧和触发销不接触,一旦摇动,弹簧就会摇动并与触发器引脚接触,以传导并产生触发信号。   在此实验中,将双色LED模块连接到树莓派以指示更改。敲击或敲击振动传感器时,它将打开,双色led将闪烁绿色,再次敲击它将变为红色,每一次敲击后会在两种颜色之间切换。

四、实验步骤

第1步:连接电路,该实验与实验6(轻触开关按键实验)相同。这里激光模块的实物与模块原理图的端口名称不一致,我们按照实物的端口名称来连接。

树莓派

T型转接板

振动开关

GPIO 0(序号11)

GPIO 17

SIG(DO)

5V

5V

VCC

GND

GND

GND

树莓派

T型转接板

双色LED

GPIO 1(序号12)

GPIO 18

R(红色端口)

GND

GND

GND

GPIO 2(序号13)

GPIO 27

G(绿色端口)

振动开关实验电路图

振动开关实验实物连接图

第2步:这次编程有两个函数要注意,是关于输入的高级应用。   有多种方式将GPIO的输入导入到程序中,polling( 轮询 )式 和 interrupt( 中断 )式( edge detection 边缘检测 ),“轮询”式如果程序在错误的时间读取值,可能会错过输入。我们这里采用中断式。   如果您没有将输入引脚连接到任何东西,它将“浮动”。换句话说,读取的值是未定义的,因为它没有连接到任何东西,直到你按下按钮或开关。它可能会由于接收电源干扰而改变很大的值。   为了解决这个问题,我们使用一个向上拉或向下拉电阻器。这样,就可以设置输入的默认值。可以使用硬件或者软件实现上下拉电阻。在硬件方式中,常常在输入通道与3.3V(上拉)或0V(下拉)之间使用10K电阻。GPIO模块允许您在编程中这样配置:

代码语言:javascript
复制
GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_UP)
  # or
GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

  我们很多时候并不关心电平值, 而关心电平从低到高,或从高到低的变化(如编码器测速/按键按下弹开等), 为避免主程序忙于其它事情错过引脚的电平改变, 有两种方式: wait_for_edge() 函数 event_detected() 函数 wait_for_edge()函数是为了阻止程序的执行,直到检测到边缘为止。换句话说,等待按钮按下的示例可以改写成:

代码语言:javascript
复制
GPIO.wait_for_edge(channel, GPIO.RISING)

   注意检测的边缘参数有 GPIO.RISING, GPIO.FALLING , GPIO.BOTH (上升沿, 下降沿 或 升降沿), 这样用几乎不占用CPU,如果你只希望在确定的时间段内查询,可以使用 timeout 参数:

代码语言:javascript
复制
# wait for up to 5 seconds for a rising edge (timeout is in milliseconds)
channel = GPIO.wait_for_edge(channel, GPIO_RISING, timeout=5000)
if channel is None:
    print('Timeout occurred')
else:
    print('Edge detected on channel', channel)

event_detected()函数被设计用来与其他事物一起在循环中使用, 不同于polling轮询, 它不会在CPU忙于处理其他事物时错过输入状态的变化。 这使得使用Pygame 或 PyQt 时非常有用,因为其中有一个主循环监听和及时响应GUI事件的基础。   只要检测到指定参数的边缘事件(上升沿, 下降沿 或 升降沿)发生时,调用GPIO.event_detected(channel)的值就为"ture"(真)。

代码语言:javascript
复制
#Note that you can detect events for GPIO.RISING, GPIO.FALLING or GPIO.BOTH.
GPIO.add_event_detect(channel, GPIO.RISING)  # add rising edge detection on a channel
do_something()
if GPIO.event_detected(channel):
    print('Button pressed')

  不过需要自己新建一个线程去循环检测event_detected()的值,还算是比较麻烦的。   可采用另一种办法轻松检测状态,这种方式是直接传入一个回调函数:GPIO通过在add_event_detect()函数中添加callback参数,RPI.GPIO为回调函数运行第二个线程。这意味着回调函数可以与主程序同时运行,以立即响应边缘。   For example:

代码语言:javascript
复制
def my_callback(channel):
    print('This is a edge event callback function!')
    print('Edge detected on channel %s'%channel)
    print('This is run in a different thread to your main program')
GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback) 
 # 这里添加了回调函数callback这个参数,就不需要GPIO.event_detected(channel)函数了

  如果你想要不止一个回调函数:

代码语言:javascript
复制
def my_callback_one(channel):
    print('Callback one')
def my_callback_two(channel):
    print('Callback two')
GPIO.add_event_detect(channel, GPIO.RISING)
GPIO.add_event_callback(channel, my_callback_one)
GPIO.add_event_callback(channel, my_callback_two)

  请注意,在这种情况下,回调函数是按顺序运行的,而不是并发的。这是因为只有一个线程用于回调,其中每个回调都按照它们被定义的顺序运行。

  由于存在开关抖动(用示波器可以看到),每次按下开关会调用多次回调函数,这不是我们希望的,有两种方式处理开关抖动:   ①在开关两个引脚之间添加一个0.1uF的电容   ②软件消抖   ③二者结合使用   使用软件消抖时, 给回调函数添加一个弹跳时间的参数( bouncetime= ), 弹跳时间(参照单片机可以为10~20ms)在ms级别, 下面的程序用200ms来消抖:

代码语言:javascript
复制
# add rising edge detection on a channel, ignoring further edges for 200ms for switch bounce handling
GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback, bouncetime=200)

  由于某些原因, 你的程序可能不希望用边缘检测了,可以停止它们:

代码语言:javascript
复制
GPIO.remove_event_detect(channel)

第3步:正式编程。定义针脚参数和初始化设置函数setup(),其中就用到了上面讲解的GPIO输入高级应用,本次实验不使用检测函数GPIO.add_event_detect(),采用“轮询”式,在循环中直接查询GPIO.input(TiltPin)的值来判定是否振动。

代码语言:javascript
复制
#!/usr/bin/env python
import RPi.GPIO as GPIO
import time

VibratePin = 11
Rpin   = 12
Gpin   = 13

tmp = 0

def setup():
    GPIO.setmode(GPIO.BOARD)       # Numbers GPIOs by physical location
    GPIO.setup(Gpin, GPIO.OUT)     # Set Green Led Pin mode to output
    GPIO.setup(Rpin, GPIO.OUT)     # Set Red Led Pin mode to output
    GPIO.setup(VibratePin, GPIO.IN, pull_up_down=GPIO.PUD_UP) 
   # Set BtnPin's mode is input, and pull up to high level(3.3V)

第4步:定义Led(x)函数,控制双色LED灯闪烁。定义Print(x),打印按键是否切换开关的提示消息。

代码语言:javascript
复制
def Led(x): #控制双色LED灯闪烁的函数
    if x == 0:
        GPIO.output(Rpin, 1)    #红灯亮
        GPIO.output(Gpin, 0)    #绿灯灭
    if x == 1:
        GPIO.output(Rpin, 0)
        GPIO.output(Gpin, 1)
    

def Print(x):   #打印按键是否切换开关的提示消息
    global tmp
    if x != tmp:
        if x == 0:
            print '    **********'
            print '    *     ON *'
            print '    **********'
    
        if x == 1:
            print '    **********'
            print '    * OFF    *'
            print '    **********'
        tmp = x

第5步:当模块平稳没有振动时,GPIO.input(TiltPin)的值为0,IF语句不执行;   当振动时,GPIO.input(TiltPin)的值为1,执行IF语句。每次执行IF语句时,Led(state)中的state值都与上次不同,所以LED的颜色会在红绿之间切换。

代码语言:javascript
复制
def loop():
    state = 0
    while True:
        if GPIO.input(VibratePin):  #每当振动产生时
            state = state + 1
            if state > 1:
                state = 0
            Led(state)
            Print(state)
            time.sleep(1)

第6步:创建destroy()函数,清除LED状态。创建程序入口,并包含异常处理。

代码语言:javascript
复制
def destroy():
    GPIO.output(Gpin, GPIO.LOW)       # Green led off
    GPIO.output(Rpin, GPIO.LOW)       # Red led off
    GPIO.cleanup()                     # Release resource

if __name__ == '__main__':     # Program start from here
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # When 'Ctrl+C' is pressed, the child program destroy() will be  executed.
        destroy()
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、介绍
  • 二、组件
  • 三、实验原理
  • 四、实验步骤
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档