树莓派 - [第二集] 输入输出,一切皆是如此。
使用 Gertboard 将树莓派连接到真实世界。
![]() |
引言在我第一篇树莓派文章中,我简单介绍了这块板子,并展示了如何轻松加载操作系统并启动它,连接到互联网并浏览 CodeProject。 在这篇文章中,我希望演示如何将这块板子连接到真实世界。与 Arduino 板不同,这里没有简单的输入输出数字输入/输出或模拟引脚,只有一组简单的通用输入输出 (GPIO) 引脚。 好消息是,有这样一块板子! |
隆重推出 Gertboard!
Gertboard 是一款接口扩展板,通过 GPIO 引脚和排线连接到树莓派。下图展示了完成后 Gertboard(左)连接到 RasPi(右)的效果。(图片由 Element14 提供)
我通过 Element 14 (零件代码 211-5337) 购买了我的板子。就像最初发布的 RasPi 一样,我订购时也有缺货的情况,只能耐心等待。
我订购的套件是未组装的单元,我并不介意重新拿出焊锡工具。直到我收到套件并发现其中有非常小的表面贴装元件时,我才意识到!总共有 33 个独立的组件包、IC 和各种排针和跳线,当然还有 1x Gertboard PCB。
在 Farnell 网站上,您现在可以订购完全组装好的板子,这可以为一些人省去一些麻烦。(零件代码 225-0034)。
Farnell 现在有专门针对树莓派的整个版块,提供各种板卡、外壳、摄像头和其他配件。
组装板卡
打开收到的包裹并摊开所有东西后。我注意到没有组装说明。所以我不知道每个组件应该放在哪里。快速搜索了一下,我在 RasPi 网站上找到了链接回 Element14 的组装手册和用户手册。
下图显示了在开始艰巨任务之前,所有东西都摊开在包装中。
下载组装手册并打开后,很高兴在引言中看到了表面贴装器件的焊接指南。我以前从未尝试焊接过这些,考虑到它们如此小,我有些紧张。例如,套件中有 2 个 0 欧姆 SMD 电阻。它们是 2 毫米 x 1.2 毫米。在上图的左下角白色袋子中,您可以看到 SMD 组件条。
我还为自己购买了新的焊台。我有一个旧的 25W 基本电烙铁,但觉得是时候告别黑暗时代了。嗯,至少我不用在火上加热电烙铁了!
所以是时候开始工作了。我做的第一件事是把 SMD 组件包都摆好。这些包上只有 Farnell/Element14 的零件号,没有内容描述。最好去网站上查找每个组件,并在包上写下其描述。SMD,无论是电容器还是电阻,看起来都一样,所以您不想混淆它们。另外,在组装板卡时,一次只专注于一种组件类型,以免混淆。完成一种组件类型后,收起任何备用件的袋子,然后转到下一个。建议从最小的组件尺寸开始,然后逐步处理像 IC 插座和保险丝座这样较大的组件。
慢慢来,遵循说明。一切顺利,一切都会好起来的!
结果怎么样?
结果还算不错。试图打开 SMD 组件包装有点麻烦,第一个包装导致电容器散落得到处都是,但设法全部找到了。我不小心将其中一个电阻桥接器放错了位置,但在焊接第一条腿时注意到了。然后我把 IC 插座装反了,但只焊了两个角,所以设法轻松地挽回了局面。
总共花了 2 小时 8 分钟组装完板卡。这包括中途去开门!下面是成品;
来个延时摄影!
在 RasPi 网站上,Mike Cook 制作了一个关于他组装 Gertboard 的延时视频。我以前从未制作过延时视频,所以也想试试。这也将是一个很好的借口来使用我的 GoPro HD Hero 2!
下面的视频是通过首先以 1 帧/5 秒 @ 3200 x 2400 分辨率拍摄构建过程的延时序列,然后使用 GoPro Cineform Studio 将其转换为 1280x720 高清输出,每秒 10 帧而创建的。
http://www.youtube.com/watch?v=hNPQao6wops
正如您在视频开头看到的,使用镊子绝对是处理 SMD 组件的必需品。它们简直是噩梦!我还有幸请我的大女儿 Maya(8 岁)稍后来加入我进行监督。真是(至少)二十个问题……
板卡上有哪些功能?
Gertboard 具有多种功能。这些都通过各种接口引出,让您可以随意使用它们。板卡上的主要功能包括;
- 2 个数模转换器(8 位)
- 2 个模数转换器(10 位)
- 12 个 LED 指示灯
- 3 个按钮
- 6 个开集电极输出
- 12 个数字 IO
- 1 个电机控制器(双向,最高 18V @ 2A)
此外,还有 3 个按钮连接到 3 个 IO,以及 12 个 LED 连接到 IO。
Gertboard 的另一个显著特点是,它还在板卡上内置了一个 ATMega328 微控制器,所有引脚都引出到一组接口。这实际上意味着板卡上还有一个 Arduino。
测试板卡
注意:版本 1(自行组装)和版本 2(预组装)在连接器和跳线方面略有不同,因此您需要参考正确的指南来操作您自己的板卡。
在用户手册中,有链接可以从 Element14 网站下载示例代码,但 Gertboard 还有许多其他资源。一个好的起点是这个论坛;http://www.raspberrypi.org/phpBB3/viewforum.php?f=42
下载并安装了最新版本的 Wheezy(按照我第一集文章中的说明),接下来需要获取合适的 Python 测试代码。
在 RasPi 的命令控制台中,您可以执行以下操作;
wget http://raspi.tv/download/GB_Python.zip
unzip GB_Python.zip
cd GB_Python
nano README.txt
在 readme 文件中,有进一步的说明和指向 YouTube 上运行代码的代码和演示视频的链接。
出于本文的目的,我将只测试其中的几个。
LED 测试
运行命令;
sudo python leds-rg.py
结果是程序会打印出您应该连接哪些跳线进行测试,然后等待您按“Enter”。这将使 LED 按照 1->12->1 等的顺序运行。
不幸的是,由于某种原因,我的板卡上只有 LED 1 到 8 可以工作。我将跳线换到 B1 和 B12 引脚上,以确认 B12 至少在驱动信号,并且当 LED1 作为 12 应该亮起时,LED1 亮起证实了这一点。接下来我决定交换 2 个 IC,以防其中一个损坏。我拔下了驱动 LED 9/10/11/12 的 IC (U5),这时我才注意到我没有安装决定它是输入还是输出的跳线。插入这些跳线,重新插入 IC 并重新运行测试,确认 LED 现在都正确地进行序列化了。虚惊一场!
RasPi.TV 在 YouTube 上发布了此测试的视频:http://www.youtube.com/watch?v=fFHEi1ur7yg (请注意,视频中您只会看到他们只连接了前 10 个 LED 而不是全部 12 个)。
按钮测试
运行命令;
sudo python buttons-rg.py
程序再次打印出需要插入的跳线说明,然后等待您按“Enter”。一旦您按下按键,程序就会输出按钮的二进制状态,例如“111”,并点亮 LED,当您按下按钮时,二进制状态和 LED 会如您所料地发生变化。
RasPi.TV 上的参考测试:http://www.youtube.com/watch?v=DwlI2Fr1AXg
代码后置
通常,学习和理解正在发生的事情的最佳方法是打开别人的代码并查看。下面的代码是来自 **leds-rg.py** 的 LED 测试;
#!/usr/bin/env python2.7
# Python 2.7 version by Alex Eames of http://RasPi.TV
# functionally equivalent to the Gertboard leds test by
# Gert Jan van Loo & Myra VanInwegen. Use at your own risk
# I'm pretty sure the code is harmless, but check it yourself.
import RPi.GPIO as GPIO
from time import sleep
import sys
board_type = sys.argv[-1]
if GPIO.RPI_REVISION == 1: # check Pi Revision to set port 21/27 correctly
# define ports list for Revision 1 Pi
ports = [25, 24, 23, 22, 21, 18, 17, 11, 10, 9, 8, 7]
else:
# define ports list all others
ports = [25, 24, 23, 22, 27, 18, 17, 11, 10, 9, 8, 7]
ports_rev = ports[:] # make a copy of ports list
ports_rev.reverse() # and reverse it as we need both
GPIO.setmode(GPIO.BCM) # initialise RPi.GPIO
for port_num in ports:
GPIO.setup(port_num, GPIO.OUT) # set up ports for output
def led_drive(reps, multiple, direction): # define function to drive
for i in range(reps): # repetitions, single or multiple
for port_num in direction: # and direction
GPIO.output(port_num, 1) # switch on an led
sleep(0.11) # wait for ~0.11 seconds
if not multiple: # if we're not leaving it on
GPIO.output(port_num, 0) # switch it off again
# Print Wiring Instructions appropriate to the board
if board_type == "m":
print "These are the connections for the Multiface LEDs test:"
print "BUFFER DIRECTION SETTINGS, jumpers on all OUT positions (1-12)"
print "GPIO 25 --- BUFFERS 1 \nGPIO 24 --- BUFFERS 2"
print "GPIO 23 --- BUFFERS 3 \nGPIO 22 --- BUFFERS 4"
print "GPIO 21 --- BUFFERS 5 \nGPIO 18 --- BUFFERS 6"
print "GPIO 17 --- BUFFERS 7 \nGPIO 11 --- BUFFERS 8"
print "GPIO 10 --- BUFFERS 9 \nGPIO 9 --- BUFFERS 10"
print "GPIO 8 --- BUFFERS 11 \nGPIO 7 --- BUFFERS 12"
else:
print "These are the connections for the Gertboard LEDs test:"
print "jumpers in every out location (U3-out-B1, U3-out-B2, etc)"
print "GP25 in J2 --- B1 in J3 \nGP24 in J2 --- B2 in J3"
print "GP23 in J2 --- B3 in J3 \nGP22 in J2 --- B4 in J3"
print "GP21 in J2 --- B5 in J3 \nGP18 in J2 --- B6 in J3"
print "GP17 in J2 --- B7 in J3 \nGP11 in J2 --- B8 in J3"
print "GP10 in J2 --- B9 in J3 \nGP9 in J2 --- B10 in J3"
print "GP8 in J2 --- B11 in J3 \nGP7 in J2 --- B12 in J3"
print "(If you don't have enough straps and jumpers you can install"
print "just a few of them, then run again later with the next batch.)"
raw_input("When ready hit enter.\n")
try: # Call the led driver function
led_drive(3, 0, ports) # for each required pattern
led_drive(1, 0, ports_rev)
# run this once, switching off led before next one comes on, forwards
led_drive(1, 0, ports)
# run once, switch led off before next one, reverse direction
led_drive(1, 0, ports_rev)
# (1, 1, ports) = run once, leaving each led on, forward direction
led_drive(1, 1, ports)
led_drive(1, 0, ports)
led_drive(1, 1, ports)
led_drive(1, 0, ports)
except KeyboardInterrupt: # trap a CTRL+C keyboard interrupt
GPIO.cleanup() # clean up GPIO ports on CTRL+C
GPIO.cleanup() # clean up GPIO ports on normal exit
如您所见,它相当直接,并且有注释可以帮助理解内容,无需更多说明。下面的代码来自按钮测试,它将使我们能够理解如何读回按钮的状态并显示在屏幕上(**buttons-rg.py**);
#!/usr/bin/env python2.7
# Python 2.7 version by Alex Eames of http://RasPi.TV
# functionally equivalent to the Gertboard buttons test by
# Gert Jan van Loo & Myra VanInwegen
# Use at your own risk - I'm pretty sure the code is harmless,
# but check it yourself.
import RPi.GPIO as GPIO
import sys
board_type = sys.argv[-1]
GPIO.setmode(GPIO.BCM) # initialise RPi.GPIO
for i in range(23,26): # set up ports 23-25
GPIO.setup(i, GPIO.IN, pull_up_down=GPIO.PUD_UP) # as inputs pull-ups high
# Print Instructions appropriate for the selected board
if board_type == "m":
print "These are the connections for the Multiface buttons test:"
print "GPIO 25 --- 1 in BUFFERS"
print "GPIO 24 --- 2 in BUFFERS"
print "GPIO 23 --- 3 in BUFFERS"
print "Optionally, if you want the LEDs to reflect button state do the following:"
print "jumper on BUFFER DIRECTION SETTINGS, OUT 1"
print "jumper on BUFFER DIRECTION SETTINGS, OUT 2"
print "jumper on BUFFER DIRECTION SETTINGS, OUT 3"
else:
print "These are the connections for the Gertboard buttons test:"
print "GP25 in J2 --- B1 in J3"
print "GP24 in J2 --- B2 in J3"
print "GP23 in J2 --- B3 in J3"
print "Optionally, if you want the LEDs to reflect button state do the following:"
print "jumper on U3-out-B1"
print "jumper on U3-out-B2"
print "jumper on U3-out-B3"
raw_input("When ready hit enter.\n")
button_press = 0 # set intial values for variables
previous_status = ''
try:
while button_press < 20: # read inputs until 19 changes are made
status_list = [GPIO.input(25), GPIO.input(24), GPIO.input(23)]
for i in range(0,3):
if status_list[i]:
status_list[i] = "1"
else:
status_list[i] = "0"
# dump current status values in a variable
current_status = ''.join((status_list[0],status_list[1],status_list[2]))
# if that variable not same as last time
if current_status != previous_status:
print current_status # print the results
# update status variable for next comparison
previous_status = current_status
button_press += 1 # increment button_press counter
except KeyboardInterrupt: # trap a CTRL+C keyboard interrupt
GPIO.cleanup() # resets all GPIO ports used by this program
GPIO.cleanup() # on exit, reset all GPIO ports
使用 DS18B20 1-Wire 温度传感器进行温度测试
我有一个项目,想要监控家里的中央供暖、热水、太阳能热水和太阳能光伏系统。为了能够监控温度,我购买了一批“1-Wire”温度传感器。这些传感器预先连接到防水探头,并带有 1 米长的导线。这些传感器是 Dallas Semiconductos DS18B20,每个传感器都有一个唯一的 ID,允许它们进行总线连接和轮询。
下图是我的测试设置,从左到右依次是 RasPi、Gertboard、面包板、Arduino(碰巧连接在面包板上,但本文未使用)。您可以在图像的中间底部看到传感器的尖端。
为了进行测试,而不是重新发明轮子,在 Google 上快速搜索后,我在 Adafruit 上找到了一个很棒的教程:Adafruit 的树莓派课程 11. DS18B20 温度传感。
按照教程中的示例操作后,如下图所示,我成功地从控制台和 Python 脚本中读取了设备。
在上面的 Python 输出中,您可以看到温度以摄氏度和华氏度显示,例如(33.5、92.3)。
温度测试代码
下面是教程示例代码的稍作修改的版本;
import OS
import glob
import time
import subprocess
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
base_dir = 'sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
print "Device Folder: " + device_folder
print "Device File : + device_file
def read_temp_raw():
catdata = subprocess.Popen(['cat', device_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = catdata.communicate()
out_decode = out.decode('utf-8')
lines = out_decode.split('\n')
return lines
def read_temp():
print "Raw device data :"
lines = read_temp_raw()
print lines[0]
print lines[1]
print lines[2]
while (lines[0].find('YES') > 0):
lines = read_temp_raw()
equal_pos = lines[1].find('t=')
if equal_pos != -1:
temp_string = lines[1][equal_pos+2:]
temp_c = float(temp_string) / 1000.0
temp_f = temp_c * 9.0 / 5.0 + 32.0
return temp_c, temp_f
while True:
print "Current Temperature ('C, 'F):"
print(read_remp())
print ""
print "Sleeping.....(1 Second)."
time.sleep(1)
如您在上面的代码中看到的,它基本上是对字符串进行解析以从行“t=”中提取温度。这个值已经被缩放,因此需要除以 1000 才能得到摄氏度读数。该代码目前只能用于单个总线传感器,需要进行修改才能读取多个传感器。
What Next?
嗯,我对迄今为止的成果感到满意。
接下来,我将研究如何将其扩展到我的多个温度传感器和光学传感器(我想查看燃烧器观察窗以了解何时正在运行供热需求)。然后研究集成我的太阳能系统等。
根据后续情况,这可能会成为未来文章的主题。
感谢您读到这里……也许下集再见。
参考链接
- http://www.raspberrypi.org/archives/tag/gertboard - 树莓派 Gertboard 标记项
- http://raspi.tv/download/rpigpio.txt - GPIO Python 速查表
- http://www.youtube.com/user/RasPiTV/videos - YouTube 上的 RasPi.TV 频道
- http://www.sbprojects.com/projects/raspberrypi/temperature.php - 1-Wire 温度计演示
历史
2013 年 12 月 5 日 - 文章首次发布。