玩转树莓派树莓派张国平玩树莓派

树莓派基础实验10:干簧管传感器实验

2020-02-16  本文已影响0人  Maker张

一、介绍

   磁簧开关(Reed Switch)也称之为干簧管,它是一个通过所施加的磁场操作的电开关。基本型式是将两片磁簧片密封在玻璃管内,两片虽重叠,但中间间隔有一小空隙。当外来磁场时将使两片磁簧片接触,进而导通。 一旦磁体被拉到远离开关,磁簧开关将返回到其原来的位置。可以用来计数或限制位置。


二、组件

★Raspberry Pi主板*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模块允许您在编程中这样配置:

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
ReedPin = 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(ReedPin, 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(ReedPin, GPIO.BOTH, callback=detect, bouncetime=200)

  第4步:定义Led(x)函数,控制双色LED灯闪烁。定义Print(x),打印按键是否切换开关的提示消息。检测到磁铁时,传感器输出低电平,干簧管簧片拉在一起,电路联通,红灯亮;拿开磁铁时,传感器输出高电平,干簧管簧片分开,电路断开,绿灯亮。

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 '    *   Detected Magnetic Material!   *'
        print '    ***********************************'

  第5步:检测到磁铁时(或者拿开磁铁时),边缘事件检测函数都会回调detect(chn)函数,产生低电平信号(或者高电平信号),GPIO.input(ReedPin)的值为0(或1),LED灯会呈红(或绿)颜色。

def detect(chn):
    Led(GPIO.input(ReedPin))    #控制双色LED灯闪烁的函数
    Print(GPIO.input(ReedPin))  #打印检测到磁性物质
    print GPIO.input(ReedPin) #验证GPIO.input(ReedPin)的值
def loop():
    while True:
        pass

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

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()
上一篇下一篇

猜你喜欢

热点阅读