树莓派基础实验7:倾斜开关实验

时间:2022-07-25
本文章向大家介绍树莓派基础实验7:倾斜开关实验,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、介绍

   带有金属球的球形倾斜开关。它用于检测小角度的倾斜。


二、组件

★Raspberry Pi 3主板*1

★树莓派电源*1

★40P软排线*1

★倾斜传感器模块*1

★双色LED模块*1

★面包板*1

★跳线若干

三、实验原理

倾斜传感器

倾斜传感器实验原理图

  在倾斜开关中球以不同的倾斜角度移动,以制造触发电路。倾斜开关模块使用双向传导的球形倾斜开关。当它向一侧倾斜时,只要倾斜度和力满足条件开关就会通电,从而输出低电平信号。

四、实验步骤

第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模块允许您在编程中这样配置:

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()函数是为了阻止程序的执行,直到检测到边缘为止。换句话说,等待按钮按下的示例可以改写成:

GPIO.wait_for_edge(channel, GPIO.RISING)

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

# 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"(真)。

#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:

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)函数了

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

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来消抖:

# 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)

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

GPIO.remove_event_detect(channel)

第3步:正式编程。定义针脚参数和初始化设置函数setup(),其中就用到了上面讲解的GPIO输入高级应用,添加边缘事件检测函数GPIO.add_event_detect()。

#!/usr/bin/env python
import RPi.GPIO as GPIO

TiltPin = 11
Rpin   = 12
Gpin   = 13

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(TiltPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)    # Set BtnPin's mode is input, and pull up to high level(3.3V)
    GPIO.add_event_detect(TiltPin, GPIO.BOTH, callback=detect, bouncetime=200)

第4步:当模块水平放置时,信号是高电平,GPIO.input(TiltPin)的值为1,即LED(x)中的x==1,绿灯亮,无打印信息;   当倾斜时,开关通电,从而输出低电平信号,GPIO.input(TiltPin)的值为0,即LED(x)中的x==0,红灯亮,打印显示“Tilt! ”。

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):  #打印按键是否倾斜的提示消息
    if x == 0:
        print '    *************'
        print '    *   Tilt!   *'
        print '    *************'

def detect(chn):
    Led(GPIO.input(TiltPin))    #控制双色LED灯闪烁
    Print(GPIO.input(TiltPin))  #打印按键是否倾斜的提示消息

第5步:很多程序都提供了“空语句”支持,Python 也不例外,Python 的 pass 语句就是空语句。有时候程序需要占一个位、放一条语句,但又不希望这条语句做任何事情,此时就可通过 pass 语句来实现。通过使用 pass 语句,还可以让程序更完整,因为如果定义一个空函数程序会报错,当你没有想好函数的内容时可以用 pass 填充,使程序可以正常运行。

def loop():
    while True:
        pass

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()