树莓派使用Python检测连续脉冲

树莓派使用Python检测连续脉冲 1、应用场景 使用树莓派作为智能小车主控制器时,需要对轮子进行测速,采用的是马达+霍尔传感器的形式,小车运动时霍尔传感器会输出连续脉冲信号,通过转换就可以得到小车的速度,前行的距离等等。本博文用于流量传感器检测连续脉冲场景,通过转换可以得到流量大小。
2、检测方式 使用到了树莓派GPIO的输入(Input)功能,可分为以下几种情况(需要先安装RPi.GPIO)。

# Python 2.X pip install RPi.GPIO # Python 3.X pip3 install RPi.GPIO

上拉/下拉电阻
当GPIO没有连接任何元件时,其状态是不可控的,为解决这一问题,需要使用到上拉和下拉电阻,用于设定输入的默认值。使用硬件方式,通常需要将一个 10K 的电阻连接在输入通道与 3.3V(上拉)或 0V(下拉)之间。而树莓派可以通过软件实现GPIO的上拉和下拉:
GPIO.setup(channel, GPIO.IN, pull_up_down``=``GPIO.PUD_UP)

或者
GPIO.setup(channel, GPIO.IN, pull_up_down``=``GPIO.PUD_DOWN)

轮询(Polling)
可在某一时刻获取GPIO输入值:
if GPIO.input(channel): print('Input was HIGH') else: print('Input was LOW')

也可以循环判断:
while GPIO.input(channel) == GPIO.LOW: time.sleep(0.01)# 为 CPU 留出 10 毫秒,供其处理其它事物

中断和边缘检测
可使用中断或者边缘检测监测GPIO状态,可用到以下两个函数:
  • wait_for_edge() 函数
  • event_detected() 函数
wait_for_edge() 用于在检测到边缘之前阻止程序的运行。换句话说,上面的示例中,等待按钮被按下的语句可以改写为:
GPIO.wait_for_edge(channel, GPIO.RISING)

  • GPIO.RISING:上升沿触发
  • GPIO.FALLING:下降沿触发
  • GPIO.BOTH:都触发
event_detected() 设计用于循环中有其它东西时使用,但不同于轮询的是,它不会错过当 CPU 忙于处理其它事物时输入状态的改变。这在类似使用 Pygame 或 PyQt 时主循环实时监听和响应 GUI 的事件是很有用的。
GPIO.add_event_detect(channel, GPIO.RISING) # 在通道上添加上升临界值检测 do_something() if GPIO.event_detected(channel): print('Button pressed')

触发方式也有三种,同上。
线程回调 RPi.GPIO 在第二条线程中执行回调函数。这意味着回调函数可以同您的主程序同时运行,并且可以立即对边缘进行响应。例如:
def my_callback(channel): print('这是一个边缘事件回调函数!') print('在通道 %s 上进行边缘检测'%channel) print('该程序与您的主程序运行在不同的进程中') GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback) # 在通道上添加上升临界值检测``... 其它程序代码 ...

如果您需要多个回调函数:
def my_callback_one(channel): print('回调 1') def my_callback_two(channel): print('回调 2') GPIO.add_event_callback(channel, my_callback_one) GPIO.add_event_callback(channel, my_callback_two)

【注意】在该示例中,回调函数为顺序运行而不是同时运行。这是因为当前只有一个进程供回调使用,而回调的运行顺序是依据它们被定义的顺序。
开关防抖
按键按下时,回调操作调用不止一次,这种现象称为“开关抖动”,有两种方式可以解决:
  • 将一个0.1uf电容连接到开关上
  • 软件去抖
软件去抖可以在回调函数中添加bouncetime参数:
# 在通道上添加上升临界值检测,忽略由于开关抖动引起的小于 200ms 的边缘操作 GPIO.add_event_detect(channel, GPIO.RISING, callback = my_callback, bouncetime = 200)

或者
GPIO.add_event_callback(channel, my_callback, bouncetime=200) remove_event_detect()

由于某种原因,您不希望您的程序检测边缘事件,您可以将它停止:
GPIO.remove_event_detect(channel)

3、检测代码
#霍尔脉冲读取函数 GPIO.setup(18, GPIO.IN,pull_up_down=GPIO.PUD_UP)#通过18号引脚读取左轮脉冲数据 GPIO.setup(35, GPIO.IN,pull_up_down=GPIO.PUD_UP)#通过35号引脚读取右轮脉冲数据 counter=0#左轮脉冲初值 counter1=0#右轮脉冲初值 def my_callback(channel):#边缘检测回调函数,详情在参见链接中 global counter#设置为全局变量 if GPIO.event_detected(18):#检测到一个脉冲则脉冲数加1 counter=counter+1 #这里的channel和channel1无须赋确定值,不能不写。 def my_callback1(channel1): global counter1 if GPIO.event_detected(35): counter1=counter1+1 GPIO.add_event_detect(18,GPIO.RISING,callback=my_callback) #在引脚上添加上升临界值检测再回调 GPIO.add_event_detect(35,GPIO.RISING,callback=my_callback1)

参考连接
  • 树莓派中用python检测连续脉冲
  • 【树莓派使用Python检测连续脉冲】使用 RPi.GPIO 模块的输入(Input)功能

    推荐阅读