国外的设计接口设计得很棒,包括问题:读脏与防抖,还包括读这个数据提供了两种方式,一种是阻塞等待方式,还有一种是回调函数,前一种是通讯中常用的方式,后一种来自系统架构设计的整体性考虑。这种硬件接口设计的思路值得我们学习。

Inputs(输入)

There are several ways of getting GPIO input into your program. The first and simplest way is to check the input value at a point in time. This is known as 'polling' and can potentially miss an input if your program reads the value at the wrong time. Polling is performed in loops and can potentially be processor intensive. The other way of responding to a GPIO input is using 'interrupts' (edge detection). An edge is the name of a transition from HIGH to LOW (falling edge) or LOW to HIGH (rising edge).

中文速读:有很多方式将gpio输入我们的程序,最简单的是轮询,这种方式在不同时间采集数据会丢失,还多花费CPU资源,另一种方式为中断,中断依据边缘进行触发(数字电路中学过的)到么下边界触发,要么上边界触发。

Pull up / Pull down resistors(下拉、下拉电阻)

If you do not have the input pin connected to anything, it will 'float'. In other words, the value that is read in is undefined because it is not connected to anything until you press a button or switch. It will probably change value a lot as a result of receiving mains interference.

To get round this, we use a pull up or a pull down resistor. In this way, the default value of the input can be set. It is possible to have pull up/down resistors in hardware and using software. In hardware, a 10K resistor between the input channel and 3.3V (pull-up) or 0V (pull-down) is commonly used. The RPi.GPIO module allows you to configure the Broadcom SOC to do this in software:

中文速读:当接口没接任何设备时,这个值读出来可能有多种结果,这是“变动的”,解决它我们可以用下拉或下拉数阻,通常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)

(where channel is the channel number based on the numbering system you have specified - BOARD or BCM).

Testing inputs (polling)测试输入

You can take a snapshot of an input at a moment in time:

if GPIO.input(channel):
print('Input was HIGH')
else:
print('Input was LOW')

To wait for a button press by polling in a loop:

while GPIO.input(channel) == GPIO.LOW:
time.sleep(0.01) # wait 10 ms to give CPU chance to do other things慢0.01让cpu去做其它事,其它进程的并发性能考虑

(this assumes that pressing the button changes the input from LOW to HIGH)

中文速读:这里假设按键从低到高改变输入

Interrupts and Edge detection(中断与边界检测)

An edge is the change in state of an electrical signal from LOW to HIGH (rising edge) or from HIGH to LOW (falling edge). Quite often, we are more concerned by a change in state of an input than it's value. This change in state is an event.

To avoid missing a button press while your program is busy doing something else, there are two ways to get round this:

中文速读:改变边界状态是从电平信号从低到高,或者从高到低,与此同时,我们更关心的是输入的状态值,这种改变就是事件,为了避免并发丢失,即事件丢失,gpio提供了两种方式来解决忙中丢失问题:阻塞等待与线程回调函数

  • the wait_for_edge() function
  • the event_detected() function
  • a threaded callback function that is run when an edge is detected

wait_for_edge() function(阻断意外,等边界检测)

The wait_for_edge() function is designed to block execution of your program until an edge is detected. In other words, the example above that waits for a button press could be rewritten as:

GPIO.wait_for_edge(channel, GPIO.RISING)

Note that you can detect edges of type GPIO.RISING, GPIO.FALLING or GPIO.BOTH. The advantage of doing it this way is that it uses a negligible amount of CPU, so there is plenty left for other tasks.

If you only want to wait for a certain length of time, you can use the timeout parameter:

# 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)
中文速读:这种方式是指阻塞了,等了多长时间可以在GPIO上设timeout参数,这种适用于异步工作方式,我们不清楚要等多少时间,因些应用场景对实时要求不高的。

event_detected() function

The event_detected() function is designed to be used in a loop with other things, but unlike polling it is not going to miss the change in state of an input while the CPU is busy working on other things. This could be useful when using something like Pygame or PyQt where there is a main loop listening and responding to GUI events in a timely basis.

GPIO.add_event_detect(channel, GPIO.RISING)  # add rising edge detection on a channel
do_something()
if GPIO.event_detected(channel):
print('Button pressed')

Note that you can detect events for GPIO.RISING, GPIO.FALLING or GPIO.BOTH.

中文速读:主动测试

Threaded callbacks

RPi.GPIO runs a second thread for callback functions. This means that callback functions can be run at the same time as your main program, in immediate response to an edge. 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) # add rising edge detection on a channel
...the rest of your program...

If you wanted more than one callback function:

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)

Note that in this case, the callback functions are run sequentially, not concurrently. This is because there is only one thread used for callbacks, in which every callback is run, in the order in which they have been defined.

中文速读:就是回调函数

Switch debounce(消抖)

You may notice that the callbacks are called more than once for each button press. This is as a result of what is known as 'switch bounce'. There are two ways of dealing with switch bounce:

  • add a 0.1uF capacitor across your switch.
  • software debouncing
  • a combination of both

To debounce using software, add the bouncetime= parameter to a function where you specify a callback function. Bouncetime should be specified in milliseconds. For example:

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

or

GPIO.add_event_callback(channel, my_callback, bouncetime=200)

Remove event detection(取消事件测试)

If for some reason, your program no longer wishes to detect edge events, it is possible to stop them:

GPIO.remove_event_detect(channel)

raspberry-gpio-python(树莓派GPIO与Python编程)的更多相关文章

  1. Python自动化编程-树莓派GPIO编程(二)

    树莓派我们编程一般都直接用高效的python,针对于GPIO编程,python也是有这一方面的库的,这里最有名也是最常用的就是RPI.GPIO了.这个库是专门为树莓派GPIO编程所设计的,利用它你可以 ...

  2. 自己动手实现智能家居之树莓派GPIO简介(Python版)

    [前言] 一个热爱技术的人一定向往有一个科技感十足的环境吧,那何不亲自实践一下属于技术人的座右铭:“技术改变世界”. 就让我们一步步动手搭建一个属于自己的“智能家居平台”吧(不要对这个名词抬杠啦,技术 ...

  3. 树莓派高级GPIO库,wiringpi2 for python使用笔记(一)安装

    网上的教程,一般Python用RPi.GPIO来控制树莓派的GPIO,而C/C++一般用wringpi库来操作GPIO,RPi.GPIO过于简单,很多高级功能不支持,比如i2c/SPI库等,也缺乏高精 ...

  4. 树莓派高级GPIO库,wiringpi2 for python使用笔记(二)高精度计时、延时函数

    学过单片机的同学应该清楚,我们在编写传感器驱动时,需要用到高精度的定时器.延时等功能,wiringpi提供了一组函数来实现这些功能,这些函数分别是: micros() #返回当前的微秒数,这个数在调用 ...

  5. 树莓派python 控制GPIO

    sudo pip install rpi.gpio #!/usr/bin/env python # encoding: utf-8 import RPi.GPIO as GPIO import tim ...

  6. 树莓派高级GPIO库,wiringpi2 for python使用笔记(四)实战DHT11解码

    DHT11是一款有已校准数字信号输出的温湿度传感器. 精度湿度+-5%RH, 温度+-2℃,量程湿度20-90%RH, 温度0~50℃. 我买的封装好的模块,上边自带了上拉电阻,直接查到树莓派上即可灰 ...

  7. 树莓派高级GPIO库,wiringpi2 for python使用笔记(三)GPIO操作

    GPIO库的核心功能,当然就是操作GPIO了,GPIO就是"通用输入/输出"接口,比如点亮一个LED.继电器等,或者通过iic spi 1-wire等协议,读取.写入数据,这都是G ...

  8. 树莓派GPIO口的使用

    树莓派的优势在于Liunx操作系统加GPIO口,其中IO口时物联网组成中不可缺少的,高低电平的控制是很有必要的存在,再加有python的支持,玩转GPIO相对就容易多了 管脚编号 BCM: 编号侧重 ...

  9. 树莓派GPIO控制LED彩灯

    树莓派使用GPIO接口来控制LED灯,自制五彩炫光的节日彩灯. 1.硬件准备 a. 树莓派(Raspberry Pi)一个 b. 彩色RGB二极管 c. 杜邦线 d. 5V电源引脚 以上所有零件均可在 ...

随机推荐

  1. 一键删除数据库所有的外键约束-FOREIGN_KEYS

    DECLARE @ESQL VARCHAR(1000);DECLARE FCursor CURSOR --定义游标FOR (SELECT  'ALTER TABLE '+O.name+' DROP  ...

  2. openwrt_在PPPOE上网的同时_访问光猫

    openwrt_在PPPOE上网的同时_访问光猫 转载注明来源: 本文链接 来自osnosn的博客,写于 2019-11-14. 参考文章: 光猫桥接模式下,通过路由器访问光猫.简单设置 设置Open ...

  3. 死磕 java线程系列之线程池深入解析——构造方法

    (手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本. 简介 ThreadPoolExecutor的构造方法是创建线程池的入口,虽然比较简单,但是信息量很大,由此也能 ...

  4. 从零开始的vue学习笔记(一)

    前言 项目要用vue.js,今天开始自学vue.js官方教程,记录下自己的学习摘要,方便后面查阅(此笔记按照学习天数,每天一篇) Vue.js是什么 Vue是一套用于构建用户界面的渐进式框架,Vue ...

  5. 知道内存中一个图片的指针IntPtr大小,转换成图片显示

    //nSize 为总长度//pImageData 为总数据//nImageSize //一个图片的长度 byte[] _bytes = new byte[nImageSize];// //IntPtr ...

  6. Prometheus监控(二)

    Prometheus监控(二) 数据类型 Counter(计数器类型) Counter类型的指标的工作方式和计数器一样,只增不减(除非系统发生了重置),Counter一般用于累计值. Gauges(仪 ...

  7. SpringMVC框架之第四篇

    5.SpringMVC异常处理 5.1.异常分类 1.可预知异常: Java编译时可检测异常,例如:IOException.SQLException等. 自定义异常(继承Exception父类的自定义 ...

  8. 学习Linux必看的命令(一)

    学习Linux必看的命令(一) 一:什么是Linux ​ Linux命令是对Linux系统进行管理的命令.对于Linux系统来说,无论是中央处理器.内存.磁盘驱动器.键盘.鼠标,还是用户等都是文件,L ...

  9. diango下载、创建、启动

    下载 命令行 pip install django==1.11.26 -i https://pypi.tuna.tsinghua.edu.cn/simple pycharm 创建项目 命令行 djan ...

  10. 阿里云ECS服务器部署HADOOP集群(六):Flume 安装

    本篇将在阿里云ECS服务器部署HADOOP集群(一):Hadoop完全分布式集群环境搭建的基础上搭建. 1 环境介绍 一台阿里云ECS服务器:master 操作系统:CentOS 7.3 Hadoop ...