树莓派上的立体视觉和深度知觉

随着树莓派超低成本的计算模块的发布,依赖于树莓派简单的编程环境,简单硬件扩展和丰富的开发资源,使我们利用树莓派创造大量的产品变得可能,

Pi具有强大的多媒体处理能力,但是因为通常在Pi上编程比较简单直接,最大限度的利用其多媒体系统和为它的VideoCore模块编程是较复杂的。

Argon Design精通于在此类系统上的编程,并且可以优化树莓派上的多媒体算法。为了评测计算模块的能力,展示我们的技能,我们设计了本次展示。

这次展示是关于立体深度感知-利用两个放置位置具有一定间距的摄像机,从不同的视角拍摄物体来获取深度信息。与此同时这还使用了树莓派计算模块的另一个令人兴奋的特性,那就是它支持双摄像头(标准树莓派仅仅支持单一摄像头)

###立体深度感知

—————————–

深度感知方面的文献中记录了很多好的算法。它们中很多使用了相同的视频压缩算法,Argon Design在这个领域有丰富的经验。都是基于把图像分成块,对于每幅图像中的每个块,在另外的一个或多个图片中搜索“匹配”的块。

然而,与视频压缩相比,深度知觉需要更加可靠的结果。文献中还记载了很多改善输出的基本算法。因为这只是一个概念验证,所以我们的标准是选择那些不需要花费太长时间去实现的改进算法,这些算法不需要很大的计算量并且可以给出相当好的改善结果。基于块的视频压缩和我们最终的算法之间最基本的差别在于:

– 对比两个间距已知的摄像机同时拍摄的两幅图片。这表示我们在测量视差,我们可以通过它来得到摄像机和物体的间距。对于视频压缩我们则会去对比同一个摄像机在不同时期拍摄的几幅图片,所以这种算法意在测量运动。

– 假设摄像机都是水平对齐的。这使得二维搜索降低到一维,节省了大量的处理时间。这需要对摄像机进行校准,不过我们可以使用已知的方法来进行校准,人工的或者自动的都可以。

– 使用更加准确(但是更加耗时)的方法来测量两块之间的相关性,基于如下两篇文章:

– [1]. Heiko Hirschmüller, “Improvements in Real-Time Correlation-Based Stereo Vision” CVPR 2001

– [2]. Olivier Faugeras et al, “Real t ime correlation-based stereo: algorithm, implementations and applications” INRIA 1993

特别的,我们决定结合使用[2] 中的”C5″相关方程(“C5″ correlation function)和[1]中提到的多窗口方案(multi-window scheme)。总的来讲,我们的程序既可以使用5×5窗口方案或是7×7方案。7×7的方案计算时间更长但是也会稍微准确一些。

###性能

——————————

使用了三种不同版本的实现方式:

– 原始版本使用Python和NumPy,用以评价其他方案的准确性。

– 使用C语言的版本,在变换中尽可能多的使用算法来增强效果。最大的改进来自于通过仔细的安排代码来避免冗余的计算,我们也使用了一个自定义的排序网络来替代通用排序算法(多窗口方案使用的算法),速度提高了大概4倍。

– 使用VideoCore的视频处理单元(VPU)的汇编程序,使用了C版本的结构但是利用了VPU的架构特性(比如说它的16路向量单元(16-way vector unit )和16KB的处理器局部储存器(processor-local memory)

一个中等大小(768×576像素)的图像,在不同版本下的处理时间大概是:

– Python, on x86 (~3GHz): 63 seconds

– Python,x86平台(~3GHz):63秒

– C, on x86 (~3GHz): 56 milliseconds

– C,x86平台(~3GHz):56毫秒

– C, on Pi ARM core (700MHz): 1 second

– C, 树莓派ARM内核(700MHz): 1 秒

– Assembler on VideoCore VPU (250MHz): 90 milliseconds

– 汇编,VideoCore视频处理单元 (250MHz):90毫秒

请注意VideoCore版本仅仅比x86平台上的C版本耗时长大约50%,而x86平台比VideoCore的时钟速度快了12倍。

我们还编写了一个演示程序,它会从两个摄像机获取图像,处理他们并且把计算得出的深度数据以彩色的方式显示。摄像机的处理和展示会添加少量的补偿,来对我们减小图像尺寸到VGA (640×480)进行补偿。

最终的帧速率是12fps。对于概念验证已经足够,同时在某种程度上展示了图像处理工作,而且我们可以用比较合理的开发速度在树莓派上实现它。

###应用

我们创建的示例程序可以以下面三种不同的方式进行展示

– 仅显示摄像机原始图像

– 把视差数据转换为彩色数据并覆盖在图像上

– 把距摄像机某个距离上的所有点全部移除

结果的截图如下,同时还有一些用到的设备的照片。

然而,能做的不仅仅只有这些,还包括:

– 把两个或多个摄像机的图片缝合形成全景图

– Argon之前做过的一个项目是使用扩展卡尔曼滤波(Extended Kalman Filter)来分离摄像机的运动和一个场景中物体的运动。结合这些可以生成某个环境的动态的3D地图。

– 展示程序中的背景一处会切掉物体的一部分,这个问题可以结合边缘检测滤波的结果来进行补救。

– 这一算法非常适合在FPGA上执行,因为大多数的计算都可以并行工作。因此上面介绍的任何东西都可以轻松的提高到实时处理1080p30或4K视频。

###使用到的技能

[软件工程](http://www.argondesign.com/what-we-do/#software_engineering),

[处理器架构](http://www.argondesign.com/what-we-do/#processor_architectures),

[算法及运算](http://www.argondesign.com/what-we-do/#algorithms_mathematics),

[图像处理](http://www.argondesign.com/what-we-do/#image_processing),

[多媒体](http://www.argondesign.com/what-we-do/#multimedia )

Adafruit的树莓派教程:热释电传感器感知运动

概览

在这节课里,你将学习到如何使用PIR热释电传感器连接GPIO来激活门禁。

这节课,我们将把注意力放到感知运动和激活门禁开关上。我们会在后面的课程中构建这个安全感知系统,使用小派作为数字输出来在侦测到运动时控制电力设备。

你需要的

要完成这节课讲述的内容,你需要下面的东西。

PIR热释电传感器

电磁门禁传感器

树莓派扩展板

小型面包板

一把跳线

最后,当然是小派啦

硬件部分

我们将会把两个传感器都连接到树莓派上。两个传感器都不需要额外的部件。

PIR热释电传感器是带插座的引脚。一定要确保引脚插得是正确的,红色的应该插在5V上,黑色接地,黄色的插在扩展板的18引脚上。

尽管PIR传感器需要5V的电源供电,但它的输出却是对小派友好的3.3V,所以它可以直接连接到GPIO的上作为输入。

门禁开关使用了一个叫做磁簧开关(reed switch)的东西。在一个玻璃管里装着两个簧片相互连接,然后外面包裹着塑料。当一个磁性物体(另一个白色方块)靠近这个磁簧开关的时候,两个簧片接触,然后开关关闭。因为这是个开关,所以正着接反着接都行。

我们会利用小派自身来在磁簧开关针脚上创建一个内部的上拉电阻,所以我们就不需要额外的上拉电阻了。

软件部分

这个程序只是一个循环,在侦测到运动的时候打印一个消息,或者磁力从门上移除。

程序使用了Rpi.GPIO类库。

import time import RPi.GPIO as io io.setmode(io.BCM) pir_pin = 18 door_pin = 23 io.setup(pir_pin, io.IN) # activate input io.setup(door_pin, io.IN, pull_up_down=io.PUD_UP) # activate input with PullUp while True: if io.input(pir_pin): print(“PIR ALARM!”) if io.input(door_pin): print(“DOOR ALARM!”) time.sleep(0.5)

程序里把pir_pin置为一个普通的输入针(a plain old input)。这是因为PIR传感器有一个3.3V或0V的数字输出。与之相比,door_pin是一个开关,不会产生电压作为数字输入。所以,这个输入针使用了一个额外的参数(pull_up_down=io.PUD_UP)。这将激活一个内部的电阻使得输入变高(上拉)除非有更强的电流(比如开关接地)来把它拉低。

然后循环轮流读取输入然后打印一条响应的消息。记住门禁开关报警只会在磁力从传感器附近移除时才会被激活。

配置与测试

有许多方式可以连接到你的树莓派上。也许最简单的方式是使用SSH并使用下面的命令打开一个编辑器:

nano switches.py

然后把代码粘贴进去,按Ctrl+X保存。

在开始运行程序之前,把磁铁靠近开关并且在PIR传感器上盖上一些东西。

然后使用下面的命令运行程序:

sudo python switches.py

然后你可以看到终端有输出了,当你移走磁铁,或者把盖在PIR传感器上的东西拿开。

一个好的方式或许是把你的孩子放在PIR传感器前面,看他们能坚持多久!

Adafruit的树莓派教程:电力控制

概览

树莓派可以成为你家里强大的自动化控制终端,但最实用的应该是控制家用电器以及灯的打开关闭了。那就意味着小派应该能够安全的控制110V电力。

这节课里,你将学习把PIR(人体热式传感器)与Adafruit电力开关尾插Module 2型结合,在检测到与运动时自动开关设备。

你需要的

要完成这节课的内容,你需要下面的东西:

PIR人体热式传感器

电力开关尾插2型模块

树莓派扩展板

小型面包板

树莓派

一把跳线

硬件部分

Adafruit电力开关尾插2型看起来是一个110V插头中间带了一个小盒子。

如果你主要使用的是220V电压,那么这篇教程不适合你 – 如果我们获悉了某种等效的220V电力控制器,我们会在这里附上链接的

那个小盒子实际上是一个光隔离固态继电器。光隔离的意思是实际上在低电压与100V主电压转换之间并没有电力连接。这对于小派来说非常的安全,大大降低了烧毁小派的可能性。

更进一步的是它的控制输入电流是3mA,输入电压是3.3V,这意味着我们能够直接通过小派的输出针脚控制它。

PIR传感器将会连接到与第十二课不同的针脚上,所以请确保黄色针脚连接正确。

电力开关尾插带有一个LED指示灯来显示它是否是开着的,所以你不需要在上面连接高电压。

软件部分

这个项目可能是所有自动控制灯项目中被过度设计(over-engineered)的一个。实际上你不需要一个树莓派来开关电力,但是这个实例可以很容易的被应用到其他用途上。比如,你可以通过结合温度,湿度,光线或者一些互联网的天气预报信息来控制加热器,风扇或者是加湿器。

import time import RPi.GPIO as io io.setmode(io.BCM) pir_pin = 24 power_pin = 23 io.setup(pir_pin, io.IN) io.setup(power_pin, io.OUT) io.output(power_pin, False) while True: if io.input(pir_pin): print(“POWER ON”) io.output(power_pin, True) time.sleep(20); print(“POWER OFF”) io.output(power_pin, False) time.sleep(5) time.sleep(1)

这个程序首先设置了两个用到的GPIO针脚,一个用于把PIR传感器作为输入,另一个输出到电力开关尾插上。

主循环一直等待PIR传感器侦测运动,然后打印一条信息,之后打开电力开关,等待20秒之后关闭开关。

一旦输出被打开,那么将会等待5秒防止在5秒内重新触发输出。

然后每次循环会延迟一秒。

测试与配置

有许多方式可以连接到你的树莓派上。也许最简单的方式是使用SSH并使用下面的命令打开一个编辑器:

nano powerswitch.py

然后粘贴代码,并按Ctrl+X保存。

在开始运行之前,拿东西改在PIR传感器上,这样它就不会在你没准备好之前激活了。

然后使用下面的命令运行程序:

sudo python powerswitch.py

拿走PIR上面的覆盖物你应该能看到一条”POWER ON”输出然后电力开关上的小LED会点亮,并在20秒之后熄灭。

树莓派用AirPlay播放实现WiFi连无线音响外放

本文转载自 王晔的流水账。

之前有一篇文章介绍了如何使用蓝牙实现手机连接无线音箱外放,在网上搜索相关资料的过程中,我发现了树莓派另外一个强大的功能,那就是可以实现苹果(Apple)的AirPlay播放技术,简单的介绍一下,AirPlay类似于蓝牙音响播放,但是其是建立在WiFi局域网基础上的,在接入有AirPlay播放技术的局域网上,苹果的设备就会显示支持AirPlay。综合AirPlay的优势,我开始在Raspberry Pi(树莓派)上实现相关功能。

同样的,关于树莓派一些好玩的功能国外资料较为丰富,经过查阅后《Raspberry Pi Airplay Tutorial》(原文超级详细)这一篇文章对我帮助较大,具体步骤如下。

1. 升级Raspberry Pi系统的软件

sudo apt-get update sudo apt-get upgrade

2. 将音频输出变更为默认的音频输出口

通常情况下树莓派的音频输出使用的是HDMI接口,我们需要下面的命令将其变更为普通音频输出口:

sudo amixer cset numid=3 1

这一步我遇到一个错误:

ALSA lib pulse.c:243:(pulse_connect) PulseAudio: Unable to connect: Access denied amixer: Control default open error: Connection refused

提示没有权限,如果不使用sudo则没有这类问题,比较郁闷。如果你也遇到同样的问题,先跳过,我们继续下面的步骤。

3. 安装系统所必需的软件包

sudo apt-get install git libao-dev libssl-dev sudo apt-get install libcrypt-openssl-rsa-perl libio-socket-inet6-perl sudo apt-get install libwww-perl avahi-utils libmodule-build-perl

4. 安装Perl Net-SDP协议软件

cd ~ git clone https://github.com/njh/perl-net-sdp.git perl-net-sdp cd perl-net-sdp perl Build.PL sudo ./Build sudo ./Build test sudo ./Build install cd ..

5. 使用Shairport将树莓派设置为AirPlay接收器

cd ~ git clone https://github.com/hendrikw82/shairport.git cd shairport make

6. 启动Shairport以支持AirPlay

./shairport.pl -a WangyePi

这里我们指定了一个名字叫做WangyePi,大家可以根据实际进行修改,自此,你可以使用苹果设备来访问AirPlay了,当然每次使用这个命令略显不便,下面介绍如何将其变成系统服务。

7. 将Shairport设置为系统服务

cd shairport sudo make install sudo cp shairport.init.sample /etc/init.d/shairport cd /etc/init.d sudo chmod a+x shairport sudo update-rc.d shairport defaults

好了,上面的步骤将移植Shairport到系统路径下,同时创建名称为shairport的服务,你可以使用 sudo service 控制这个服务。

接下来编辑这个启动文件:

sudo nano /etc/init.d/shairport

找到 DAEMON_ARGS=”-w $PIDFILE” 这行,并且修改成 DAEMON_ARGS=”-w $PIDFILE -a WangyePi” ,同样的这里WangyePi为你的AirPlay名字。

启动AirPlay看看效果吧:

sudo service shairport start

8. 一些问题

如果上面步骤完成后一切正常的话,那么恭喜你,这一步可以略过了。我亲自试验下来没有那么顺利,假如AirPlay不能播放的话,建议使用 tail /var/log/syslog 命令查看系统日志以便于确定问题原因,比如我就遇到下面的错误:

May 11 04:57:05 raspberrypi pulseaudio[2563]: [pulseaudio] protocol-native.c: Denied access to client with invalid authorization data.

具体的处理方式如下,之前我注意到 sudo amixer cset numid=3 1 命令会导致pulseaudio拒绝访问报错,特诡异,居然管理员权限还有不能访问的资源。

然后我检查了pulseaudio和shairport启动的用户,发现pulseaudio是以pulse账户启动的,而shairport是以root身份启动的,很有可能问题出在这儿,我们只需要让两个都以pulse账户启动就万事大吉了。

命令 sudo nano /etc/init.d/shairport 修改shairport启动文件,将 PIDFILE=/var/run/$NAME.pid 改为 PIDFILE=/var/run/shairport/$NAME.pid ,然后找到两处 start-stop-daemon ,分别加上 -c pulse 参数,我的最终修改如下:

#!/bin/bash # # This starts and stops shairport # ### BEGIN INIT INFO # Provides: shairport # Required-Start: $network # Required-Stop: # Short-Description: shairport – Airtunes emulator! # Description: Airtunes emulator! # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 ### END INIT INFO # Source function library. . /lib/lsb/init-functions NAME=shairport DAEMON=”/usr/local/bin/shairport.pl” PIDFILE=/var/run/shairport/$NAME.pid DAEMON_ARGS=”-w $PIDFILE -a AirPi” [ -x $binary ] || exit 0 RETVAL=0 start() { echo -n “Starting shairport: ” start-stop-daemon -c pulse –start –quiet –pidfile “$PIDFILE” \ –exec “$DAEMON” -b –oknodo — $DAEMON_ARGS log_end_msg $? } stop() { echo -n “Shutting down shairport: ” start-stop-daemon -c pulse –stop –quiet –pidfile “$PIDFILE” \ –retry 1 –oknodo log_end_msg $? } restart() { stop sleep 1 start } case “$1” in start) start ;; stop) stop ;; status) status shairport ;; restart) restart ;; *) echo “Usage: $0 {start|stop|status|restart}” ;; esac exit 0

然后创建PID所在文件夹并设置权限:

sudo mkdir /var/run/shairport sudo chown pulse /var/run/shairport

最后重启shairport服务,看看是不是正常了。

sudo service shairport restart

参考文档

2014年5月12日更新

在上面第8点有些问题的叙述上需要更正一下,今天发现建立在 /var/run 路径下的 shairport 目录消失,导致shairport启动失败,于是我将启动文件 /etc/init.d/shairport 修改如下:

#!/bin/bash # # This starts and stops shairport # ### BEGIN INIT INFO # Provides: shairport # Required-Start: $network # Required-Stop: # Short-Description: shairport – Airtunes emulator! # Description: Airtunes emulator! # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 ### END INIT INFO # Source function library. . /lib/lsb/init-functions NAME=shairport DAEMON=”/usr/local/bin/shairport.pl” PIDDIR=/var/run/shairport PIDFILE=$PIDDIR/$NAME.pid DAEMON_ARGS=”-w $PIDFILE -a AirPi” [ -x $binary ] || exit 0 RETVAL=0 start() { echo -n “Starting shairport: ” if [ ! -d $PIDDIR ]; then mkdir -p $PIDDIR chown pulse:pulse $PIDDIR fi start-stop-daemon -c pulse –start –quiet –pidfile “$PIDFILE” \ –exec “$DAEMON” -b –oknodo — $DAEMON_ARGS log_end_msg $? } stop() { echo -n “Shutting down shairport: ” start-stop-daemon -c pulse –stop –quiet –pidfile “$PIDFILE” \ –retry 1 –oknodo log_end_msg $? } restart() { stop sleep 1 start } case “$1” in start) start ;; stop) stop ;; status) status shairport ;; restart) restart ;; *) echo “Usage: $0 {start|stop|status|restart}” ;; esac exit 0

树莓派从 DHT11 温度湿度传感器读取数据

时序图参考厂家说明书:DHT11数字湿温度传感器的原理和应用范例

四个阵脚连接:VCC接3.3伏电源,Dout接GPIO口,我接的是物理12针脚,NC留空,GND接地。

波折1:电阻被错接进了VCC,于是看了无数遍时序图,改了无数遍的驱动无论怎么改都是读不出数据。

波折2:偶然看了网上的DHT11上拉电阻电路图才发现错误,于是果断去掉电阻。但为了显示传感器工作正常在电源和VCC间接了个发光二极管进去,数据倒是读出来了,但各种错误。(原因不明)

去掉了电阻,去掉了led,优化了写的python,读数正常。再一次赞一个python。

写DHT11的驱动需要注意时序之间很紧密,python执行任何程序都要花费时间,在获取时序时需要注意所写调试用的代码也是占用时序的,在这一点上也走了一点弯路。

# -*- coding: utf-8 -*- “”” Created on Sun Jan 26 14:24:43 2014 @author: pi “”” import RPi.GPIO as gpio import time gpio.setwarnings(False) gpio.setmode(gpio.BOARD) time.sleep(1) data=[] def delay(i): #20*i usdelay a=0 for j in range(i): a+1 j=0 #start work gpio.setup(12,gpio.OUT) #gpio.output(12,gpio.HIGH) #delay(10) gpio.output(12,gpio.LOW) time.sleep(0.02) gpio.output(12,gpio.HIGH) i=1 i=1 #wait to response gpio.setup(12,gpio.IN) while gpio.input(12)==1: continue while gpio.input(12)==0: continue while gpio.input(12)==1: continue #get data while j<40: k=0 while gpio.input(12)==0: continue while gpio.input(12)==1: k+=1 if k>100:break if k<3: data.append(0) else: data.append(1) j+=1 print "Sensor is working" #get temperature humidity_bit=data[0:8] humidity_point_bit=data[8:16] temperature_bit=data[16:24] temperature_point_bit=data[24:32] check_bit=data[32:40] humidity=0 humidity_point=0 temperature=0 temperature_point=0 check=0 for i in range(8): humidity+=humidity_bit[i]*2**(7-i) humidity_point+=humidity_point_bit[i]*2**(7-i) temperature+=temperature_bit[i]*2**(7-i) temperature_point+=temperature_point_bit[i]*2**(7-i) check+=check_bit[i]*2**(7-i) tmp=humidity+humidity_point+temperature+temperature_point if check==tmp: print "temperature is ", temperature,"wet is ",humidity,"%" else: print "something is worong the humidity,humidity_point,temperature,temperature_point,check is",humidity,humidity_point,temperature,temperature_point,check 测试python程序时间代码 # -*- coding: utf-8 -*- """ Created on Sun Jan 26 16:01:59 2014 @author: pi """ import time def delay(i): k=0 for j in range(i): k+=1 n=5000 j=0 a=time.time() i=1 c=time.time() d=c-a print d a=time.time() for i in range(n): j+=1 c=time.time() d=c-a print d a=time.time() delay(n) c=time.time() d=c-a print d via

树莓派驱动4位数码管显示时间

数码管的显示分为静态和动态两种。静态就是一个GPIO控制一个LED小灯管。

但是随着控制数码管数量的增加,GPIO口就占用太多了,所以多个数码管可以有 共阴 和 共阳 两种共享引脚。这个时候如果采用静态点亮数码管的方式,共享引脚的数码管显示完全一样。所谓动态方式,就是通过GPIO选择引脚,选择要点亮的某个数码管,然后通过共享引脚点亮LED小灯管。然后快速切换点亮其他数码管,由于点亮的切换频率非常快所以感觉上数码管一直亮着。

当然也可以使用辅助芯片,如MAX7129等,只需要用更加简化的方式控制显示数据。

点击查看详细文档。

这里我使用树莓派自己编码,动态刷新各个数码管。买的数码管有24位引脚,37个led小灯,这个掩饰只使用了4 × 7 = 28 个led灯。

代码:

import RPi.GPIO as GPIO import time, random “”” Display date to LED lights There are four lights, it displays 4 number “”” GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) def setp(n, status=’on’): if status == ‘on’: GPIO.output(n, GPIO.HIGH) else: GPIO.output(n, GPIO.LOW) for i in pins + sels: GPIO.setup(i, GPIO.OUT) setp(i, ‘off’) for i in sels: setp(i, ‘on’) # # __2_ # | | | 0 -> 011 1111 -> 0x3f # 1 | | 3 | 1 -> 010 0001 -> 0x21 # |__7__| | 2 -> 111 0110 -> 0x76 # | | | 4 -> … # 6 | | 4 | … # |__5__| | 9 -> … -> 0x5f # pins = [27, 17, 22, 10, 25, 24, 11] #GPIO ports sels = [14, 15, 18, 23] #GPIO ports to select led, there are four led lights nums = [0x3f, 0x21, 0x76, 0x5e, 0x4d, 0x5b, 0x7b, 0x0e, 0x7f, 0x5f] def flush(sel, n): setp(sels[sel], ‘off’) n = nums[n] for i in sels: if i != sels[sel]: setp(i, ‘on’) for i in range(7): if (n & (1 << i)): setp(pins[i], 'on') for i in range(7): if (n & (1 << i)): setp(pins[i], 'off') try: while True: t = time.gmtime() flush(3, t.tm_min / 10) flush(2, t.tm_min % 10) flush(1, t.tm_sec / 10) flush(0, t.tm_sec % 10) except: GPIO.cleanup() 其中灯管编号,引脚对应关系可以根据自己的连线方式自定义和修改: # # __2_ # | | | 0 -> 011 1111 -> 0x3f # 1 | | 3 | 1 -> 010 0001 -> 0x21 # |__7__| | 2 -> 111 0110 -> 0x76 # | | | 4 -> … # 6 | | 4 | … # |__5__| | 9 -> … -> 0x5f

pins = [27, 17, 22, 10, 25, 24, 11] #GPIO ports sels = [14, 15, 18, 23] #GPIO ports to select led, there are four led lights nums = [0x3f, 0x21, 0x76, 0x5e, 0x4d, 0x5b, 0x7b, 0x0e, 0x7f, 0x5f] #0,1,2,3~9 对应编码

演示视频:(为了效果明显这里显示的是 分钟 和 秒)

树莓派GPIO的编号规范

树莓派和普通电脑不一样的地方在于它还带了17个可编程的GPIO(General Purpose Input/Output),可以用来驱动各种外设(如传感器,步进电机等)。但GPIO的编号方法有些混乱,不同的API(如wiringPi,RPi.GPIO等)对GPIO的端口号编号并不一样,下面则用图表标明了对应的叫法,这样在看程序例子的时候可以确定物理是哪个接口。

GPIO库

wiringPi C,有Perl, PHP, Ruby, Node.JS和Golang的扩展,支持wiringPi Pin和BCM GPIO两种编号 RPi.GPIO Python,支持Board Pin和BCM GPIO两种编号 Webiopi,Python, 使用BCM GPIO编号 WiringPi-Go, Go语言,支持以上三种编号

编号规范

第一列是wiringPi API中的缺省编号, wiringPiSetup() 采用这列编号 第二列(Name)往往是转接板的编号 第三列是树莓派板子上的自然编号(左边引脚为1-15,右边引脚为2-26), RPi.GPIO.setmode(GPIO.BOARD) 采用这列编号 树莓派主芯片提供商Broadcom的编号方法,相当于调用了 WiringPiSetupGpio() 或 RPi.GPIO.setmode(GPIO.BCM) 采用这列编号

wiringPi Pin Name Board Pin BCM GPIO 0 GPIO 0 11 17 1 GPIO 1 12 18 2 GPIO 2 13 21 3 GPIO 3 15 22 4 GPIO 4 16 23 5 GPIO 5 18 24 6 GPIO 6 22 25 7 GPIO 7 7 4 8 SDA 3 0 9 SCL 5 1 10 CE0 24 8 11 CE1 26 7 12 MOSI 19 10 13 MISO 21 9 14 SCLK 23 11 15 TXD 8 14 16 RXD 10 15

Rev.2 新增的引脚:

树莓派用蜂鸣器实现整点报时

树莓派外加一个有源蜂鸣器,实现一个简单的报时功能。

可能有些新手对于有源、无源蜂鸣器的区别,这里简短介绍下:

一、无源蜂鸣器:

1 无源内部不带震荡源,所以如果用直流信号无法令其鸣叫。必须用2K~5K的方波去驱动它

2 声音频率可控,可以做出“多来米发索拉西”的效果。

3 在一些特例中,可以和LED复用一个控制口

二、有源蜂鸣器:

1 有源蜂鸣器内部带震荡源,所以只要一通电就会叫

2 程序控制方便,单片机一个高低电平就可以让其发出声音,而无源蜂鸣器却做不到。

笔者采用的是有源蜂鸣器:

电压:3.5—5.5V

电流:<25mA 频率:2300±500 为了使蜂鸣器鸣叫的程序模块化,将这一部分代码放到独立的 libbeep.py 文件中。 import RPi.GPIO as GPIO import time PIN_NO = 12 #GPIO编号,可自定义 GPIO.setmode(GPIO.BOARD) GPIO.setup(PIN_NO, GPIO.OUT) #哔1次,时长作为参数传递 def beep(seconds): GPIO.output(PIN_NO, GPIO.HIGH) time.sleep(seconds) GPIO.output(PIN_NO, GPIO.LOW) #哔N次,时长、间隔时长、重复次数作为参数传递 def beepAction(secs, sleepsecs, times): for i in range(times): beep(secs) time.sleep(sleepsecs) #beepAction(0.02,0.02,30) 然后在 alarm.py 中实现整点报时,代码如下: import RPi.GPIO as GPIO import time import libbeep while True: t = time.localtime() h = t.tm_hour m = t.tm_min s = t.tm_sec w = time.strftime('%w',t) print h,m,s,w time.sleep(0.3) if m == 0 and s == 0: if h>22 or h<8:#为了晚上22点之后,上午8点之前不被打扰,设定了条件 print "continued" continue if h>12: h = h-12 libbeep.beepAction (0.3,0.5,h) time.sleep(1) if m == 30 and s == 0: if h>22 or h<8: print "continued" continue libbeep.beepAction (0.05,0.05,2) time.sleep(1) 最后运行脚本: sudo python alarm.py

披着NES外壳的树莓派NES游戏机

NES Pi已经完成了!我希望它和当初看起来一模一样。

它的内部主要是树莓派B板和电源电路。

外部的DHMI和micro USB接口。

电源电路细节。

在Amazon上买的很便宜的USB hub,主要用来连接游戏手柄。

电源LED灯。

USB插槽,用来连接控制手柄。

还是Amazon上买的NES游戏手柄。

运行RetroPie。

里面是游戏模拟器。

NES游戏列表。

让我们一起尽情的玩耍吧!

通过串口、超级终端与树莓派传输文件

超级终端。这个名字本身就代表着一段被遗忘的历史,本文则要介绍如何用串口传输数据并存入SD卡。

硬件连接

十块钱一个的USB转TTL小板,加三条杜邦头插线。连接:

RX ———— TX

TX ———— RX

GND ———— GND

树莓派端

一、禁止树莓派本身的串口命令行界面

树莓派会把一个控制台映射到串口。这么做平常很好,因为可供我们通过串口登录到命令行。

但现在要传输文件,串口命令行就碍事了。先把这个控制台释放开,让系统不占用串口。

sudo nano /etc/inittab

注释掉这一行:

#Spawn a getty on Raspberry Pi serial line T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

然后sudo reboot重启。

二、安装启动minicom

安装经典的串口工具minicom。事实上在我学校学生实验用的ARM开发板上,直到现在还在用minicom下载程序。

sudo apt-get install minicom

执行需要注意:只打minicom会提示找不到设备。必须手动把设备文件告知minicom。另外ARM板子用的串口可真的不是ttyS0啊!!

minicom -D /dev/ttyAMA0

不知道minicom怎么操作是肯定的……。先按Ctrl+A,再按Z,调出命令介绍界面。

接收文件是R,按提示按R。

选接收文件的协议:zmodem ymodem xmodem kermit

推荐zmodem。这是调制解调器时代最先进的文件传送协议。

(不过其实都行,因为电脑的超级终端全都支持。)

然后看到rz准备接收了就回电脑。

电脑端

打开“超级终端”。XP应该在附件->通讯里,Win7删除了超级终端,下载一个。(下载地址点此)

(第一次打开要输区号,必须输入,但是没有用处。输真的假的随便…)

新建连接,名称和图标没用,随意填

“连接到”对话框里,选正确的COM口

波特率、数据位、停止位看minicom界面的最下边一行。和minicom保持一致。

第一幅图里能看到:“115200 8N1”,就是115200波特率,8数据位,1停止位。

(一般只需要改波特率。)

连上之后按传送->发送文件

协议不用动,按发送。

由于树莓派已经准备好了接收,所以传送立刻就能开始。

速度大致如此,基本和老式拨号上网一致……所以没事千万别发上MB的文件…

其它

(一)

可以灵活一些。像上文那样树莓派先开接收,或者是电脑先发送树莓派再开接收,都可以。

(二)反向,树莓派给电脑传文件:

minicom上使用S命令。

电脑超级终端上使用传送->接收文件。

官方:树莓派A+版正式发布

树莓派官网刚发布了“树莓派A+”版本,正如开发团队于今年7月所声称的“我们将发布更多生产成本更低的衍生版本”。而今天发布的A+版本价格则低至20美元。

树莓派A+版本主要做了以下几处改动:

外形更小,功耗更低更节能

A+版与A版一样采用了 BCM2835 处理器,256MB 内存

65MM×86MM 更小的主板尺寸和完全兼容HAT

集成了B+版对B版的各项改进,包括:

更多的 GPIO 针脚,40针!(老版本是26针)

用Micro SD插口替换了老的SD插口

音频优化,音频电路采用了专用的低噪音电源。

A+完整的规格如下:

配256MB内存的700MHz博通BCM2835处理器

40针的扩展GPIO

1个USB 2.0端口

4通道立体声输出和复合视频端口

全尺寸HDMI端口

连接树莓派摄像头的CSI端口

连接树莓派触控显示屏幕的DSI端口

用于加载系统和储存数据的MicroSD端口

Micro USB电源

更小的主板尺寸和完全兼容HAT

能够支持1080P高清视频输出

A+与B+详细参数对比如下:

给树莓派添加重启关机按钮

最近一段时间开始捣鼓树莓派了,弄的都是试验性质的。经常会出现些问题导致连不上树莓派可能是卡死或者断网什么的,有没有显示器也不知道到底是什么情况。 没办法只有拔掉电源重启了。

后来想想长期这样弄也不是办法SD卡禁不起折腾啊,于是就想办法给它添加了个“关机和重启按钮”。

这里实现上用了GPIO接口,通过读取一个接口的高低状态然后调用重启以及关机命令。

我的pi是B版v1。GPIO接口和v2稍微不一样。具体看下图把代码的接口定义替换成对应的就行了

另外使用pin的编号有两种方式

Board Pin 这种是自然排序的,重p1到p26 BCM GPIO Broadcom的编号方法 (上图中的绿色方块部分GPIO*)

我在代码中使用的是 *BCM *。

这里用到了两个GPIO接口,7和17 你也可以自己修改下。 一个用来接收按键信号,另外一个驱动led显示状态

led有三个状态 长亮:正在重启,闪动:正在关机,不亮:等待状态。

面包板连接

若你有杜邦线的话也可以不通过面包板连接,按钮那个GND的线也不是必须的,用手直接触摸 GPIO7 也能起到把这个电压拉低的效果

实现代码

#!/usr/bin/env python # coding=utf-8 # author:ksc import RPi.GPIO as GPIO import time import os,sys import signal GPIO.setmode(GPIO.BCM) #define GPIO pin pin_btn=7 pin_led=17 GPIO.setup(pin_btn, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(pin_led, GPIO.OUT, initial=GPIO.LOW) press_time=0 count_down=10 led_on=1 def cleanup(): ”’释放资源,不然下次运行是可能会收到警告 ”’ print(‘clean up’) GPIO.cleanup() def handleSIGTERM(signum, frame): #cleanup() sys.exit()#raise an exception of type SystemExit def onPress(channel): global press_time,count_down print(‘pressed’) press_time+=1 if press_time >3: press_time=1 if press_time==1: GPIO.output(pin_led, 1) print(‘system will restart in %s’%(count_down)) elif press_time==2: print(‘system will halt in %s’%(count_down)) elif press_time==3: GPIO.output(pin_led, 0) print ‘cancel ‘ count_down=10 GPIO.add_event_detect(pin_btn, GPIO.FALLING, callback= onPress,bouncetime=500) #signal.signal(signal.SIGTERM, handleSIGTERM) try: while True: if press_time==1: if count_down==0: print “start restart” os.system(“shutdown -r -t 5 now”) sys.exit() led_on=not led_on GPIO.output(pin_led, led_on)# blink led if press_time==2 and count_down==0: print “start shutdown” os.system(“shutdown -t 5 now”) sys.exit() if press_time==1 or press_time==2: count_down-=1 print “%s second”%(count_down) time.sleep(1) except KeyboardInterrupt: print(‘User press Ctrl+c ,exit;’) finally: cleanup()

使用方法

#创建程序,把代码粘贴进去保存 root@mypi:~# vi reboot.py #修改可执行 root@mypi:~# chomod 775 reboot.py #测试下 root@mypi:~# ./reboot.py

按一下按钮系统进入重启状态倒计时10秒,在这段时间内你可以接着按一下切换到关机状态。按第三下取消关机进入等待状态。这三种状态可通过按按钮不断切换。

#若没问题就可以让它后台运行了, root@mypi:~# nohup ./reboot.py & #想结束后台运行? ps auxf #查找PID kill PID

参考

上拉电阻和下拉电阻

使用 RPI.GPIO 模块的输入(INPUT)功能

RPI.GPIO WIKI

树莓派vim代码高亮

MCC 172是一个两通道DAQ HAT,用于通过IEPE传感器(如加速度计和麦克风)进行声音和振动测量。它的每个通道具有24位A/D,最大采样率为51.2 kS/s/Ch。