65.9K
CodeProject 正在变化。 阅读更多。
Home

树莓派 - [第二集] 输入输出,一切皆是如此。

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.82/5 (8投票s)

2013 年 12 月 5 日

CPOL

10分钟阅读

viewsIcon

30174

使用 Gertboard 将树莓派连接到真实世界。

Raspberry Pi Logo

引言

在我第一篇树莓派文章中,我简单介绍了这块板子,并展示了如何轻松加载操作系统并启动它,连接到互联网并浏览 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?

嗯,我对迄今为止的成果感到满意。

接下来,我将研究如何将其扩展到我的多个温度传感器和光学传感器(我想查看燃烧器观察窗以了解何时正在运行供热需求)。然后研究集成我的太阳能系统等。

根据后续情况,这可能会成为未来文章的主题。

感谢您读到这里……也许下集再见。

参考链接

历史

2013 年 12 月 5 日 - 文章首次发布。
 

© . All rights reserved.