10-个-LED-极客项目-全-
10 个 LED 极客项目(全)
原文:
zh.annas-archive.org/md5/997a4a29ecf4719e8691e6d2cc550d3d译者:飞龙
第一章:作者:Matthew Beckler
欢迎来到10 个适合极客的 LED 项目,本书展示了 10 个难度不同的项目,你可以使用电子元件来制作它们。在本书中,你将使用 Raspberry Pi 和 Arduino 来创造各种小工具和发明。在本书的介绍中,你将学习如何开始使用这两块开发板,包括如何安装必要的软件,同时你还会认识到本书的核心电子元件——LED。
在本介绍的最后,你还会找到一份列出项目所需零件的常见供应商列表。
LED 的所有内容
在你开始使用 LED 制作酷炫项目之前,让我们先花点时间来定义一下它们。LED是一种电路元件,将电能转化为光。LED 有各种颜色、形状和尺寸,广泛应用于各种项目。大多数 LED 用于指示,意味着它们向附近的人指示某物的状态,比如“门已打开”、“收音机开着”或“安全系统已启用”。如今,已有更大且更亮的 LED 可用于照明物体或区域。图 1 展示了一些用于指示的基本 LED。

图 1: 各种单颗 LED
LED 代表发光二极管。这里有几个词需要解释,但我们先从“二极管”开始。在电路中,二极管像一个单向阀门,只允许电流朝着一个预定的方向流动。如果你尝试反方向传输电流,它将无法流动。二极管将交流电(AC)转化为直流电(DC),这个过程称为整流。二极管最初是为 AM 收音机接收器设计的,用来整流无线电频率信号,但现在被广泛应用于许多需要电流单向流动的场合。例如,许多消费电子产品中的二极管有助于保护电路免受电池反向插入的损害。然而,通常情况下,LED 的二极管特性并不重要。名字中的“发光”部分意味着这种类型的二极管在电流通过时会发光。
LED 的工作原理
LED 是一种半导体器件,由像硅和锗这样的晶体金属构成,并且加入少量杂质来改变材料的特性。这些杂质通过一个叫做掺杂的过程添加到半导体中。添加的元素叫做掺杂剂,它将基础材料转变为p 型或n 型半导体。
P 型和 N 型的区别取决于掺杂物是添加了过多的自由电子,还是导致自由电子的缺乏。这两种掺杂半导体相遇的地方被称为P-N 结,这里是光的生成区域。通过结的电能使一些载流子激发,载流子在返回到其非激发状态时会发出光,这一过程被称为电致发光。
半导体材料的精确化学成分决定了所涉及材料的带隙,进而决定了所产生的光的颜色。第一代 LED 开发于 1960 年代,发出的光位于光谱的红外端,虽然人眼不可见,但在科学实验中仍然具有重要价值。后来,其他半导体和掺杂物的发展引入了新的可见颜色,导致 1960 年代末红色 LED 的大规模生产,1970 年代初黄色 LED 的大规模生产。
高亮度蓝色 LED 的开发非常困难,直到 1994 年,三位日本科学家终于找到了蓝色 LED 的秘密,它被认为是 LED 世界中的圣杯。他们因此成就获得了 2014 年的诺贝尔物理学奖!
人工照明简史
在人类历史上,人工照明的发展对技术进步至关重要。没有人工照明,日落后几乎不可能进行任何高效的工作,无论是手工制作、娱乐还是教育。长期以来,产生人工光源的唯一方法是燃烧某种燃料,如木材、蜂蜡、石油、煤气或煤油。这一切在 1800 年代末电力配电网的发展中发生了变化,电照明得到了广泛应用。
早期的电照明由白炽灯泡组成,这些灯泡通过加热一根细小的灯丝直到其发出白色热光,通常是在充满惰性气体的灯泡中(以延长灯丝寿命)。这些灯泡只将输入能量的一小部分转化为光,其余部分以热量的形式浪费掉。白炽灯泡最终被气体放电灯泡取代,包括荧光灯、霓虹灯和高强度放电(HID)灯,如街灯,这些灯泡通过电弧通过封闭气体的管道产生更高效的光。气体放电灯泡通常需要高电压,因此不适用于便携式和低功率应用。而发光二极管(LED)则不需要让任何物质变得白热化,也不涉及气体电弧,仅通过高效的光生产来实现照明。
LED 配置
LED 广泛应用于各种类型的人工光源,并且有许多不同的配置。让我们来了解一些你最常遇到的类型。
单色和双色 LED
基本的单色 LED配置有两个连接点:阳极和阴极。如果施加足够的电压,LED 会亮起。非常简单!单色 LED 有各种不同的形状、大小和颜色,其中一些,如图 1 中显示的第二个和第四个 LED,额外带有塑料外壳,帮助将产生的光线引导通过电子设备外壳侧面的开口。
双色 LED 在同一个两引脚封装中包含两个 LED,通常是将两个 LED 连接成阳极对阴极,如图 2 所示。

图 2: 双色 LED 具有两个连接成阳极对阴极的 LED。
通常这两个 LED 的颜色不同,使得电路只使用两个引脚就能显示两种不同的颜色。例如,如果电流从左到右流过电路,下方的 LED 会亮起。如果电流从右到左流过电路,上方的 LED 会亮起。
另一种有趣的类型是烛光闪烁 LED,它包含一个小型计算机芯片,使 LED 以闪烁的模式开关,旨在模拟蜡烛的自然闪烁。你可能在高档餐厅、婚礼宴会或任何想要拥有蜡烛氛围却没有火灾风险的地方见过这些 LED。
红绿蓝 LED
红绿蓝(RGB)LED 将三个 LED 集成在一个封装中,实际上允许你创造出整个颜色光谱,而不仅仅是红色、绿色和蓝色。例如,你可以将红色和绿色光混合,得到黄色;将绿色和蓝色光混合,得到青色;将红色和蓝色光混合,得到紫色。将三种颜色的光以相同的强度混合,便会产生白光。
通过组合这三种颜色的光,并在每种颜色上调整亮度,可以创造出数百万种颜色;这就是你的电视和手机用来显示全彩图像的方法。通常,为了调整亮度,每种颜色会非常快速地开关,这会使我们的眼睛看到每种颜色的不同亮度。最简单的 RGB LED 有四个连接点,每种颜色一个连接点,再加上一个与三个 LED 公用的连接点。这个公用连接点可以是共阳极 (CA)或共阴极 (CC),它描述了四脚 RGB LED 的内部连接。图 3 显示了共阳极 RGB LED 的连接示意图。

图 3: 共阳极 RGB LED 包含红色、绿色和蓝色 LED,且有四根引线
另一种常见的 RGB LED 类型是数字控制 RGB LED,它包含一个微小的计算机芯片,用于控制每种颜色的亮度。你的微控制器与每个 RGB LED 中的芯片进行通信,并设置所需的颜色。RGB LED 中的芯片通常是 WS2812B 或 SK6812,并且几乎任何你想使用的系统(包括 Arduino、树莓派等)都有相应的软件库。
使用数字控制 RGB LED 的最大好处是,你可以“设置并忘记”它们,这样你的微控制器就可以更新 LED 到最新的所需颜色,然后继续执行其他任务,而不需要不断更新 LED 的亮度。你还可以将 RGB LED 串联在一起,形成大型的 RGB LED 串或阵列,使其在艺术项目和户外展示中非常有用。
这些 LED 有多种形态,如图 4 和图 5 所示。

图 4: 各种 RGB LED:微型表面贴装芯片;四脚插孔封装;预先安装在小电路板上的 LED

图 5: 一种灵活的数字控制 RGB LED 网格
这些图形展示了各种封装形式的数字控制 RGB LED,包括微型表面贴装芯片、四脚插孔封装、附加在小电路板上的 LED,甚至是预先安装在灵活网格中的 LED。
最后一种类型的 RGB LED 是双连接、内部控制的 LED。如果你只需要两个引脚的非常便宜的 RGB LED,这些是一个不错的选择。这些 LED 内部有一个小控制芯片,但不同于数字控制 RGB LED,你不能真正控制它们的行为。例如,当你为这些 LED 提供电源时,内部控制芯片会开始在 RGB LED 上显示预录的颜色序列,通常是循环显示每种主色和次色,并在每个颜色之间有漂亮的颜色渐变。
阅读 LED 数据表
任何 LED 的制造商通常都会提供一份技术数据表,里面充满了事实和数据。它可能看起来很复杂,但别担心!对于本书的目的,你只需要知道两个重要的数字,以确保安全使用 LED。图 6 展示了你将用来查找关键细节的典型 LED 数据表,这些细节在这里被红色高亮显示。

图 6: 高亮显示前向电流和前向电压的 LED 数据表
当电流通过 LED 时,它会发光,但过多的电流会使其过热并损坏它。通过使用数据表中的前向电压和最大电流参数,我们可以计算出需要多大尺寸的电阻来安全地驱动 LED。
前向电压
LED 的正向电压,或V[f],是 LED 开始导电所需的最小电压。它测量的是 LED 开启时阳极和阴极之间的电压差。如果你施加的电压低于 V[f],LED 将无法导电或点亮。当 LED 正常工作时,LED 两端的电压将等于 V[f]。我们将在稍后的计算电路参数时用到这个事实。
LED 的 V[f]取决于所用材料的化学成分,这也决定了 LED 的颜色。例如,红色 LED 的典型 V[f]为 1.5 到 2 V,而蓝色或白色 LED 的 V[f]值通常较高,范围为 2 到 3 V。
最大电流
如果电压超过 V[f],LED 会尽可能多地导电,这可能导致过热并损坏 LED。为避免这种情况,我们需要从数据表中获取第二个数值:最大电流,即 LED 能够通过的最大电流而不会导致过热。
大多数 LED 有一个最大稳态电流和一个较高的最大脉冲电流。通常,我们在计算时使用最大稳态电流。电流的单位是安培(A),也可以用千分之一安培来表示,称为毫安(简写为mA)。电流是通过设备流动的电量,它决定了 LED 的亮度。例如,大多数小型 LED 只需 10 至 30 mA 的电流就能点亮。一些较大的 LED 和 LED 组件需要几百毫安甚至几安培的电流!
电阻、LED 与欧姆定律
为了安全地驱动 LED,我们需要在 LED 两端提供至少 V[f]的电压,同时还要限制电流,以确保它保持在数据表所允许的最大电流以下。最简单的做法是将一个电阻“串联”(inline)到 LED 中。电阻是最简单的电路元件,其电压、电流和电阻之间有着非常简单的关系。这个关系被称为欧姆定律,可以通过以下方程表示:
电压 = 电流 × 电阻
我们可以通过使用字母I来代表电流,简化这个表达式,得到我们熟悉的V = I × R的欧姆定律方程。电阻的单位是欧姆,简写为Ω。
让我们通过一个实际的例子来理解这种关系。假设有一个电阻,其电阻值为 1,000 Ω。如果我们对这个电阻施加 12 V 的电压,那么通过它的电流是多少?为了回答这个问题,我们只需将方程中的变量替换为给定的信息:

使用欧姆定律,你可以看到,当我们对一个 1,000 Ω的电阻施加 12 V 时,会有 12 mA 的电流通过这个电阻。现在我们再做一次相同的计算,不过这次电压是 36 V:

现在,让我们看看电阻器如何帮助我们保护 LED 不至于承受过多电流。
计算与 LED 配套使用的电阻
如果我们将 LED 和电阻器配对,它们共同工作,限制流过两个设备的电流。图 7 展示了这一工作原理。

图 7: 使用串联(内联)电阻器与 LED 一起限制电流并保护 LED
请注意,LED 的电流与电阻器中的电流是相同的。你可以看到,电源的总电压也等于 LED 的电压与电阻器的电压之和。我们可以用两个简单的方程式来描述我们的电路:

我们已经知道 LED 的电流需要低于它能承受的最大值。对于这个电路,假设我们希望 LED 的最大电流为 20 mA。我们还知道 LED 的正向电压(V[f])来自数据手册。对于这个示例,假设正向电压为 2 V,电源电压为 5 V。根据这些已知条件,我们可以将一些变量代入这两个方程式。

所以我们已经计算出电阻器电流为 20 mA,电阻器电压为 3 V。现在我们需要做的就是利用欧姆定律计算所需的电阻值。

重新排列后,我们发现:

这告诉我们,我们需要 150 Ω的电阻来保持 LED 电流在 20 mA,电源电压为 5 V。请记住,大多数电阻器的准确度仅在其标称值的 5%以内。这意味着一个 1,000 Ω的电阻器的实际电阻值会在 950 到 1,050 Ω之间,某些电阻器的准确度容差可能甚至高达 10%。如果你的计算结果得到的电阻值不是常见的标准值,可以四舍五入到最近的可用值。增加电阻可能会略微减少电流,但总比略微增加电流并可能导致 LED 过载要好!
我们可以将这个计算推广到一个情况,其中你有一个 LED 和串联电阻连接到电源:

这涉及很多数学计算。但这种技术如何应用呢?让我们来看看人们使用 LED 的几种方式。
世界上的 LED
我们在各种各样的应用中使用 LED,无论是显而易见的还是不那么显而易见的方式。例如,许多家电(如微波炉或收音机)上的数字时钟显示屏都为每个时间数字配备了一个七段显示。这个显示屏由七个 LED 组成,排列成一个块状的数字 8 形状,如图 8 所示。通过打开或关闭这七个段,我们可以显示从 0 到 9 的所有数字。

图 8: 一个七段显示器由多个 LED 集成到一个塑料外壳中,能够显示数字 0 到 9。
一个不太显眼的 LED 应用是它们在许多光纤和红外遥控器中的通信用途。连接城市和大陆的巨大海底互联网电缆由细玻璃纤维丝组成,每端都有一个 LED(或有时是激光器),通过电缆传输光脉冲以进行数据通信。图 9 显示了光纤电缆的示例。

图 9: 一束光纤电缆
电视和其他家电的红外(IR)遥控器使用一种特殊类型的 LED,产生人眼不可见的红外光,只有设备的传感器能够检测到。由于许多摄像机对红外光敏感,我们在安防摄像头中使用红外 LED,生成夜间照明,且这种照明对人眼不可见。
许多新的交通信号和汽车灯现在使用 LED,如图 10 所示,这有助于提高能见度并减少功耗和废热产生。

图 10: 一个 LED 交通信号灯
随着最近开发的令人愉悦的“暖白”LED,如图 11 所示,许多家庭和企业开始采用 LED 照明。这些 LED 灯泡的效率比白炽灯泡高出 10 倍以上,其降低的能耗使得其更高的购买价格在使用几年后便能得到回报。

图 11: 设计适配标准灯座的白色 LED 灯泡
现在您已经了解了不同类型的 LED 及其工作原理,您几乎准备好开始项目了!除了各种各样的 LED,本书中的一些项目还需要树莓派或 Arduino。接下来的部分将指导您如何设置这两者。如果您已经完成这些设置,或者希望稍后在需要时再进行设置,您可以暂时跳过这些部分,直接进入第一个项目!
开始使用树莓派
本节将向您展示如何使用格式化的 SD 卡和 Raspbian 操作系统设置您的树莓派。
所需材料
树莓派可能是目前市场上最著名的小型计算机。树莓派大约有信用卡大小,是一款微型计算机,包含处理器、USB 和其他连接器以及输入/输出引脚,如图 12 所示。

图 12: 一款树莓派单板计算机
树莓派有几种不同的型号,任何一款 Pi 都可以用于本书中的目的。
和任何计算机一样,Pi 需要一个键盘、鼠标、显示器、电源供应和一些存储来放置操作系统。你可以使用任何 USB 鼠标和键盘,以及任何 HDMI 显示器,如计算机显示器或电视。电源供应是微型 USB 连接器,就像你在许多手机中找到的那样,所以如果你已经有旧手机充电器,可以重复使用它。虽然许多计算机使用旋转的磁性硬盘驱动器作为存储设备,但 Pi 需要一个单独的 micro SD 卡来存储操作系统(OS)和你创建的文件。因此,你需要购买一个 8GB 或 16GB 的 micro SD 卡——越大越好。我们将按照官方的 Raspberry Pi 软件指南进行操作(* www.raspberrypi.org/learning/software-guide/quickstart/ *)。
使用 NOOBS 安装 Raspbian
最受欢迎的 Raspberry Pi 操作系统叫做 Raspbian,你可以通过将文件从另一台计算机复制到 micro SD 卡上来轻松安装它。开始使用 Raspberry Pi 最简单的方式是使用 NOOBS(“新盒子外软件”)系统,它可以让你选择要安装的操作系统。
要安装 NOOBS,访问 Raspberry Pi 网站的下载部分(* www.raspberrypi.org/downloads/noobs/ *)。然后选择 NOOBS(离线和网络安装) 选项。不要选择 NOOBS LITE,因为它默认没有包含 Raspbian。要下载 NOOBS,点击 下载 ZIP 选项。如果你熟悉使用 BitTorrent 软件,也可以选择 下载 Torrent(这有助于减少 Raspberry Pi 基金会的带宽成本)。无论哪种方式,当下载完成后,使用解压程序打开 ZIP 压缩包,并将文件提取到你的计算机中。将它们放在容易找到的位置,比如桌面或 文档 目录。
准备 SD 卡
接下来,我们需要格式化 micro SD 卡,以便准备接收 NOOBS 文件。即使你的 SD 卡是全新的,我也推荐格式化它,因为它需要完全为空才能接收操作系统。如果你的计算机运行 Windows 或 macOS,可以从 SD 协会网站下载 SD Formatter 4.0(* www.sdcard.org/ *),进入下载部分并找到适合你当前操作系统的格式化工具。按照说明安装软件,并使用它格式化你的 micro SD 卡。
注意
如果你的计算机运行 Linux,你可以使用任何磁盘格式化工具将 SD 卡格式化为主引导记录(MBR)并创建一个 FAT 分区。
格式化 micro SD 卡后,将提取的 NOOBS 文件拖放到 micro SD 卡驱动器中。等待文件复制完成后,安全移除 micro SD 卡并插入 Raspberry Pi。
启动你的 Pi
如果你还没有连接键盘和鼠标,请插入它们。使用 HDMI 电缆连接显示器。如果你有以太网电缆可用,将树莓派连接到互联网,在此时插入电缆。最后,插入微型 USB 电源电缆,树莓派应该开始启动。与大多数电脑不同,树莓派没有电源按钮,但在插入电源连接器时会自动启动。请参阅图 12,查看各端口的对应关系。
如果这是你第一次使用此 micro SD 卡,NOOBS 系统将要求你选择要使用的操作系统。因为 Raspbian 特别为树莓派设计并内置在 NOOBS 系统中,所以我推荐使用 Raspbian,但也有其他选项,可能需要互联网连接进行下载。
现在,你已经完成了树莓派和 Raspbian 操作系统的设置,准备好开始构建一系列项目。本书中的项目 6 使用了树莓派。之后,你可以尝试一些网上记录的有趣项目,既可以在官方树莓派网站(*www.raspberrypi.org/resources/)上找到,也可以在像 Instructables 和 Hack-a-Day 这样的网站上找到。
开始使用 Arduino 和 Arduino IDE
本书中的一些项目使用 Arduino 作为其核心。Arduino 比树莓派更简单,因为它没有像树莓派那样的计算和网络功能,而是简单地重复运行一个程序,直到你拔掉它。然而,Arduino 在许多硬件项目中表现出色,尤其是在需要高精度计时的情况下(例如与数字 RGB LED 进行通信)。让我们了解一下什么是 Arduino,学习如何安装它,并熟悉 Arduino 的工作流程。
什么是 Arduino?
Arduino 项目始于 2003 年,旨在让人们更容易入门电子学、编程和互动设计。该项目创造了多种开源微控制器电路板,并提供了一系列的软件库,这些库都集成在一个易于使用的集成开发环境(IDE)中。Arduino 板提供了一个在数字世界和现实世界之间的接口,使用户能够轻松读取来自按钮、开关、温度计等传感器的数据,同时驱动灯光、电机和 LED 显示器等执行器。围绕核心 Arduino 系统,已经建立了一个完整的生态系统,提供了大量的附加硬件和软件,供你设计下一个伟大的机器人、艺术装置或乐器。
基本的 Arduino 工作流程大致如下:首先,在计算机上的 Arduino IDE 程序中编写编程代码,称为草图。其次,使用 USB 电缆将 Arduino 电路板连接到计算机。第三,在 Arduino IDE 中选择上传按钮,将代码传输到 Arduino 板子中。然后,代码会自动开始运行,读取传感器并驱动执行器与现实世界进行交互。
最受欢迎的 Arduino 板是Arduino Uno,我们将在本节中以此为例,说明将代码上传到板子的过程。Arduino 板子有一个主处理器芯片(例如 Arduino Uno 上的 Atmel ATMega328),以及一个 USB 芯片,用于处理计算机和主处理器之间的接口。这些板子只需通过 USB 电缆就可以连接到你的计算机。
其他兼容 Arduino 的板子,如 EMSL Diavolino 和 SparkFun Arduino Pro Mini,通常没有 USB 芯片,通常是为了降低成本。对于这些板子,你需要一个单独的硬件设备,提供计算机和主处理器芯片之间的 USB 接口。因为 Arduino 最常用的 USB 接口芯片是由名为 FTDI 的公司制造的,所以我们称这个 USB 接口为FTDI 电缆,或FTDI 朋友。
安装和使用 Arduino IDE
要开始使用 Arduino,你首先需要从官方网站的www.arduino.cc/软件部分下载安装 Arduino IDE。我建议你下载离线版本的 IDE,而不是依赖于网页版编辑器。Windows、macOS、Linux 发行版和 Raspberry Pi 都有安装包可供选择。
图 13 显示了在 Windows 10 上运行的 Arduino IDE。

图 13: Arduino IDE 界面
在不同平台上,界面应该看起来相似。重要的工具栏按钮如下:
➊ 对勾 检查是否有错误,并验证草图是否可以编译
➋ 右箭头 上传并将草图传输到电路板中
➌ 放大镜 打开串口监视器,查看 Arduino 板发送的信息
草图的编程代码输入到屏幕中间的较大文本区域。Arduino 使用的编程语言叫做Wiring,它与 C++语言相似。
Arduino 草图的样子
Arduino IDE 带有大量示例草图,旨在演示 Arduino 可以做的各种事情。最简单的草图叫做Blink,它使 LED 灯闪烁。大多数 Arduino 板子都有一个内置的 LED,你可以通过草图代码打开和关闭它,而 Blink 草图将此内置 LED 作为输出信号。这个草图是测试新 Arduino 板并确认 IDE 是否正确设置的好方法。
要打开 Blink 示例草图,使用菜单选择 文件 ▸ 示例 ▸ 01.基础 ▸ Blink,如图 14 所示。

图 14: 选择并打开 Blink 草图
每个 Arduino 草图至少有两个编程代码部分,我们称之为 函数。第一个必需的函数是 setup(),它只在板子第一次通电或重置时调用一次。setup() 函数是我们放置所有初始化和配置活动的地方,例如初始化每个引脚的功能和配置外部库的功能。另一个必需的函数是 loop(),它在 setup() 函数执行完一次后会被重复调用。您也可以创建自己的函数来帮助组织草图代码。列表 1 展示了 Blink 草图的完整程序列表。
列表 1: Blink 草图的完整代码列表
// the setup function runs once when you press reset
// or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH
// is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by
// making the voltage LOW
delay(1000); // wait for a second
}
在这里,您可以看到 setup() 函数将 LED 的引脚配置为输出引脚,可以使 LED 开启或关闭。这与输入引脚不同,输入引脚会读取 HIGH、LOW 或者施加到引脚上的变化电压。
注意
以 // 开头的行和短语是注释,不会影响代码的执行。
loop() 函数包含了两个其他的 Arduino 函数。最简单的是 delay(),它会暂停程序执行指定的毫秒数(千分之一秒)。每次程序执行到 delay(1000) 这一行时,程序会停止并等待 1 秒钟,然后继续执行。
digitalWrite() 函数仅对先前配置为输出的引脚有效,它将输出电压设置为 HIGH 或 LOW。LOW 电压始终为 0 V(通常称为 地),而 HIGH 电压则取决于特定的电路板,但通常为 5 V 或 3.3 V。
总结来说,这个草图首先将 LED 的引脚配置为数字输出,然后点亮 LED,等待 1 秒,熄灭 LED,再等待 1 秒,重复这个过程,直到 Arduino 板被重置或断电。
配置您的板子和端口
在我们编译并上传草图到 Arduino 板之前,我们需要使用工具菜单告诉 Arduino IDE 我们使用的是哪种 Arduino 板。图 15 展示了如何通过选择 工具 ▸ 板 来选择 Arduino Uno。在这里,我们使用 Uno 作为示例,但请确保选择与您使用的板子匹配的选项。

图 15: 使用工具菜单选择连接的 Arduino 板
一些 Arduino 开发板提供额外的选项,可以用来指定可用内存的大小、运行速度或安装的处理器类型,但 Uno 开发板没有类似的选项。所有开发板都有端口选项,用来指定设备连接到哪个 USB 端口。当然,这取决于平台,因为 macOS、Windows 和 Linux 上的端口名称不同,但大多数现代的 Arduino 开发板能够传输它们的名称,并且这个名称应该会出现在端口菜单中,如图 16 所示。

图 16: 从端口菜单中选择正确的 Arduino 开发板
配置好开发板和端口后,最后一步是使用“上传”按钮准备(编译)并上传草图代码到连接的 Arduino 开发板。要执行此操作,点击工具栏上的右箭头按钮,或者选择 草图 ▸ 上传 菜单选项。你应该能够在草图代码下方的黑色区域看到编译器输出,该区域还显示了剩余的程序存储空间和全局变量空间。由于每个 Arduino 开发板为存储编译后的草图和全局变量分配的空间不同,请务必关注这些数字,以便跟踪芯片的使用情况。
虽然 Blink 草图不会向串口监视器发送任何调试信息,但许多其他草图使用串口监视器作为提供程序反馈的一种方式。一些草图甚至从串口监视器获取输入,并利用这些输入来影响程序的运行方式。通过这种方式,你可以让你的草图与计算机或任何可以连接到 USB 串口的设备进行交互。
现在你已经学会了使用 Arduino IDE 编译和上传代码的基本流程,让我们再简要介绍一下本书中使用的一些附加组件。
本书中的一些项目使用了 Arduino 附件来完成特定任务。例如,Adafruit Trinket 用于项目 2:桌面 UFO,而 Adafruit Lilypad 通常用于开发可穿戴设备,出现在项目 9:可穿戴定时护腕中。每个使用附加组件的项目都会解释如何设置和使用它。
没有内建 USB 连接的 Arduino 开发板
如前所述,一些与 Arduino 兼容的开发板省略了 USB 接口芯片,以节省成本或减少功耗,或者两者兼顾。像 Arduino Pro Mini 这样的流行开发板由 SparkFun 创建。Arduino Pro Mini(如图所示;左侧)需要一个独立的板子,FTDI Friend(如图所示;右侧)来提供与计算机的 USB 接口。这两块板子一起工作,提供一个低成本的 Arduino 开发板,并且有一个可拆卸(且可重复使用)的 USB 接口。

这些照片是根据电路板连接在一起时的排列方式对齐的。只需在 Arduino Pro Mini 的右侧焊接一些插针,这样它们就可以连接到 FTDI Friend 的插座上。使用 Arduino IDE 的 Boards 菜单选择Arduino Pro 或 Pro Mini。这样应该会启用板选项下方的 Processor 选项;请确保选择正确的处理器类型和速度。
推荐供应商
在本书中,每个项目都会列出少数几个在线商店,作为项目中所用元件的来源。尽管如此,每家商店都有其独特的产品,所以更多的来源总是更好!以下是服务于全球或地区市场的在线商店。
美国
Adafruit(纽约州; www.adafruit.com ) 这家电子商店有大量的 LED 产品,以及令人印象深刻的微控制器、扩展板和套件。
BGMicro(德克萨斯州; www.bgmicro.com ) 我们喜欢这家别具一格的商店中那些稀有和过时的零件。
Digi-Key(明尼苏达州; www.digikey.com ) 在这个庞大的在线商店中,你可以迷失在各种零件的海洋里。
Evil Mad Scientist(加利福尼亚州; www.evilmadscientist.com ) 套件制造商和元件销售商的杰出代表。店主 Lenore Edman 和 Windell H. Oskay 还共同编写了本书的 Project 1。
Jameco Electronics(加利福尼亚州; www.jameco.com ) 自 1974 年以来,Jameco 可能真的是你父亲的电子商店。它有一本很棒的纸质目录。
Mouser Electronics(德克萨斯州; www.mouser.com ) 如果你需要稀有传感器或成千上万的元件,可以到这个超级分销商那里查找。
SparkFun Electronics(科罗拉多州; www.sparkfun.com ) 由一位大学生创办的 SparkFun,已经发展成为一家在线销售套件和单独元件的零售商。
Tower Hobbies(伊利诺伊州; www.towerhobbies.com ) 位于香槟的 Tower Hobbies 是一家无线电遥控和无人机超级商店。
欧洲
Elextra(丹麦; www.elextra.dk ) 这个有趣的商店提供套件、工具以及比普通商店更多的电子产品选择。
Farnell/Newark element 14(英国; www.newark.com ) 总部位于利兹的 Farnell 在全球范围内销售电子元件。总部位于芝加哥的 Newark 是其姊妹公司。
Maplin(英国; www.maplin.co.uk ) 电子零售商 Maplin 在英国拥有超过 200 家门店,并且也提供在线销售。
Play Zone(瑞士; www.play-zone.ch ) 这个爱好电子网站,提供英语和德语版本,涵盖从建套件到树莓派以及各种单独元件。
RS Components(英国;uk.rs-online.com/web) 这家电子超级商店拥有超过五十万种产品。
亚洲
AliExpress(中国;www.aliexpress.com) 你无法列举出你可以在类似 eBay 的 AliExpress 上购买的所有疯狂商品。
DealExtreme(香港;www.dx.com) 所有你能想象的东西都有,且价格令人瞠目结舌——会有什么问题呢?
HobbyKing(香港;www.hobbyking.com) 这是一个拥有美国仓库的遥控和无人机超级商店。
Seeed Studio(深圳;www.seeedstudio.com) 不仅仅是一个在线商店,Seeed 还运营着商业孵化器 Seeed Propogate 以及原型制作商店 Seeed Fusion。
第二章:Lenore Edman 和 Windell Oskay 的四个简单项目
在本章中,你将完成四个简单的 LED 项目。

有一个原因使得 LED 项目成为许多电子爱好者的入门项目:它们既简单,又能发出光亮的效果。以下项目曾在 Evil Mad Scientist Laboratories 博客上发布(www.evilmadscientist.com/)。这些简单的项目将为你应对书中后面更为复杂的项目做准备。首先,我们将教你如何制作一个 LED 照亮的海胆壳,接着你将制作一个边缘发光的节日卡片、一个黑暗探测 LED 和电动折纸。
#1:LED 照亮的海胆
在一次假期的海滩商店里,我们发现了一些小巧的海胆壳,薄如蛋壳,轻盈异常。能做什么呢?当然是用 LED 将它们点亮!
海贝灯并不是什么新奇的东西,但通常是用大而重且色彩鲜艳的贝壳做的。相比之下,这些海胆壳较小且轻盈,照明效果突出了它们的自然美感。
获取零件
对于这个项目,你需要找到一些小型的海胆壳,或者其他类似的容器,要求壁薄到足够透明。理想的大小约为 4 英寸宽。
-
LED(例如,Evil Mad Scientist
emsl.us/743或 SparkFun P/N 12062) -
硬币电池 CR2032(SparkFun P/N 338)
-
小巧、轻盈的海胆壳
每个海胆壳底部都有一个足够大的孔,可以容纳一个相当大的 LED,尽管不一定能同时容纳电池。当壳体被点亮时,它们应该看起来像图 1-1 一样。

图 1-1: 不同颜色的 LED 构成了多种颜色的海胆。
制作它
首先,我们将 LED 与手表电池连接,这种组合被称为抛投灯,因为它们小巧且便宜,理论上你可以随意抛掷它们。虽然我们不会让你在这个项目中抛掷任何东西,但你会利用这些抛投灯来照亮海胆壳。
-
制作抛投灯。 选择任何颜色的 LED。长腿是正极,短腿是负极。只需将引脚连接到电池端子,将正极腿贴到电池的正极侧,负极腿贴到负极侧,就得到一个微小的光源,如图 1-2 所示。将引脚弯曲,使 LED 指向上方,远离电池。
![image]()
图 1-2: 将电池和 LED 结合在一起,轻松便捷地实现照明效果。
-
组装海胆。 将 LED 抛投灯放入壳底的孔中。如果电池不合适,只需将 LED 的头部穿过壳体,电池可以直接放在壳体下方。对于多个壳体和颜色,你可以重复此过程。
完成了!海胆已经制作完成并发出炫目的光芒,展示出精美的外壳结构。你的灯具应该能持续一到两周,具体取决于 LED 的颜色。
#2: 边缘发光圣诞卡
在这个项目中,你将使用透明塑料和简单的 LED 装配,制作自己的 LED 发光圣诞卡。图 1-3 展示了我们制作的一些卡片。我们使用的技巧通常被称为边缘发光,即将一个点亮的 LED 放置在雕刻好的亚克力边缘。这种方法可以使雕刻区域发出柔和的光芒,同时不露出可见的电线或其他硬件。

图 1-3: 为你的亲人制作 LED 卡片。
获取材料
你只需要一些基本的材料,就能制作出 LED 圣诞卡。
-
带透明镜头的 LED,最好是 3 毫米或矩形的(例如,
emsl.us/533或 SparkFun P/N 08285) -
透明塑料(大约 2.5 × 3 英寸,1/16 英寸厚)
-
电工胶带
-
CR2032 硬币电池(SparkFun P/N 338)
-
钢笔
-
纸张和卡纸
-
剪刀
-
美工刀
开始制作
要制作自己的圣诞卡,首先你需要一个设计。你将把这个设计雕刻到塑料上,然后 LED 从底边点亮它,光线反射到雕刻线条上,形成发光效果。你需要保持设计简洁(比如图 1-3 中的圣诞树和雪花设计),因为雕刻到塑料上的方法并不是最精确的绘图方式。
你将从一块大约 2.5 × 3 英寸(65 × 75 毫米)并且 1/16 英寸(1.6 毫米)厚的透明塑料开始。我们使用的是亚克力,但你也可以使用聚碳酸酯、聚丙烯或其他许多透明塑料。你可以从厚壁透明塑料容器中切割出一块,或者在五金店或爱好商店购买类似材料。我们的透明亚克力两面有保护蓝膜。
-
剪下一块塑料。 如果你的塑料片比 2.5 × 3 英寸大,你需要把它剪下来。这种材料不能用剪刀剪——它会裂开和碎裂——所以你需要用锋利的美工刀或箱切刀以及金属直尺进行打刻,然后沿着刻痕迅速折断。使用这种方法,可以相当快速地从大板材中切出合适尺寸的塑料片。图 1-4 展示了带保护膜的塑料。
![image]()
图 1-4: 剪下一块塑料,匹配你的卡片设计。
-
制作纸质模板。 在纸张上描绘出塑料片的尺寸。然后,在第一个矩形内部绘制第二个矩形(图 1-5),留出大约 0.5 英寸(13 毫米)的间隙。你的设计需要很好地适应内矩形,以确保最终设计在塑料上居中。
![image]()
图 1-5: 描绘塑料片,然后在其内部绘制矩形。
-
绘制设计并描摹。 当你的纸上图纸完成后,将其放在塑料片上,用雕刻刀沿着图纸轮廓描摹。
很明显,形状的酷炫程度会影响最终产品的效果。图 1-6 只是一个简单的树形图案——并不复杂。对于雪花图案,你可以打印并描摹一些真实的雪花图案。
![image]()
图 1-6: 在内矩形区域内绘制你的设计。
-
连接 LED 和电池。 这个项目使用了与“LED 照明海胆”项目中相同的经典 LED 投射方式。按照 “建造它” 中的说明,将 LED 直接连接到 CR2032 锂硬币电池的引脚上,详见第 27 页,但这次不要将引脚弯成直角。现在,当你将亮光 LED 放置在塑料片的边缘时(如图 1-7 所示),它将照亮你已刻划的区域。
-
用胶带封住边缘。 持续将 LED 灯固定在塑料片的底部边缘,以便光线能够进入刻线中。接下来,使用黑色电工胶带限制光线向其他方向泄漏。先放下一段胶带,粘性面朝上,然后将塑料片和 LED 固定在胶带的上半部分。接着,在顶部放上一段配套的胶带,紧密封住 LED,确保光线只向塑料片内部照射 (图 1-8)。
接着,用黑色胶带封住塑料板的另外三面,如图 1-9 所示。注意,胶带只需要覆盖塑料的边缘部分。完成这一过程后,单个 LED 将点亮刻在塑料上的设计,而不会让光线泄漏到其他地方。
![image]()
图 1-7: 从底部边缘照亮设计
![image]()
图 1-8: 用胶带封住 LED,确保没有光线泄漏
![image]()
图 1-9: 封住设计的边缘
-
准备纸卡。 接下来,你需要开始制作卡片本身。我们使用了 9 × 12 英寸的厚布里斯托纸卡,但其他厚的不透明纸也可以使用,尺寸并不是特别关键。将纸对折两次,制作出经典的贺卡形状,前后两层的大小大约为 4.5 × 6 英寸。
将完成的边缘发光塑料组件放在折叠卡片上,确保它适合,并确定你打算将其放置的位置。
接下来,你需要在卡片的前面切一个窗口,以便展示塑料设计。将步骤 2 中的内矩形从模板上剪下并在卡片的前面描摹轮廓。在切割之前先展开卡片,确保只切割前面的那一层。用雕刻刀沿着轮廓刻划,然后小心地用雕刻刀或剪刀将其剪出。你将把边缘发光的塑料组件固定在你刚切出的窗口后面。
![image]()
图 1-10: 剪切与设计匹配的矩形
-
组装卡片。 现在将塑料组件放入卡片中,使设计位于窗口中央,切割过的塑料面朝外。将其固定好,包括电池部分(见图 1-11)。
![image]()
图 1-11: 固定电池位置
使用这种设置,卡片将一直亮着,直到电池在一周左右耗尽。如果你是亲手送礼,这没问题,但如果是邮寄,就不太适用了。为此,你可以将其设置成直到接收者打开卡片时,LED 才会亮起。
-
插入拉条(可选)。 在粘贴电池之前,将一条纸条插入 LED 的一个引脚和电池之间,使纸条的一端露出来。这个纸条将切断电路,防止 LED 亮起。在纸条的末端写上Pull(拉)字样,并将电池固定好。当卡片的接收者拉起纸条时,LED 的引脚将再次接触电池,完成电路并点亮 LED。
进一步探索
另一个额外酷的技巧:使用两层颜色,堆叠独立的边缘光显示屏,一层使用绿色 LED,一层使用红色 LED。你可以在图 1-12 中看到一个例子,红色 LED 的塑料层位于绿色层的上方。
用相机拍摄并不容易,但红色的点非常清晰并漂浮在绿色的树木前面,这是由于第二层的原因。3D 效果真的非常棒。我们在红色层上制作这些点,是用图钉压入塑料而不是用刀片。卡片内部正如你所预期:两层塑料,每层底部都有一个 LED,电池周围用电工胶带封边以防止光泄漏。这实际上是一种非常古老的显示技术。堆叠足够多的层,你甚至可以制作一个侧光的数字显示时钟!

图 1-12: 将两层或更多层塑料叠加在一起,为设计添加多种颜色。
#3:光暗检测 LED
这里有一个常见问题:如何在黑暗时点亮 LED?你可以称其为“夜灯问题”,但它出现在许多熟悉的场景中——紧急灯、街灯、电脑键盘背光,等等。
解决这个问题有很多方法。传统的方法是使用一个CdS 光敏电阻,有时称为光电池或光依赖电阻(LDR)。光敏电阻非常可靠,且每个仅需大约 1 美元,但因为它们含有镉这种有毒重金属,而且其使用正受到越来越严格的管制,所以它们的使用逐渐减少。幸运的是,还有许多其他选择。
这个项目将向你展示如何使用光电晶体管设计自己的光暗检测 LED,见图 1-13。

图 1-13: 当灯光熄灭时,这个 LED 会亮起。
使用这个便宜的光控 LED 电路,你几乎可以做任何事情,但其中一个有趣的应用是制作 LED 抛物器,它能在白天自动关闭以节省电力。抛物器通常能持续工作长达两周,加入像这样的光敏开关可以显著延长它们的使用寿命。
获取零件
为了制作这个项目,你需要使用附录中描述的焊接工具。此外,你还需要使用以下电子元件,这些元件在图 1-14 中有所展示。
-
超亮 LED(例如,*
emsl.us/620* 或 *emsl.us/606*;或者 SparkFun P/N 528 或 10632) -
硬币电池 CR2032(SparkFun P/N 338)
-
LTR-4206E 光敏晶体管(*
emsl.us/437* 或 Mouser P/N 859-LTR-4206E) -
2N3904 晶体管(*
emsl.us/98* 或 SparkFun P/N 521) -
1 kΩ电阻(*
emsl.us/234* 或一个包含多种规格的套件,如 SparkFun P/N 10969)
最后三个部分总共花费大约 0.30 美元,批量购买时价格会更便宜。

图 1-14: 构建你的暗光探测 LED 所需的组件
LTR-4206E 是一种 3 毫米黑色封装的光敏晶体管。黑色封装能够阻挡可见光,因此该光敏晶体管只对红外光敏感——它能感应到阳光和白炽灯光,但不能感应到荧光灯或大多数放电灯,这意味着它可以被编程为只在夜晚开启。
如同之前的项目,你将首先制作一个 LED 抛物器。然后,加入光敏晶体管,并使用其输出信号控制晶体管,从而开启 LED。
工作原理
当光线照射到光敏晶体管时,它开始导电,电流可达大约 1.5 mA,这会将电阻两端的电压降低 1.5 V。这将关闭晶体管,从而关闭 LED。在黑暗中,光敏晶体管能通过 LED 导电约 15 mA,因此当 LED 关闭时,电路的电流消耗仅为原来的十分之一。
构建它
现在是时候开始构建了。你当然可以在面包板上搭建这个项目,但我们这里所演示的紧凑且可部署的构建方式更令人满意。
-
焊接电阻和晶体管。 首先准备好晶体管和电阻。2N3904 晶体管的引脚,从前方看,从左到右分别是发射极、基极和集电极。你需要按照图 1-15 所示,将电阻焊接在晶体管的基极和集电极之间。(如果你从未焊接过或需要一些指导,请参考附录。)将电阻的引脚保持与晶体管的引脚呈 90 度角焊接,然后剪掉基极(中间引脚)和集电极(右侧引脚)多余的电阻引脚。
![image]()
图 1-15: 光暗探测 LED 的电路图
-
连接光电晶体管。 接下来,添加光电晶体管,如图 1-16 所示。注意它有一个扁平的一面,就像 LED 一样。扁平侧的引脚是光电晶体管的集电极。将扁平侧的集电极焊接到晶体管的基极(中间引脚),同样是 90 度的角度。暂时将光电晶体管的另一引脚(发射极)保持未连接状态。
![image]()
图 1-16: 光电晶体管是图中上方中央的黑色小球
-
测试 LED。 对于这一步,你需要知道哪个 LED 腿是正极,哪个是负极。不幸的是,LED 的标记并不一致,因此检查极性的最佳方法是用锂硬币电池测试:将 LED 横跨电池的端子,两只腿分别放在两侧。如果第一次没有点亮,交换一下两腿的位置。当 LED 点亮时,注意接触的是哪个端子(+端子);这个就是正极腿(通常是较长的那根)。将 LED 的正极引脚焊接到晶体管的发射极(左侧引脚),该引脚没有连接任何东西。修剪掉焊点之后多余的 LED 引脚。将 LED 的负极引脚焊接到光电晶体管的发射极——即未扁平化的一侧引脚,该引脚现在还没有连接任何东西。不要修剪这个引脚。
到目前为止,只有两个引脚从组件下方伸出:一个连接到电阻器和晶体管的集电极(最右侧引脚),另一个连接到光电晶体管的发射极和 LED 的负极腿。要测试电路,将硬币电池夹在这两个端子之间,正极面接触电阻器。图 1-17 显示了在黑暗房间中的电路;其 LED 亮起了。

图 1-17: 黑暗触发了组装好的 LED 电路。
现在你有了一个微小的光暗探测灯!你可以通过将腿部固定在电池上,使它更加稳定。这个灯在门框顶部做一个不错的夜灯——当房间的灯关掉时,它会在天花板上投射出一个明亮的光点。
进一步展开
虽然这个小电路可以独立工作,但它也可以作为更大电路的一部分使用。当然,这是用光传感器控制 LED 最简单且最便宜的方法之一,因此你可以制作多个并将其应用于许多用途,例如将其与第一个项目中的海胆壳结合,用于制作海胆夜灯。
#4: 电动折纸
在图 1-18 中看到的那个小型 LED 照明立方体,远不止一个纸灯笼:它是一个透明的薄膜电子电路,将电池与 LED 连接,并且足够灵活,可以折叠成折纸盒。这些电路最酷的地方?你可以在家制作它们。
在本项目中,你将结合基本的 LED 抛光和纸艺,形式为传统的折纸气球,制作一个可以称为LED 折叠灯的物品。电路由铝箔电路组成,铝箔被熨贴到粘合纸上(如冰箱纸或照片粘贴纸),或用激光打印的图案。这种结构随后可以折叠以容纳 LED 和电池,从而完成电路。
注意
本项目的模板可在书籍资源中找到 (nostarch.com/LEDHandbook/)。

图 1-18: 这个 LED 灯笼使用了粘附在纸上的铝箔电路。
获取零件
收集以下零件和材料:
-
LED(例如,
emsl.us/369或 SparkFun P/N 12062) -
硬币电池 CR2032(SparkFun P/N 338)
-
折纸纸(我们使用的是标准的 10 英寸正方形)
-
铝箔
-
冰箱纸或照片粘贴纸(与折纸纸张大小相同)
制作它
设计像这样的三维电路的第一步是创建外壳,并查看各个组件的位置。之后,你将展开模型,绘制你想要连接的各个点之间的电路路径,然后继续进行。
-
折叠气球原型。 开始之前,首先折叠一个折纸气球。(如果需要指导,网上有成千上万的教程。)这个气球不是你最终使用的气球,但你将在其上绘制电路。不要给气球充气——保持它的最终折叠形状,因为你将把设计转移到一张冰箱纸上。
折纸气球具有一些对本项目有用的特点。它们在侧面有一个方便的小袋子,用于放置锂币电池。底部还有一个小孔,LED 灯将放在这里,所以请把电线引脚藏进与电池相对的折叠部分。图 1-19 展示了组件暂时放置在气球上的样子。
![image]()
图 1-19: 临时将组件放置在你的气球原型上。
-
展开气球。 在折纸气球还没有展开时,标记电池和 LED 端子的位置信息,然后将其展开。这就是你的电路板。此时,你应该已经标记了组件的位置,但尚未绘制它们之间的连接线。你可以在图 1-20 中看到展开后的气球。
![image]()
图 1-20: 展开气球,看看电路如何工作。
-
绘制电路。 接下来,你将添加电池与 LED 之间的电路线路(电路板电线或线路),如图 1-21 所示。绘制将正极 LED 引脚连接到电池正极,将负极 LED 引脚连接到电池负极的线路。你需要将这些线路从箔片中剪下来并粘贴到纸上。将纸艺与电子元件结合时要记住的一点是:如果电路线路能够覆盖 LED 引脚以保持良好的接触,这样是有帮助的,因此在线路的两端留点余量总是一个好主意。
在连接好所有线路后(可以这么说),你就得到了电路的布局。这里很简单——只有两条线路!这两块圆形焊盘分别接触电池的两端,两个角度焊盘则接触 LED 的两根引脚。
![image]()
图 1-21: 绘制线路
-
制作电路板。 下一步是实际制作电路板。我们称之为冷冻纸附着法,即将箔片线路粘贴到涂有塑料的纸上。将电路图铺在一块铝箔上(见图 1-22),然后用雕刻笔(木签或钝牙签效果很好)沿着图形描绘,留下一个凹陷的轮廓。
![image]()
图 1-22: 电路板开始组合。
-
剪裁并附加线路。 接下来,剪下你描绘的图案。当然,用剪刀就可以了。小心不要撕破箔片!图 1-23 展示了剪裁好的图案,准备剪裁。
![image]()
图 1-23: 描绘好的图案,准备剪裁
-
层压箔片。 预先将冷冻纸折叠成折纸气球形状,并与电路布局进行对比,确定铝箔片在冷冻纸上的位置。将箔片放置在冷冻纸的光面上,如图 1-24 所示。为了防止熨斗粘到胶粘剂上,可以在冷冻纸上放一大张羊皮纸。将电路线路定位好后,使用设置为华氏 330 度的熨斗将箔片层压到纸上。
![image]()
图 1-24: 将箔片放置在纸张的光面上。
我们使用了小型爱好铁将箔片熔接到不同的纸张上,但普通的熨斗同样有效。干式装裱胶不需要太高的温度,但熨斗必须设置为高温,以熔化冷冻纸的塑料。
我们尝试了涂蜡纸,但它对铝箔不够粘,而且我们甚至试图将铜叶应用到蜡纸上,但它太脆弱,折叠时线路断裂。这种组合可能在不需要折叠的应用中能很好地工作:它非常美观,但在折纸中完全不可靠。图 1-25 展示了折叠时的线路。
![image]()
图 1-25: 熨烫过程中折叠气球
-
完成气球。 一旦箔纸粘附到纸上,再将气球重新折叠,使线路在外侧,从底部的孔吹气给气球充气,然后测试气球。将组件放入正确的位置,气球应该会亮起。如果没有,试着将电池反转。如果它仍然不亮,确保 LED 的引脚与线路接触。它是通过摩擦固定的,其强度取决于折纸的紧密度。
提示
你插反了 LED 并不会损坏它,所以这比实际去跟踪极性是一个更好的方法。LED 折叠面自然会坐落在最重的部分——电池上,LED 会投射到气球的一侧。电池的重量有助于保持电路连接。
当你把一切弄好后,它应该看起来像图 1-26。

图 1-26: 完成的气球
深入探讨:直接碳粉方法
我们的最后一次突破是创造了一个 PDF 图案来打印出来。我们发现你可以将箔纸直接熔合到激光打印机的碳粉上。这只适用于激光打印机,不适用于喷墨打印机。你可以打印出图案,并将箔纸直接熨烫到纸上——加热的碳粉会附着在箔纸上。
这种方法有一个注意事项。虽然箔纸能很好地粘附在碳粉上,但它的强度不足以让你直接将一整块箔纸熨烫上去然后撕下,只让它粘附在有碳粉的地方,因此你仍然需要至少粗略地剪下箔纸形状。打印出图案后,将其放置在铝箔上,描绘轮廓,并剪下箔纸块。
小心地将箔纸放在图案上,用非常高的温度熨烫。一定要用烘焙纸覆盖你的作品,否则你会在熨斗上沾上碳粉。当箔纸粘附到碳粉上并且冷却后,剪下气球的方形部分,准备进行折叠。
温柔地折叠,尽量减少对线路的干扰。可能在多次折叠的区域线路会松动,但应该足够牢固以便组装。给气球充气,安装电池和 LED,然后欣赏它的光辉。如前所述,如果遇到问题,试着将电池反转,确保 LED 的引脚与箔纸接触。
总结
在本章中,你了解了最简单的 LED 项目——投掷灯(throwie),并将其应用于多个(非投掷的!)项目中。你还学到了一些更具挑战性的技巧,这些技巧会对你有很大帮助,比如制作自己的电路线路。希望这些简单的项目激发了你对未来项目的好奇心!
第三章:James Floyd Kelly 制作的桌面 UFO
在这个项目中,你将制作一个可以发光的装饰性 UFO。

我的桌面总是堆满了几件极客小饰品——这里有个手办,那里有几张旧的星球大战收藏卡,有时还会有一个没有实际用途的新的小玩意,只是为了发出声音。有些我会保留在桌面上,以便写作时能获得灵感,其他的则只是为我的日常生活增添了一些色彩和趣味。如果你的桌面缺少这些无用的小饰品,那就用你自己的桌面 UFO 版本来装点它吧。
桌面 UFO 由 LED 灯提供照明,发出一种迷人的神秘光芒。它有一个开关来节省电力,占用的空间非常小。它由 3D 打印组件和一些你可能在家里找到的物品,以及一些电子组件组成。包括 3D 打印时间,整个项目即使是初学者也可以在六小时内完成。
如果你没有 3D 打印机,也不用担心。仔细观察桌面 UFO,你会发现一些非常基本的形状。任何类型的塑料飞碟都可以替代 3D 打印版,着陆垫可以用塑料或木材或任何可以钻孔的小平物体制作。如果有的话,可以看看当地的图书馆和创客空间是否提供可以使用的 3D 打印机。
获取零件
这里是你需要制作桌面 UFO 的工具和组件列表。这个项目需要一些焊接工作;如果你需要指导,请参阅附录。
组件
-
Adafruit NeoPixel 环,24 × 5050 RGB LED 带集成驱动器(Adafruit P/N 1586)
-
Adafruit Trinket(Adafruit P/N 1501)和 A 到 MicroB USB 电缆(Adafruit P/N 898)
-
电池座,3 × AAA,带开关和两针 JST(Adafruit P/N 727)
-
40 个针脚(Adafruit P/N 3002)
-
5 英寸或 7 英寸的母对母跳线
-
22 号固体电线(Adafruit P/N 1311)
-
具有至少 1.5 厘米垂直空间的塑料盖
-
三根可弯曲的塑料吸管
-
(可选)小型塑料口香糖机玩具外壳盖
-
喷漆
工具
-
3D 打印机或 3D 打印机的使用权限
-
PLA 或 ABS 耗材(取决于 3D 打印机)
-
钻床、手钻和/或旋转工具
-
焊接铁
-
焊锡
-
电线剪刀和钳子
-
热熔胶枪
-
电工胶带
-
油漆胶带
介绍 NEOPIXEL
在开发 UFO 的创意时,我发现 Adafruit NeoPixel 组件,如图 2-1 所示,提供了一个很棒的特殊效果。NeoPixel 是一个 LED 条或环,你可以编程使其按模式发光,形成一个在飞碟下方旋转发光的环。

图 2-1: Adafruit NeoPixel
NeoPixel 将被放置在桌面 UFO 下面,电线将穿过一根或两根我们用饮料吸管做的脚。控制 NeoPixel 上灯光的电池盒和 Trinket 控制器将位于一个从塑料容器回收的圆形塑料盖子下方。UFO 的主体和着陆垫将在 CAD 应用程序(Tinkercad)中创建,并通过 3D 打印机打印出来。让我们开始吧!
构建它
首先我们将设置 Trinket,如图 2-2 所示。这是整个项目的控制板,它将告诉 NeoPixel 上的 LED 如何工作。接着,我们将为 NeoPixel 准备电池,并将所有组件放入最后制作的 UFO 主体中。

图 2-2: Trinket 板
当一切建成后,我们将上传一个短程序,称为草图,它告诉 Trinket 如何触发 NeoPixel 环中各种 LED 的图案。当电压被提供时,LED 将亮起。NeoPixel 为每个 LED 提供一个“地址”,因此草图可以指示 Trinket 在任何时刻向哪些 LED 提供电压。
准备 Trinket
在运行告诉 NeoPixel LED 按照特定顺序亮起的草图之前,您需要完成以下步骤以准备您的 Trinket:
-
在 Trinket 上安装软件。 使用 A 到 MicroB 的 USB 电缆将 Trinket 连接到桌面计算机或笔记本电脑。(USB 电缆有许多种类型;Trinket 使用 MicroB 类型。如果您快速搜索 USB 电缆类型,您可以找到更多如何识别正确电缆的细节。)
Mac 和 Linux 电脑无需安装额外的驱动程序,但如果您使用的是 Windows,您需要下载驱动程序。请访问
nostarch.com/LEDHandbook/,然后按照链接获取项目 2 的驱动程序。 -
下载adafruit_drivers.exe文件。 双击运行adafruit_drivers.exe安装文件(文件名也将包含最新的版本号),然后按照提示进行操作,完成所有驱动程序的安装。
您还需要安装 Arduino IDE。请参见第 15 页上的“Arduino 和 Arduino IDE 入门”部分了解详细步骤。如果您在 IDE 或驱动程序安装过程中遇到问题,以下两个链接会很有帮助:
learn.adafruit.com/introducing-trinket/starting-the-bootloader和learn.adafruit.com/introducing-trinket/setting-up-with-arduino-ide。您需要使用 Arduino IDE 以便将草图上传到 Trinket。
-
测试 Trinket。 现在,我们将设置 Arduino IDE 与 Trinket 的通信,并使用 Arduino IDE 中安装的一个简单示例程序来测试 Trinket。确保 Trinket 连接到电脑并打开 Arduino IDE。进入工具菜单,选择板子,在列表中选择Adafruit Trinket 8MHz作为板类型。在工具菜单中,点击程序员,选择USBtinyISP。按下 Trinket 上的红色按钮,准备上传示例程序。进入文件 ▸ 示例 ▸ 01.Basics ▸ Blink。一个新的 IDE 界面将打开并显示 Blink 示例程序,如图 2-3 所示。
![image]()
图 2-3: Arduino IDE 中的 Blink 示例程序
当 Trinket 上的红色 LED 闪烁时,点击 Arduino IDE 工具栏上的上传按钮(
)上传 Blink 示例程序。我们稍后会上传本项目的示例程序,但现在我们只是在检查我们的设置是否正常。Trinket 上的红色 LED 应反复闪烁。这表示它正在工作!如果你没有看到 LED 闪烁,请尝试重新上传示例程序,并确保 Trinket 完全连接到电脑。
-
上传 NeoPixel 示例程序。 我们控制 NeoPixel 的代码基于 Adafruit 的一个示例程序(
learn.adafruit.com/kaleidoscope-eyes-neopixel-led-goggles-trinket-gemma/software),并做了一个小的修改。在原始代码的这一行:for(i=0; i<16; i++) {我们将 16 改为 24,因此该行代码应为:
for(i=0; i<24; i++) {定制的示例程序UFO.ino可以在本书的资源中找到,链接为*
nostarch.com/LEDHandbook/*。下载文件并保存。你还需要将 NeoPixel 库保存到你的库文件夹中。这个库也可以在本书的资源中找到。通过在 Arduino IDE 中选择文件 ▸ 打开并找到文件,上传UFO.ino。这段代码将使 NeoPixel 显示多个随机动画。如果你擅长编程,可以修改代码制作任何类型的动画。
注意
希望编辑代码的程序员可以使用十六进制代码 0xff0000 表示红色, 0x0000ff 表示蓝色, 0x00ff00 表示绿色。
上传了 Adafruit NeoPixel 示例程序到 Trinket 之后,就可以开始添加接线了。
接线电子元件
接下来,是时候连接电路并进行测试,然后再设计 UFO 外壳。
注意
有关焊接说明,请参阅附录。
-
焊接引脚。 Trinket 是未组装的,需要进行一些焊接。Trinket 中附带有可以拆分并焊接到 Trinket 上的引脚。
对于本项目,我们将在 Trinket 上使用以下位置:
-
BAT
-
5V
-
0
-
GND
将引脚焊接到 Trinket 的这些位置。你可能还想焊接更多的引脚,如图 2-4 所示。如果你以后想为 Trinket 添加更多功能,这样做可以避免再次焊接。
注意
作为使用引脚的替代方法,你可以将四根 8 英寸的导线直接焊接到 Trinket 上标有 BAT、5V、#0 和 GND 的小铜质孔上。
![image]()
图 2-4: 将引脚焊接到 Trinket 上。
-
-
焊接导线到 NeoPixel。 接下来,将导线焊接到 NeoPixel 上的以下位置:
-
PWR +5V(有两个引脚,任意一个都可以使用)
-
GND(有两个引脚,任意一个都可以使用)
-
数据输入
你可以使用三个引脚,但我发现使用三根 8 英寸的导线效果最好,如图 2-5 所示。请注意,导线是从 LED 侧插入孔内,然后直接焊接到 NeoPixel 背面的铜环上(黑色的一面)。一般约定使用红色导线连接电源,黑色导线连接 GND(地)。
![image]()
图 2-5: 将导线焊接到 NeoPixel 环上。
注意
如果你剪掉两个母跳线的末端并将它们焊接到电池盒的红黑导线上以延长这些导线,这一步将变得更容易。
-
-
焊接插头。 接下来,拿起电池盒,剪掉末端的白色插头,并剥去红黑两根线末端大约 1/4 英寸的绝缘层。
红线将为 Trinket 提供电源,我们稍后会将其连接到 BAT 引脚。黑线不会直接连接到 Trinket;相反,NeoPixel 上的 GND 引脚和电池盒的黑线必须共享 Trinket 上的 GND 引脚。为实现这一点,请拿出之前放置的三个引脚,用焊锡将它们一侧的所有引脚焊接,以创建一个共同连接点,您可以将三根导线连接到此处,如图 2-6 所示。
![image]()
图 2-6: 使用引脚创建一个小的共享连接。
-
连接各个部件。 一旦所有引脚都准备好,使用在第 2 步中焊接的导线或指定位置的母跳线(见图 2-7)进行以下连接:
-
将 NeoPixel 的数据输入连接到 Trinket 上的#0 引脚
-
将 NeoPixel 的 PWR +5V 连接到 Trinket 上的 5V 引脚
-
将 NeoPixel 的 GND 连接到三个公共连接引脚中的一个
-
将电池盒的红线连接到 Trinket 上的 BAT 引脚
-
将电池盒的黑线连接到三个公共连接引脚中的一个
-
将 Trinket 上的 GND 通过母跳线连接到三个公共连接引脚中的一个
如果你有热缩管,可以将其套在焊接点上;如果没有,普通的电工胶带也可以。
-

图 2-7: 所有组件接线完成,准备测试
一旦所有连接完成,将电池放入电池盒并将开关拨到“开”位置。如果 NeoPixel 草图已正确加载到 Trinket,并且接线正确,你将看到 NeoPixel 上显示的随机动画和颜色。
故障排除
如果你没有看到任何动画,首先检查所有接线连接。小的三头常用连接器经常是问题所在,所以确保所有电线都有良好的连接。
如果接线没问题,将 Trinket 连接到你的电脑,再次上传草图;上传未来的草图时,你无需断开所有电线。你也可以重新上传 Blink 草图,并用它来测试 Trinket 是否正常工作。
一旦你看到 NeoPixel 显示出色彩斑斓的动画,就可以开始制作 UFO 机身组件了。
创建 UFO 机身和着陆垫
创建自定义的 UFO 机身可能需要一些时间,因此我已经将我用来制作 UFO 机身和着陆垫的 3D 打印文件与本书的资源一起提供在* nostarch.com/LEDHandbook/*。如果你熟悉 CAD 软件,可以轻松修改这些文件或创建自己的设计。
UFO 机身作为一个整体打印。它的底部是空心的,这里将放置 NeoPixel 环。机身上还会有三个孔,三个吸管将被插入这些孔中,作为支撑腿。
UFO 机身是在 Tinkercad 中创建的(* www.tinkercad.com*),如图 2-8 所示。它基于从 NeoPixel 环、吸管和底座的直径所测得的尺寸。我还测量了塑料圆顶的尺寸,以便在 UFO 机身上为其预留适当的空间。尺寸如下:
NeoPixel 外径 6.5 厘米,内径 5.3 厘米
吸管 外径 0.5 厘米
塑料圆顶 外径 2.9 厘米
底座 直径 12 厘米

图 2-8: Tinkercad 中的 UFO 机身设计
项目的基础仅仅是一个大塑料容器的圆形盖子。你需要确保盖子至少有 1.5 厘米高,并且足够大,可以将电池盒放在下面,而不会使整个结构摇晃。记住,电线将从底部插入,通过吸管隐藏在视线之外。
我们还需要三个小型着陆垫,中间有孔,用于将 Trinket 和电池盒的电线通过吸管引入 UFO 机身。图 2-9 展示了着陆垫的最终设计,这些着陆垫也可以使用 3D 打印机制作。

图 2-9: 着陆垫的设计
图 2-10 展示了最终打印的 UFO 机身,准备组装(并且稍后进行上色)。

图 2-10: 3D 打印的飞碟机身
在电子组件准备好,飞碟机身、着陆垫和底座都收集齐全之后,只有几个最后的步骤需要完成,你的飞碟就可以启动了。
组装它
我们将分阶段组装桌面飞碟。我建议在开始组装之前,先阅读整个部分,这样你就能了解整个过程和各个部件如何配合。
-
安装电池盒。 在飞碟底部(塑料盖)钻一个 3/8 英寸的孔,以便电池盒的开关可以访问。你可以选择自己喜欢的位置,但我选择在底座的边缘附近钻孔,如图 2-11 所示。
![image]()
图 2-11: 用于访问开关的孔
将电池盒放置在一个可以更换电池的位置。在粘合之前,确保电池盒的开关与钻好的孔对齐。将少量热熔胶涂抹在电池盒的背面,并将其固定在底座的底部。图 2-12 显示了电池盒已粘贴到位。
![image]()
图 2-12: 将电池盒用热熔胶粘到底座底部。
等胶水干透后,将底座翻过来,确保你可以通过钻孔移动开关,如图 2-13 所示。
![image]()
图 2-13: 应该能访问开关。
-
安装 NeoPixel。 接下来,使用两小块热熔胶将 NeoPixel 固定在飞碟机身的底部。图 2-14 显示了我如何在 NeoPixel 的两侧使用热熔胶;如果在将其放入机身之前让热熔胶稍微冷却几秒钟,它不会损坏 NeoPixel,并且可以帮助你将其中心对准飞碟机身。
![image]()
图 2-14: 用热熔胶将 NeoPixel 环固定在飞碟机身下方。
使用蓝色油漆胶带将三根电线固定在机身边缘。你还应使用小块胶带标记 NeoPixel 的每根电线(GND、PWR +5V 和数据输入)。
-
准备着陆垫。 在每根吸管的可弯曲部分周围涂上一些热熔胶,并将短而灵活的末端插入每个着陆垫,如图 2-15 所示。不要把吸管插入孔里太深;只需插入足够让胶水把吸管固定在着陆垫上的长度即可。每个着陆垫上方应该有一点吸管的可弯曲部分可见。
![image]()
图 2-15: 用热熔胶将每根吸管的柔性部分粘到着陆垫上。
完成将柔性端粘入着陆垫后,从每根吸管的较长部分剪下约 3 英寸;你可以在组装完 UFO 后再微调长度,但 3 英寸或更多的长度应该足够你在平衡飞碟与支脚时进行实验。
-
固定 Trinket 并为着陆垫钻孔。 Trinket 需要固定在底座下面;你可以使用画家胶带暂时将其固定,直到桌面 UFO 完成,然后用热熔胶或更强的胶带将其固定。
图 2-16 显示了我已经固定好 Trinket,并将电线整理到接近我要为着陆垫钻孔的位置。
你只需要在一个着陆垫下方钻孔。这个孔也可以用 3/8 英寸的钻头来钻(而且你可以在钻之前描述的开关孔时同时钻这个孔)。柔性吸管使你可以弯曲支脚,因此不必精确地确定钻孔位置,但尽量想象一个等边三角形,着陆垫将在 UFO 机体下方粘贴,并在距离电池盒开关最远的地方钻孔。
![image]()
图 2-16: Trinket 已固定好,电线被捆绑在一起。
你需要断开一些电线,以便通过吸管;图 2-17 显示了一个着陆垫的孔和从 Trinket 拉出的电线。
![image]()
图 2-17: 着陆垫孔和 Trinket 电线
-
将 Trinket 的电线连接到 NeoPixel。 使用你制作的着陆垫和吸管的一根支脚,插入 Trinket 的三根电线,使电线末端从吸管穿出来。如果吸管太长,修剪它,直到三根电线的末端可以方便地连接到 NeoPixel 的电线,如 图 2-18 所示。
![image]()
图 2-18: Trinket 电线连接到 NeoPixel 电线
记得,将 Trinket 的 5V 电线连接到 NeoPixel 的 PWR +5V 电线。(在照片中,这根电线是红色的,但你的电线颜色可能不同。)Trinket 的 GND 电线连接到 NeoPixel 的 GND 电线,Trinket 的 #0 电线连接到 NeoPixel 的数据输入电线。
所有电线连接好后,翻转开关,测试 NeoPixel 是否仍然显示动画。如果没有,重新检查所有连接是否符合之前的说明,并返回查看 “故障排除” 部分,参见 第 55 页。
-
粘贴着陆垫。 在每个着陆垫的底部放一点热熔胶;你可能需要从吸管上修剪掉更多的塑料,以便让垫子平稳地贴合在底座上。图 2-19 显示了三个着陆垫都已经粘到底座上的情况。
你可以利用吸管的柔性部分调整着陆垫的角度。调整着陆垫的角度,让 UFO 的机身能够稳稳地落在三只脚上。把透明圆顶放到顶部,打开开关。希望你能看到 UFO 底部透出的漂亮光芒!
![image]()
图 2-19: 用热熔胶将三个着陆垫固定在底座上。
如果你对动画效果满意,可以使用一些额外的热熔胶将 UFO 机身固定在支腿上;翻转底座和支腿时要小心,最好有人帮忙确保支腿粘牢。使用胶带或涂上一点热熔胶,把 UFO 机身底部暴露的线缆藏起来。
用一些油漆(我推荐使用银色给 UFO 机身上色),最终你将得到一个很酷的桌面雕塑。
进一步提升
这个 UFO 可以轻松修改。你可以添加一些武器,或者改变形状让它看起来更具威胁性。你还可以将 NeoPixel 替换成 Adafruit 的其他特色 LED——有很多种变化,你很可能会找到吸引眼球的设计。
以下是一些其他的想法,可以用来升级桌面 UFO:
-
在透明圆顶下方添加一个脉冲 LED
-
添加随机音效
-
在 UFO 下方放一个玩具奶牛小雕像
总结
有很多方法可以装饰桌面 UFO,这确实是一个很好的项目,能够教年轻学生一些关于电学、编程以及原型设计的基础知识。最终的 UFO 不需要完美;这款 UFO 有些瑕疵,但它能正常工作并且看起来很酷——对我来说,这就足够了!
第四章:约翰·贝奇塔尔的《作弊者的掷骰器》
在这个项目中,你将构建一个带有小惊喜的数字掷骰器。

你是否因为玩太多龙与地下城或其他桌面角色扮演游戏而患上了“多面骰肘”?(我说的就是那些有许多不同形状的骰子。玩家扔这些骰子太多次可能会拉伤韧带!)或者你只是想享受用电子方式生成骰子结果的便捷?无论哪种情况,这个掷骰器都能为你提供解决方案,甚至更多。
你可以在标准的 20 面 D&D 骰子和两颗 10 面骰子之间切换,适用于《战锤奇幻角色扮演》和其他系统,虽然我会教你如何将其定制成任何两位数的组合。然而,这不仅仅是一个普通的掷骰器:内置的作弊功能使它与众不同。我会教你如何在不让任何不知情的游戏伙伴察觉的情况下,利用磁铁、传感器和一些巧妙的手法,触发高掷或低掷骰子的结果。
我将项目外壳做成了一个中世纪城堡的形状,使用激光切割木材制作。本章的最后部分将进一步讨论我的外壳设计理念以及如何制作你自己的外壳。
获取部件
获取以下部件来构建你的掷骰器。我大多数部件是从 Adafruit 和 SparkFun 订购的。
组件
注意
请参见 “开始使用 Arduino 和 Arduino IDE” 章节中的 第 15 页,了解设置说明。
-
Arduino Uno(Adafruit P/N 50 或 SparkFun P/N 11021)
-
USB A-B 数据线(Adafruit P/N 62)
-
两个 8 × 8 LED 矩阵,带 I²C 背包(Adafruit P/N 872)
-
两个簧片开关(SparkFun P/N 8642)
-
大型按钮(例如,SparkFun P/N 9336)
-
双投掷开关(Adafruit P/N 805)
-
墙插式电源适配器或 9V 电池夹(Adafruit P/N 63 或 Adafruit P/N 80)
-
蜂鸣器(Adafruit P/N 1739)
-
10 kΩ电阻(SparkFun P/N 10969 是一个不错的多件套)
-
足够强大的磁铁,用来可靠地触发传感器(例如,Adafruit P/N 9)
-
(可选)面包板(SparkFun P/N 12002)
注意
为项目供电,可以选择 9V 墙插式电源适配器(如 Adafruit P/N 63)或 9V 插头适配器(如 Adafruit P/N 80),然后插入 Arduino 上的电源插口。
工具
-
激光切割机或锯子(如曲线锯或带锯)
-
焊接铁
-
焊锡
-
电线剪和钳子
-
电线
-
热熔胶枪
-
木工胶水
-
喷漆
介绍 LED 矩阵
我们使用 8 × 8 LED 矩阵来显示骰子投掷的结果。LED 矩阵的每个像素都是独立的,你可以选择性地触发它们,点亮或调暗每个 LED 来形成图案。最简单的方式是将每个像素的状态存储在数组中。例如,图 3-1 展示了一个选择性点亮的 LED 数组,形成了一个笑脸。

图 3-1: 使用数组存储笑脸图案。
你可以使用 Arduino 上的代码控制 LED 矩阵。Arduino 草图查看数组以查看每个 LED 的状态,在每次草图循环时点亮或关闭它们。
以下代码片段可以让你了解它是如何工作的:
smile_bmp[] =
{ B00111100,
B01000010,
B10100101,
B10000001,
B10100101,
B10011001,
B01000010,
B00111100 },
每一行代表矩阵上的一行,每个数字代表一个 LED。当 LED 的值设置为 1 时,它会亮起;当设置为 0 时,它会熄灭。你可以用这种方法设计任何你想要的图形。
然而,每次为每个设计手动输入这些内容可能会很繁琐,因此有一个方便的数据库,其中包含由 Arduino 库控制的矩阵形状,这些形状用于本项目中的矩阵。该库存储了绘制字母和数字的函数,以及基础形状,如方形和圆形,因此你不需要从头开始设计这些形状。在第 71 页的 “代码实现” 中,我将解释草图如何与库交互来绘制这些默认形状。
注意
如果你需要焊接说明,请参见附录。
构建它
按照以下步骤构建一个骰子滚动器,可以秘密地执行你的命令:
-
将矩阵焊接到它们的板子上。 矩阵配有被称为 背包 的迷你控制板,这些控制板通过仅用少数几根电线来管理 64 个 LED 的复杂性。你需要将这些背包焊接到矩阵上:将矩阵添加到背包上,IC(集成电路,也称为 微芯片)位于底部,然后将引脚焊接到孔中。最终效果应如下所示:图 3-2。矩阵没有上下之分,只要你将它添加到板子的正确一面即可。如果你需要更多指导,请参考该产品(P/N 872)在
www.adafruit.com/上的页面。![image]()
图 3-2: 焊接一个或两个跳线来更改矩阵的 I²C 地址。
-
焊接引脚或电线。 有四个引脚将矩阵与项目的其余部分连接。如果你计划将矩阵与面包板一起使用,请焊接随附的头引脚。如果你打算使用电线代替,引脚可以不焊接。
-
焊接板引脚 A1。 特别重要的是两个 A0 和 A1 焊盘,见于图 3-2,它们允许你通过选择性地焊接焊盘来将最多四个矩阵串联在一起。这被称为“更改 I²C 地址”。如果不焊接任何焊盘,则该矩阵的 I²C 地址默认为 0x70。焊接 A0 将地址设置为 0x71,焊接 A1 将地址设置为 0x72,焊接 A0 和 A1 两个焊盘则将地址设置为 0x73。为每个矩阵分配独立的地址,可以让我们在共享电线的情况下与某个矩阵通信,而不会干扰其他矩阵。你只需要在一个板子上的引脚上加焊,因此请在引脚 A1 上加焊。
-
连接矩阵到 Arduino。 将矩阵放置在面包板上,并分别将电源和接地轨道连接到 5V 和 GND,然后将面包板两侧的电源轨道连接,如图 3-3 所示。将第一个矩阵的电源和接地引脚分别连接到板上的电源和接地引脚,然后连接两个矩阵的电源和接地引脚,使它们都能获得电源。还需要连接数据线和时钟线。将 Arduino 的 A4 和 A5 引脚分别连接到第一个背包的 D 和 C 引脚,另外用一对电线将第一个矩阵的 D 和 C 引脚连接到第二个矩阵的 D 和 C 引脚。在图 3-3 中,数据线和时钟线分别是黄色和绿色的。
![image]()
图 3-3: 连接矩阵。
根据你的项目需求,你可能需要用电线连接矩阵,而不是将它们插入面包板,以便它们能适配。如果是这种情况,仍然可以像图 3-3 所示那样连接矩阵。
-
连接双刀开关。 接下来,按照图 3-4 所示连接双刀开关,中间的引线连接到 5V(粉色线),左侧和右侧的引线分别连接到 Arduino 的数字引脚 10 和 11(棕色线)。同时,将开关的左右引线通过 10 kΩ电阻接地,如图 3-4 所示。这种开关将决定是使用 D&D d20 模式还是 Warhammer d100 模式:Arduino 可以通过扫描 10 号和 11 号引脚来检查开关的位置。
![image]()
图 3-4: 添加双刀开关
-
连接簧片开关。 接下来是连接簧片开关。如图 3-5 所示,将开关连接到 Arduino 的 5 号和 6 号引脚(紫色线),另一个引线连接到地(灰色线)。
![image]()
图 3-5: 簧片开关告诉 Arduino 何时有磁铁靠近。
-
添加重置按钮。 重置按钮并不是用来在出错时重新开始的;它实际上是你的掷骰子按钮。项目软件规定骰子掷一次然后停止,你必须断电或重置 Arduino 才能重新掷骰子。图 3-6 显示了按钮的安装位置。将一个引线连接到 Arduino 电源总线上的 Reset 引脚(橙色线),另一个引线连接到 GND(粉色线),根据需要将电线焊接到按钮的引脚上。当按钮被按下时,Arduino 会重新启动并自动重新运行骰子滚动程序。
![image]()
图 3-6: 添加一个按钮来重置 Arduino
-
安装蜂鸣器。蜂鸣器完成了整个项目。它会发出声音来表示骰子投掷已完成。我在零件列表中包含的蜂鸣器具有适合面包板的引线,并且如图 3-7 所示进行连接:将正极引线连接到 Arduino 的 9 号引脚,负极引线连接到 GND。
![image]()
图 3-7:蜂鸣器接线
现在是时候添加代码了!
编写代码
现在电子组件已经组装好,是时候通过将代码上传到 Arduino 来测试项目了。
LEDBackpack 库在此脚本中完成了大部分繁重工作。背包的库包含完整字母表的代码,并且可以绘制诸如线条、圆形和方形等形状。你需要从 Adafruit 产品页面下载此库(* learn.adafruit.com/adafruit-led-backpack/0-8-8x8-matrix *),并将其保存到你的 Arduino 库文件夹中,才能使用它。如果你想了解更多,还可以访问该页面,里面有教程和大量信息。
项目的代码也包含在本书的资源中,所以现在打开 Arduino IDE 并让我们逐节查看代码。
代码的第一部分包含对示例中使用的三个库的引用。
#include <Wire.h>
#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"
接下来,背包正式初始化:
Adafruit_8x8matrix matrix1 = Adafruit_8x8matrix();
Adafruit_8x8matrix matrix2 = Adafruit_8x8matrix();
我们将背包命名为matrix1和matrix2。然后我们启用串口通信,以便进行调试:
void setup() {
Serial.begin(9600);
这使得我们可以与串口监视器进行通信。接下来,我们初始化一些引脚:
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(9, OUTPUT);
pinMode(10, INPUT);
pinMode(11, INPUT);
与双投掷开关、蜂鸣器和簧片开关交互的引脚已初始化。在后一种情况下,已初始化引脚以使用 Arduino 的内置电阻器,确保不会出现误触发作弊模式的情况。
这一行初始化随机数:
randomSeed(analogRead(0));
通过读取 A0 引脚的值,我们初始化将用作骰子投掷的随机数。接下来,我们需要启动矩阵:
matrix1.begin(0x70); // the default
matrix2.begin(0x72); // with A1 soldered
matrix1.clear();
matrix2.clear();
这让 Arduino 知道启动矩阵,并确保所有 LED 从关闭状态开始。这是开关的引脚声明:
int reedLow = 5;
int reedHigh = 6;
int switch1 = 10;
int switch2 = 11;
记住我们有两种不同类型骰子的设置。这是 d100 骰子的数字生成功能:
// switch selection roll d100
if (digitalRead(switch1) == HIGH) {
int tensDigit = random(0, 10);
int onesDigit = random(0, 10);
Serial.print(tensDigit);
Serial.println(onesDigit);
Serial.println();
我们将使用投掷开关在 d100 模式和 D&D 骰子模式之间切换。在此模式下,如果开关设置为 d100,Arduino 将投掷两个随机数,每个数值在 0 到 9 之间。然后它将这些数字打印到串口监视器,但尚未打印到矩阵上。
接着,我们需要监听簧片开关,看看它们是否被磁铁触发,通过两个if语句来实现——这就是我们的作弊方式。
if (digitalRead(reedLow) == LOW) {
tensDigit = 0;
onesDigit = 1;
}
if (digitalRead(reedHigh) == LOW) {
tensDigit = 0;
onesDigit = 0;
}
如果簧片开关被触发,产生的随机值将被一个最大值或最小值所替代,具体取决于触发了哪个簧片开关。两个数字将被写入matrix1和matrix2:
// write result
matrix1.setTextSize(1);
matrix1.setTextWrap(true);
matrix1.setTextColor(LED_ON);
matrix1.print(tensDigit);
matrix1.writeDisplay();
matrix2.setTextSize(1);
matrix2.setTextWrap(true);
matrix2.setTextColor(LED_ON);
matrix2.print(onesDigit);
matrix2.writeDisplay();
}
然后,我们有 d20 的随机数生成器:
// switch selection roll d20
if (digitalRead(switch2) == HIGH) {
int d20result = random(0, 20);
Serial.print("d20 result: ");
Serial.println(d20result + 1);
Serial.println();
如果开关设置为 d20,即经典的 D&D 骰子,Arduino 将生成一个 0 到 19 之间的随机数,增加 1,然后将结果发送到串口监视器。以下一系列的if语句允许草图在触发簧片开关时,用作弊手段覆盖掷出的数字:
if (reedLow == LOW) {
d20result = 0;
}
if (reedHigh == LOW) {
d20result = 19;
}
if (d20result == 19) {
tensDigit = 2;
onesDigit = 0;
}
else if (d20result > 9) {
tensDigit = 1;
onesDigit = d20result - 9;
}
else if (d20result == 9) {
tensDigit = 1;
onesDigit = 0;
}
else if (d20result < 9) {
tensDigit = 0;
onesDigit = d20result + 1;
}
}
无论结果如何,掷出的数字需要在矩阵上显示:
// write result
matrix1.setTextSize(1);
matrix1.setTextWrap(true);
matrix1.setTextColor(LED_ON);
matrix1.print(tensDigit);
matrix1.writeDisplay();
matrix2.setTextSize(1);
matrix2.setTextWrap(true);
matrix2.setTextColor(LED_ON);
matrix2.print(onesDigit);
matrix2.writeDisplay();
这会显示结果。程序运行一次后停止。
}
void loop() {
}
因为我们只需要代码运行一次,所以不需要使用循环,它也就没有被使用!草图完成。
组装它
接下来,你需要一个盒子来封装你的项目。你可以有几种不同的方式来处理这一步。
激光切割你自己的外壳
我的第一个建议通常是设计并自己动手制作。我的设计像一个小城堡(见图 3-8),这不仅让你感受到剑斗和魔法咒语的氛围,而且还能帮助掩盖你触发簧片开关、改变游戏结果的方法。(关于最后一点,我会在这一部分之后详细说明。)在这里,我将展示我如何制作我的城堡外壳。

图 3-8: 我的城堡骰子掷骰器,准备就绪
-
设计外壳。 使用像 Inkscape (
inkscape.org/) 这样的矢量图形程序,或者像 MakerCase (www.makercase.com/) 这样的在线工具来设计你的外壳。你还可以下载我在书中提供的城堡设计资源 (nostarch.com/LEDHandbook/),并根据需要重新创建或修改它。图 3-9 显示了我在 Inkscape 中设计的外壳。你可以用四分之一英寸的胶合板或等效材料来切割——我使用了双层的八分之一英寸胶合板。 -
输出设计。 在 CNC 路由器或激光切割机上切割设计。图 3-10 展示了我从激光切割机中取出的设计。
![image]()
图 3-9: 我在 Inkscape 中设计了我的城堡设计,并借助了makercase.com。
![image]()
图 3-10: 我的设计,刚刚激光切割完成
-
组装城堡。 清理并组装城堡,如图 3-11 所示。很少有设计能够直接从机器上出来就能组装,因此你应该计划使用锉刀和砂纸处理切割部件,以使它们能够合适地拼接。当你准备好时,将部件粘合在一起。
![image]()
图 3-11: 组装激光切割的部件。
-
涂装并装饰城堡。 涂装城堡,正如图 3-12 所示。我建议使用光面喷漆,以防止污垢和指纹。另一个不错的涂料来源是当地的爱好商店,那里肯定有各种各样的“地下城灰”和“史莱姆绿”,可以用于增加细节。没有血迹和苔藓,怎么能算是一个合适的骰子滚筒呢?
![image]()
图 3-12: 一层银色涂料为城堡增添了光彩。
-
添加电子元件。 将你的项目放入外壳中,确保按钮可以触及。街机按钮体积较大,可能会影响 Arduino 的位置。你还需要注意簧片开关的位置。在固定它们之前,务必用磁铁测试开关的位置,确定磁铁需要放置的位置,以便开关能够感应到它。
替代外壳
如果你没有激光切割机或铣床,那么就需要找到其他方法来容纳你的项目。这里有几个建议:
-
重新利用另一个盒子。 只需找到一个结实的合适大小的盒子来放置组件,并把它们放进去。切出孔洞,以便安装按钮、开关和矩阵。
-
购买外壳。 你还可以在网上找到许多便宜的项目盒子。我最喜欢的来源之一是 Jameco Electronics(
www.jameco.com/),它提供不同尺寸和耐用性的盒子。和重新利用的盒子一样,你需要注意项目内部的空间占用。像 Jameco P/N 18869 这种 8×6×3 的项目盒就能完美适用。 -
用乐高积木搭建一个外壳。 你家里很可能已经有一个合适的外壳,放在地下室的桶里,旁边堆着节日箱子。我说的就是乐高!只需搭建一个合适大小的盒子,留出按钮、开关、LED 矩阵和电源线的位置。
使用它
只需通过将墙壁适配器或 9V 电源适配器插入电源插孔,给骰子滚筒供电,然后每次想掷骰子时按下按钮,根据你的邪恶目标使用磁铁靠近任一簧片开关。
我通过将一个底部有空心塑料基座的游戏人物伪装成磁铁,使用热熔胶将磁铁粘在基座上,正如图 3-13 所示。簧片开关被放置在城堡顶部附近,触发它们时,只需将带有磁铁的人物放置在城堡的城垛旁,并与一些无害的人物一起摆放。在游戏过程中,你可以将人物移到“城堡”周围,根据需要将触发人物移到正确的位置。

图 3-13: 将磁铁用热熔胶粘在游戏人物的底座上,并用它触发骰子滚筒。
总结
当你完成这个项目的硬件和软件部分时,它应该看起来像第 65 页的照片,或者是你自己富有创意的设计的变体。
希望你也在为欺骗你的游戏伙伴的道德问题而挣扎。祝你这个项目顺利!
第五章:由 John Baichtal 制作的彩色编码 LED 手表
在这个项目中,你将制作一款使用颜色显示时间的手表。

尽管手机、微波炉甚至咖啡机中都有数字时钟,你可能会认为再做一个时钟是多余的。另一方面,多久你在重要电话中、徒步旅行时,或者完全不在厨房附近时需要知道时间呢?便携式手表依然有它的市场,而为了让它更现代化,我想出了一个解决方案:一款定制的数字时钟,拥有一个引人入胜、神秘的显示屏。
在这个项目中,你将使用一对八点 NeoPixel LED 条来通过颜色展示时间。虽然一开始可能不清楚如何通过颜色来判断时间,但继续跟进,你会发现其中的窍门。我们手表的大脑将是 Arduino,它简化了部分时间显示的过程,但也带来了特别的挑战。
获取部件
你将需要以下部件来构建这个项目。
注意
请参见 “使用 Arduino 和 Arduino IDE 入门”(第 15 页)中的设置说明。
组件
-
Arduino Pro Mini(SparkFun P/N 11113;附加引脚可以通过 P/N 00116 获取。)
-
FTDI 基本扩展板(SparkFun P/N 09716;这是一个必要的编程器,用于编程 Arduino Pro Mini。)
-
2 根 NeoPixel 条(Adafruit P/N 1426 或 SparkFun P/N 12661;这是一条包含八个 LED 的 RGB 条。)
-
DS1307 RTC 扩展板(SparkFun P/N 12708;其他选择包括 Adafruit P/N 255 或 Adafruit P/N 3013。)
-
470 Ω 电阻(SparkFun P/N 10969 是一个不错的多件装)
-
外壳(我的外壳的最大边长为 85 mm × 55 mm,深度为 30 mm;可以通过在线搜索其 P/N,WCAH2855 来找到它。一个类似的部件是 RadioShack 的经典 3 × 2 × 1 项目外壳,P/N 2701801。)
-
手表带(任何普通的尼龙或橡胶手表带都可以。我使用了来自亚马逊的山寨 iWatch 手表带。)
-
9 V 电池包和电池(一个标准的 9 V 连接器带导线;我使用的是 Jameco P/N 109154。你也可以购买 SparkFun P/N 00091 的快拆连接器,并剪掉插头。)
-
按钮(我使用了 SparkFun 的面板安装瞬时按钮,P/N 11992。按钮越小越好。如果你希望显示器一直显示,直到你关闭它,可以将按钮替换为开关。)
-
螺丝(我使用了 HobbyKing 的 M2 × 10 mm 螺丝和螺母,P/N HA0506。)
我们使用的这款小型 Arduino 提供了与其他 Arduino 相同的体验,但去掉了所有花哨的功能,以便能适配小型外壳。例如,你不能通过 USB 编程它,你需要一个 FTDI 扩展板(例如 SparkFun P/N 09716)来编程它。在开始构建这个项目之前,请参见 “没有内建 USB 连接的 Arduino 板”(第 21 页)了解如何设置 Arduino Pro Mini 和 FTDI。
在选择外壳时,记住 LED 条和 9V 电池是尺寸的主要限制。你可能还需要一个夹子来防止电池在外壳盒内滚动,尽管我的外壳已经密集地塞满了,什么都无法移动。
工具
-
烙铁和焊锡
-
Dremel 或类似的旋转工具,带切割和钻孔工具
-
(可选)喷漆
介绍实时时钟模块
事实证明,保持准确的时间并不是 Arduino 擅长的事情。它们能够从秒到秒地很好地跟踪时间,得益于板上内置的时钟晶体,但它们必须使用自己的内部存储器来保留这些信息,因此当内存满时,时钟就会停止工作。另一个问题出现在 Arduino 失去电源时——你会失去时间,并且当你再次启动 Arduino 时需要重置时间。这些挑战的解决方案在于一个附加板,称为实时时钟(RTC)模块。
RTC 由一个专用的时间保持芯片和一个电池备份组成,因此即使主项目断电,它也能保留时间。它负责保持时间,因此你的 Arduino 就不必做这个工作。
图 4-1 显示了由 Adafruit Industries 销售的 DS1307 RTC 模块。它可以准确计算到 2100 年的日历,并考虑闰年的因素,通过两线接口与 Arduino 进行通信。

图 4-1: Adafruit 的 DS1307 扩展板帮助你的 Arduino 保持时间。
工作原理:LED 的颜色编码
由于只能使用一个小的时钟面,我们仅限于使用两个八个 LED 的条形灯来显示时间。我设计了一个系统——如图 4-2 所示——它通过 LED 的颜色来传递信息。我选择了五种颜色来代表数字,如表 4-1 所列。
表 4-1: 颜色的编号代码
| 颜色 | 数值 |
|---|---|
| 黑色 | 0 |
| 蓝色 | 1 |
| 红色 | 2 |
| 黄色 | 4 |
| 绿色 | 5 |
顶部的 LED 条将指示小时,底部的 LED 条将指示分钟。如前所述,每条 LED 条将有八个 LED。每个 LED 在条中的位置将是你应用于颜色在表 4-1 中所关联数字的倍数。例如,第七个点亮的黄色 LED(4)将是 4 × 7,所以如果它在底部条亮起,将表示 28 分钟。
你可以使用更多或更少的颜色,但为了简便,我决定只使用四种颜色(加上黑色)。我希望我的时钟使用与制造商用于电阻器颜色编码相同的颜色——在他们的世界里,0 是黑色,1 是棕色,2 是红色,依此类推。然而,棕色作为可见光并不容易显示出来,所以我用蓝色代替了它。最终,选择每个时间点的颜色并不重要。如果它对你有意义,就可以使用它。
为了避免使用更多的颜色来显示较大的时间,我们将在底部条形灯上点亮第二个 LED,你可以将底部条形灯的两个数字加起来,计算出时间。记住,顶部条形灯表示小时,底部条形灯表示分钟。假设时间是上午 7:56,或者 756。为了表示这个时间,我可以在顶部条形灯的第 7 位点亮一个蓝色 LED,在底部条形灯的第 4 位(16)点亮一个黄色 LED,在第 8 位(40)点亮一个绿色 LED。图 4-2 展示了应该是什么样子的。如果你不确定我是如何得出这些数字的,请参考表 4-1。这将是一个很好的考验你心算能力的机会。

图 4-2: LED 的颜色和位置表示时间。这个模拟显示屏显示的是上午 7:56。
制作它
这款手表由电子元件和它们的外壳组成。我们将同时进行这两部分的工作。
注意
如果你需要焊接的说明,请参阅附录。
-
焊接 NeoPixel 条形灯。 焊接两根短导线,将两个 NeoPixel 条形灯串联起来,如图 4-3 所示。将标记为 Dout(数据输出)的引脚连接到标记为 Din(数据输入)的引脚,这在图 4-3 中用橙色导线表示。将剩余的两个引脚,4-7VDC(红色)和 GND(灰色),分别连接到另一个条形灯的对应引脚。注意,有两个 GND 引脚,任意一个都可以使用。
![image]()
图 4-3: 将 LED 条形灯焊接在一起。
-
钻孔外壳。 一旦你将 LED 条形灯接好,将它们放在外壳顶部,并用记号笔标记它们的安装孔位,以便钻孔;你还应该标记出导线将进入外壳的位置。与此同时,标记出你希望放置电源按钮的位置。
一旦外壳标记好,就可以钻孔了。你也许还想考虑如何佩戴这款手表。如果你打算使用腕带,你需要弄清楚如何将腕带固定到外壳上。图 4-4 展示了我已经钻好孔的外壳。
![image]()
图 4-4: 在外壳上钻孔。
-
涂装外壳。 如果黑色涂层让你觉得不满意,可以考虑给外壳涂上一层油漆。图 4-5 展示了我正在给外壳上色。我选择了类似军事风格的橄榄绿色。
![image]()
图 4-5: 用一抹色彩为普通黑色盒子进行个性化装饰。
-
将 RTC 连接到 Arduino。 在油漆干燥时,开始焊接内部组件。首先连接 RTC 模块,将其接到 Arduino Pro Mini 上;参考图 4-6。将 RTC 上的 5V 接到 Arduino 的 VCC 引脚(在图 4-6 中用红色导线表示),将 GND 接到 Arduino 的 GND 引脚(用黑色导线表示)。将 SCL(串行时钟,用绿色导线表示)连接到 Arduino 的 A5 引脚,将 SDA(用黄色导线表示)连接到 A4 引脚。
![image]()
图 4-6: 将 RTC 连接到 Arduino。
注意
FTDI 板未在接线图中显示,但你应该已经将它连接到你的 Pro Mini。如果你还没有这么做,请参见第 21 页的“没有内置 USB 连接的 Arduino 板”。
-
将 LED 条安装到外壳上。 涂料干燥后,你可以使用 M2 螺丝将 LED 条安装到外壳上。注意,LED 条的具体方向会影响你是否能准确读取数据。两条 LED 条必须朝相同的方向排列。在第 81 页我的原型照片中,你可以看到我有一条 LED 条与另一条方向相反。不过,这证明是一个问题,我在最终设计中修正了这个问题。确保按照接线图中显示的方向安装 LED 条。
-
连接 LED 条到 Arduino。 将 LED 条的电源、接地和数据线按图 4-7 所示连接到 Arduino 上。
![image]()
图 4-7: 将 NeoPixel LED 条连接到 Arduino。
数据线(以黄色电线表示)连接到 Arduino 的 6 号引脚,并通过一个 470 Ω的电阻保护 LED 条免受电力波动的影响。电源(红色)和接地(黑色)分别连接到+5V 和接地。
-
安装按钮或开关。 将按钮接线并用随附的面板安装硬件将其固定在外壳上。将按钮的一根引脚连接到电池包的红线,如图 4-8 所示。将按钮的另一根引脚(以紫色表示)连接到 Arduino 的 RAW 引脚。电池包的 GND 线连接到 Arduino 的 GND 引脚。你也可以替换为一个开关,这样你需要手动打开和关闭显示器。代码无需修改——只要 LED 和项目的其他部分有电,LED 每秒更新一次。
![image]()
图 4-8: 安装按钮并将其引脚焊接到 Arduino 上。
-
安装手表表带。 安装表带。我使用 Dremel 工具在外壳口和盖子之间铣出一个槽,能够在盖子固定后“夹住”表带。图 4-9 展示了表带的安装情况。
![image]()
图 4-9: 系上表带!
编写代码
让我们来看看这个项目的 Arduino 代码。你可以在本书的资源中找到名为led_watch.ino的文件,网址为nostarch.com/LEDHandbook/。清单 4-1(Listing 4-1)中设置了脚本。
清单 4-1: 库文件和声明
➊ #include <Adafruit_NeoPixel.h>
#include <Wire.h>
#include "RTClib.h"
➋ RTC_DS1307 RTC;
#define PIN 6
➌ Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN,
NEO_GRB + NEO_KHZ800);
我们从库声明开始 ➊。然后初始化 RTC ➋ 和 NeoPixel LED 条 ➌。按钮/开关不需要声明,因为它只是将电源连接到 Arduino。
如果你还没有安装相关库,那么在代码运行之前,你需要先安装它们。你可以从各自的产品页面下载并安装 NeoPixel 和 RTC 库,相关信息可以参考www.adafruit.com/。你应该已经安装了 Wire 库,因为它包含在 Arduino 软件中。
接下来,让我们深入探讨代码的核心部分,参见清单 4-2,它初始化了跟踪不同时间对应颜色的数组。
清单 4-2: 初始化数组
byte numberMatrix[60][8] = { //array of numbers
{ //time 0
2, 2, 2, 2, 2, 2, 2, 2 //all pixels red
},
{ //time 1
1, 0, 0, 0, 0, 0, 0, 0 //pixel 1 is blue
},
{ //time 2
0, 1, 0, 0, 0, 0, 0, 0 //pixel 2 is blue
},
--snip--
一共有 60 个条目——每分钟一个——但为了节省空间,这里只列出了三个作为示例。手表通过相同的数组来显示小时,因此 7 点的颜色编码与 7 点整后的分钟相同。部分出于调皮,部分为了调试,我让 0 点的颜色全部是红色。这样,你可以看到每小时的开始,同时如果你恰好在整点附近调试代码,这也能确认代码是否正常工作。
清单 4-3 定义了setup()函数。
清单 4-3: setup()函数
void setup() {
Serial.begin(57600);
➊ Wire.begin();
➋ RTC.begin();
strip.begin();
strip.show(); // Initialize all pixels to 'off'
if (! RTC.isrunning()) {
➌ Serial.println("RTC is NOT running!");
// The following line sets the RTC to the date and time
// this sketch was compiled
➍ RTC.adjust(DateTime(__DATE__, __TIME__));
}
}
这一段代码首先引入 Wire ➊库,用于管理串行通信,并激活 RTC ➋。如果 RTC 芯片没有响应,Arduino 会将错误信息➌发送到串口监视器。接着,脚本会调整 RTC 的时间,使其与编译程序时的日期和时间匹配 ➍。
清单 4-4 包含loop()函数,其中包含控制 LED 条激活的代码。
清单 4-4: 激活循环
void loop() {
//determine time
DateTime now = RTC.now();
int hourDisplay = (now.hour(), DEC);
int minuteDisplay = (now.minute(), DEC);
Serial.println();
Serial.print("time: ");
Serial.print(hourDisplay);
Serial.print(':');
Serial.println(minuteDisplay);
//hour display
for (int thisPin = 0; thisPin < 8; thisPin++) {
int LEDcolor = numberMatrix[hourDisplay][thisPin];
switch (LEDcolor) {
case 0:
strip.setPixelColor (thisPin, 0, 0, 0);
break;
case 1: //make that pixel blue
strip.setPixelColor (thisPin, 0, 0, 100);
break;
case 2: //make that pixel red
strip.setPixelColor (thisPin, 100, 0, 0);
break;
case 4: //make that pixel yellow
strip.setPixelColor (thisPin, 100, 50, 0);
break;
case 5: //make that pixel green
strip.setPixelColor (thisPin, 0, 100, 00);
break;
}
}
for (int thisPin = 0; thisPin < 8; thisPin++) {
int LEDcolor = numberMatrix[minuteDisplay][thisPin];
switch (LEDcolor) {
case 0:
strip.setPixelColor ((thisPin+8), 0, 0, 0);
break;
case 1:
strip.setPixelColor ((thisPin+8), 0, 0, 100);
break;
case 2:
strip.setPixelColor ((thisPin+8), 100, 0, 0);
break;
case 4:
strip.setPixelColor ((thisPin+8), 100, 50, 0);
break;
case 5:
strip.setPixelColor ((thisPin+8), 0, 100, 00);
break;
}
strip.show();
}
Serial.println();
delay(1000);
}
一旦你开启 Arduino 电源(通过按下按钮或切换开关),程序就会启动。循环会从 RTC 读取时间,然后根据适当的颜色点亮 LED,只要电路板通电,LED 会持续显示。每个 LED 都有一个编号(0–7 代表小时,8–15 代表分钟),并从程序开头的数组中接收颜色数据。如果使用开关代替按钮,LED 会持续点亮,时间每秒更新一次。
总结
完成物理搭建并上传代码后,你的手表就完成了!它可能不是一个精密的仪器,但肯定会引发几次对话。
第六章:实时音乐可视化器,作者:Michael Krumpus
本项目向你展示如何使用 Arduino 和 LED 灯带创建一个炫酷的音乐可视化器。

构建完此项目后,你将能够将任何音乐源插入电路,LED 灯带会根据音乐同步显示酷炫的多彩灯光秀。这个项目非常适合派对、DJ 舞台,甚至你的宿舍!想要看到可视化器的实际效果,可以查看这个简短的视频: youtu.be/GkjBT-EmRw8。
首先,我们将了解制作音乐可视化器的原理,以便在开始构建之前,你对其工作原理有所了解。在电路搭建完成后,你将了解代码如何工作以及如何将代码加载到 Arduino 中。最后,我们将讨论一些如何修改代码的技巧,以便让其表现不同,让你可以自己进行实验。
获取零件
实时音乐可视化器所需的零件非常容易找到。本清单推荐 Adafruit 提供一些更专业的零件,Mouser 提供简单的被动元件。
注意
你的 LED 灯带的长度决定了你的电力需求。对于 2 米的灯带,2 A 的电源就足够了。但如果使用 3 米的灯带,你将需要 5 A 或 10 A 的电源。Adafruit P/N 658 是一个适用于 10 A 的好选择。
-
Arduino Uno (Adafruit P/N 50; 请参阅 “Arduino 入门与 Arduino IDE” 第 15 页 ([intro.xhtml#page_15]) 获取安装说明)
-
1, 2 或 3 米 WS2812B RGB LED 灯带 (例如,Adafruit NeoPixel P/N 1461)
-
5 V,2 A 电源 (Adafruit P/N 276,或 P/N 658 用于 10 A)
-
2.1 mm 直流面包板电源插座 (Adafruit P/N 368)
-
两个面包板音频插座 (Adafruit P/N 1699)
-
10 kΩ 电位器 (例如,Adafruit P/N 356)
-
无焊接全尺寸面包板 (Adafruit P/N 239)
-
22 号实心连接线,用于连接组件 (Adafruit P/N 1311)
-
三个 4.7 kΩ 电阻 (Mouser P/N 291-4.7K-RC)
-
两个 100 kΩ 电阻 (Mouser P/N 291-100K-RC)
-
2.2 kΩ 电阻 (Mouser P/N 291-2.2K-RC)
-
470 Ω 电阻 (Mouser P/N 291-470-RC)
-
0.047 μF (47 nF) 陶瓷电容器 (Mouser P/N 594-K473K10X7RF5UH5)
-
10 μF 铝电解电容器 (Mouser P/N 80-ESK106M016AC3AA)
-
1,000 μF 铝电解电容器 (Mouser P/N 647-UVR1C102MPD)
-
两根 3.5 mm 音频线 (Adafruit P/N 2698)
-
你选择的音乐播放器和音响
工作原理:将音乐转化为数据
要可视化你的音乐,视觉化工具必须分析音频信号的内容,并在 LED 条上显示相应的内容。那么,如何用 Arduino 代码分析音频信号呢?其中的秘诀在于快速傅里叶变换(FFT)算法,这是一种追溯到 19 世纪的数学技术。我们不会深入讨论数学细节,因为数字信号处理相当复杂,但基本思想是,随着时间变化的信号(如音频信号的电压)可以被分析并分解为其频率成分。如果你曾在立体声设备或计算机上的音乐播放器中见过频谱分析仪,那么你可能已经熟悉了这一概念,见于图 5-1。

图 5-1: 一个典型的频谱分析仪
垂直条形代表频带,左侧的条形代表低频(低音),右侧的条形代表高频(高音)。本项目中的 Arduino 代码将对音频信号的电压进行采样,并对音频样本执行 FFT 算法,以确定每个频带中的信号强度。然后,我们将使用低频频带的电平(音乐的低音节奏)来在 LED 条上创建一个有趣的显示效果。
在视觉化电路中,你将把计算机、手机、平板或其他音乐设备连接到一个 3.5 毫米(1/8 英寸)输入插孔,以接收音乐信号。你将连接一个输出插孔到你电源驱动的扬声器、立体声放大器,或其他用于放大音乐并输出到扬声器的设备。换句话说,电路位于你的音乐源和放大器/扬声器设备之间,这样它就可以“听”到音乐并展示效果。电路的其余部分由一些简单的元件和一个 Arduino 组成。处理音频信号在电子学中有一些棘手的地方,因此本节描述了我们将用于使电路工作的一些技术。本节将教你很多关于音频处理的知识!
输入偏置
Arduino 板可以测量其六个模拟输入引脚上的电压,这些引脚在板上标记为 A0 到 A5。你的视觉化工具将会把音频信号连接到 Arduino 的 A0 引脚,以快速进行大量采样测量,然后应用 FFT 算法将信号转换为 Arduino 可以分析的数据。
如果你熟悉 Arduino 上的模拟输入测量,你就知道,调用analogRead()函数从模拟引脚读取数据时,返回的值在 0 到 1023 的范围内,这代表测得的电压范围为 0 至 5 伏。但当我们想测量模拟音频信号时,会遇到一个问题:音频是交流电,而不是直流电。也就是说,电压在地面(0 伏)上方波动,然后低于地面,变为负电压(见图 5-2)。

图 5-2: 一个简单的音频信号在正负电压之间振荡
Arduino 无法测量低于 0 V 的电压,因此我们不能将音频信号直接连接到 A0 引脚,否则可能会损坏 Arduino。我们该如何解决这个问题?
解决方法是将电压“偏置”到更高的水平,这样它就不再围绕 0 V 而是围绕更高的电压波动。这意味着当电压下降时,它不会低于 0 V。我们通过一个由两个相等电阻值组成的电压分压器来实现这一点。音频信号有一个电阻将其连接到 5 V,另一个电阻将其连接到 0 V(图 5-3)。这样就将信号偏置到 0 V 和 5 V 之间的中点,即 2.5 V。

图 5-3: 音频信号的输入偏置电路
图 5-4 显示了相同的信号,但它是围绕 2.5 V 而不是 0 V 进行偏置的。现在,Arduino 可以测量音频电压,而不必担心它们会低于地电位。音频信号通常只有几伏特的峰值到峰值电压,因此这种方法效果很好。

图 5-4: 一个音频信号,现在偏置为 2.5 V
灵敏度控制
音频信号需要足够强,以便电压在一个足够大的范围内波动,这样可视化工具才能有效地分析它。但一些音频源输出的信号并不十分强烈。我们需要为电路提供调节灵敏度的能力,以便可以处理弱信号。本节描述了一个巧妙的技巧来实现这一点。
回想上一节内容,Arduino 可以测量 0 V 到 5 V 之间的电压,并且我们已经将音频电压偏置为围绕 2.5 V。若音频信号较弱,电压变化不大,我们就会得到类似于 图 5-5 中显示的信号。这可能出现在“线路电平”信号中,其中峰值到峰值电压仅为 1 V。

图 5-5: 一个弱音频信号
测量这个信号会得到大约 512 的 analogRead(0) 值(0–1023 范围的中点),但这些值变化不大,无法给我们提供有效的分析。
幸运的是,Arduino 板上有一个特别的引脚,称为 模拟参考 (AREF)。我们可以在这个引脚上提供电压,并告诉 Arduino 代码,这就是我们在模拟输入上要读取的最高电压。例如,要测量 0 V 到 2 V 之间的电压,并使得 analogRead() 的值使用完整的 0–1023 范围,我们就在 AREF 引脚上提供 2 V 的电压。此时,2 V 的测量值会是 1023,而不是更低的值。
在这个电路中,我们将使用一个电位器为 AREF 引脚提供电压。为了提高灵敏度,我们只需通过调节电位器来提供更低的电压。
容易吧?别着急!记住,音频信号是围绕 2.5 V 的。如果我们将模拟参考电压调得过低,我们就会忽略信号的上部分,因为信号的峰值会被“截断”。在这种情况下,FFT 算法将无法正确处理信号。解决方法是我们还需要将输入偏置电路的最高电压降低,这样偏置电路就能将音频信号居中于 0 V 与我们提供给 AREF 的电压之间的中点。图 5-6 展示了我们得到的弱音频信号,它的波动只有大约 1 V 的峰-峰值。电路中的可调电阻提供了一个 2 V 的 AREF 电压,我们也将其作为偏置电路的上限。现在,音频信号居中在 1 V,填充了更广泛的analogRead()值范围。实际上,我们已经放大了信号!我们并没有实际增加信号的电压,而是减少了我们测量的电压范围,使得弱信号可以填充更多的范围。巧妙。

图 5-6: 一个弱音频信号,灵敏度调整到设定的最高电压为 2 V
搭建它
现在是时候开始在面包板上搭建音乐可视化电路了。这些说明将通过多个步骤展示整个过程,以便更容易地搭建电路。你可以选择不同的方式布局你的组件,但这些示意图旨在为你提供最大的清晰度。让我们开始吧!
-
将音频插孔添加到面包板上。 如图 5-7 所示,将输入插孔的左声道和右声道直接连接到输出插孔的左声道和右声道。这样,音乐信号就可以流到输出端。插孔的中间引脚应连接到地。同时,使用红色和黑色导线将电路板两侧的电源轨连接起来,如图所示。
![image]()
图 5-7: 音频插孔和电源轨连接
-
使用音频汇总电路滤除噪声。 现在,通过每个通道上的电阻将左声道和右声道连接起来,以防止它们之间的串音(干扰)。在每个通道上加一个 4.7 kΩ的电阻,如图 5-8 所示。然后在左侧加上一个 10 μF 的电容器,负极(较短的引脚)连接到输出插孔,通过 4.7 kΩ电阻连接。接着添加一个 0.047 μF(或 47 nF)的电容器,并将一端连接到 10 μF 电容器的正极,另一端连接到地,如图所示。这些有助于滤除噪声并阻止直流电流。
![image]()
图 5-8: 音频汇总电路和滤波器
-
构建输入偏置和模拟参考电路。 回想一下,我们的电压分压器由两个 100kΩ的电阻器组成,它将音频信号中心化于 0V 和模拟参考电压之间,模拟参考电压通过 10kΩ的可调电阻来控制。将这些电阻器插入面包板,其中第一个电阻器的一端直接连接到电源地轨道,另一端与第二个 100kΩ电阻器连接,如图 5-9 所示。确保第二个电阻器与第一个电阻器相邻插入。现在,在面包板上放置一个可调电阻,并通过一个 2.2kΩ电阻将最右边的引脚连接到电源地。将一个 4.7kΩ电阻连接到可调电阻的中间引脚——这将最终连接到 Arduino 的 AREF 引脚——并确保这个电阻跨越面包板的中央分隔。这个中间引脚还应该连接到第二个 100kΩ电阻器的第二个引脚。可调电阻的最后一个空引脚连接到电源轨道。
![image]()
图 5-9: 输入偏置组件
-
连接电源插口为电路供电。 将电源插口连接到面包板的电源轨道。还要将大的 1,000μF 电解电容器连接到电源线路,如图 5-10 所示。电解电容器是有极性的,所以要注意极性:正极引线比负极引线长,并应连接到正电源轨道。电容器的负极一侧也有一条白色的标线。这个电容器为电路提供电压储备,以防 LED 条带一次性吸收大量电流。例如,将 LED 条带上的所有 LED 灯同时设置为白色会消耗大量电流,但电容器有助于平滑由此产生的电压下降,从而避免电路过载。
![image]()
图 5-10: LED 条带的电源连接
-
将 LED 条带连接到电路中。 LED 条带有三个连接端口:5V、电源地和数据输入(DIN)。这些电气连接在不同的 LED 条带上可能顺序不同。例如,DIN 连接通常位于中间,但图 5-11 中它显示在顶部。只需密切注意 LED 条带上的标签。如果你的 LED 条带没有连接器,可能需要将导线焊接到条带上(有关焊接的说明,请参见附录)。无论如何,请按照图 5-11 所示,将 5V、电源地和 DIN 连接到电路中,DIN 引脚连接到一个 470Ω电阻(电阻的另一端将连接到 Arduino)。
![image]()
图 5-11: 连接 LED 条带
-
连接 Arduino。 我们快完成了!最后的电线连接到你的 Arduino 板,如图 5-12 所示。绿色电线连接 Arduino 的 6 号引脚到 DIN 连接处的 470 Ω 电阻。蓝色电线连接到 Arduino 的 AREF 引脚。黄色电线是音频信号,连接到 Arduino 的模拟引脚 A0。最后需要连接的是将面包板的接地信号连接到标有 GND 的 Arduino 接地引脚,但此时不要进行此连接。如果 Arduino 上已经有程序在运行,连接电路时可能会损坏电路的部分元件。因此,为了安全起见,我们会先加载本项目的草图,然后再完成 Arduino 的连接。
![image]()
图 5-12: 将 Arduino 连接到电路
编写代码
这个电路在没有 Arduino 上的精彩代码之前是不会做任何事情的!我们将使用的 Arduino 草图相当复杂,这里没有足够的空间将其全部打印出来,但本节将描述它的基本工作原理,帮助你掌握基础。你可以从书本资源中下载草图,网址是 nostarch.com/LEDHandbook/。
工作原理
Arduino 程序的工作是通过在缓冲区捕获电压样本来“监听”音乐,然后对这些样本进行 FFT 分析,以确定每个频率带的水平。这给我们提供了类似普通频谱分析仪的数据——在任何特定时刻每个频率带的信号强度。
然而,我们并不是仅仅显示一列列的 LED,而是做一些更有趣的事情。每当检测到频率带中出现新的最大值或峰值时,代码会生成一对从 LED 带中间起始并向两端移动的动态像素。像素的移动速度取决于峰值的强度,并且像素在向外移动时会逐渐变暗。峰值的颜色是随机变化的。请注意,我们只关注底部的三个频率带(总共八个频率带),以便可视化音乐的节拍。
这是主循环的代码,并附有解释性的注释:
void loop() {
// While the ADC interrupt is enabled, wait. The program is
// still gathering audio samples in the capture buffer.
while (ADCSRA & _BV(ADIE)) {
// Wait...
}
// The sampling interrupt has finished filling the buffer,
// so show the output we computed last time through the
// loop. This sends the data to the LED strip.
strip.show();
// Perform the FFT algorithm to convert samples to
// complex numbers.
fft_input(capture, bfly_buff);
// Now that we've updated the LED strip and processed the
// audio samples with FFT, we can resume the collection
// of audio samples in the sample buffer. The interrupt
// service routine (ISR) will run while we compute the next
// LED output based on the audio samples we captured.
startSampling();
// Perform the rest of the FFT computation:
fft_execute(bfly_buff); // Process complex data
fft_output(bfly_buff, spectrum); // Complex -> spectrum
// Now call this to analyze the audio. See comments in this
// function for details.
analyzeAudioSamples();
// The peak values for each of the 8 bands has been
// computed. A bit in the 8-bit value newPeakFlags
// indicates whether the analysis found a *new* peak
// in the band.
for (i = 0; i <= CUTOFF_BAND; i++) {
// If a new peak was found in band i...
if (newPeakFlags & (1 << i)) {
// Map the peak value to a magnitude in range [0,255].
// We pass in the band number because the mapping is
// different for different bands.
uint8_t magnitude = getMagnitude(i, bandPeakLevel[i]);
// A nonzero magnitude means that the peak value is
// large enough to do something visually with it. We
// ignore small peaks.
if (magnitude > 0) {
// We want to store the information about the peak
// in a peak_t structure. When we actually draw a
// visualization, the peak_t structures in peaks[]
// represent the "visually active" band peaks.
// Look through the list of peak structures 'peaks'
// for an unused one.
for (j = 0; j < N_PEAKS; j++) {
if (peaks[j].magnitude == 0) {
// Unused peak found.
peakIndex = j;
break;
}
}
// If an unused one not found, we use the last one
// that was used (peakIndex).
// Initialize the structure.
peaks[peakIndex].age = 0;
// A random component for a visualization to use. For
// example, to shift the color a small amount.
peaks[peakIndex].rnd = random(255);
peaks[peakIndex].baseColor =
getRandomBaseColor(peaks[peakIndex].rnd);
peaks[peakIndex].magnitude = magnitude;
}
}
}
// Clear the last frame.
strip.clear();
// Draw the peaks on the LED strip.
doVisualization();
} // end loop()
代码中远不止这一个主循环,许多繁重的计算工作由 analyzeAudioSamples() 和 doVisualization() 函数完成。尽管如此,你完全不需要理解它是如何工作的就能享受这个项目。在下一节中,你将把代码加载到 Arduino 上。
获取代码
项目的完整源代码可以在书籍资源中的nostarch.com/LEDHandbook/找到。你还可以在资源中找到用于驱动 RGB(红绿蓝)LED 灯条的库,你需要将其安装到 Arduino IDE 中。Adafruit 提供了一个关于如何安装 Arduino 库的优秀指南,地址是learn.adafruit.com/adafruit-neopixel-uberguide/arduino-library-installation。安装后,你的 Arduino 目录应具有以下结构:
your_sketchbook
|
+--libraries
| |
| +--ffft
| |
| +--Adafruit_NeoPixel
|
+--RealtimeMusicVisualizer
|
+--RealtimeMusicVisualizer.h
+--RealtimeMusicVisualizer.ino
现在打开 Arduino IDE 并加载 RealtimeMusicVisualizer 草图。编译并将其上传到你的 Arduino。通常最好在给 Arduino 供电前,先将 Arduino 从新的电路中断开连接。上传代码到 Arduino 后,你可以按照之前描述的方式将四个线路连接到电路中。
使用它
使用音乐可视化器就像进行几个简单的连接一样容易:
-
使用 3.5 毫米音频电缆将音频输入插孔连接到你的音乐源。
-
将音频输出插孔连接到你的立体声接收器或一些有源扬声器。
-
将你的 5V 电源连接到面包板电路上的电源插孔。电源必须能够提供至少 2A 的电流。
-
将电源连接到你的 Arduino 板,可以使用 USB 电缆或其他电源适配器。否则,你也可以通过将一根线连接到 Arduino 上的 5V 引脚,从面包板的 5V 电源为 Arduino 供电。
现在打开音乐,享受表演吧!你可能希望将音乐播放器的音量调高,尤其是当设备较小,如手机或平板时。电脑通常输出更强的信号。如果音乐没有产生太多的可视化效果,可以通过顺时针旋转面包板上的电位器旋钮来增加灵敏度,直到你能清楚地看到音乐的节奏。
进一步操作
如果你有 Arduino 编程经验,可能会想对代码进行修改,让它执行不同的功能。这里有一些探索的想法:
-
更改 LED 数量。 如果你的 LED 灯条有不同数量的 LED,你应该调整代码。例如,如果你有一个 3 米长、180 个 LED 的灯条,请在RealtimeMusicVisualizer.ino文件中更改定义
N_LEDS的那一行,将其改为新值:#define N_LEDS 180 -
让像素向一个方向移动。 不再让移动的像素从灯条的中心朝两个方向移动,你可以让它们仅从一端开始。将RealtimeMusicVisualizer.ino中的
SINGLE_DIRECTION设置为true:#define SINGLE_DIRECTION true -
使代码响应更多频率带。 当前代码只关注底部三个频率带。通过更改
CUTOFF_BAND的值,你可以听到更多频率带。目前的值为2,因为底部三个频率带编号为 0、1 和 2。如果你想响应底部五个频率带,可以将这一行改成这样:#define CUTOFF_BAND 4 -
改变亮度。 可视化工具太亮了吗?也许你不是在举办一场盛大的派对,而只是想为你的宿舍增添一些亮点。你可以通过减少
MAX_BRIGHTNESS的值来调低亮度。默认值是255,你可以尝试设置一个较低的值,比如100:#define MAX_BRIGHTNESS 100 -
改变颜色随时间的变化方式。 这个可视化工具展示了两种颜色的像素,它们随着时间变化。对于这两种颜色,每种颜色随时间变化的速度由
MIN_COLOR_CHANGE_COUNT和MAX_COLOR_CHANGE_COUNT的值控制。当选择新颜色时,会在这两个最小值和最大值之间设置一个值,表示在选择新颜色之前,多少个像素将显示为当前颜色。默认的最小值和最大值是5和10。如果你希望所选颜色在改变之前显示更长时间,可以增加这些值。如果你希望每个像素都是新颜色,你可以将这两个值都设置为1:#define MIN_COLOR_CHANGE_COUNT 1 #define MAX_COLOR_CHANGE_COUNT 1 -
编写你自己的可视化。 如果你有一个全新的可视化创意,你可以修改或重写函数
doVisualization()。这个函数绘制由数组peaks中的peak_t结构定义的移动像素。如果你仔细研究代码,你会理解它是如何工作的。这个项目基于一个更复杂的可视化工具,它有许多不同的可视化效果:Lumazoid 板(一个认知设计产品)。你可以从*github.com/nootropicdesign/lumazoid*中的 Lumazoid 源代码获取不同可视化效果的灵感。
摘要
如果你已经搭建好了电路并且一切正常,恭喜你!你现在有了一种非常酷的方式来为你的音乐增添光彩,希望你在这个过程中也学到了些东西。如果你已经阅读了本章所有关于如何通过数字信号处理分析音乐,以及如何使用简单的电子学技巧处理音频信号电压的内容,你已经比大多数人更了解音频信号的真实性质。
第七章:自动红外遥控,由 Kaas Baichtal 编写
在这个项目中,你将使用红外 LED 和树莓派自动操作遥控设备。

工作原理:红外光
在 19 世纪初,天文学家威廉·赫歇尔发现,通过棱镜分解的阳光,越接近红色光谱端的部分温度越高。然而,红色之外的光谱区域则更热。原来有一种温度更高的光——称为红外(IR)——人类能感觉到,但看不见。
红外意味着“低于红色”,因其频率(每秒波数)低于可见红光。电磁波谱图在图 6-1 中展示了所有辐射能量之间的关系,包括光、电波、微波、伽马射线和 X 射线。

图 6-1: 电磁波谱
红外 LED
红外 LED 自 20 世纪 60 年代初就已经存在。事实上,它们的发明比发出可见光的 LED 早一到两年。图 6-2 展示了一个红外 LED 的例子。

图 6-2: 一个红外 LED。内部较大的部分对应于负极引脚。
像所有二极管一样,LED 是一种半导体。电流在正向方向通过二极管的阻力较小,而在反向方向则较大。当电流通过二极管时,它还会发出少量电磁辐射。该辐射位于电磁波谱中的位置取决于制造二极管时所使用的材料。由硅和锗制成的常规二极管通常不发光,而其他半导体材料则可以发出各种颜色的可见光,以及紫外光和红外光。红外 LED 通常由砷化镓(GaAs)或铝镓砷(AlGaAs)制成。
当 LED 被反向偏置(反向连接时),不会产生光。
视距通信
红外 LED 有许多重要应用,包括数据通信。使用 IR LED 发送数据的电路称为发射器。接收红外光并将其转换回数据的电路称为接收器。
因为红外组件传输和接收光,它们需要能够“看到”彼此才能成功通信(见图 6-3)。这通常被称为视距通信。传输 LED 发出的光束越窄,发射器就越需要精确对准接收器。没有什么不透明物体可以阻碍光的传播,然而,在必要时,光也可以通过使用镜子、光纤和光导管等方式引导或反射到非视距方向。

图 6-3: 这个红外遥控器有一个孔用于发射器的 LED 发射光束,而它控制的空调则有一个小红色窗口,允许红外光照射到接收器上。
虽然这看起来像是一个劣势,但红外通信的视距特性实际上有其优点:红外传输不太可能干扰到发生在完全不同房间或建筑中的其他红外通信。任何曾经被邻居的遥控器开关天花板风扇的用户,都会理解这一点!
在本项目中,我们将使用简单的视距通信,将附加在树莓派上的红外发射器定向,使其可以毫无问题地被空调接收。
数据传输
从最简单的角度来看,红外发射器通过开启和关闭 LED 来传输数据。例如,用 LED 发送摩尔斯电码也是可能的。然而,为了通过红外进行数据通信,已经开发了几种复杂的语言和系统,称为协议。几十年来,遥控器发送的消息需要传递越来越多的信息。这激发了许多提高信噪比、错误校正和数据承载能力的创新方法。以下是协议规范中可能包含的一些内容的概述:
-
使用的红外光频率
-
使用的载波频率
-
支持的设备数量
-
每个设备的命令数量
-
编码中使用的位数
-
编码过程
-
键到码的映射
-
数据传输速率,可能是可变的
-
传输脉冲的调制方案和/或它们之间的间隔
在可编程微控制器出现之前,发射器和接收器需要额外的电路来完成协议所要求的一切。普遍缺乏兼容性导致了“万能遥控器”的发展,这些遥控器要么预先编程了许多其他遥控器的负载,要么只是记录其他遥控器的信号,并在命令下将它们原样播放。这后一种方法是我们在本项目中开始“教”树莓派如何控制空调时所使用的过程,利用一个 USB 红外玩具(见图 6-4)。USB 红外玩具在同一电路板上集成了发射器和接收器,因此我们可以用它来记录空调遥控器的信号并模仿它们。

图 6-4: USB 红外玩具
获取零件
本项目中的说明将使用这里列出的设备。电子项目新手?坚持使用这个零件清单,我会让你轻松搞定!
如果你有更多经验,能够修改步骤,随时可以替换你自己的发射器、接收器、计算机、操作系统和空调或其他要控制的设备。
-
USB 红外发射器和接收器(我使用的是 Dangerous Prototypes USB IR Toy 2,它有预装版本和套件版。预装版可在 Seeed Studios 购买,SKU 编号为 #102990037;*
www.seeedstudio.com/USB-Infrared-Toy-v2-p-831.html*)。 -
配有 A 型和迷你 B 型连接器的 USB 电缆(例如,Adafruit P/N 260)
-
Raspberry Pi(任何型号都可以使用,但需要通过 NOOBS 安装 Raspbian—有关设置说明,请参阅 Raspberry Pi 入门,详见 第 13 页)。
-
一台带有红外遥控器的空调(我使用的是海尔 HWR08XC7 型号)。
本节剩余内容涉及修改,如果你使用的是列出的零件,可以跳到 “动手制作” 部分,详见 第 117 页。
任何具有 USB 端口并支持运行 LIRC(Linux 红外遥控控制)的计算机都可以用于这个项目。我选择了 Raspberry Pi,因为我可以在亚马逊上以较低的价格购买带有外壳、电源和 NOOBS SD 卡的套件。Raspbian 是本书中其他项目使用的操作系统,因此我将提供基于该系统的说明,但我们在这里所做的一切应该都能修改适配你的机器。
无论你使用什么设备,你都需要 LIRC 包(* www.lirc.org *)来完成这个项目。LIRC 对于这种任务非常有用,因为 1) 它可以安装在多种类 Unix 系统和 Windows 操作系统上;2) 它允许多个程序监听一个接收器;3) 它附带有用于记忆遥控器和手动发送命令的有用工具;4) 它的网站有丰富的硬件兼容信息,因此你可以轻松地调整这个项目来适配其他硬件。
例如,有很多预配置的 .conf 文件,适用于不同的手持遥控器,存放在 lirc-remotes.sourceforge.net/remotes-table.html 网站上。理论上,你可以控制任何与这些列出的红外遥控器兼容的设备,无需编写任何代码,甚至不必翻找沙发垫下的遥控器。但很少有预配置的遥控器是为空调设计的,因此在本项目中,我们将创建自己的 .conf 文件,而不必为找匹配的文件而烦恼。
事实上,由于我们反正会创建自己的 .conf 文件,你可以使用任何支持红外控制的设备,操作步骤完全相同,只要你仍然拥有它的物理遥控器来模拟代码即可。Xbox?Roomba?DVD 播放器?没问题!
如果你打算为这个项目购买空调,选择一个除了具有红外功能外,还能满足你制冷需求的,并且是你所在地区常见的品牌即可。
对于我的红外发射器和接收器,我选择了 Dangerous Prototypes 的 USB IR Toy 2,原因有三:它与 LIRC 完全兼容;它的价格相对便宜,预组装版只需$20(如果你自己组装几乎不花钱);最后,由于它同时具有发射器和接收器,我只需要处理一个设备。虽然实际上控制空调只需要发射器,但由于我们正在创建自己的初始配置文件,所以也需要接收器。
构建它
让我们开始这个项目吧!以下步骤假设你已经拥有一个组装好的红外发射器和接收器、空调设备和遥控器,并且你的树莓派拥有sudo根权限。(Raspbian 提供了“pi”用户用于此目的。)
备注
在撰写本文时,也有用户贡献的 v23 和 v24 版本,它们可以在网站的论坛中找到。
-
升级你的 USB IR Toy 2 固件。 请按照 Dangerous Prototypes 网站上 USB IR Toy 2 页面的说明(
dangerousprototypes.com/docs/USB_IR_Toy_firmware_update),将其固件升级到最新版本,在撰写本文时,官方版本是 v22。根据你的设备附带的固件版本,进行固件升级可能会避免很多麻烦,因为一些早期版本并不支持发射功能!你可以通过 USB 端口使用几乎任何计算机来升级固件。在从 Dangerous Prototypes 网站下载并解压固件升级包后,按照网站提供的说明操作。具体过程和结果会根据你的设置有所不同,因此我不会详细讲解,除了提到在我的 Windows 7 桌面上,我必须手动安装inf-driver子目录中的驱动程序,而这个细节在说明中并没有提到。
一旦计算机识别到 USB IR Toy 2,运行固件子目录中的update-USBIRToy.v22.bat文件,并在系统提示时,提供分配给设备的端口号(详情请参见备注)。
备注
如果你没有收到 COM 端口,并且在设备管理器或类似工具中找不到它作为 COM 端口列出,只需在此问题出现时按 ENTER 键即可。如果你是自动分配端口号的,才需要端口号。
我发现每次插入或更改任何内容时稍作暂停会很有帮助,因为在这个过程中,Windows 会多次重新识别 USB IR Toy 2,而这个中断会导致固件更新程序无法找到设备。一旦设备成功识别,固件升级过程便又快速又简单。
-
升级树莓派的操作系统和固件。 我建议在开始之前,确保你的操作系统已经 100%打上补丁/升级,树莓派的固件也已经更新到最新版本。
-
检查 LIRC 的依赖项。 现在,确保你的系统具备 LIRC 所需的所有内容。相关列表可以在
www.lirc.org/html/install.html#dependencies找到。我通过在 Linux 命令行输入以下命令来检查:$ which make $ which gcc $ which g++ $ which ld $ which modinfo $ which pkg-config $ which xsltproc每个命令应该输出相关项目的完整路径。如果没有响应,说明该项目在系统中缺失。你还应进行两个检查:
$ dpkg -l python3-yaml $ dpkg -l raspberrypi-kernel-headers如果你有这些,你应该看到关于该软件包的一些信息;如果没有,你应该看到一个抱怨,提示找不到这些软件包。我的新安装的 Raspbian 系统缺少这些软件包,以及前面提到的 xsltproc,因此我按如下方式安装了必要的项目:
$ sudo apt-get install xsltproc python3-yaml \ raspberrypi-kernel-headers -
安装 LIRC。 接下来,下载 LIRC 源代码,可以在 SourceForge 上获得,地址是
sourceforge.net/projects/lirc/files/LIRC/。选择最新版本的代码所在的目录,保存该版本的.tar.gz文件,然后进入保存位置。要解压并安装 LIRC,请在 Linux 命令行输入以下命令,替换为你的正确版本号:$ tar xjf lirc-version.tar.bz2 $ cd lirc-version $ ./configure $ make $ sudo make install $ sudo ldconfig -
连接 USB IR Toy 2。 现在,关闭你的 Pi 电源,然后插入 USB IR Toy 2。每次插入或拔出你的 Toy 时,确保关闭 Pi 的电源,否则可能会损坏设备!重新启动机器后,查看
dmesg日志文件,看看 Pi 是否找到了你的设备:$ dmesg | grep –e usb你应该看到类似这样的输出:
[ 2.982746] usb 1-1.2: new full-speed USB device number 4 using dwc_otg [ 3.090984] usb 1-1.2: New USB device found, idVendor=04d8, idProduct=fd08 [ 3.092965] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 3.096209] usb 1-1.2: Product: CDC Test [ 3.097827] usb 1-1.2: Manufacturer: Dangerous Prototypes [ 3.099458] usb 1-1.2: SerialNumber: 00000001 [ 4.358474] usbcore: registered new interface driver cdc_acm这个输出表明 Pi 找到了我的 USB IR Toy 2,并且能够自动找到并加载正确的内核级驱动程序
cdc_acm。如果你的机器在找到 Toy 后没有加载内核级驱动程序,你可以修改系统,使其每次启动时加载此驱动程序。如果你使用的是 Raspbian,可以通过编辑文件/etc/modules并添加以下行来实现:注意
如果你为你的项目使用了完全不同的 IR 发射器/接收器,你很可能会有不同的内核级驱动程序。这个驱动程序也可以在/etc/modules中加载。
cdc_acm一旦这一步正常工作,你可以使用
dmesg如下操作来查找分配给 USB IR Toy 2 的设备名称(这是下一步需要的):$ dmesg | grep -e cdc_acm我的输出给出了以下内容:
[ 4.332559] cdc_acm 1-1.2:1.0: ttyACM0: USB ACM device [ 4.358474] usbcore: registered new interface driver cdc_acm [ 4.360314] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters在这种情况下,我的 USB IR Toy 2 已被分配到设备/dev/ttyACM0。记录下你的设备分配。
-
配置lirc_options.conf。 LIRC 已经将一些默认配置文件放在/usr/local/etc/lirc中。此步骤需要以超级用户身份编辑/usr/local/etc/lirc/lirc_options.conf,并将
driver参数(此处不是内核级驱动程序,而是 LIRC 插件)更改为irtoy,将device参数更改为你在dmesg中看到的设备的完整路径。打开/usr/local/etc/lirc/lirc_options.conf文件,并将这些参数更改为如下所示:driver = irtoy device = /dev/ttyACM0如果你使用的不是 USB IR Toy 2,你可以使用以下命令找到所有其他可用插件的列表:
$ lirc-lsplugins在你进行此操作时,你可能还需要更改
pidfile和output的默认位置,以便它们与系统实际安装位置匹配。以我使用的 NOOBS 安装的 Raspbian 为例,我必须在每个位置前面加上 /usr/local。如果 LIRC 报告无法写入 PID 文件,说明你失败了!output = /usr/local/var/run/lirc/lircd pidfile = /usr/local/var/run/lirc/lircd.pid -
偏执检查。 为了确保你没有偏离轨道,请通过以下命令检查你使用的设备和驱动程序是否正确:
$ sudo mode2 -H irtoy -d /dev/ttyACM0将任何 IR 遥控器对准 USB IR Toy 2 并按下几个按钮。你应该会看到屏幕上出现流动的数据,表示通过按键操作,Pi 上的串行数据已经可用。我的开始是这样的:
Using driver irtoy on device /dev/ttyACM0 Trying device: /dev/ttyACM0 Using device: /dev/ttyACM0 Running as regular user pi space 1000000 pulse 3861 space 1000000 space 1000000 pulse 21 space 76799 pulse 127 space 12501 pulse 63 space 1112467 pulse 42 space 1000000 space 1000000 pulse 5119 space 4543 pulse 554 space 575 pulse 533 space 575 pulse 554 --snip--完成后,按 CTRL-C 退出该程序。
-
为你的按钮选择名称。 你所有遥控器的信息将存储在 .conf 文件中,位于 /usr/local/etc/lirc/lircd.conf.d 目录下。接下来的步骤是在这里为空调创建一个文件。我们将使用一个名为 irrecord 的程序来完成这项工作。
你遥控器上的每个按钮都需要在配置文件中有一个名称。写下你的选择,以便在录制按键时方便查看。LIRC 有一些标准的按钮名称,你可以选择使用或禁用;为了简单起见,我们在这个项目中将使用这些标准名称。你可以通过输入以下命令获取列表:
$ irrecord -l对于我的按钮,我选择并记录了以下内容:
on/off: KEY_POWER mode: KEY_MODE speed: KEY_FASTFORWARD timer: KEY_TIME temp/time up arrow: KEY_UP temp/time down arrow: KEY_DOWN -
额外加分:获取遥控器的型号。 虽然对于这个项目来说这不是严格必要的,但为了好看(也是 LIRC 的惯例),将配置文件命名为你正在使用的遥控器的名字是个不错的做法。我通过仔细查看海尔官网的备件部分并找到匹配项,找到了我的遥控器型号,Haier AC-5620-30。
注意
如果在录制过程中 USB IR Toy 2 停止工作,我建议在 Pi 断电的情况下重启 Pi,并拔掉/重新插上 USB IR Toy 2 的电缆。我不确定问题出在哪里,但录制可能会有些不稳定!
-
记录遥控器发送的代码。 现在,你将通过命名按钮并按下它们来创建一个粗略的初始配置文件,以便将原始(尚未解码的)代码记录并与其正确的按钮名称关联。记录原始信号将允许 LIRC 在你编程让电脑控制空调时,之后将其作为输出重现。
首先,移动到一个你有写权限的临时目录:
$ cd /home/pi/手持遥控器,并将 USB IR Toy 2 安排好,使其 LED 指向你,输入:
$ sudo irrecord -H irtoy -d /dev/ttyACM0 -f确保使用正确的驱动程序和设备名称。程序会引导你通过一些步骤收集你的遥控器发送的信号的技术信息。首先它会要求你输入遥控器的名称。然后它会要求你按下许多随机按钮,这样它就能了解这些按钮在新遥控器的未知协议中如何工作。一旦它确认能区分不同的按钮按压,它将要求你一一输入你选择的按钮名称,并为每个按钮展示按压操作。
按照所有指示操作直到完成。完成后,内容会保存到一个以你提供的遥控器型号为开头,以 .lircd.conf 结尾的文件中。
如果你之后发现某些按钮没有正确录制,你可以通过指定要更新的配置文件并使用
-u重新录制那些按钮。例如:$ irrecord -H irtoy -d /dev/ttyACM0 -f -u \ Haier_AC-5620-30.lircd.conf这种技术也可以用来将他人的配置文件适配到你的遥控器,只要它们足够兼容。
-
编辑你的 .lirc.conf 文件。 使用你喜欢的文本编辑器打开你新创建的配置文件,你应该会看到它有三个部分:
-
首先是一个注释区域,用井号 (#) 括起来,里面有空白处供你填写遥控器和其他相关细节。LIRC 社区希望这些信息以统一格式填写完整,以防你决定将文件与他人分享。如果你打算将文件保留为个人使用,填写注释是可选的。
-
接下来,在
begin remote下面,应该有一个部分,包含遥控器的名称和一些信号的基本串行通信特性。这个信息是在你执行第 10 步时,irrecord 收集到的,并且不同类型的遥控器会有所不同。我的配置看起来是这样的:begin remote name Remote_Haier_AC-5620-30.conf flags RAW_CODES|CONST_LENGTH eps 30 aeps 100 gap 108529 -
第三部分会列出你选择的按钮名称,每个按钮旁边都有 irrecord 关联的代码块。你可能会注意到其中一些看起来异常简短,或者与其他按钮明显不同。这些可能是录制错误的按钮。你将在下一步确认这一点。这是我在该部分的第一个按钮:
begin raw_codes name KEY_POWER 8981 4565 533 575 533 597 511 575 533 1706 511 1727 533 575 511 597 533 1706 511 1706 554 1685 533 1706 533 1706 533 575 511 1727 533 1706 533 575 533 1706 533 575 511 597 511 1727 533 1706 533 575 533 575 533 597 511 575 533 1706 533 1706 533 597 511 575 533 1706 533 1727 511 1706 533
-
-
测试你的 .lirc.conf 文件。 将 .lirc.conf 文件的副本移动到配置目录,方法如下:
$ sudo cp Haier_AC-5620-30.lircd.conf \ /usr/local/etc/lirc/lircd.conf.d/如果你没有使用默认的配置文件 devinput.lircd.conf,你可能希望将其更名为 devinput.lircd.conf.unused,这样 LIRC 就不会尝试使用它。
接下来,让我们测试配置文件。通过输入以下命令启动 LIRC:
$ sudo lircd在 LIRC 运行时,通过输入以下命令测试你的新配置文件:
$ sudo irw现在按下遥控器上的按钮,并对准 USB IR Toy 2。测试每个按钮,确保当你按下它时,屏幕上出现你为它选择的名称。如果有任何按钮按下后显示错误的名称,或者有按钮导致系统混乱(你会知道,因为它不会显示任何内容,而且在再次按下按钮之前会有很长时间的停顿),请做个记号。这些按钮可能是记录错误的。
测试完成后,按 CTRL-C 退出
irw,然后使用以下命令终止 LIRC 进程:$ sudo killall lircd拿着你列出的错误按钮,并使用第 10 步最后描述的
–u技巧重新录制它们。如果 irrecord 无法连接到 USB IR Toy 2,你可能需要断电重启 Pi 和 USB IR Toy 2。完成重新录制后,再次运行 sudo lircd。然后再次运行 sudo irw,测试按钮。重复此步骤,直到你的配置文件 100% 准确!这是 LIRC 在你要求它生成用于控制空调的代码时会查看的文件,因此这部分必须做好。
-
测试空调控制。 接下来,你必须验证录制的命令是否足够准确,以便在 LIRC 重现时能控制空调。你可以使用
irsend命令来做到这一点。首先,启动 LIRC:$ sudo lircd现在输入:
$ irsend list "" ""你应该能看到配置文件中列出的任何遥控器名称——在我的例子中,只有一个:
Haier_AC-5620-30你可以通过精确插入其名称,列出某个遥控器可用的命令,如列表中所示:
$ irsend list Haier_AC-5620-30 ""对我来说,这会产生以下内容:
0000000000000001 KEY_POWER 0000000000000002 KEY_FASTFORWARD 0000000000000003 KEY_UP 0000000000000004 KEY_DOWN 0000000000000005 KEY_TIME 0000000000000006 KEY_MODE我从第 8 步选择的按钮名称与这个列表的相似性绝非巧合!它是从我们创建的配置文件中读取名称的。现在应该可以取其中一个按钮名称,并将其与遥控器名称组合,发送如下命令:
$ irsend SEND_ONCE Haier_AC-5620-30 KEY_POWER哇!我的空调开了。如果你打算长期使用这个来控制某些设备,你需要充分测试所有按钮,确保你的 LIRC 和 USB IR Toy 2 能够稳定地配合工作。
修补不稳定的 LIRC
当我第一次使用 LIRC 0.9.4d 达到这一步时,发现它非常不稳定。每执行几条命令,LIRC 和 USB IR Toy 2 都会死机并显示错误信息。如果我重新插拔 USB IR Toy 2 并重新运行 LIRC,它又会正常工作——持续几个命令。如果你像我一样遇到这个问题,可以在 sourceforge.net/u/bengtmartensson/lirc/ci/experimental-irtoy/ 上找到一个补丁,应该可以修复这个问题。尽管 diff 补丁设计成可以自动应用,但由于版本的不同,你可能需要手动应用这个补丁。
要应用补丁,首先备份你的 lirc_options.conf 文件,如下所示:
$ sudo mv /usr/local/etc/lirc/lirc_options.conf \
/usr/local/etc/lirc/lirc_options.conf.backup
然后返回到你编译 LIRC 的目录,在我的例子中是 ~/lirc-0.9.4d/。从那里,编辑 ./plugins/irtoy.c,并根据 diff 中的绿色和红色行进行增减。接着清理目录并像下面这样重新编译:
$ ./configure
$ make clean
$ make
$ sudo make install
重新编译完成后,恢复你自己的lirc_options.conf文件:
$ sudo mv /usr/local/etc/lirc/lirc_options.conf.backup \
/usr/local/etc/lirc/lirc_options.conf
如果你之前更改过devinput.lircd.conf的名称,你需要删除编译后添加的新副本:
$ sudo rm /usr/local/etc/lirc/lircd.conf.d/\
devinput.lircd.conf
现在重复第 13 步,看看系统是否现在能可靠运行。补丁完全解决了我的问题!
-
分析你的.conf文件。 当你对.conf文件的性能 100%满意时,你可以通过以下命令告诉 LIRC 更彻底地分析遥控器的协议:
$ cd ~ $ sudo cp /usr/local/etc/lirc/lircd.conf.d/\ Haier_AC-5620-30.lircd.conf . $ irrecord –a ~/Haier_AC-5620-30.lircd.conf从技术上讲,你本可以在第一次录制后立即尝试这个方法,但就我个人而言,我发现如果先处理任何错误或缺失的按钮会更有效。一旦分析完毕,我的整个文件已经大大缩小,现在看起来像这样:
begin remote name Haier_AC-5620-30 bits 32 flags SPACE_ENC|CONST_LENGTH eps 30 aeps 100 header 8984 4554 one 525 1712 zero 525 584 ptrail 529 gap 108529 toggle_bit_mask 0x0 frequency 38000 begin codes KEY_POWER 0x19F69867 KEY_MODE 0x19F610EF KEY_FASTFORWARD 0x19F620DF KEY_TIME 0x19F658A7 KEY_UP 0x19F6A05F KEY_DOWN 0x19F6906F end codes end remote这不仅比第 11 步中显示的原始版本(部分)更简洁、更易读,而且现在关于空调所使用的协议有了更多的了解。除了头部、频率等信息外,实际的命令已经被解码,并以十六进制的形式表示,而不是模仿不同长度的闪烁信号。这意味着 LIRC 现在真正知道它在做什么,而不是重复它无法理解的内容。对于准确控制空调来说,这无疑是件好事!
将分析结果剪切并粘贴到原始的.lircd.conf文件中,然后杀死并重新启动 LIRC 来尝试一下,应该能正常工作。
注意
如果在尝试分析文件时没有任何变化或发生任何事情,说明 LIRC 无法识别你的协议。在这种情况下,继续使用原始的.conf文件。
-
自动运行 LIRC。 一旦你正确配置了 LIRC,你可以最后一次运行它并让它保持运行。如果你计划设置任务来控制空调,且希望机器重启后能够继续工作,你还可以设置它在启动 Pi 时自动运行。要在 Raspbian 系统上做到这一点,作为超级用户编辑/etc/rc.local文件,并添加以下行:
lircd -
编程 Pi 来控制空调。 现在你已经让 USB IR Toy 2 与 LIRC 通信,并证明可以用它控制空调,你有很多有趣的选项来自动化空调的实际运行。请访问
www.lirc.org/software.html,查看与 LIRC 相关的兼容软件和应用程序,允许你以不同的方式操作空调,或将其与多媒体设备集成。我喜欢使用命令行,所以我的示例脚本将使用 bash 编写。但不要让这个限制了你对所有可能工具的尝试!假设你的空调所在的房间在白天升温,而你在上班或上学时不在家。你可以让空调整天开着以保持房间凉爽,但如果在你回家前才开空调,经济性会更好。那么假设你希望空调在下午 4:30 开启。Linux 有一个叫做
cron的守护进程,可以按计划运行程序。你可以写一个cron任务来实现这个目标,输入:$ sudo crontab –e然后在你的 crontab 中添加类似这样的行:
30 16 * * * /path/to/your/script/air_conditioner.sh这指定了一个名为air_conditioner.sh的脚本,将在每天 16 点 30 分运行。(如果你想更深入了解
cron,可以尝试阅读man crontab!)接下来,创建实际的脚本并在文本编辑器中保存为air_conditioner.sh。一个打开空调的 bash 脚本示例可能是非常简单的:
#!/bin/sh # # Sample program to control A/C # irsend SEND_ONCE Haier_AC-5620-30 KEY_POWER这假设空调在你早上离开时总是关闭的。由于这是一个开环控制系统(意味着计算机无法知道空调最初是开着还是关着),为了使其正常工作,必须知道初始状态。因此,一些你想要做的事情可能需要你自己动脑筋,确保初始状态总是已知的。
进一步操作
修改这个项目的一个选择是将其变成一个闭环系统,在这个系统中,树莓派实际上可以检查空调的状态。你可以在房间里安装一个温度传感器,或者在空调电源线安装一个感应电流传感器,然后让树莓派读取这些信号来确定空调的工作状态。如果你有摄像头,并且有些雄心壮志,你甚至可以让树莓派通过检查空调前面板上的 LED 灯状态来判断空调的工作情况。
即使你保持开环系统,还是有办法利用外部信息为自动化提供动力。这里有一个你现在可以尝试的实验:假设你希望空调只有在外面气温超过 90 华氏度时才在 4:30 开启。你可以在早上关闭空调,并让你的树莓派检查 NOAA(美国国家海洋和大气管理局)网站,获取你所在地区的当前天气状况,像这样:
wget -q -O current_conditions.txt "http://forecast.weather
.gov/MapClick.php?CityName=Los_Angeles&state=CA&site=LAX&lat
=34.06076&lon=-118.23510"
注意
像所有网站一样,NOAA 网站的 URL 或内容可能会发生变化,这可能会导致你的脚本失效。如果发生这种情况,请修改 URL 和/或脚本中的 sed 模式匹配,以获取你想要的信息。
除非你住在洛杉矶,否则当你完成这一部分时,想要更改为你自己城市的 URL。以下命令将去掉保存的网址,仅保留当天的当前温度:
grep -e myforecast-current-lrg current_conditions.txt | sed 's/.*myforecast-current-lrg\">\(.*\)\°F<\/p>.*/\1/g'
添加日志功能是很有用的,这样你就可以看到树莓派是否尝试发送开机命令。你可以使用logger命令来实现,比如:
logger 'Your message here'
将所有内容结合起来,我为你提供了这个示例程序,供你编辑和尝试:
#!/bin/sh
#
# Sample program to control A/C
#
CONTROL_TEMP=90
wget -4 -q -O current_conditions.txt "http://forecast
.weather.gov/MapClick.php?CityName=Los_Angeles&state=CA&site
=LAX&lat=34.06076&lon=-118.23510"
CURRENT_TEMP=`grep -e myforecast-current-lrg
current_conditions.txt | sed 's/.*myforecast-current-lrg\">\(.*\)\°F<\/p>.*/\1/g'`
if [ $CURRENT_TEMP -ge $CONTROL_TEMP ];
then
irsend SEND_ONCE Haier_AC-5620-30 KEY_POWER
logger 'Temperature of '$CURRENT_TEMP' is at or above '$CONTROL_TEMP'. Air conditioner power command sent.'
else
logger 'Temperature of '$CURRENT_TEMP' is below '$CONTROL_TEMP'. Air conditioner power signal not sent.'
fi
总结
在本章中,你了解了红外光和红外 LED,以及一些——希望!——引人入胜的通信协议知识。你创建了一个系统,通过红外光从计算机远程控制空调。我希望你能在书籍和网上进一步探索,因为串行通信、电路设计和 LED 技术有很多值得学习的内容。要深入学习如何从离散元件设计电子电路,包括 LED,我推荐霍罗维茨和希尔的《电子艺术》。
第八章:星域灯效盒,由 Adam Wolf 设计
在这个项目中,你将制作一个带有星域灯效的装饰性显示盒。

星域效果是最早的计算机效果演示之一:星星在屏幕上呈现并被模糊,使得看起来就像在星际中飞行。远离你的星星移动缓慢,靠近你的星星则快速飞过。许多人认识这个效果是通过 Windows 3.1 的屏幕保护程序,但它至少自 70 年代末就已存在。在这个项目中,我们将使用 32 × 32 LED 矩阵和 SmartMatrix SD Shield 创建一个星域演示,SmartMatrix SD Shield 作为微控制器与 LED 之间的中介硬件。这款 Shield 微控制器处理了驱动所有 LED 所需的复杂工作。
我将矩阵安装在带有黑色扩散器的影像盒中。我将其称为 Bowman 盒子,灵感来自于 2001 太空漫游 中的 Dave Bowman。
获取零件
我已经尽力将此项目的代码和说明做得易于适配任何 LED 矩阵,但如果你使用 SmartMatrix SD Shield 和与其兼容的 SmartMatrix SD Shield LED 矩阵,项目会更加简单。
组件
注意
如果你修改项目,使得更多的 LED 同时点亮,你需要找到一个额定电流更高的开关,或者直接将电源连接到板子上。
-
32 × 32 RGB LED 矩阵(Adafruit P/N 1484 或 SparkFun P/N 12584;必须与直接插入 Hub75 连接器的 SmartMatrix SD Shield 兼容)
-
5 V 4A+ 壁式电源适配器(Adafruit P/N 1466;必须具备标准的 2.1 毫米中心正极连接器)
-
SmartMatrix SD Shield(可从制造商或 Adafruit P/N 1902 购买;v3 是截至本文写作时的最新版本)
-
Teensy 3.1 或 3.2(Adafruit P/N 2756;这是一款小巧、廉价且功能强大的微控制器开发板)
-
MicroUSB 电缆
-
带有 2.1 毫米连接器的内联电源开关(Adafruit P/N 1125 或 SparkFun P/N 11705)
-
影像盒(8 × 8 英寸)
-
扩散器(一种能够扩散光线的半透明材料,填补 LED 之间的空隙;我使用的是一块薄黑色毡布,但你也可以使用纸巾、塑料,甚至是涂抹在玻璃上的东西)
-
(可选)纸板(用于将所有组件紧凑地安装在影像盒中)
工具
-
烙铁和焊料
-
斜口钳
-
剥线钳
-
小螺丝刀
-
剪刀
-
锯子、钻机或锉刀
-
黑色马克笔
构建它
首先,按照制造商的说明组装 SmartMatrix SD Shield,并将其连接到 LED 矩阵。接着,你需要将扩散器夹在 LED 显示屏和影像盒的玻璃之间。检查一切是否都能恰好装入影像盒后,再取下盒子背面,剪一个小缺口以便电源线通过,上传程序并重新组装一切。
注意
如果你需要焊接说明,请参阅附录。
-
组装 SmartMatrix SD Shield。 访问制造商网站
docs.pixelmatix.com/并导航到 SmartMatrix Shield 部分。找到 SmartMatrix SD v3 部分,然后在左侧菜单中点击 Kit Assembly。这应该会带你到 Shield 的组装说明。阅读并仔细遵循制造商的说明——这需要大量的焊接——然后仔细检查你的工作。当你的 Shield 完成后,将其插入 LED 面板的输入连接器中,如 图 7-1 所示。
![image]()
图 7-1: 组装好的 SmartMatrix SD Shield 插入 LED 显示屏
Smart Matrix SD Shield 使用 Teensy 3.1 或 3.2 微控制器板。我们将在 Arduino 中编程 Teensy,Arduino 支持 Windows、macOS 和 Linux 系统。
-
设置 Teensy。 从
www.arduino.cc/下载最新版本的 Arduino IDE,从www.pjrc.com/teensy/teensyduino.html安装 Teensyduino,然后通过 IDE 的库管理器安装 SmartMatrix3 库。使用 microUSB 电缆将 Teensy 连接到计算机,并将显示器连接到电源。进入 工具 ▸ 板 并选择 Teensy 3.2/3.1。 -
测试 Teensy。 通过进入 文件 ▸ 示例 ▸ SmartMatrix3 ▸ FeatureDemo 来加载 FeatureDemo 示例。将代码上传到 Teensy,Teensyduino Uploader 应该会出现并将代码发送到 Teensy。如果你以前从未使用过 Teensy,可能会发现它看起来不同于标准的 Arduino IDE,但 Teensy 部分会自动完成,因此你无需额外操作。
如果一切正常,你应该会看到一个演示在 Teensy 上播放,展示 SmartMatrix3 库的各种功能。你会看到不同的颜色、移动的形状和滚动的文本。这表明计算机、LED 面板、SmartMatrix SD Shield 和 Teensy 都在正常工作。现在让我们完成外壳部分。
-
切割扩散器。 拆下影像盒的背面并测量内部尺寸。用剪刀裁剪扩散器材料,如 图 7-2 所示。你可以精确匹配影像盒的内部尺寸,或者稍微切大一些,这样你可以将边缘粘贴到盒子的侧面。
![image]()
图 7-2: 切割扩散器
如果尺寸稍微偏差一点,可能也没关系!盒子内部的其余部分是黑色的,所以任何缝隙都不会太显眼。
-
将显示器试装到影箱内。 清理影箱玻璃上的污渍,然后将影箱的玻璃面朝下放在桌子上,接着将扩散器放入影箱并贴合玻璃。接着将显示器(LED 面朝下)放在扩散器上。如果你有小磁螺丝,将它们拧到 LED 面板的四个角落。检查一下影箱的背面是否仍然能装上,如图 7-3 所示。
如果装配过紧,试着去除影箱背面任何黑色的天鹅绒材料,或者取下 LED 面板框架上的磁螺丝。如果装配过松,你可以使用一些纸板作为垫片,确保一切都固定好。
![image]()
图 7-3: 测试一切是否适配在影箱内
-
在影箱的背面切一个缺口。 再次取下影箱的背面。将 2.1 毫米的直插开关电源插头插入 SmartMatrix SD Shield 的 DC 电源连接器中。电缆应该恰好能伸出箱外。按照图 7-4 的示意,在影箱背面切一个小缺口,深约 3/4 英寸,宽约 1/4 英寸,用来穿过电源线。我建议你在一个边缘的中间或角落切这个缺口。你可以使用许多工具来完成这个切割,比如手锯、电钻、锉刀,甚至是尖嘴钳。
![image]()
图 7-4: 带有切割缺口以便电源线通过的影箱背面
如果你的影箱背面有天鹅绒衬里,你也需要在背面切一个缝隙,并确保它与背面切割的缺口对齐。最后,用黑色马克笔修复任何擦伤的痕迹。
-
组装它。 现在重新安装影箱的背面。一切应该都很合适。如果不合适,可以用一些纸板作为垫片和隔板。安装完后,任何小的外观问题都可以忽略,尤其是当星星飞速掠过时。说到这,还是把背面再取下来,这样我们就可以访问 Teensy 进行编程了!
如果你想直接跳到下一步骤,可以跳到第 140 页的“编码它”部分。如果你对星空效果的原理感到好奇,继续往下读。
生成星空效果
我们需要创建一个穿越一群星星的效果。近距离的星星应该更亮并且移动得比远距离的星星更快。所有的星星都应该从中心向外径向移动。
为了在软件中实现星空效果,我们将创建一个星星的列表,并将它们随机分布在一个三维空间的坐标系统中。我们将用三个坐标值来表示每个点,比如 (x, y, z),其中 x 代表水平轴,y 代表垂直轴,z 代表深度。你可以把 z 看作是你与点的距离——z 值越高,点看起来就越远。我们的眼睛,即三维空间中的默认点,位于原点 (0, 0, 0)。
一旦我们完成了随机放置的星星列表,我们就得克服在 2D 显示器上绘制 3D 空间中的点的问题。想象一下把空间区域画成一个四面体,上面和下面被切掉了。这就是所谓的视锥体,如图所示。

黄色的方块代表我们的显示屏,每个单位在x和y上都有一个 LED。这意味着坐标为(0, 0, 0)的点位于显示器的中间,坐标为(–8, –8, 0)的点位于左下角的中间,坐标为(8, 8, 0)的点位于 LED 面板的右上角中间。
我们还需要考虑z距离。坐标为(8, 8, 100)的点不应该绘制在 LED 面板右上角的中间。它应该比坐标(8, 8, 0)更靠近显示器的中间,因为它离相机更远。换句话说,随着 z 坐标变大,x 和 y 坐标需要向眼睛移动。
为了将 3D 坐标转换为 2D 坐标,我们将每个 x 和 y 坐标除以z。可以把 2D 坐标看作是在特定深度(或z)下总框架大小的百分比。将 x 和 y 坐标除以z,我们得到的是视锥体边缘的 45 度角,这样对于每一步的z,我们就可以看到在x和y上的额外一步。我们可以尝试不同的因子,比如将其除以 2 倍的z,或者将其除以z的一半,这会改变视锥体边缘的坡度。
在我的 Bowman Box 中,任何距离的星星都是由一个 LED 绘制的,但 LED 的亮度与距离成正比:距离我们最远的星星亮度最小,位于圆锥体最前面中心的星星亮度最大。为了简化程序,我们仅根据 z 值进行缩放。
哎呀!编程比解释短得多!现在我们知道如何在显示器上绘制星星,我们需要移动!我们想要穿越星星,但不是让眼睛在z轴上向前移动,而是让所有星星在z轴上朝着眼睛移动。这样做让编程更简单。一旦星星超过了我们的视线,我们当然看不见它了,所以我们会在距离我们最远的地方重新创建它。
编程它
如果你想跳过所有关于代码和它如何工作的解释,你可以直接下载代码到nostarch.com/LEDHandbook/并将其上传到你的项目中。完整的代码可以在清单 7-1 中查看。
清单 7-1: 星域效果代码
/* StarfieldEffect.ino
by Adam Wolf
Uses a SmartMatrix SD Shield, a 32 by 32 RGB LED display,
and a Teensy to show a starfield effect.
*/
➊ #include <SmartMatrix3.h>
#define COLOR_DEPTH 24
const uint8_t kMatrixWidth = 32;
const uint8_t kMatrixHeight = 32;
const uint8_t kRefreshDepth = 36;
const uint8_t kDmaBufferRows = 4;
const uint8_t kPanelType = SMARTMATRIX_HUB75_32ROW_MOD16SCAN;
const uint8_t kMatrixOptions = (SMARTMATRIX_OPTIONS_NONE);
const uint8_t kBackgroundLayerOptions =
(SM_BACKGROUND_OPTIONS_NONE);
const uint8_t kScrollingLayerOptions =
(SM_SCROLLING_OPTIONS_NONE);
const uint8_t kIndexedLayerOptions = (SM_INDEXED_OPTIONS_NONE);
SMARTMATRIX_ALLOCATE_BUFFERS(matrix, kMatrixWidth,
kMatrixHeight, kRefreshDepth, kDmaBufferRows,
kPanelType, kMatrixOptions);
SMARTMATRIX_ALLOCATE_BACKGROUND_LAYER(backgroundLayer,
kMatrixWidth, kMatrixHeight, COLOR_DEPTH,
kBackgroundLayerOptions);
SMARTMATRIX_ALLOCATE_SCROLLING_LAYER(scrollingLayer,
kMatrixWidth, kMatrixHeight, COLOR_DEPTH,
kScrollingLayerOptions);
SMARTMATRIX_ALLOCATE_INDEXED_LAYER(indexedLayer, kMatrixWidth,
kMatrixHeight, COLOR_DEPTH, kIndexedLayerOptions);
struct Star {
int16_t x;
int16_t y;
float z;
};
#define NUM_STARS 32
struct Star stars[NUM_STARS];
const int X_RANGE = 400;
const int Y_RANGE = 400;
const int HALF_X_RANGE = X_RANGE / 2;
const int HALF_Y_RANGE = Y_RANGE / 2;
const int MAX_Z = 16;
const uint8_t SCREEN_WIDTH = 32;
const uint8_t SCREEN_HEIGHT = 32;
const uint8_t HALF_SCREEN_WIDTH = SCREEN_WIDTH / 2;
const uint8_t HALF_SCREEN_HEIGHT = SCREEN_HEIGHT / 2;
const float SPEED = 0.1;
➋ void randomizeStarPosition(struct Star* s) {
s->x = random(-HALF_X_RANGE, HALF_X_RANGE);
s->y = random(-HALF_Y_RANGE, HALF_Y_RANGE);
s->z = MAX_Z; // Put the star in the back.
}
void drawStar(struct Star* s) {
uint8_t display_x = (int) (s->x / s->z);
uint8_t display_y = (int) (s->y / s->z);
➌ display_x = display_x + HALF_SCREEN_WIDTH;
display_y = display_y + HALF_SCREEN_HEIGHT;
// Let's check if our calculated point should be displayed.
if (display_x >= 0 &&
display_y >= 0 &&
display_x < SCREEN_WIDTH &&
display_y < SCREEN_HEIGHT) {
uint8_t brightness = map(s->z, 0, MAX_Z, 255, 0);
drawPoint(display_x, display_y, brightness); // It fits,
// so draw it!
} else {
randomizeStarPosition(s); // It does not fit,
// so make a new star.
}
}
void advanceStar(struct Star* s) {
s->z -= SPEED;
if (s->z <= 0) {
randomizeStarPosition(s); // If the star has passed us,
// make a new one.
}
}
void setup() {
➍ randomSeed(analogRead(A1));
for (int i = 0; i < NUM_STARS; i++) {
Star* current_star = &stars[i];
randomizeStarPosition(current_star);
➎ current_star->z = random(0, MAX_Z);
}
setupDisplay();
}
void loop() {
clearDisplay();
for (int i = 0; i < NUM_STARS; i++) {
drawStar(&stars[i]);
}
paintDisplay();
for (int i = 0; i < NUM_STARS; i++) {
advanceStar(&stars[i]);
}
}
uint16_t distanceToStar(struct Star* s) { // distance
return sqrt(sq(s->x) + sq(s->y) + sq(s->z)); // from (0, 0, 0)
}
void clearDisplay() {
backgroundLayer.fillScreen({0x00, 0x00, 0x00});
}
void drawPoint(uint8_t x, uint8_t y, uint8_t brightness) {
// Note this doesn't actually show it on the display.
backgroundLayer.drawPixel(x, y,
{brightness, brightness, brightness});
}
void paintDisplay() {
// Send the image we've built up to the screen.
backgroundLayer.swapBuffers(false);
}
➏ void setupDisplay() {
matrix.addLayer(&backgroundLayer);
matrix.addLayer(&scrollingLayer);
matrix.addLayer(&indexedLayer);
matrix.begin();
backgroundLayer.enableColorCorrection(true);
}
在阅读这个草图时,有几件事需要注意。Arduino 草图首先运行setup()函数,然后反复运行loop()函数。
➊和➏处的代码块直接来自与 IDE 一起提供的 SmartMatrix 示例,用于设置 SmartMatrix 库。
我们使用了一个结构体(struct),它是一个变量的集合,用来存储我们草图中的一些信息。结构体可以通过将相关信息分组,使代码的意图更加清晰。我们在程序开始时创建了一堆星星结构体。当一颗星星移动到我们视野之外或被我们超越时,我们随机化那颗星星的坐标,并将其设置得远离我们,以便我们能够再次遇到它➋。这样我们就能重用这些结构体,而不需要无限量的星星。
我们希望星星的原点位于显示屏的中央,但 SmartMatrix 库将原点设置在左下角,因此在显示星星时,我们需要调整这一点➌。
我们还需要一个随机数生成器来将星星放置在随机的位置。Arduino 本身没有真正的随机数生成器,因此我们通过在➍读取一个未连接的引脚来初始化系统,以便每次获得不同的伪随机数。读取未连接的引脚并不是一个很好的“随机种子”,因此如果你多次运行,可能会看到它以相同的方式启动。有一些方法可以使其更加随机,但我们为了清晰性保持了简单。
因为通常新星只会出现在背景中,所以我们在初始化星星的位置时,将它们散布在整个 z 轴上➎。
确保你已经将电源连接到电源开关上,然后打开开关。将代码上传到你的 Teensy,确保一切上传正确,然后重新将背面装回你的影像盒。
总结
恭喜!你现在应该有了一个漂亮的 LED 矩阵,装在一个精致的盒子里。你可以以多种方式改进和扩展这个项目。但请记住,在我们的项目中,大多数 LED 在任何时刻都是关闭的。如果你改变项目,同时开启更多的 LED,你需要注意电源问题。内联开关的额定电流不足以支撑整个屏幕的全亮度,但你可以移除它,并将电源直接插入板子。
作为进一步的升级,我考虑添加一个加速度计,这样我就可以通过移动框架来操控,改变飞行时的角度和速度。我甚至可能添加彩色星星——不是明亮的彩虹色星星,而是稍微带点红色和蓝色的星星,用来代表行星和星云。天空才是极限!尝试一些不同的方式,看看哪种效果最适合你。
第九章:John Baichtal 的光学螺丝刀
这个项目是一个基于光的打击乐器,呈魔杖形状,与配有光传感器的合成器一起使用,创造酷炫的音效。

在这个项目中,你将制作一个光学螺丝刀,通过 LED 闪烁向光传感器发送信号,传感器根据接收到的输入告知合成器播放哪些节奏。你可以修改节奏的速率和时长,创造复杂的合成音乐。
我将向你展示如何制作三种不同的螺丝刀,从简单到高级。你不必做全部三种,只需选择你准备好处理的“酷度”级别。
第一个版本是一个超级基础的 Arduino 项目,任何人都可以轻松构建。你还需要组装一个测试装置——一个基本的合成器,由 Arduino、扬声器和光传感器组成——以确保它能正常工作。之后,我将向你展示如何通过几个改进来升级你的螺丝刀:简化的微控制器和一块棒状的印刷电路板(PCB)。
构建基础螺丝刀
让我们从最简单的光学螺丝刀配置开始:一个普通的 Arduino,配备 LED 和三个可调电位器,如图 8-1 所示。虽然它看起来不特别像魔杖,但它给你一个不那么华丽但同样有效的等效物——它使得光学 LED 闪烁,与配有传感器的合成器互动。三个电位器将用于控制 LED 闪烁的速度、持续时间和暂停。

图 8-1: 螺丝刀的基础版本
获取零件
完成这个项目的第一阶段,你只需要一些零件。我还包括了你需要构建的测试装置的零件,只有通过它才能听到任何声音。测试装置只是一个光传感器、Arduino 和扬声器。
注意
参见 “Arduino 和 Arduino IDE 入门” 在 第 15 页 获取设置说明。
-
两块 Arduino Uno 板或类似的(Adafruit P/N 50)
-
半尺寸面包板(Adafruit P/N 64)
-
跳线套件(Adafruit P/N 153)
-
电池适配器或 9V 电池夹(Adafruit P/N 63 或 Adafruit P/N 80)
-
超亮 LED(例如,SparkFun P/N 531)
-
三个 10 kΩ电位器(我使用了 SparkFun P/N 9939,但 P/N 9288 也可以使用;我使用了 Adafruit 的细旋钮,P/N 2057)
-
光传感器(Adafruit P/N 161)
-
8 Ω 扬声器(例如,Adafruit P/N 1313;你需要自己焊接电线)
-
220 Ω 和 10 kΩ 电阻(SparkFun P/N 10969 是一个不错的多包装)
组装电路
最基础的螺丝刀可能不会给你带来太大挑战,但不用担心——这个项目升级得很快!我们开始吧:
-
插入 LED。 将 LED 的长脚连接到 9 号引脚,中间加上一个 220 Ω电阻,然后将短脚连接到 GND 旁边。图 8-2 显示了它应该是什么样子。
![image]()
图 8-2: 将 LED 和电阻添加到面包板上
-
连接电位器。 添加三个电位器。对于每个电位器,将最左侧的引脚连接到 GND,最右侧的引脚连接到 5V。中间的引脚是数据连接,如图 8-3 所示。哪一个是 GND,哪一个是 5V 并不重要,只要中间引脚连接到数据即可。将每根线的一端连接到 A0、A1 和 A2 引脚,如图 8-3 中的紫色线所示。
![image]()
图 8-3: 将电位器连接到适当的模拟引脚
-
添加电源。 通过将 Arduino 连接到墙壁电源或 9V 电池来为其供电。你还需要为原型板供电,因此将 Arduino 的 5V 和 GND 引脚连接到板两侧的电源和接地总线。这些新线用红色(电源)和黑色(接地)表示,如图 8-4 所示。
![image]()
图 8-4: 将面包板连接到 Arduino 的 5V 和 GND 引脚
编写代码
这个草图基本上是 Blink 示例草图,我在其中添加了电位器来修改节奏。你可以在* nostarch.com/LEDHandbook/* 下载它以及本书的其他项目文件。
让我们逐部分了解代码:
void setup() {
pinMode(9, OUTPUT); //change to 0 with the Tiny85
pinMode(A0, INPUT);
pinMode(A1, INPUT);
pinMode(A2, INPUT);
}
注意
如果你使用 ATtiny85 微控制器,请记得将所有 pin 9 的实例更改为 pin 0——稍后会详细介绍!
void setup() 函数在 Arduino 通电或重置时运行一次。在本例中,setup 函数告诉 Arduino 哪些引脚用作输入,哪些用作输出。
接下来是循环部分。
void loop() {
int speedKnob = analogRead(A0);
int durationKnob = analogRead(A1);
int skipKnob = analogRead(A2);
int currentSpeed = map(speedKnob, 0, 1027, 10, 900);
int currentDuration = map(durationKnob, 0, 1027, 100, 800);
int currentSkip = map(skipKnob, 0, 1027, 1, 150);
void loop()的第一部分声明了一系列变量,与三个电位器对应——速度、时长和跳过。为了方便编写代码,我将节奏之间的时间标记为speed,每个节拍的时长标记为duration,LED 在“关闭”状态下的亮度级别标记为skip。这样,我们就有了“从亮到暗”的选项,而不是“开或关”,使得流畅度更高。
最后,代码将三个电位器的读数映射出来,并将其值转换为我们可以使用的内容——电位器的输出范围是 0–1023,因此代码将该值转换为秒数。你可以随意更改这些值,以便使螺丝刀更好地为你工作!
digitalWrite(9, HIGH); //the LED turns on
delay(currentDuration);
digitalWrite(9, LOW); //the LED turns off for a moment
delay(10);
digitalWrite(9, currentSkip); //the LED dims
delay(currentDuration * 0.5);
digitalWrite(9, LOW); //the LED turns off
delay(currentSpeed);
}
代码的最后部分控制草图的实际工作:打开和关闭 LED。LED 的亮灭时间等于currentDuration的值,或者在 100 到 800 微秒之间。当合成器的光传感器检测到这些节拍时,它会发出声音。将螺丝刀靠得更近会产生更大的节拍声音,而拉远它则会发出更微妙的声音。
搭建测试设备
除非你手头有一个光感合成器,否则你需要自己制作一个。这个平台发出一个节拍,节拍通过光传感器传送的数据进行修改,因此它能够与螺丝刀互动。你需要从零件清单中获取额外的 Arduino 以及扬声器。你可以在 图 8-5 中看到我制作的超级简单的测试平台。

图 8-5: 测试平台帮助你确保螺丝刀正常工作。
-
接线扬声器。 将扬声器的正极引脚插入第二个 Arduino 的 9 号引脚,负极引脚插入 GND。图 8-6 显示了它的连接方式。
![image]()
图 8-6: 将扬声器连接到 Arduino
-
连接光传感器和电阻。 将光传感器的一端连接到 A0 引脚,另一端连接到 5V。将一个 10 kΩ 电阻插入同一个 A0 引脚,或者将光传感器的引脚和电阻连接在一起。将电阻的另一端连接到 GND,如 图 8-7 所示。
![image]()
图 8-7: 连接光传感器和电阻
-
编写代码。 测试平台的代码是
tonePitchFollower示例草图的一个变种,根据光传感器检测到的级别来改变音调。我通过将节拍长度和暂停长度与同一个光传感器绑定,加入了一些额外的创意,使光学螺丝刀能够同时通过光传感器修改节拍的音调、长度和节拍间的时间。void setup() { } void loop() { int sensorReading = analogRead(A0); int thisPitch = map(sensorReading, 400, 1000, 120, 1500); int reverseReading = map(sensorReading, 400, 1000, 1023, 1); tone(9, thisPitch, reverseReading); delay(10); } -
测试。 测试平台创建一个循环的音调序列,每秒 100 个音调,频率等于光传感器的读数,并通过重新映射传感器读数来确定音调的持续时间。即使没有螺丝刀,你也可以通过把手指放在光传感器上并改变其读数来玩这个测试平台。
当你将螺丝刀那闪烁的怪异光线加入其中时,随着光的波动产生复杂的声音结构,更加复杂的模式也随之出现。
使用 ATtiny85 构建魔杖版
接下来,我将向你展示如何换上 ATtiny85,这是一款比 Arduino 中的 ATmega328p 更小的微控制器。它是一个更简单的芯片,没有 Arduino 板的额外功能,但它也更紧凑,这使得你能够将螺丝刀电路从原型板上移到一个更便于携带的魔杖上。
获取零件
获取以下零件,使用 ATtiny85 构建一个焊接版的基础螺丝刀。如果你愿意,可以重新使用之前原型构建中的零件。
组件
-
Arduino Uno(重新使用 “构建测试平台” 中的那个,第 152 页)
-
ATtiny85 微控制器(例如,SparkFun P/N 9378)
-
超亮 LED(例如,SparkFun P/N 531)
-
两个 220 Ω 电阻
-
10 μF 电容(SparkFun P/N 523)
-
Perma-Proto 板(Adafruit P/N 571;这些板需要你焊接组件)
-
8 针 IC 插座(Adafruit P/N 2202)
-
三个可调电阻(我建议使用 SparkFun P/N 9288,因为它们可以焊接到位)
-
5V 电源(例如,SparkFun P/N 12889)
-
电源的桶形插座(Adafruit P/N 373 或 SparkFun P/N 10811)
注意
你不应该使用 9V 电池,因为 ATtiny85 缺乏 Uno 的电源管理功能,Uno 可以将输入电压转换为 5V。如果使用 9V 电池,芯片将过载。
工具
-
焊接铁
-
焊接
注意
请参见附录中的焊接说明。
让我们来看一下 ATtiny85 的技术细节。它有八个引脚,包括电源、接地以及各种模拟和数字数据引脚。图 8-8 展示了引脚布局。

图 8-8: ATtiny85 的八个引脚控制了惊人的计算能力。
烧录 ATtiny85
使用 ATtiny85 的一个缺点是,我们失去了一些在使用 Arduino 时所拥有的编程便利性。Arduino 具有一个非常方便的基于 USB 的引导加载程序,但它的较小版本没有,因此你需要使用另一块 Arduino 来编程 ATtiny85。由于芯片的引脚需要用于编程,我们不能在编程之前组装项目。使用这个版本的光学螺丝刀,当芯片安装到电路板上后,你将无法重新烧录芯片。
操作方法如下:
-
连接 ATtiny85。 按照第 152 页中的“构建测试平台”使用 Arduino,如图 8-9 所示。在这一步中,图 8-8 中显示的引脚分配变得非常重要。将引脚 1 连接到数字引脚 10,图 8-9 中的蓝色线表示。将引脚 4 通过黑线连接到 GND。将一根红线从引脚 5 插入电源总线。将引脚 6、7 和 8 分别连接到 Arduino 的 13、12 和 11 引脚,图 8-9 中的黄色、白色和绿色线表示。
-
连接 LED 和电容器。 你还需要连接一个 LED,并为其配上一个 220Ω的电阻来保护它,连接到 ATtiny85 的引脚 8;这个 LED 会闪烁,显示它正在工作。接下来,你需要将一个 10µF 电容器的短引脚连接到 Arduino 的复位引脚(用紫红色线表示),长引脚连接到 GND。
-
连接电源和接地。 最后,将面包板的电源和接地总线连接到各自的 Arduino 引脚。
-
在 Uno 上安装 ArduinoISP 草图。 在 Arduino 程序的工具菜单中找到这个选项,然后将 Uno 的程序器设置为“ArduinoISP”,从程序员列表中选择ArduinoISP。然后转到工具 ▸ 板子,选择正确的 ATtiny 型号。接着上传草图!
你还可以购买一些产品,让你无需第二块 Arduino 即可编程 ATtiny85——例如,SparkFun 的 Tiny AVR Programmer(P/N 11801)和 Evil Mad Scientist 的 ISP Shield(* emsl.us/253 *)。
这是一个简化版的过程描述。若要获取更全面的 ATtiny 编程指南,请访问 MIT 的 High-Low Tech 页面,点击 highlowtech.org/,然后点击 教程,再点击 使用 Arduino 1.6(或 1.0)编程 ATtiny 的链接。David Caminati 也提供了一个很好的教程,网址是 fritzing.org/projects/programmer-for-attiny85-with-arduino-uno-as-interf/。

图 8-9: 使用另一块 Arduino 编程 ATtiny85
制作 ATtiny85 螺丝刀
接下来的挑战是将那一团凌乱的电线变得更加稳固。你将使用 Adafruit 的一块信用卡大小的原型板,并将其设计成,除了电源线之外,你可以一手持有整个螺丝刀。
-
焊接电位器。 如 图 8-10 所示,将三个电位器焊接到原型板上。将每个电位器的外部两个引脚连接到电源和地面。
![image]()
图 8-10: 安装电位器
-
安装 IC 插座。 接下来,如 图 8-11 所示,焊接 IC 插座。ATtiny85 顶部有一个缺口,应该朝向星标,正如图中所示。将第 2、3 和 7 引脚分别连接到每个电位器的中间引脚(从右到左),并将第 8 引脚连接到电源,第 4 引脚连接到地面(有关 ATtiny85 引脚配置,请参阅 图 8-8)。如果这些连接顺序错误,可能会出现意外结果,因此一定要注意每个电位器连接到哪个引脚。
![image]()
图 8-11: 焊接 IC 插座
-
连接 LED。 将 LED 的长引脚通过一个 220 Ω 电阻器连接到 ATtiny85 的第 5 引脚,将 LED 的短引脚连接到地面。图 8-12 展示了该如何连接。
![image]()
图 8-12: 添加 LED 和电阻器
-
添加电源。 焊接圆形插口(如 图 8-13 所示),将中间引脚连接到电源,任意一个侧边引脚连接到地面。
只要你已经将 ATtiny85 刷写了草图,应该就可以立刻插入使用了。
![image]()
图 8-13: 焊接电源插口
这就是你已经焊接好的电路!
编写代码
初始构建中的代码在这个版本中也适用!不过,你需要做一个关键的修改。ATtiny85 上没有第 9 引脚,所以你需要将其改为 0。还记得原始代码中的这一行吗?
pinMode(9, OUTPUT); //change to 0 with the Tiny85
你需要将那个 9 和接下来的所有 9 改为 0。
digitalWrite(9, HIGH); //the LED turns on
delay(currentDuration);
digitalWrite(9, LOW); //the LED turns off for a moment
delay(10);
digitalWrite(9, currentSkip); //the LED dims
delay(currentDuration * 0.5);
digitalWrite(9, LOW); //the LED turns off
delay(currentSpeed);
当你做完修改后,使用本章前面提到的编程设备上传草图——也就是将 ATtiny85 连接到 Arduino,然后将代码加载到 Arduino 上。一旦 ATtiny85 被编程,它可以插入插座中,你就可以开始使用了。
制作 PCB 魔杖
不需要完整的 Arduino,你就可以将光学螺丝刀做得更小巧、更有吸引力。事实上,你可以把它做得足够小,以适应一个魔杖形状的印刷电路板(PCB),如图 8-14 所示。之前版本的螺丝刀是为那些不想购买或加工自己电路板的人设计的。如果你愿意接受挑战,这个版本的项目就适合你了!

图 8-14: 这种魔杖形状的 PCB 容纳了螺丝刀的组件。
关于 Fritzing
Fritzing 是一款简单的电路设计程序,允许你通过传统的电路符号、面包板组件或 PCB 设计来构建电路。要创建设计,你只需要从调色板中拖动组件并在它们之间绘制连线。我一直在使用这款程序,你可能也会觉得它很有用。你可以从 www.fritzing.org/ 下载它。

获取零件
这些部件大多数与我们在项目的前一版本中使用的组件相同。你将需要以下零件来完成这个版本。
组件
-
超亮 LED(例如,SparkFun P/N 531)
-
ATtiny85 (SparkFun P/N 9378)
-
8 脚 IC 插座(Adafruit P/N 2202)
-
三个 10 kΩ电位器(SparkFun P/N 9939 或 P/N 9288)
-
微型电源开关(SparkFun P/N 102)
-
电池夹(SparkFun P/N 7949)
-
表面贴装 LED(SparkFun P/N 12619)
-
两个表面贴装电阻(Jameco P/N 2008882)
-
两节 AA 电池
工具
-
焊接铁
-
焊锡
注意
请参见附录中的焊接说明。
制作它
按照以下步骤构建你的光学螺丝刀魔杖,见图 8-15。

图 8-15: 完成的光学螺丝刀在使用中
-
设计 PCB 轮廓。 我使用了 Inkscape(
inkscape.org/)来绘制一个与我想要的 PCB 形状相对应的矢量图。图 8-16 展示了我绘制的形状:一个大约 8 英寸长、3/4 英寸宽的铅笔形状。Inkscape 文件与本书的其他资源一起提供(nostarch.com/LEDHandbook/*)。你可以将电路板做成任何你想要的形状。在 Inkscape 文件中,PCB 可以是任何颜色,但这不会影响最终效果;程序关注的是矢量图形。Fritzing 提供了一个关于如何制作适用于该程序的形状的教程,地址是fritzing.org/pcb-custom-shape/。![image]()
图 8-16: 我在 Inkscape 中设计了一个铅笔形状,用于魔杖。
-
在 Fritzing 中制作电路。 将电路添加到电路板形状中,如图 8-17 所示。别担心——我会逐步说明如何进行每个子步骤!
![image]()
图 8-17: 添加到电路板设计中的光学螺丝刀
-
添加 PCB 轮廓。 若要添加在 Inkscape 中制作的电路板轮廓,单击一次默认的 PCB,然后在检查器中单击加载图像文件按钮,用自己的图像替换它。图 8-18 显示了准备加载组件的 PCB 轮廓。记住,蓝色并没有特殊含义,它只是一个占位符。真正的颜色决策是在你支付 PCB 加工费用时作出的。
![image]()
图 8-18: PCB 文件已加载。
-
添加电池。 从零件面板中拖动电池夹并将其添加到电路板上。按照图 8-19 中的示意图,将两块电池串联连接。图中的黑色线条代表将在 PCB 上出现的丝印,而圆圈则表示 PCB 上的孔位,绿色表示已焊接的端子,红色表示未焊接的端子。
![image]()
图 8-19: 添加电池夹
-
添加开关。 开关有三个安装孔(参见图 8-20);你应该将电池连接到中间的孔。
![image]()
图 8-20: 添加开关
-
添加表面贴装 LED 和电阻。 从图 8-21 可以看到,LED 和电阻没有安装孔,而是安装焊盘。这意味着这些组件是表面贴装的,而不是穿孔安装的。将开关的顶部引脚连接到 LED 的第一个焊盘,将 LED 和电阻串联连接,然后将电阻接地到电池组的负端。这种电阻作为电源指示器,因此无论螺丝刀发生什么,你都能知道电池是否正常工作!
![image]()
图 8-21: 添加 LED 和电阻
-
添加三个电位器。 从面板中拖动三个电位器,并按图 8-22 中的示意图添加。左侧引脚通过开关连接到电源,右侧引脚连接到接地。中间(数据)引脚暂时不接线。
![image]()
图 8-22: 连接三个电位器
-
添加 ATtiny85。 通过将引脚连接到与前一个项目相同的方式,添加 ATtiny85 插座:引脚 2、6 和 7 连接到电位器,而引脚 4 连接到接地,8 引脚连接到电源。图 8-23 显示了正确的接线方式。
![image]()
图 8-23: 添加 ATtiny85 插座
-
添加电阻和超亮 LED。 最后一步是添加 LED 和保护它的电阻。将这两个元件串联,电阻连接到 ATtiny85 的第 5 针脚,LED 的负极引脚连接到地线。图 8-24 展示了完成的电路板。
![image]()
图 8-24: 电路板已完成。
-
-
输出 Gerber 文件。 导出 Gerber 文件,这是生产人员用来铣削电路板的设计文件。进入文件 ▸ 导出 ▸ 用于生产,然后选择扩展 Gerber 文件。系统会提示您将文件保存到文件夹中。
当输出 Gerber 文件时,请使用 Gerber 检查工具如 MCN(图 8-25),该工具可以从
mcn-audio.com/获取。该工具允许您检查电路板上的痕迹,确保它们按预期布线。我曾因为盲目相信软件能够正确处理而导致许多电路板损坏,因此我强烈推荐使用此工具。![image]()
图 8-25: 使用 MCN 或类似应用检查您的 Gerber 文件。
-
铣削电路板。 选择其中一种 PCB 铣削服务。我使用 OSHPark(*
www.oshpark.com/)](http://www.oshpark.com/),因为它们简单且价格便宜。图 8-26 展示了我从服务商那里返回的铣削电路板。![image]()
图 8-26: 电路板已完成,现在可以开始添加元件!
-
焊接元件。 按照预期焊接元件。特别需要注意的是 ATtiny85,它容易受到损坏。与其将 IC 直接焊接到电路板上,不如先焊接座子,再将 IC 放入座子中。这样还可以在未来的某个时间刷新 ATtiny85。
-
编写代码。 按照本章前面描述的方法,将光学螺丝刀的代码上传到 ATtiny85 上。它应该能够正常工作!您完成的项目应类似于图 8-27。
![image]()
图 8-27: 完成的螺丝刀,通过自制合成器闪烁出节拍
总结
虽然被许多人认为是最简单的电子项目,闪烁的 LED 仍然能提供一些很酷的挑战和机会。本项目展示了如何将数字和模拟结合,制作一个有趣的工具,您可以自己动手制作。
第十章:由 Mike Hord 设计的可穿戴计时护腕
在这个项目中,你将制作一个发光的手腕计时器,非常适合 LARP 服装。

我有很多朋友参加实景角色扮演(LARP)游戏。作为一个概念,它与桌面角色扮演类似,只不过没有回合制,没有骰子,而且你周围发生的一切都有现实成分。
游戏中的一个元素是计时效果;例如,一个魔法可能会让你睡觉 10 分钟,固定你 1 分钟,或者让你 uncontrollably 笑 5 分钟。由于游戏发生在一个幻想的奇幻世界中,使用手表来计时会显得格格不入,破坏了游戏的氛围。玩家需要一种不引人注意的方式来保持时间。为了解决这个问题,在这个项目中,我们将制作一个护腕(或护手)配有神秘发光的宝石,并且还能告诉你效果还会持续多久。作为额外奖励,我们将让它可以与智能手机连接,这样你就可以在不重新编程项目的情况下设置计时器的持续时间!
这个护腕上有四颗宝石,每颗宝石在按下时都会启动计时器。默认情况下,计时器会持续 1 分钟、5 分钟或 10 分钟。宝石会在效果持续期间脉动发光,计时器结束时熄灭。
获取零件
这个项目包括了缝纫和电子部分。我将材料分为两份清单,以便于使用。你可以在任何库存较全的缝纫用品或面料商店找到这些手工用品。
组件
-
LilyPad Simblee 板(SparkFun P/N 13633)
-
4 个 LilyPad 像素板(SparkFun P/N 13264)
-
4 个 LilyPad 按钮板(SparkFun P/N 08776)
-
1,000 mAh 锂聚合物离子电池组(SparkFun P/N 13813)
-
LilyPad FTDI 基础板(SparkFun P/N 10275)
-
Mini-B USB 电缆(SparkFun P/N 11301)
-
导电线(SparkFun P/N 13814)
手工材料
-
眼圈工具包
-
缎带、花边或其他类似线状的装饰材料;我使用的是降落伞绳
-
各种缝纫用品,如线和缝针
-
弹性织物胶水
-
透明或半透明的宝石或珠子,约 1/2 到 1 英寸大小
-
旧礼品卡或过期的信用卡
-
5 到 10 张预切的毡片(9 × 12 英寸)
-
1/3 码的人造皮革
工具
-
锤子(用于设置眼圈)
-
剪刀
制作过程
由于手工部分的尺寸会根据个人喜好和穿戴者的尺寸有所不同,很多部分需要通过“试试看”的方法来调整。
我还假设你对缝纫有足够的熟悉度,所以不需要我解释缝纫部分的每一步。如果你以前从未做过电子纺织品项目,我建议你先查看这些优秀的教程,帮助你掌握基础知识:
-
www.sparkfun.com/tutorials/313这个非常实用的视频教程解释了基本的电子纺织缝合技巧。 -
www.sparkfun.com/tutorials/306我们将使用本教程中的技术来制作启动定时器的按钮。 -
learn.sparkfun.com/tutorials/dungeons-and-dragons-dice-gauntlet这个项目制作了一种类似风格的服装,但它用来隐藏掷骰子机制,而不是定时器。
最终的护腕将有三层:最上层是类似皮革的材料,中间层包含带电路的材料,底部是另一层毛毡或布料。我们开始吧。
-
剪裁布料。 图 9-1 显示了你需要剪裁的大致形状。具体的尺寸取决于你想要护腕的大小,尽量做得大一点,以便容纳电子元件。可以用纸或废布尝试不同的形状和尺寸,直到找到合适的尺寸。
一旦你找到喜欢的形状和大小,从毛毡中剪下两块相同形状的材料,再从人造皮革中剪下一块。让皮革材料稍微大一点,这样它可以将下面的毛毡部分遮盖住。
![image]()
图 9-1: 剪裁毛毡和人造皮革的大致形状
-
布置一些电子元件。 现在你将尝试将电子元件如何布置在毛毡护腕的形状上。你需要找到一个你觉得舒适的位置。
首先,你需要将 LilyPad Simblee 板朝向一个边缘,六针连接头指向外侧,这样你才能访问这些引脚进行编程和充电。其次,像素板(我简短地称之为 LED)应该沿着护腕的中央形成一条直线,这样更符合美观的考虑。图 9-2 展示了我如何设置的。
在这个阶段,你只需要布置 LED、蓄电池和 Simblee 板。按钮会稍后添加。
![image]()
图 9-2: 将电子元件排列在形状的中央。
-
缝入 LED 的导电电源线。 使用导电线,首先将 LED 的正 (+) 和负 (–) 电源线缝制到位。你需要在电子元件的一侧沿着正极焊盘连接一根电源线,另一侧连接负极焊盘。请参见 图 9-3 了解缝线的布置。
![image]()
图 9-3: LED 的正负电源线
注意 LED 的朝向!确保你将 Simblee 板上的负极垫与 LED 上的负极垫缝合。当你确信所有线路布置正确时,用导电线缝合这些垫片,确保缝线较长,并且缝线之间有适当的间隔,就像图 9-3 中所示的那样。在下一步中,你需要将另一根线穿过负电源线,最简单的方式是将它穿过两针缝隙之间。你将电子元件缝制的毡布将成为中间层,位于仿皮革层下方。
-
将数据线从 Simblee 板缝制到 LED。 现在你需要将 LED 与 Simblee 板连接起来,这样 Simblee 就可以控制它们。图 9-4 展示了如何缝制导电线。
![image]()
图 9-4: 将 Simblee 板连接到 LED
在图 9-4 中,我使用了黄色虚线来更清晰地展示数据线从 Simblee 板上的垫子(板上标记为垫子 3)到第一个 LED 的路径,以及连接 LED 的连续线。
请注意,数据线会横跨负电源线,正如我在前一步中提到的。你必须确保这两根线不要接触,否则你的项目会发生短路。为了实现这一点,确保数据线从两个缝隙之间穿过负电源线。
-
在每个 LED 板下的毡布上切孔。 每个 LED 下面需要一个按钮,这样当你按下 LED 时,它就会触发开关。为了确保最佳连接,在每个 LED 下方的毡布中心切一个小孔,以便 LED 板能直接接触到按钮,而不被毡布隔开。但要小心不要切孔太大;你不想不小心切到已经放置的线,或者削弱周围的毡布,导致它撕裂!
-
放置、缝制并穿线按钮板。 在每个 LED 下方放置一个按钮板,使按钮面朝 LED 板的背面。每个 LED 下方应正好有一个按钮板,如图 9-5 所示。
再次强调,我用黄色高亮了线的路径。顶部的长线是来自另一侧毡布的负电源线,这是你之前铺设的。
![image]()
图 9-5: 将按钮板连接到支架
用导电线将每个按钮板的一侧缝到之前铺设的负电源线上。与 LED 板不同,按钮板没有极性,因此你可以将任何一端穿到负电源线上。
接下来,从每个按钮的另一侧穿过一根线到 Simblee 板,如图 9-5 所示。将最靠近的按钮缝到垫片 15 上,下一个缝到垫片 12,再下一个缝到 11,最后一个缝到 9。一定要特别小心这些线与之前的正电源线交叉的位置。你需要非常确定这些线不会接触到,否则那个按钮将无法工作,修复起来会非常麻烦。
-
将背面材料粘贴到按钮板上。 现在将旧的礼品卡或类似的硬材料剪成大约与 LED 板直径相同的方块。将其中一个粘贴到每个按钮板的背面,如图 9-6 所示。
![image]()
图 9-6: 胶水粘贴在每个按钮板背面的纸板方块
我使用了一种专门设计用于柔韧性的织物胶。这些纸板方块为按钮提供了一个坚固的支撑,使按钮可以被按下而不会沉入下面的层中。这个步骤很重要,不容忽视。
-
将各层缝合并放置孔眼。 你一直在使用的材料形成了中间层;顶层是类似皮革的材料,底层是另一层毡或布料。沿着一边缝合这三层,如图 9-7 所示。确保使用普通的、非导电的线。
![image]()
图 9-7: 将各层缝合在一起并放置孔眼
一旦你将各层的边缘缝合在一起,就可以在这一边放置孔眼。按照孔眼套件包装上的说明进行操作。然后在另一边重复缝合和放置孔眼的过程。
-
在 LED 灯珠上切割孔洞。 通过在每个 LED 灯珠上方切一个小孔来暴露 LED。如果你愿意,你还可以在每个孔上方粘贴一个半透明的宝石或珠子,以获得更闪亮的外观。我使用了带有蘑菇底座的 3D 打印宝石。如果你想自己 3D 打印这些宝石,你可以在本书资源中找到相关文件,网址是
nostarch.com/LEDHandbook/。感谢 Youmagine 用户 jensa (www.youmagine.com/jensa/designs) 提供了原始的“绿宝石”设计。图 9-8 展示了完成的项目。![image]()
图 9-8: 安装好宝石的完整护腕,覆盖在 LED 灯珠上
当护腕准备好佩戴时,将你的缎带或绳子穿过孔眼,将护腕系到你的手腕上。
按下 LED 灯珠,或者如果你添加了半透明装饰物,按钮激活时应该会发出清脆的“咔嗒”声。如果没有,添加更多层纸板到按钮板的背面,直到按钮足够坚固。
编程
让我们来看看代码。完整代码相当长——超过 500 行——因此这里只包含了最有趣的部分。你可以在书籍资源中下载代码,地址是 nostarch.com/LEDHandbook/,并阅读下面代码清单中的注释,了解它的一般工作原理。
Simblee 的支持并没有内置于 Arduino IDE 中,因此你需要自己添加它。按照* learn.sparkfun.com/tutorials/simblee-concepts*中的设置 Arduino 教程,完成相关设置。该页面会带你走完编程 Simblee 的所有步骤。你在这里需要用到 FTDI 基本板和 USB 数据线。
这段代码比它的长度看起来简单得多。它设置了四个独立的定时器,这些定时器可以通过按下隐藏在 LED 下面的按钮来触发或重置,然后在对应的 LED 上创建一个脉冲效果,表示一个正在运行的定时器。大部分代码其实是相同的,只是重复了四次,每次对应一个定时器。最后是所有必要的 UI 设置代码。
#include <SimbleeForMobile.h>
#define SFM SimbleeForMobile // A macro to shorten our later
// library calls to a
// reasonable length.
// Aliases for the pin assignments for each button.
#define BUTTON1 15
#define BUTTON2 12
#define BUTTON3 11
#define BUTTON4 9
// Linearize the output of the LED in 16 steps. Because of the
// nonlinear response of the human eye, for the LED to look
// like it is fading in a linear fashion, nonlinear steps
// of brightness are needed.
const int LEDSteps[16] = {255, 191, 154, 128, 107, 90, 76, 64,
53, 43, 34, 26, 19, 12, 6, 0};
// Timer variable definitions.
int timer1 = 60; // timer1 defaults to 60 seconds
int t1Default = 60;
long t1last = 0;
int t1LEDIndex = 0;
int t1LEDDir = 1;
int t1LEDVal = 255;
long LEDUpdateLast = 0;
// Timer active definitions.
bool t1active = false;
// Flash storage definitions and variables.
#define FLASH_PAGE 251
unsigned long *t1p = ADDRESS_OF_PAGE(FLASH_PAGE);
void setup()
{
// Our buttons need to be inputs, with pullups.
pinMode(BUTTON1, INPUT_PULLUP);
pinMode(BUTTON2, INPUT_PULLUP);
pinMode(BUTTON3, INPUT_PULLUP);
pinMode(BUTTON4, INPUT_PULLUP);
// This is the output pin for the LEDs. I didn't
// make a #define for it because this is the only
// place we use it.
pinMode(3, OUTPUT);
// This function is defined farther down in the
// code. It handles writing the current values
// of LED brightness to the four LEDs.
updateLEDs();
// Serial is only used during debugging.
Serial.begin(115200);
// SFM.deviceName and SFM.advertisementData must,
// together, contain fewer than 16 characters.
// These strings put us at 15\. Whew!
SFM.deviceName = "Bracer of Time";
SFM.advertisementData = " ";
SFM.begin();
// If we have values in the flash memory, we want to
// extract them and use those as our defaults. If we
// don't have values in flash, the flash value will
// read as -1, so we can check that to see whether we
// want to use the value in flash or not.
if ((int)*t1p > 0) t1Default = (int)*t1p;
timer1 = t1Default;
}
void loop()
{
// SFM.process() handles the UI processing, if a phone
// is connected to the device.
SFM.process();
// Timer 1 section
// Start the timer when the button is pressed and the timer
// isn't running.
if ((digitalRead(BUTTON1) == LOW) && (t1active == false))
{
delay(25); // Debounce the input.
t1active = true; // Start the timer.
t1last = millis(); // Start counting from now.
timer1 = t1Default; // Use the current default value for
// the timer.
while (digitalRead(BUTTON1) == LOW)
{/*Wait for the button to be released*/}
}
// Stop the timer if it's running.
if ((digitalRead(BUTTON1) == LOW) && t1active)
{
delay(25); // Debounce the input.
t1active = false; // Stop the timer.
while (digitalRead(BUTTON1) == LOW)
{/*Wait for the button to be released*/}
}
// Activates every 1000ms while the timer is running to
// keep the time updating.
if ((millis() - t1last > 1000) && t1active)
{
t1last = millis();
timer1--;
Serial.println(timer1);
if (timer1 == 0)
{
timer1 = t1Default;
t1active = false;
t1LEDVal = 255;
updateLEDs();
Serial.println("Timer 1 expired!");
}
}
// LED blinking section
// Updates 10 times a second, to update the LED of any
// timer that is running.
if (millis() - LEDUpdateLast > 100)
{
// First, take a note on the current time, so we
// know when to next enter this subsection of code.
LEDUpdateLast = millis();
// Update the values being displayed on the LEDs.
updateLEDs();
// Now, calculate the values that we'll display on
// the LEDs next time through the loop.
// T1 LED section
if (t1active)
{
// Adjust the LED value for this LED by changing
// the index we use from the LEDSteps array.
t1LEDVal = LEDSteps[t1LEDIndex+=t1LEDDir];
// "Bounce" the direction of adjustment when we
// reach one end or the other of the array.
if (t1LEDIndex == 0)
{
t1LEDDir = 1;
}
else if (t1LEDIndex == 15)
{
t1LEDDir = -1;
}
}
}
}
// UI Element object handles
// We could have put this stuff up at the top, but I
// wanted it closer to the UI function.
uint8_t t1Input;
uint8_t getValuesButton;
uint8_t updateButton;
// This function is a Simblee library function that
// defines the UI elements that we'll see on the phone.
void ui()
{
SFM.beginScreen();
// We need to refetch these values every time we
// reconnect to the phone, in case they changed.
if ((int)*t1p > 0) t1Default = (int)*t1p;
timer1 = t1Default;
// These are the text boxes that display the name of
// the timer the text field will be controlling.
SFM.drawText(40,80, "Timer 1:");
// These are the text fields that allow the user to input
// a number to be used for the default value of each timer.
int temp = -1;
t1Input = SFM.drawTextField(100, 70, 50, temp);
// Define two buttons: one to get the values from flash and
// populate the text fields, and one to store the values to
// flash.
getValuesButton = SFM.drawButton(40,240,150, "Get settings");
updateButton = SFM.drawButton(40, 300, 150, "Store settings");
SFM.endScreen();
}
// This is a Simblee library function that handles events caused
// by objects in the UI. We have two types of events in this
// application: text field entry events and button events.
void ui_event(event_t &event)
{
// First, handle the text field entry events. These occur when
// the "enter" key is pressed while the cursor is in a text
// field.
if (event.id == t1Input)
{
t1Default = event.value;
Serial.println(event.value);
}
// Now, the update stored values button. This records
// the values in the fields to flash memory so they
// persist through power loss or reset.
if (event.id == updateButton)
{
int rc = flashPageErase(FLASH_PAGE);
Serial.println(rc);
rc = flashWrite(t1p, (unsigned long)t1Default);
Serial.println(*t1p);
timer1 = t1Default;
}
// This button fetches the current values and puts them
// into the text fields.
if (event.id == getValuesButton)
{
SFM.updateValue(t1Input, timer1);
}
}
// Put the current intensity on each LED.
void updateLEDs()
{
RGB_Show(t1LEDVal,0,0,3);
}
使用它
你需要将 Simblee For Mobile应用下载到你的智能手机上,以便更改定时设置。这个应用就像是 Simblee 项目的浏览器,适用于 iPhone 和 Android,并且可以免费下载安装。
使用这个应用非常简单:当你的护腕通电并且 Simblee 已经加载了项目代码后,打开 For Mobile 应用,你应该能看到一个名为“Bracer of Time”的列表项。点击这个列表项,就会弹出护腕的界面,如图 9-9 所示,在那里你可以为每个定时器输入所需的延迟时间(秒),并将这些值存储到护腕的闪存中,以便断电后仍能保存。

图 9-9: 护腕界面
总结
现在你应该已经拥有一个完整的神奇定时护腕了!希望你能派上用场。
我建议查看完整的代码和其中留下的注释。你会发现一些有用的技巧,能够线性化 LED 的输出,使其从完全关闭到完全开启时,呈现平滑且均匀的渐变效果,还有一些关于在循环中执行代码而无需大量空闲等待的技巧。你可以在此项目的 GitHub 页面找到更多信息,地址是 www.github.com/mhord/bracer_of_time/。所有资源,包括完整代码,都可以在 nostarch.com/LEDHandbook/ 获取。
第十一章:可穿戴 LED 文字滚动腰带,作者:Kristina Durivage
在本章中,你将制作一个带有互动滚动文字的 LED 腰带。

小巧而明亮的 LED 非常适合制作可穿戴的物品!在晚上穿戴 LED 衣物绝对能让你在人群中脱颖而出。本章将向你展示如何制作一个可以滚动文字并让你与之无线互动的 LED 腰带。作为本书的最终项目,它在电子部分和腰带制作方面都比其他项目稍微复杂一些,但它的回报是一个可以随时通过手机修改和更新滚动文字的腰带。
获取零件
注意
缝制腰带所需的材料和工具列在“收集材料”一节中,位于第 208 页。
这份零件清单相当庞大,许多零件有不同的选择,所以你可以提前浏览本章以获取更多的规格信息。有了这些零件,你几乎可以把无线 LED 放在任何地方!
组件
-
电池(我使用的是一块 7.2V NiMH 电池,容量为 5000mAh。请参阅“计算所需电池容量”一节,位于第 186 页,了解你的项目需要多少电流。)
-
降压可调电压调节器
-
8 × 32 NeoPixel RGB LED 矩阵(Adafruit P/N 2294,SparkFun P/N 13304,或在 eBay 上搜索“WS2812”——NeoPixel 是 WS2812 类型 LED 的昵称)
-
Particle Photon 开发板,有或没有引脚(可以从*
store.particle.io/products/photon* 购买;更多细节请参阅“连接 Particle Photon 开发板”一节,位于第 196 页) -
T 型 Deans 插头连接器(1 个女性,1 个男性)
-
22 号实心连接线(黑色、红色及其他颜色)
注意
如果你想做一个更小的衣物,可以使用更小的 NeoPixel 阵列。而且,如果你希望 LED 更灵活,比如在裙摆或裤腿边缘,我建议使用绞合线而不是实心线。
本章将展示如何调整电压调节器,但如果你不熟悉这些内容,可能需要先回顾一下“连接电压调节器”一节中的开头部分,位于第 190 页,因为有几种不同的选项,操作起来可能会有些复杂。
工具
这是你在构建电子部分时所需的工具列表,还有一些只是推荐的工具,可以使工作更轻松:
-
烙铁
-
焊锡
-
援助手(或其他类型的台钳)
-
鳄鱼夹
-
钳子
-
万用表
-
电工胶带
-
热缩管
构建它
我们将分阶段构建这个项目。首先,我们将构建所需的电源。然后,我们将连接 Photon 和 LED 阵列,因为只有它们有电源才能进行测试。电子部分连接完成后,我们将制作一个合适容纳整个项目的腰带。
电力是最不起眼的部分,但拥有一个完全移动的项目将是值得的!
图 10-1 展示了最终电路的示意图。如果你卡住了,可以将此图作为参考。

图 10-1: 文本横幅的电路图
获取电力:更换电池插头
使用我们的电池时,我们将处理两根电线——电源线和接地线。这里有一个重要的规则:不要让电源线和接地线接触或与同一金属部件接触。这是一个简单的规则,但非常重要,因为如果它们接触会导致电路短路,这可能会导致项目无法正常工作,甚至会损坏组件。
计算所需的电池容量
电池容量是重量、成本和耐用性之间的折衷。为了确定你的项目需要多少电池容量,首先检查你有多少个 LED。我使用的阵列是 8 × 32 个 LED,意味着我总共有 256 个 LED。大多数情况下,一个 LED 的最大电流为 60 mA(全亮白光),平均使用电流为 20 mA。因此,如果我们将其乘以 LED 的数量,我们的计算结果显示,我们的横幅的最大电流为 15,360 mA(约 15.5 A),平均电流为 5,120 mA(5 A)。
然而,由于我们的 LED 将显示滚动文本,在任何给定时刻,大多数 LED 都是关闭的,因此我们的实际用电量将远低于此。通过万用表,我测得最终项目的电流为 0.5 到 0.7 A 之间。在这种电流下,3600 mAh 的电池大约可以使用 5 小时,而 5000 mAh 的电池大约可以使用 7 小时。
如果你想将阵列用于其他用途,比如同时驱动所有 LED,并且需要更高的电流,那么 3600 mAh 的电池将持续 13 到 42 分钟,而 5000 mAh 的电池将持续 20 到 58 分钟。这些数字并不精确——电池永远不可能完全准确——并且你还会因为电压调节器和其他组件而损失一些功率,所以最好高估你的需求。
对于这个项目,我推荐使用 7.2 V 5000 mAh 的镍氢电池。LED 和 Photon 需要 5 V,而 7.2 V 的电池提供的电压最接近。稍后,我们将使用一个调节器将电压降至 5 V,以避免损坏部件。
我们的电池需要插入充电器和项目中,但它们可能目前没有相同的连接类型。我们将把电池和充电器上的插头都更换为 T 型 Deans 插头,以使它们兼容。对于这一部分,你需要对焊接有一定的熟练度。
首先,我们给 Deans 插头标记,以免混淆电源和接地线。Deans 插头有两个端子,形状像一个 T 字形。横向端子(T 字的上方)通常用于电源(红色)线,而纵向端子用于接地(黑色)线。按照图 10-2 所示,用+标记横向端子,用–标记纵向端子。

图 10-2: 带标签的 Deans 插头,公头(左)和母头(右)
警告
不要让电源线和接地线接触或与同一金属部分接触。这会导致电路短路,可能会导致你的项目无法正常工作或损坏组件。一次只处理一根电线,并用电工胶带覆盖另一根电线。
假设你的电池没有配备 Deans 插头连接器,你需要将其插头替换为 Deans 插头。同样,最好一次处理一根电线,并用电工胶带将未处理的电线包好。
-
给电源线和接地线镀锡。 将每根电线剪到尽可能靠近电池插头的地方,剥开末端一段,长度大致与插头端子相同,将其扭转,使电线不散开,然后在裸露的电线部分四周加上焊锡(如果需要焊接建议,请参见附录)。这个过程,如图 10-3 所示,叫做镀锡电线。
![image]()
图 10-3: 扭动电线,然后加焊锡使其更易操作
-
准备母 Deans 插头。 拿出母插头(只有一侧裸露端子的那个),并将一些热缩管套在电线和插头端子上,正如图 10-4 所示。现在将热缩管放在一旁;暂时不要将它滑到端子上。我们会在将电线连接到插头后再收缩它。
如果你没有热缩管,可以用电工胶带包裹裸露的电线。热缩管看起来更整洁一些,但电工胶带可以更容易地拆卸并重新应用。
![image]()
图 10-4: 将热缩管(右)套在母 Deans 插头(左)的端子上——我们稍后会收缩它
-
焊接母 Deans 插头。 使用一对帮助手或台钳固定母 Deans 插头。插头的一侧端子上有一个凹痕。加热 Deans 插头的一个端子,在凹痕的一侧融化一小块焊锡(见图 10-5)。不过,务必不要让焊接铁的尖端接触到塑料!在两个端子的凹痕上都加上焊锡。
![image]()
图 10-5: 将焊锡融化在 Deans 插头上,以固定电线。
-
焊接电源线。 拿出从电池上出来的红线。剪下两段半英寸长的热缩管,像之前准备的那样,将一段滑到裸露的电线部分上。尽可能将它推到远离你将要焊接的部分,正如图 10-6 所示——焊接铁的热量可能会在我们准备好之前就开始收缩热缩管!
![image]()
图 10-6: 电线上的热缩管。我们会在将电线连接到 Deans 插头后,将其滑到插头端子上并收缩。
当我们完成后,所有暴露的电线部分都必须被覆盖,所以确保暴露的电线部分不长于端子——最好是稍短而不是过长。重新熔化女性 Deans 插头正极端子的焊锡池,将红色电池线的锡端插入,直到被焊锡覆盖(图 10-7)。移开电烙铁,按住电线直到焊锡冷却,但在冷却之前不要触碰。
![image]()
图 10-7: 在这个步骤中,电线会变热,所以用钳子将电线靠近 Deans 插头,在熔化焊锡并连接电线时固定住。
-
焊接接地线。 一旦接头冷却,重复在负极端子上进行此操作,使用黑色电池线——别忘了在连接到 Deans 插头之前将热缩管滑到电线上!稍后我们会收缩这些管子。
-
绝缘电线。 一旦两根电线冷却至可以触摸的温度,将热缩管移到以覆盖金属端子和连接的暴露电线。如果你没有合适大小的热缩管,你可以用电工胶带覆盖这些部件。如果需要重新操作,你需要拆开焊接,换上新的热缩管,并重新焊接。
如果你有热风枪,可以用它来加热和收缩热缩管。否则,你也可以用打火机靠近管子加热,但一定不要让火焰直接接触管子。像图 10-8 所示,扭紧红黑两根电线,增强安装的支撑。
![image]()
图 10-8: 带电线的 Deans 插头
这样,你就完成了!你已经在电池上添加了一个不同的连接器!图 10-8 显示了它应该是什么样子。
如果你的充电器当前没有 Deans 插头,你需要对充电器重复这个过程,但使用一个雄性 Deans 插头来连接你的雌性电池插头。确保在安装插头时将充电器与电源断开,以避免暴露的带电电线。
连接电压调节器
你的电池很可能提供超过 5V 的电压,因此我们需要将其降至 Photon 需要的 5V,以避免电压过高。电压调节器,如图 10-9 所示,可以将电压降到所需的水平。我们将使用可调电压调节器,因为它们是最容易找到的。
电压调节器这个术语听起来很吓人,板子看起来也挺吓人,但别担心!一旦你安装好,它就会自动工作,你再也不需要动它了。
-
购买电压调节器。 在购买电压调节器时有几点重要事项需要注意。首先,购买一款开关型电压调节器,它看起来与图 10-9 中的类似。其次,确保购买一款有两个蓝色盒子的调节器,而不是一个——这样你可以调节电流和电压。
大多数电压调节器返回的电流是 3A 或 5A。对于仅显示文本的情况,这两者都可以使用(如果你还记得电池部分,我们的电流为 0.5–0.7A),但是如果你更改了程序,让大多数 LED 灯亮起,你需要确保电流不超过调节器的最大允许值。
![image]()
图 10-9: 从上方看电压调节器
-
连接插头。 这块电路板上只有四个部分需要关注——图 10-9 顶部的两个带螺丝的塑料盒,以及两侧的 IN 和 OUT 盒子。
你需要四根电线——两根黑色的和两根红色的。一组将连接电池和电压调节器,另一组将电压调节器与其他电子设备连接。
注意
大铜包裹轮是电感线圈,它可能非常松动。如果它松动了,可以在它的两侧涂上热熔胶来固定它。热熔胶不导电,所以不会干扰电路板上的任何元件。
拿一根红线和一根黑线,把它们扭在一起,方便操作,然后对另一对线也做同样的处理。将所有八个电线的端头剥去大约四分之一英寸。按照我们之前接电池的方式,将一对红黑电线连接到一个公 Deans 插头上。公插头的两侧都有金属端子;将其中一侧焊接到较小金属件的一侧。你连接到电池上的母插头将插入这个公插头,它将是电压调节器的输入端。
-
检查电池电压。 拿出你的万用表,然后将你刚刚接好红黑电线的公 Deans 插头插入电池的母 Deans 插头。非常小心,确保电压调节器另一端的两个裸露电线绝对不接触!
将万用表设置为测量直流电压。将红色探头接触红线,黑色探头接触黑线,并检查万用表上的读数(参见图 10-10)。
![image]()
图 10-10: 测量电池电压,并测试电线与 Deans 插头的连接
如果没有显示读数,尝试以下操作:
-
检查你的万用表探头是否插入了万用表的电压和地线端口。
-
确认你的万用表已设置为测量直流电压。
-
确保电线已经连接到电池。
-
看看你是否能通过连接红色探头到正极,黑色探头到负极,使用普通电池(比如 AA 电池)来确认你的万用表是否正常工作。
-
更直接地测试电池:将电池的母式 Deans 插头放入辅助夹具中,然后将探针插入两个端子(红线连接正极,黑线连接负极),看看是否能得到读数。如果没有,尝试捏住电线与端子连接的地方,看看是否能得到读数——可能是焊接连接不够牢固。
-
尝试捏住电线与男式 Deans 插头连接的地方,看看是否能够得到读数。
-
如果你还是无法获得读数,找个人检查你的工作!只要确保在电池插入时不要携带这个设置。
一切正常后,拔掉电池,将其放置一旁,然后拿起电压调节器。
-
-
连接电压调节器。 你需要一把足够小的十字螺丝刀,以适应 IN 端子顶部的螺丝,这些端子在图 10-9 中标记为 IN。我们将红线连接到 IN+,黑线连接到 IN–。
拧松螺丝直到顶部与周围的外壳平齐,然后将男式 Deans 插头的黑线插入 IN–端子,检查是否适配(见图 10-11)。如果你看到端子中有任何裸露的电线,修剪掉一些——你不希望有裸露的电线,但希望尽可能多的电线插入端子。
一旦电线合适,拧紧螺丝以固定它们,如图 10-11 所示。重复此步骤,连接红线到 IN+,然后轻拉两根电线,确保它们不会掉出来。你可以再次将电线拧回去,确保它们紧密贴在一起;只要确保没有裸露的电线暴露或接触。
![image]()
图 10-11: 将红线旋入端子后,确保红线被裁剪得恰到好处,避免金属部分暴露。
拿起另外一组尚未连接的黑色和红色电线,按照相同的方法连接到 OUT 端子上。记住,红线连接到 OUT+,黑线连接到 OUT–。图 10-12 显示了应该如何连接。
![image]()
图 10-12: 到目前为止的电压调节器——男式 Deans 插头连接到 IN 端,裸露的电线连接到 OUT 端。
-
将电压调整为 5 V。 要调整电压,我们需要转动稳压器 OUT 端的螺丝。左侧螺丝调整输出电压,右侧螺丝调整最大输出电流。在某些板子上,螺丝端子会标记为 CV(电压调整)和 CC(电流调整)(如图 10-13 所示)。你可能想把它们标记为 V(伏特)和 A(安培),以避免混淆。
![image]()
图 10-13: CV(左)用于调节电压,CC(右)用于调节电流或安培数。
拿出你的万用表,将鳄鱼夹的一端连接到每根裸露电线的末端,另一端分别连接到正负的万用表探针,如图 10-14 所示。再次小心不要让红线和黑线互相接触。如果此时没有读取到任何数据,检查电压调节器两端的连接。
![image]()
图 10-14: 使用鳄鱼夹将每根电线的末端和万用表探针连接起来,这样你的手就可以自由调整电压调节器。
一些电压调节器有一个小灯,如果灯亮了,说明它正在接收电力,但没有输出。如果灯没有亮,说明它根本没有接收到电力,那么你应该检查电池连接。不过,在调整电线时一定要断开电池——你可不想让地线和电源线意外接触。
一旦你的万用表开始读取数据,将电压调节螺丝逆时针旋转,直到万用表显示电压变化。继续旋转螺丝,直到万用表显示 5V,最好略低于 5V,而不是高于 5V。如果逆时针旋转无法调整到所需的电压方向,尝试顺时针旋转,并记住哪个方向使电压升高或降低。
注意
这一部分可能会让人感到沮丧。两个螺丝盒看起来完全一样,而且你可能需要一段时间才能从万用表的电压变化中得到反馈。可能需要很多次旋转,但调整最终会生效,然后你就可以使用任何电池,并且拥有可穿戴的 LED 灯来参加派对。坚持下去。
-
调整电流。 电流的测量方式与电压不同:电压需要非常精确,因为像 Photon 或 LED 阵列这样的元件如果电压偏离 5V 太远,就无法正常工作。电流可以设置得很高,组件会根据需要自行吸取电流。我们将电流设置为最大值。
记住哪个方向是增大电压,并且将电流调节螺丝朝同一方向旋转。当旋转到最大时,你会听到每次旋转都会有咔哒声。好消息是,如果电流过低,所有的设备会直接关闭,不会损坏,如果电流过高,零件会只吸取它们需要的电流。记住你旋转这个螺丝的方向,以便以后调试。
-
分线。 我们的 LED 阵列需要的功率比 Photon 能够输出的要多,因此我们将从电压调节器处分开电源线,这样一组电源/地线将为 Photon 供电,而另一组将为 LED 阵列供电。我们将通过将电压调节器出来的电线分叉来实现这一点,使红线和黑线成对变成两对红线和黑线。
剪下一段约两英尺长的黑色和红色电线。将红色电线对折,并在折叠处剥开一小段电线。在折叠处将暴露的金属中间与电压调节器的红色电线暴露端连接起来,并添加一些焊料使它们固定。无论你如何将这两根电线固定在一起,都能达到目的。完成后,在这段电线处加上热缩管。
对黑色电线重复此步骤。这些步骤如图 10-15 所示。
![image]()
图 10-15: 将红色电线的裸露端绕在一根更长的红色电线的裸露中间,进行焊接并加热收缩。
-
创建两对电线。 将从分叉处出来的红色和黑色电线通过扭在一起形成一对,这样你就有了两对电线,并使用更多的热缩管在分叉处将它们固定在一起,如图 10-15 所示。记住,插入电池时,绝不要让暴露的黑色和红色电线接触!
这样,我们就完成了这个项目的电源部分!图 10-16 展示了到目前为止的项目示意图。现在你可以插入电池,一旦我们将其连接到电路板和 LED 阵列,你就能为两个组件供电,并使它们完全无线运行。

图 10-16: 到目前为止组件的示意图
连接 Particle Photon 板
本节将只涉及 Photon 的接线部分;你将把 Photon 连接到你的手机作为无线热点,并在第 200 页的“编程”中进行编程。如果你想在开始半永久性地将电线焊接到 Photon 之前先了解一下它,随时可以先去那里或查看其他使用该板的示例项目。我们将只使用 Photon 上的三个引脚——VIN、GND 和 D3。
一些 Photon 板会附带接头,而有些则不会——图 10-17 展示了它们在外观上的差异。

图 10-17: 没有接头的 Photon(左)和有接头的 Photon(右)
接头允许你通过插拔将 Photon 临时连接到面包板上,而不是焊接电线。但接头也会增加体积,而且如果组件被拉扯到错误的方向,它们更容易从面包板上脱落。
如果没有接头,你将直接将电线焊接到电路板上。这是更为永久的连接方式——你可以通过重新加热焊接点来移除电线,但这样有可能损坏电路板。
如果你想做实验,并担心搞错了,我建议使用接头和面包板,尤其是在你可能想把 Photon 用于其他用途的情况下。
如果你想使这个项目变得永久,我建议在某个时刻直接焊接到电路板上,即使你一开始使用的是面包板。以下说明假设你将电线直接焊接到 Photon 上。
-
焊接线缆。 取电压调节器上的一对红色和黑色叉形线缆,并将它们连接到 Photon 上,红色线接 VIN,黑色线接 GND,然后将它们焊接到位,如 图 10-18 所示。确保 VIN 和 GND 的焊接点不要接触到彼此或电路板上的其他任何部分。如果有任何多余的线缆突出电路板,请修剪掉,以免它们卡住。
![image]()
图 10-18: 将线缆直接焊接到电路板上
-
测试插头。 仔细检查来自电压调节器的另一对线缆是否已得到保护(如果你剥开了线端,请确保它们没有接触到任何东西),然后插入电池。你应该能看到 Photon 启动了!如果你对这个步骤感到紧张,可以只插入电池一秒钟,确保没有看到烟雾或火花。如果你确实看到烟雾或火花,说明你的 VIN/红线和 GND/黑线某处接触了。请再次检查你的焊接,确保一切连接正确,焊锡也只在应该的位置,没有溅到其他地方。
连接 LED 数组的线缆
我们将通过将第二对叉形线缆焊接到 LED 数组上来完成连接。LED 数组需要三根线:电源线、接地线和来自数字引脚(D3)的数据线。
市面上有许多不同品牌的 LED 数组,连接方式可能有所不同。你需要寻找指示数据线应连接哪一侧的箭头(指向或远离电路板)或 IN 和 OUT 字样。
应该有三个端子,分别标有 + 或 5V、– 或 GND 和 DI(或 DIN),如 图 10-19 所示。如果没有标注,请查看附带的线缆:红色通常是 +,黑色是 –,数据线是其他颜色。在移除这些线缆时,如果需要,可以在电路板上做标记。
-
移除电路板附带的线缆。 这些线缆只是焊接在表面,因此将热烙铁放在接线端子上,轻轻拉动线缆,直到焊锡足够融化,线缆可以脱落。记住,焊锡只能融化在接线端子处,不要让它溅到电路板的其他地方,也不要用烙铁接触电路板的其他部分。
-
连接电源线。 接下来,取剩下的一对红色和黑色叉形线缆,将它们连接到 LED 数组上的电源 + 和 – 端子(它们也可能标为 5V 和 GND)。首先在每个焊盘上加一点焊锡,然后剥开小段的线缆,剪裁合适长度,使其适合焊盘,接着加热焊盘上的焊锡,并将剥好的线放入焊锡中。此步骤如 图 10-19 所示。
![image]()
图 10-19: 向端子添加更多焊锡。确保暴露的线缆长度大约与焊盘相同,然后融化端子上的焊锡,将线缆连接到 LED 数组上。
-
连接数据线。 使用一根不是红色或黑色的电线,将它从 LED 阵列的 DIN 端子连接到 Photon 的 D3(或任何其他 D 引脚),如图 10-20 所示。电线的长度非常重要——Photon 和 LED 之间的电线越短,干扰的可能性就越小,这样可以避免影响 LED 显示。像电源连接一样将这条线焊接起来。
![image]()
图 10-20: 焊接 DIN 连接。
现在,通过插入电池来测试接线。您应该能看到 Photon 的灯光亮起。LED 仍然不会亮起,因为没有程序指示它们亮起。从现在起,您将插入电池以开关设备。
如果您的 Photon 的灯光没有亮起,请检查从电池到 Photon 的接线。可能某个地方的电线断开了,导致 Photon 无法接收到电力。使用万用表在不同位置测量电压,以诊断断点的位置。还要检查红线和黑线是否接反了。
如果仍然无法正常工作,您可能不小心将电流调整螺丝调得过低,而不是调高。尝试将电流螺丝调到完全相反的方向,看看是否能解决问题。
一旦 Photon 开机,您可以收起烙铁了,因为除了您在缝制腰带后可能需要进行的调整外,您已经完成了这个项目的硬件部分!接下来,我们将上传一些滚动文本的代码,进行测试,然后组装电子设备放入服装中!
编程
我们编写代码的最终目标是能够将一条短信发送到一个号码,并让该短信显示在腰带上。为了实现这一目标,我们需要在两个地方运行代码:一个是在 Photon 上,另一个是在一个等待接收消息并将其发送到您的腰带的服务器上。我们将首先关注 Photon 上的代码。
您可以从(nostarch.com/LEDHandbook/)下载此项目的完整代码。我将概述代码的各个方面,但我也在代码中添加了注释,以记录它的工作原理。
将 Photon 连接到 Wi-Fi
首先,您需要将 Photon 连接到 Wi-Fi。请参考 Photon 网站的文档(docs.particle.io/guide/getting-started/intro/photon/)了解如何开始。请注意,文档内容可能会在您阅读时有所更新,因此可能看起来有所不同,但应该很容易跟随。
这一步是可选的,可以稍后重新配置,因此如果您只想让 Photon 立即连接到互联网,请将其连接到传统 Wi-Fi 网络,并跳过此部分。一旦 Photon 连接成功,您应该很少遇到问题。
您需要下载 Particle 应用程序才能将 Photon 连接到 Wi-Fi 网络。
-
下载应用。 去你的应用商店,搜索 Particle。该应用的图标如图 10-21 所示。下载并安装 Particle 应用,并创建自己的账户。
![image]()
图 10-21: Particle 应用图标
你应该会进入“你的设备”屏幕。点击角落的+按钮,选择设置一个 Photon。现在你应该能够连接到你的 Photon 了。
-
(推荐)将你的 Photon 连接到你手机的热点。 我推荐开启你手机的 Wi-Fi 热点功能,并将你的 Photon 连接到该热点。这可能有点复杂,但它让你可以完全移动,不必依赖于连接多个 Wi-Fi 网络。
要将你的 Photon 连接到手机,请记下你手机的网络名称和密码,然后点击连接到 Wi-Fi 网络,并选择我的网络未列出。输入你的 Wi-Fi 名称和密码,如图 10-22 所示。
当应用显示一个旋转的指示器并提示正在寻找 Wi-Fi 网络时,返回设置并打开你手机的热点功能。Photon 将连接到互联网,从此只要热点功能开启,它就会连接到你手机的热点。

图 10-22: 连接到你手机的 Wi-Fi 热点的 Photon 界面
编写 Photon 代码
一旦你的 Photon 连接成功,前往build.particle.io/build。这里是你上传代码到 Photon 的地方。你需要创建一个账户,然后你将进入一个编辑器,在这里你可以发送消息到你的电子横幅!
添加 LED 库
你可以在nostarch.com/LEDHandbook/下载你的 Photon 代码,文件名为textsash1.ino,但你首先需要告诉 Particle 使用这个库来控制 LED 灯。
在编辑器中,点击创建新应用的按钮。给你的应用起一个易于识别的名字,比如 TextSashPhoton。点击左侧的保存按钮(文件夹图标)。
库图标看起来像是屏幕左侧的书签;点击它并滚动至社区库列表。你可能会看到 NeoPixel 库排在列表的顶部(图 10-23)。

图 10-23: 库图标和社区库部分
点击 NeoPixel 库,你应该会看到一些代码。暂时忽略这些代码,寻找“在应用中包含”按钮,如图 10-24 所示。点击它,然后按名称选择你最近创建的应用(如果找不到,可能是你在输入名称后忘记点击保存)。

图 10-24: 包括 NeoPixel 库
你应该会在左侧灰色栏中看到“包含的库”部分,其中列出了 NeoPixel 库,以及文件顶部的#include行,指明了neopixel库。现在你已经准备好添加更多代码了!
测试 Photon
在我们添加能够向阵列发送消息的代码之前,让我们先写一些代码,测试所有的连接线是否正确连接,一切是否按计划工作。
-
从*
nostarch.com/LEDHandbook/下载的代码文件中,打开文件testArray.ino*并将其复制到屏幕的主要部分。确保其中有包含#include的那一行。 -
现在,确保 Photon 应用知道它将上传代码到哪个设备。点击设备图标,它看起来像一个瞄准镜或十字准线(见图 10-25)。你应该会看到你新配对的 Photon 设备出现在列表中。给它命名,然后点击名称。名称左侧应该会显示一个星标—当你现在上传代码,也就是所谓的闪烁代码,它将上传到这个设备上。
![image]()
图 10-25: 设备图标
-
确保你的 Photon 已通电并连接到互联网—如果是,Photon 上的 LED 应该闪烁青色—然后点击左边栏顶部的闪烁按钮(看起来像一个闪电)。你应该会看到 Photon 闪烁品红色。如果这是你第一次上传代码,它可能会经历一些不同的颜色变化,以确保固件是最新的并进行重置。当一切完成后,阵列角落的一个 LED 应该会亮红色。
如果灯没有亮起,请进行更多的故障排除。
将代码发送到你的 LED 显示屏
一旦你的 Photon 工作正常,将书本资源中的shortstr_textsash.ino代码粘贴到 Photon 编辑器中。我已经完全记录了每个函数和代码中任何让人困惑的部分,所以可以随意查看。只需向下滚动,跳过顶部的编码字符的代码部分。
按下闪烁按钮上传代码,你应该会看到Hello World!显示在你的 LED 阵列上。这很酷,但现在让我们让它显示我们想要的内容!
请注意,目前有一个限制:你一次只能发送 63 个字符。如果发送更多字符,不会返回明显的错误;它只是无法工作。稍后我会教你如何绕过这个限制。
要向你的 LED 发送消息,你需要两个东西:Photon 的设备 ID 和访问令牌。要找到设备 ID,点击编辑器侧边栏上的设备图标,然后点击设备名称右侧的箭头。这样设备 ID 会在一个文本框中展开。现在将这个 ID 复制到文本文件中。
要找到访问令牌,点击左下角的设置,你会看到一个框里有代码。也请将其复制到一个文本文件中。
我们将使用这两个标识符将数据发送到 sash。就像你的电脑从互联网获取和发送数据一样,将 Photon 连接到互联网后,你可以将数据发送到你的特定设备,以执行代码。我们将使用 Postman,一个 Chrome 应用。你可以下载并在 www.getpostman.com/ 上了解更多。
注意
如果你有选择的程序来发送 REST 调用,可以自由使用它。
下载 Chrome 应用并打开 Postman。现在我们将设置一个调用,向你的 sash 发送文本。
-
从 图 10-26 中的下拉菜单中选择 POST,并输入
api.particle.io/v1/devices/deviceID/buildString作为 URL,将你的设备 ID 替换为 deviceID。 -
从 URL 框下方的菜单中点击 Body 选项卡,如 图 10-26 所示,选择 x-www-form-urlencoded 单选按钮。将 access_token 作为键,输入你从 Photon 账户复制的访问令牌作为值。然后,在新的一行中,输入 args 作为键,键入你想在 LED 数组上显示的文本作为值。图 10-26 显示了所有参数设置正确后的样子。记住,目前消息的字符数限制为 63 个。
![image]()
图 10-26: 如何在 Postman 中设置对 Photon 的调用
完成后,保存你的帖子并点击大蓝色的发送按钮。你应该能看到 LED 数组显示你的文本!
如果此时没有任何显示,而且之前的一切都正常工作,那么可能是你的电压调节器的电流调节设置得太低。请返回 “连接电压调节器” 第 190 页,复习一下如何设置电压调节器的电流并进行调整。
提高字符限制
现在你有了一个可以通信的 LED 数组,但你可能需要发送超过 63 个字符。返回你的 Particle 编辑器,将你一直使用的程序替换为文件longstr-textsash.ino。这样你就能创建更长的字符串,但这比想象的要复杂一些。
与之前发送单条消息不同,你现在将依次发送多条消息,Photon 将存储并合并它们,直到你告诉它完成,然后显示这些消息。
在文本编辑器中输入你想显示的内容,但将其分成每行 60 个字符。然后,不是发送一条消息,而是将每一行作为单独的消息,通过将其粘贴到 Postman 中的 args 值里发送。你的第一行必须是 1,BEGIN,最后一行是 1,END,用来表示消息结束。每行文本需要以 0, 和一个空格开头。例如,对于消息“这是一个非常长的字符串,一直在延续下去,我忍不住打字,实在是太有趣了!”你将通过 Postman 发送五个 args。
第一条消息告诉窗帘它将开始接收文本。1,END 命令告诉窗帘你已经完成文本发送,它可以展示合并后的内容。
1,BEGIN
0, This is a really long string that goes on and on and on and
0, I just can’t stop myself from typing so much. It's so much
0, fun!
1,END
这手动操作可能有些麻烦,但别担心——你不会长期使用手动发送消息的方式。
编写服务器代码以通过短信发送消息
如果你不介意以这种方式向窗帘发送消息,你可以在这里停止。否则,本节将向你展示如何设置一个服务,允许你通过短信向窗帘发送消息。这需要一个 Twilio 账户,且免费。Twilio 会为你提供一个独特的号码来发送消息,如果你使用自己的号码发送,所有的短信都会显示出来!如果在本节中遇到问题,可以访问我的 GitHub 仓库,获取如何在服务器文件夹中的不同文件保存信息的说明:github.com/gelicia/textSashChapter。
安装 node 和 npm
这段代码将用 JavaScript 编写,你需要安装 node 和 npm。根据你使用的操作系统,安装过程可能会有所不同,因此请按照 docs.npmjs.com/getting-started/installing-node 上的说明,按照你选择的操作系统安装 node 和 npm。
注意
你需要以管理员身份运行命令终端。
-
一旦 npm 安装完成,打开一个终端(在 macOS 中使用 Terminal 应用,或者在 Windows 中从开始菜单搜索 cmd 并点击命令提示符)。
-
找到 node 在你电脑上的存储位置,并使用
cd命令在终端中导航到服务器文件夹;例如:$ cd User/Program Files/nodejs/node_modules/npm -
在终端中从该文件夹运行
npm install,你应该会看到类似q@、restler@和nedb@的文本。这是 npm 在安装我们将用在服务器程序中的库,比如neopixel库。你还会看到服务器文件夹现在包含了一个名为 node_modules 的文件夹。在 node_modules 文件夹内有一些 .js 文件。你需要使用之前在 Photon 中找到的设备 ID 和访问令牌来修改一些权限。
-
首先将particleConfigTEMP.js和twilioConfigTEMP.js重命名为 particleConfig.js 和 twilioConfig.js(即,去掉TEMP)。particleConfig.js文件更简单——你已经通过 Postman 获得了设备 ID 和访问令牌。
设置一个唯一的 Twilio 号码
你需要对twilioConfig.js文件进行的更改将需要一个 Twilio 帐户。
-
在*
www.twilio.com/*上注册一个 Twilio 帐户,确保选择你将使用 SMS(其余问题不重要,可以留空)。你需要提供一个有效的手机号码来接收确认代码,并使用它完成注册。 -
当你登录时,你应该看到一个“开始使用”按钮;点击它,然后点击获取号码。你应该会被提供一个号码;点击选择这个号码。记下这个号码以备后用。你将从这个号码发送消息以显示在腰带上。如果找不到它,请从仪表板向下滚动到“电话号码”并点击它。
-
你应该看到你的号码被列出。记下这个号码,然后点击主页按钮。你应该在页面上看到你的帐户 SID 和身份验证令牌。将它们放入你在本节开始时重命名的twilioConfig.js文件中——记住,如果你需要更多指导,可以查看我 GitHub 上的文件。
-
将你的 LED 阵列连接到电源,然后在终端中运行
node bot.js。现在,从你的手机发送你想要显示的消息到你的 Twilio 号码。你应该看到消息排队出现在终端中,然后它应该显示在 LED 阵列上。如果有问题,检查控制台中的错误消息,并确认你是否正确设置了权限 ID。
现在你有了与 LED 互动的简单方式!你可以自己保留号码并发送新消息,或者将号码给一些可信的朋友让他们也可以发短信。
深入了解服务器
本节的最后一步是将此程序放到一个即使计算机关机也不会关闭的地方。这超出了本书的范围,但如果你有这方面的知识或有朋友懂,我建议使用 DigitalOcean(他们有很好的新手帮助)和 npm 库forever (github.com/foreverjs/forever),它允许你持续运行bot.js脚本,并在脚本失败时重新启动它。
组装它
最后,我们将制作一个衣物来容纳 LED 显示屏。你有两个选择——要么从头开始制作一切,要么买现成的东西并进行修改以适应你的项目。这就是为什么先做电子部分很重要的原因:你需要知道要放进口袋的东西,然后才能开始做口袋。
我将向你展示如何制作一个腰带,里面有三个口袋,用来放电池、电压调节器、Photon 和 LED 阵列,如图 10-27 所示。

图 10-27: 腰带由三个口袋和固定电线的带子组成。
收集材料
我们将制作一个黑色腰带,它能够很好地展示 LED 灯的颜色。然而,深色可能会吸收光线,使得显示的文字难以看清,因此我们需要两层材料——首先是一层薄薄的毛巾布,可以用剪下来的白色毛巾或洗脸巾,然后再加上一层黑色布料。
毛巾布很好地扩散了光线,并抵消了黑色布料吸光的效果。图 10-28 至 10-31 展示了不同布料下的同一 LED 灯光效果。

图 10-28: 没有覆盖物的 LED 阵列

图 10-29: 被黑色布料覆盖的 LED 阵列。注意,灯光完全没有扩散——滚动时这很难阅读。

图 10-30: 被毛巾布覆盖的 LED 阵列。注意,灯光非常扩散,彼此之间融合得很好。

图 10-31: 被毛巾布和黑色布料覆盖的 LED 阵列。这是最终的作品。
材料
你将需要以下物品:
-
1.5 码的黑色布料(我使用的是普通的黑色棉布)
-
白色毛巾布(可以是大块的毛巾布或剪下来的毛巾)
-
报纸或废纸
工具
你还需要以下工具:
-
剪刀——最好是布料剪刀或波浪边剪刀
-
卷尺
-
标记笔
-
针、线和直别针
-
(可选)缝纫机;你也可以选择手工缝制腰带
-
(可选)白色布料笔或粉笔;这有助于标记出需要缝制的位置
-
(可选)熨斗
制作腰带
首先,考虑一下你可能放置项目部件的位置;我们需要将电池放在靠近底部的位置,因为它很重且笨重,如果放在顶部会逐渐下拉。我们希望 LED 阵列位于中央,同时需要将 Photon 放在附近,以减少电线的干扰。我们将先尝试用纸制作腰带,实验一下各个部件的合适位置。
-
首先,从肩膀顶部到对侧臀部的距离进行测量,以估算腰带的大小。对我来说,30 英寸大约合适。
-
将两页报纸或一大张新闻纸平放在地上。腰带的前后形状相同,因此可以同时剪出两块。将软尺放在纸上,稍微弯曲,模拟出你希望腰带的形状(图 10-32)。在报纸上画出这个弯曲线,标记出你之前测量的长度的起点和终点。
-
关于宽度,考虑 LED 阵列的宽度,以及你希望两边留多少空间。LED 阵列宽度为 3.5 英寸,我一开始设计的腰带宽度大约是 7 到 8 英寸。使用你画的线作为中心,在两侧标记出你宽度的一半(图 10-33)。
![image]()
图 10-32: 使用卷尺确保腰带大致的正确长度
![image]()
图 10-33: 使用中心线和你想要的宽度在报纸上画出其余的腰带形状。
-
你将得到两块大致像腰带形状的纸片。将它们从纸上剪下来,然后用胶带将两端粘合在一起形成腰带。把这个纸质腰带放上去(图 10-34),看看是否需要对形状进行任何调整。我通常会从肩部和底部修剪掉一些,因为它会突出。
![image]()
图 10-34: 试穿纸质腰带,并根据需要修剪。
不断调整形状,直到你满意为止。我的最终纸质腰带看起来像图 10-35。
![image]()
图 10-35: 调整后的腰带形状
-
一旦形状正确,你可以将其作为模板来剪裁布料。为了让腰带更结实,我们会使用两层布料,所以你需要剪裁出两个完整的腰带形状并将它们缝合在一起。最好的方法是将布料对折,使折边从肩部穿过。
直接在布料上标出纸样的轮廓,或将纸样别在布料上,沿着纸样裁剪。
如果你有包边机,使用布料剪刀剪裁腰带。如果没有,使用锯齿剪来防止布料散边。
-
如果你无法将布料折过肩部,只需将两块布料缝合在一起,使其看起来像图 10-36,即前后在顶部缝合。你将需要两块这种形状。
-
如图 10-36 所示,标记两侧并将两层布料缝合在一起,可以使用包边机,或者如果你用锯齿剪裁布料,则使用直线缝合缝制锯齿边缘。
![image]()
图 10-36: 标记缝合两层布料的地方。
-
将布料翻到里面,这样缝合的边缘就会在里面。你可以将布料熨平,或者在上面缝一层以确保它们保持平整。完成后,你应该得到像图 10-37 那样的效果。
![image]()
图 10-37: 腰带基础部分基本完成!
-
现在缝合其中一端并将另一端的毛边收进内侧,这样就能得到一个漂亮的折边。将缝合好的端口放入折叠的端口大约一英寸的位置,然后缝合两端以关闭腰带。
现在腰带的基础部分已经完成,我们还需要一些其他的东西:三个口袋(一个用来放电池和电压调节器,一个用来放 LED 阵列,另一个用来放 Photon)和用来固定电线的带子。我们从电池和电压调节器的口袋开始。
缝制电池和电压调节器口袋
电池需要紧密地适应口袋,以防止它在口袋里晃动。为了实现这一点,我们将制作一个类似盒子的口袋,侧面大约有一英寸深。这个口袋将放在腰带的底部靠背的位置,这样它就会靠在你的下背部。这可以平衡前面 LED 阵列的重量。最重要的是确保电池能合适地放入。我已经扔掉了很多口袋,因为它们太大或太紧。
-
为了确保口袋适合电池和电压调节器,将电池放在一块面料的中间,围绕它画出形状,四周留出几英寸,再剪掉多余的部分。将面料的一边折起来一点,做成缝边并缝牢——这将成为口袋的开口端。
-
在与缝边相对的那一侧,将末端和两侧折约一英寸,再将角落折进去,直到三角形的尖角与电池的角对齐,然后将折叠部分用别针固定(见图 10-38,顶部)。
-
将口袋的两侧折叠,使角落处形成的三角形将侧面和底部支撑起来(见图 10-38,中间),然后用别针固定。即使它看起来不太美观也不用担心,因为没人会看到口袋的底部。
-
用电池测试尺寸,如果合适,就将角落的三角形缝合固定,再沿每个角的外边缘缝一圈以确保稳固(见图 10-38,底部)。
![image]()
图 10-38: 开始塑形口袋底部
-
将口袋垂直放置,开口朝上。你将把口袋放在腰带后部的底部,因为它较重,你希望它远离视线并不显眼。
-
用别针将口袋固定在位置,先缝制底部,再缝制两侧,然后缝到腰带上。在角落留出一些未缝合的空间,以便如果需要的话,口袋可以稍微膨胀。
-
试着将电池和调节器放入口袋,并将腰带系上。稍后你可以在另一侧添加更多重量以平衡,但如果需要移动电池或使用其他方式固定它,随时可以调整。
缝制 LED 阵列口袋
接下来是 LED 口袋,它是一个平口袋。我们将在口袋内部添加一层毛巾布,以便扩散光线。所以,从身体向外的层次将是:两层黑色腰带面料,然后是 LED 阵列,再然后是毛巾布和口袋的外部黑色面料。
-
在毛巾布上标出并剪裁出 LED 矩阵的区域,留出一点点活动空间,如图 10-39 所示。如果没有包缝机,可以使用锯齿剪。顶部留出更多空间,这样你可以将一块黑色面料折叠并缝制在口袋顶部。
![image]()
图 10-39: 剪裁并缝制毛巾布和面料层
-
锁边毛巾布的边缘,或者如果你没有锁边机,可以留一个锯齿边。我们会用口袋布料覆盖这些边缘,所以它们不会显现出来。将毛巾布放在黑色布料上,围绕它画出轮廓,四周留出 3 到 4 英寸的空隙。
-
将黑色布料折叠约一英寸,然后再将其折叠到毛巾布上,以便毛巾布的锯齿边缘或毛边不显露出来,并将折叠部分别针固定。按此方式处理所有四边,如图 10-39 的底部面板所示。
-
将 LED 阵列放置在布料上,确保它仍然适合。
-
确定你想要口袋放置的位置,将其对齐,然后将其别针固定。这是一个很好的机会再次试穿腰带,确保穿上后口袋看起来合适,并且阵列适合。将口袋缝合在腰带上,尽量保持靠近口袋的边缘。
现在我们将制作一个光子口袋。
缝制光子口袋
如果你的光子没有接头,按照 LED 口袋的做法制作一个平口袋。如果你的光子有接头,按照电池口袋的做法来适应体积。你可能需要手工缝制底部。然后按如下方式将其放置在腰带上:
-
一旦做完光子口袋,将它放置在 LED 口袋上方,如图 10-40 所示,使得光子与 LED 之间的电线尽可能短。
![image]()
图 10-40: 光子口袋位于 LED 口袋上方约一小段距离处
-
只缝合两个长边,这样电线可以从顶部和底部出来。它们将固定光子。如果看起来光子突出太多,你可以在口袋顶部加一个按扣来固定光子。
添加电线带子
最后我们要加上小带子,用来固定电线在腰带上。
-
切下一条大约 3 英寸宽、1.5 英尺长的布料。将长边缝合或锁边在一起,做成一个圆筒,然后翻转它——你可能想在其中一端的一侧附上安全别针,再把它从另一端推过去,这样会更容易。
-
一旦正面朝外,你会得到一个更像管状而非带状的物品。缝合与接缝相对的长边,或者熨平它以保持平整。
-
将布料剪成较短的部分,大约 3 英寸长。你可能需要大约四个。现在先保留它们;一旦你确定下一部分电线会从哪里突出,你可以将它们缝到腰带上。
-
现在你需要根据腰带的大小调整项目的连接电线长度。
这是你的项目,所以你可以做任何调整!我已移除一些接缝,让电线可以从口袋的侧面出来,给没有封口的口袋加了按扣等等。
要延长或缩短电线,你只需拆开焊接,剪短或添加新的电线,并确保记下重新连接的位置。更多焊接技巧请参见附录。
记住,电压调节器不一定需要焊接,因此你可以卸下电线,把它们穿过带子,再将它们重新连接。如果需要回顾接线部分,可以回头看本章的电子部分。现在你应该能将电子元件放入你的腰带中了!
-
一旦确定了电线长度,沿着腰带间隔好带子,使电线平整地贴合。固定带子后再缝上。我只需要那些从前面穿过肩膀到背部电池口袋的带子。参见图 10-41 了解我如何放置带子以固定电线。
![image]()
图 10-41: 腰带的正面和背面,电线长度适当并且位于带子下方。所有组件都放入了它们的口袋里,准备佩戴!
完成之后,把所有物品放入口袋,将电线固定在其支架里,你的腰带就完成了!
总结
现在你拥有一个可穿戴的 LED 阵列,可以显示文本。我提供了一个示例服务器来发送文本消息,但也有其他选择。小图片、颜色和设计都可以使用。只需记住:一次点亮的 LED 越多,所需的电流也越大。带着你自己的超酷 LED 腰带走向世界吧!
附录
《焊接入门》由 Matthew Beckler 编写
焊接是一项简单的技能,但如果你从未做过焊接,你可能需要一些指导。此附录提供了焊接组件到电路板的快速介绍。
焊接是通过融化焊锡(通常是由锡和铅制成的金属合金)将两块金属连接在一起的过程。焊锡液化,包裹住两块金属,随后重新固化,形成强大的电气和机械连接。这是电气组件、导线和电路板之间连接的常用方法。
焊接工具
你需要以下工具来进行焊接:
-
焊接铁
-
焊锡(用于电子,不是管道。可使用无铅或含铅焊锡。)
-
焊接的对象,比如印刷电路板
-
电线剪
-
要焊接的零件(这些可能是导线或电子元件。如果这是你的第一次焊接,建议先焊接导线,因为它们较便宜。)
你需要一个干净的工作空间,并且需要一个耐热的地方来放置烙铁,烙铁架就是为了这个目的。你还可以使用帮助架来固定你的零件,以便在焊接时保持稳定。除了这些工具,建议随身准备一个湿海绵,用来定期清洁烙铁的尖端。
六步焊接方法
在印刷电路板(PCB)上有焊盘,这些是暴露的金属小块,通常位于孔的周围。这个孔是你插入组件引脚或导线并焊接的地方。
在焊接前,先收集好所有零件和 PCB,并将它们放在平坦的表面上以保持稳定。我们将使用一个电阻器作为示例。按照以下步骤操作,并参照图 A-1 作为视觉指南。
-
将组件的引脚插入焊盘中的孔内。使用焊接铁的尖端加热焊盘和穿过孔的引脚。
-
等待几秒钟,让所有部件加热。
-
使用戳的动作将焊锡添加到热接头处。
![image]()
图 A-1: 焊接组件到 PCB
-
当你在引脚周围形成一个漂亮的焊锡堆,并且覆盖了焊盘但不接触其他焊盘时,停止添加焊锡——这应该类似于图 A-2 的情况。
-
在停止加焊锡后,将烙铁保持在接头上几秒钟。这可以确保焊锡完全流入接头中。然后移开烙铁,让焊锡冷却。
-
焊锡完全冷却后,修剪掉多余的引脚,检查你的焊接工作。
焊接每个接头后,确保其表面光亮光滑,如图 A-2 所示。

图 A-2: 焊锡量适当的接头
焊锡的量不应过多或过少。它应该像一个小火山一样围绕着引脚。
保持烙铁尖端清洁
每次焊接完毕后,务必保持烙铁头的清洁。这会提高热量传导到连接点的效率,使焊接更加轻松。图 A-3 展示了一个相对干净的焊接烙铁头示例。

图 A-3: 使用干净的烙铁头能使焊接变得更容易。
当烙铁加热时,定期用湿海绵或湿纸巾擦拭烙铁头,然后重新涂上一点焊锡,使其闪亮!
附加资源
想了解更多焊接知识,可以参考 Mitch Altman、Andie Nordgren 和 Jeff Keyzer 合作的《焊接很简单》漫画书。你可以在书籍资源中免费下载,链接地址为 nostarch.com/LEDHandbook/ 或 mightyohm.com/blog/2011/04/soldering-is-easy-comic-book/。
第十二章
资源
访问 nostarch.com/LEDHandbook/ 获取项目模板和代码文件、更新、勘误表以及其他信息。
更多直截了当的书籍来自
NO STARCH PRESS

20 个简单的 Raspberry Pi 项目
玩具、工具、小玩意儿,及更多!
作者 RUI SANTOS 和 SARA SANTOS
2018 年 4 月,288 页,$24.95
ISBN 978-1-59327-843-4
全彩色

儿童电子学
玩转简单电路,实验电力!
作者 ØYVIND NYDAL DAHL
2016 年 7 月,328 页,$24.95
ISBN 978-1-59327-725-3
全彩色

废品堆乐队
DIY 音乐乐器和噪音制造器
作者 DAVID ERIK NELSON
2015 年 10 月,408 页,$24.95
ISBN 978-1-59327-611-9

Arduino 项目手册
25 个实用项目,助你起步
作者 MARK GEDDES
2016 年 6 月,272 页,$24.95
ISBN 978-1-59327-690-4
全彩色

制造者的僵尸末日指南
使用简单电路、Arduino 和 Raspberry Pi 来防御你的基地
作者 SIMON MONK
2015 年 10 月,296 页,$24.95
ISBN 978-1-59327-667-6

硬件黑客
制作与拆解硬件的冒险
作者 ANDREW “BUNNIE” HUANG
2017 年 3 月,416 页,$29.95
ISBN 978-1-59327-758-1
精装版
1.800.420.7240 或 1.415.863.9900 | sales@nostarch.com | www.nostarch.com





















)上传 Blink 示例程序。我们稍后会上传本项目的示例程序,但现在我们只是在检查我们的设置是否正常。

































































































浙公网安备 33010602011771号