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

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. docker快速部署本地项目到服务器(tomcat8+mysql8)

    目标是:将本地运行的spring项目,部署到服务器上 为什么使用docker? 环境隔离 服务器上,各种环境交杂,使用docker,能清楚的把各个项目进行隔离,不单维护的人员方便,也会省去很多维护这些 ...

  2. LINUX OS 正常关机失败

    描述:LINUX OS运行命令shutdown now显示:Telling INIT to go to single user mode....   解决方法:运行命令exit重新登录,再运行 hal ...

  3. 【译】如何使用docker-compose安装anchore

    如何使用docker-compose安装anchore,本篇译自Install with Docker Compose. Preface 在本节中,您将学习如何启动和运行独立的Anchore引擎安装, ...

  4. 【nagios监控】基于linux搭建nagios监控

    nagios工作原理 nagios的功能是监控服务和主机,但是其自身并不包括这些功能,所有的监控.检测功能都是通过各种插件来完成的. 启动nagios后,它会周期性的自动调用插件去检测服务器状态,同时 ...

  5. How to: Supply Initial Data for the Entity Framework Data Model 如何:为EF数据模型提供初始数据

    After you have introduced a data model, you may need to have the application populate the database w ...

  6. JS 算数

    JS 算数 Math(算数)对象的作用是:执行常见的算数任务. random() 来返回 0 到 1 之间的随机数. max() 来返回两个给定的数中的较大的数.(在 ECMASCript v3 之前 ...

  7. 使用动态SQL处理table_name作为输入参数的存储过程(MySQL)

    关于mysql如何创建和使用存储过程,参考笔记<MySQL存储过程和函数创建>以及官网:https://dev.mysql.com/doc/refman/5.7/en/create-pro ...

  8. mysql登录错误:'Access denied for user 'root'@'localhost'

    首先是不知道怎么忽然mysql用命令行,workbench都登录不了,都提示'Access denied for user 'root'@'localhost'. 数据库卸载重装了几次都不行.好像感觉 ...

  9. 在 Cocos2d-x 中添加自己的微博链接

    配置:OS X 10.10 + Xcode 6.0 + Cocos2d-x-3.2 一.Android 端代码 1.在 Cocos2dxActivity.java 中添加openUrl函数并导入响应包 ...

  10. 关于ajax请求不到后台页面提示400 bad request的问题

    解决方法一: 在contrller控制器中对应方法的 @RequestMapping注解中添加 method="RequestMethod.POST"属性