Arduino-游乐场-全-

Arduino 游乐场(全)

原文:zh.annas-archive.org/md5/d60944781d09c0aff16be19b5c7188dc

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

image

欢迎来到Arduino Playground!本书提供了一系列展示 Arduino 微控制器板灵活性和多功能性的项目。每个项目都包含了构建所需的所有信息,包括原理图、组件清单以及任何草图(这是 Arduino 用户对程序的称呼)。我还尽力提供了每个项目中机械部分的所有信息,包括材料清单,这样你就可以完成任何外壳、运动部件、框架等。所有特殊工具的需求也在项目中有所描述。

我尝试通过包含一些背景解释来使这些项目不仅仅是拼接零件的配方,我将分享我如何想到这些项目以及技术如何运作。我希望这些项目能够成为有用的成品,凭借一些创造力,或许甚至能为你提供一个起点,让你创造属于自己的项目。

本书适用对象

本书中的项目不需要工程学位、先进的机械能力或编程专长。不过,为了最大程度地发挥本书的作用,你需要具备以下一些基本要求:

• 理解基础电子学,包括能够阅读原理图并识别电阻、电容等元件

• 理解如何使用计算机和编写软件(如果你想显得高深,可以提到冯·诺依曼架构);了解 Arduino 或其他微控制器架构会有所帮助

• 有焊接连接和电线的经验

• 有限的机械技能,如如何操作电钻、各种锯子等

我的希望是,无论是初学者还是有经验的 Arduino 用户,都能在这些项目中学到一些新的电子学知识。

本书结构

每一章都集中在一个项目上,描述如何在面包板上进行原型测试,简要讨论草图的工作原理,最后展示如何构建最终产品。

第零章:设置和有用的技能为你提供一些基本知识,这些知识你将在全书中使用,包括如何准备 Arduino 板、如何编程、如何使用 PCB 软件以及如何制作自己的 PCB。

• 在第一章:反应时间机器中,你将利用 Arduino 微控制器的实时功能来测量用户对刺激的反应。这个项目既快速又容易构建,你将学习一些使用控制器进行定时的基础知识,并有大量机会进行草图实验。完成的设备将为你和你的朋友、家人带来数小时的乐趣和娱乐。

第二章:PCB 蚀刻的自动搅拌器展示了如何通过改变电流的流量来让电路发生变化。在这个案例中,电流的变化使电机的转向发生反转,从而可以用来在蚀刻溶液中搅拌印刷电路板。蚀刻 PCB 只是该技术的一个应用,正如本章所解释的那样。

第三章:稳压电源中的项目可能最终会成为你工作台上使用最频繁的产品之一。它是一个带有电压和电流数字显示的稳压可调电压电源。设计简单而有效,而且制作起来很有趣。

第四章:手表自动上链器中的项目是我最喜欢的之一。它的实用功能是当自动(自上链)手表不佩戴时,保持手表继续上链,但它的酷炫设计也使其成为一个很棒的动态雕塑。手表自动上链器使用 Arduino Nano 来处理所有保持手表上链的定时功能,并包括一个多色 LED 光显示。一些组装技巧可能对初学者构成挑战,但付出的努力绝对值得。

第五章:车库守卫停车助手中的项目是一个高科技设备,旨在帮助你将车辆停入车库。这是网球挂绳装置的电子版本,旨在测量你想要进入车库的距离。它引入了超声波发射器和接收器,并演示了如何将其与 Arduino 控制器结合使用。虽然这是该技术的一个非常实用的应用,但其他应用(如液体测量)仅受限于你的想象力。

• 在第六章:电池保护器中,你将制造一个设备,帮助防止铅酸蓄电池因意外放电而损坏。设计基本上是一个与电池串联的高电流开关,当电池电量降至危险水平时,它会断开。虽然如今大多数汽车都集成了此类电路,但我发现这个项目在船只和多功能车辆(如拖拉机、割草机等)上特别有用,它可以避免你不必要地更换这些昂贵的电池。

• 在第七章:定制 pH 计中,你将制造一台用于测量多种液体 pH 值的精密仪器。虽然定制 pH 计使用的是专业探头,但其电子设备和显示依赖于 Arduino 处理器。如果你从事家庭酿酒、酿酒、种植水培植物或养鱼,或者仅仅是管理游泳池中的化学物质,定制 pH 计将是一个非常有用的工具。

第八章:两种弹道计时仪中的项目旨在测量各种枪支的枪口速度,从气枪和步枪到 BB 枪和铅弹枪。虽然这个项目并不适用于常规火器,但它的测量能力超过了每秒 2500 英尺。它还引入了一些新的技术,包括一些独立的逻辑、计数器和 DAC。文中描述了两种版本的计时仪;较小的版本,Chronograph Lite,可以测量速度最高达每秒 700 英尺的射弹。

• 在第九章:方波发生器中,你将构建一个低成本的电子波形生成仪。该项目的起源是为第八章中的弹道计时仪提供一个模拟器,但它的效果如此之好,以至于我将其独立成了一个项目。虽然它在分辨率和灵活性上无法与常规实验室仪器相媲美,但你会发现它在设计和测试各种产品时非常有用——而且价格只是常规设备的一小部分。

• 在第十章:彩色温度计中,你将创建一个小巧的设备,通过一系列彩色 LED 显示温度。虽然最初的设计很简单,但这个项目发展出了更加复杂的变化。你可以添加数字显示、一个高精度传感器,以及多种机械变体,用于从监控鱼缸到墙面装饰等不同场景。

本书并没有深入探讨每个项目背后的基本工程或编程概念,因为假定读者具备足够的背景知识,可以通过简要的解释理解这些概念。但对于好奇的读者,文本中提供了相关参考资料,可以在其中找到关于设计和技术的额外信息。书中还提供了项目的背景历史:为什么我会构建这个项目(以及你为什么可能想要构建它)。在所有情况下,都力求提供一个用户可以欣赏和理解的学习体验。

在可能的情况下,项目还建议了高级读者可以尝试的替代方法。为了展示我为何选择特定方法,我说明了一些替代做法如何解决某些问题并带来其他问题。每个项目都有很大的个性化空间,甚至可能进行改进,无论是包装、构建技术还是草图本身。例如,手表上链器可以是一个实用设备,或者是一个高端的动能雕塑。

什么是机电一体化?

在写这本书的过程中,我多次遇到了机电一体化这个术语。作为一个有点传统的(或者说是个守旧的老家伙),我忽略了最初的几个提及。然而,最终我还是花时间查阅了这个术语,发现它听起来和我们在这本书中做的事情非常相似。

简单来说,机电一体化是结合电子学和机械工程进行设计的过程。1969 年,日本雅马哈公司的高级工程师森哲郎创造了这个术语,用来描述建造工业机器人时所需要的电气、机械和计算机工程。机电一体化工程师将力学、电子学和计算学的原理结合起来,创造出更简单、更经济、更可靠的系统。

关于零件清单

在本书的设计阶段,项目所需的零件选择通常是根据我在工作间里现有的物品来决定的。例如,第四章中的手表上链器所用的轴承,最初是我在废料箱里找到的,但后来我把它们替换成了零件清单上提到的那些。我已经尽力根据描述的工具和材料制作项目,但我鼓励你使用手头有的物品。

注意事项

几乎我认识的每个程序员在编写 Arduino 程序时,都会从简单的“闪烁”示例开始。因此,许多人认为 Arduino 与 LED 的开关密切相关。在本书中,我尽量通过包括 LEDs 的项目,来强化这种关联。虽然让 LED 闪烁并没有触及 Arduino 的所有功能,但 LEDs 使得项目更加有趣,并且具有视觉互动性

工具和材料

在你开始本书的项目之前,回顾一下以下的工具和材料清单,并注意你缺少的物品。并非每个项目都需要这些所有工具,所以当你准备做一个项目时,查看该章节的所需工具和材料清单,看看是否缺少什么必需品。大多数物品你可以在当地的五金店购买,但我会指出在哪些情况下在线购买可能是更好的选择。

钻孔、切割和组装

螺丝刀 你需要准备十字螺丝刀和一字螺丝刀,多种尺寸的都有。

Dremel 工具(或同类工具) 一款小型钻机或旋转工具对于多种任务非常有用,从钻孔和切割到刻蚀和抛光。一个不太贵的台式附件可以把 Dremel 工具变成一个小型钻床,这非常方便,尤其是在钻孔电路板时。

电动钻 最好是电池驱动的。如果可能,我建议使用 3/8 英寸或 1/2 英寸容量的夹头——容量越大越好。

钻头套件 我建议购买一个带有编号的钻头套装(即,标有#1 到#60 的钻头),另外还可以购买一个分数制钻头套件。

钳子 我发现一把约 6 到 8 英寸长的可调钳子,能够满足许多需求,比如夹持、固定物体和拧紧。我还建议购买一把好的尖嘴钳。

锯子 简单的钢锯非常适合多种任务。对于切割塑料,有很多选择:钥匙孔锯效果不错,或者如果你不介意花更多的钱,一把小型变速手持锯(或弯锯)非常适合做各种切割。如果你从未使用过弯锯,可以先在废木材上练习锯割。一旦掌握了使用技巧,弯锯可以成为车间中最得力的工具之一。

锋利的刀和剪刀

螺钉和螺母 我建议尝试获取少量的英制和公制螺钉和螺母的组合。如果你当地的五金店没有好的选择,eBay 上有很多这样的组合。

丝锥和板牙套件 对于大多数项目来说,套件并非必需,因为单独的丝锥和板牙也可以购买,但套件便宜且随手可得,非常实用。

锥形铰刀 锥形铰刀在许多书中的项目中都很有用,是我强烈推荐拥有的工具。我使用的是一套便宜的铰刀,是我在 Amazon 上购买的,它们在塑料、铝和软钢上效果非常好。我建议购买能够打孔直径达到 7/8 英寸的铰刀。

胶带 我建议备有遮蔽胶带、双面泡沫胶带和坚固的户外双面胶带(3M 品牌效果很好)。

原型制作、焊接与测试

鳄鱼夹或夹线套件 有很多鳄鱼夹可以选择,它们在组装面包板时非常有用。套件可以从多个渠道购买,包括 RadioShack 和 Amazon。

面包板和跳线 这些可以从多个渠道购买,包括 Pololu 和 Amazon。

数字万用表 提供了各种类型的万用表。你可以支付不到$5 的价格,也可以花几百美元,但便宜的便携型万用表就足够用了。你会发现万用表是家用工具集中的一个受欢迎的补充。

电阻组件 我建议你可以查看 eBay 或 Amazon,那里可以轻松批量购买电阻。有些组件可能包含每种价值 10 个单元,20 或 30 个不同值的电阻,而其他组件可能每个值包含 100 个或更多电阻。这些价格非常经济。

烙铁和焊锡 烙铁在五金店很容易买到,通常不到$10。Jameco 甚至提供了一个在线焊接教程(* www.jameco.com/Jameco/workshop/learning-center/soldering-basics.html *),如果你是初学者,读一读可能会有所帮助。

焊锡膏 仅在你焊接表面贴装元件时遇到困难时才需要。虽然这些项目只使用了一小部分表面贴装元件,但未来你可能会使用更多,因为制造商制作的新的集成电路越来越少采用插脚式版本。我使用一种无铅的焊锡膏,名为 Chip Quik。不过别担心:你也可以使用普通的松香芯焊锡和电烙铁焊接表面贴装元件,正如在《使用 SOIC》中所描述的,见第 20 页。

焊锡吸取带 虽然我们都不会粗心大意地在连接处形成焊锡桥,但有时顽皮的小妖精会悄悄地搞这一招。在这种情况下,焊锡吸取带(一种带有少许松香的铜编织带,用于吸收多余的焊锡)能帮助你干净地去除焊锡。

如果你喜欢构建完整的 Arduino 项目,考虑补充你工具箱中缺失的任何工具。这里描述的每一项工具,在某些时刻肯定会派上用场。

在线零售商

如果你在当地的五金店找不到电子元件或工具,可以尝试以下这些在线零售商:

• Adafruit (www.adafruit.com/)

• Amazon (www.amazon.com/)

• Bitsbox(在英国不错; bitsbox.co.uk/

• Digi-Key (www.digikey.com/)

• eBay(几乎可以找到这本书所需的任何东西,价格低廉; www.ebay.com/

• 电子金矿 (www.goldmine-elec-products.com/)

• Farnell(全球配送; www.farnell.com/

• Harbor Freight (www.harborfreight.com/)

• Jameco (www.jameco.com/)

• MCM 电子 (www.mcmelectronics.com/)

• Mouser (www.mouser.com/)

• Newark Electronics (www.newark.com/)

• Newegg (www.newegg.com/)

• Pololu 机器人与电子 (www.pololu.com/)

• SparkFun (www.sparkfun.com/)

关于在线资源

每个项目都有一个下载部分,列出了任何提供的草图、PCB 或模板文件。使用这些文件是可选的——你可以手动从书中复制草图,设计自己的 PCB,并决定自己在哪里打孔。但如果你想要一个起点,可以从 www.nostarch.com/arduinoplayground/ 下载资源文件。

第一章:设置与实用技能

image

本书假设你已经有一定的硬件经验,因此其中的项目不会手把手地指导你。但如果你需要复习一些基本技能,例如布线和编程 Arduino 板,请继续阅读。

本章还介绍了一些你可能会觉得有用的技巧,尽管它们并非构建项目所必需。例如,在大多数项目中,我提供了可以用来制造屏蔽 PCB 的 PCB 文件,但如果你想制作 PCB 而不是将电路焊接到原型板上,可以阅读第 13 页的“制作自己的 PCB”章节。如果你从未自己组装过连接器或需要关于使用小型外形集成电路的指导,可以在第 20 页的“使用 SOICs”章节中找到相关信息。

准备 Arduino 板

无论你使用的是 Arduino Nano、Pro Mini,还是它们的克隆板,你的板子很可能会以插针分开且未焊接的形式到达。所有我购买的板子都是这种情况(见图 0-1)。

image

图 0-1:一块带插针的 Arduino Nano 克隆板和面包板,作为焊接的辅助工具。

在你能使用 Arduino 或其克隆板之前,需要先将插针焊接上。处理器板附带的插针条通常比所需的插针多,第一步是将它们修剪到所需的数量。黑色塑料固定件上有凹槽,便于剪切。我使用一把简单的斜口钳来剪切塑料(见图 0-2)。

image

图 0-2:Arduino Pro Mini 克隆板,插针已修剪至适当长度。五针插条适配板子的末端。

下一步是将插针插入面包板,确保处理器板上的孔能正好覆盖在插针上。将插针的长端插入面包板,如图 0-3 所示。在两排插针之间留有四排空孔——也就是三排加上中间的分隔空隙——这样处理器板就能合适地放置。

最后的步骤是将处理器板放置在插针的短端上,如图 0-4 所示,并进行焊接。

image

图 0-3:插针已经插入面包板,准备好进行焊接 Nano 克隆板。

image

图 0-4:Nano 克隆板已放置在面包板上,准备好进行焊接。

现在你的板子已经安装好所有插针,准备接线了。

固定 I²C 板到 LCD 上

本书中的许多项目也使用带有集成电路(I²C)接口的液晶显示器(LCD)(见图 0-5)。本书使用的 LCD 可以带或不带 I²C 适配器板,尽管我通常需要单独购买 LCD 和适配器板。

如果适配器板尚未连接到 LCD,将两者连接的方法与准备 Arduino 板相似。适配器板通常带有已安装的排针,因此你只需将其插入显示器并进行焊接。

连接显示器和适配器通常没有任何问题,但在某些情况下,适配器可能具有几乎接触显示板的电路。为了避免连接短路,我建议在 LCD 背面贴上电气胶带,以将其与 I²C 适配器板上的连接隔离开。

image

图 0-5:16×2 LCD 和 FTDI 模块

你可能还会发现,I²C 板上的排针突出穿过 LCD 板,导致在将显示器安装到外壳时出现问题。尽量将 I²C 板焊接得尽可能远离 LCD 板,以最小化排针穿过板的长度。图 0-6 显示了一个适配器板,准备将排针插入 LCD 基板。

image

图 0-6:I²C 板已就位,准备焊接

如果将适配器板焊接在这样的位置过于困难,可以将插针插到极限,焊接它们,然后使用线切割器修剪,使它们尽可能与 LCD 板齐平。

根据你的 LCD 和适配器板,可能需要输入到草图中的 I²C 地址会有所不同。有一个非常简单的扫描器可用,访问playground.arduino.cc/Main/I2cScanner/即可。只需按照说明操作即可找出 LCD 的 I²C 地址。0x27 和 0x30 是常见的地址。

上传草图到你的 Arduino

在你将项目的电路组装到面包板上之后,接下来就是将草图加载到微控制器上并进行测试。我建议使用 Arduino Nano、Pro Mini 或它们的克隆板,适用于本书中的大多数项目。

安装 Arduino IDE

你可能已经在计算机上安装了免费的 Arduino 集成开发环境(IDE);如果没有,立即下载并安装该程序。只需访问www.arduino.cc/,点击下载,然后下载适合你操作系统的 Arduino IDE 版本。最新版本是 1.6.x。然后,访问 Arduino 的入门页面,并按照官方安装说明进行操作。

注意

如果你不熟悉 IDE,可以在 Arduino 网站上找到许多教程和示例代码文件。我强烈建议你阅读这些资料,以便熟悉软件使用

使用 Arduino IDE

安装完成后,打开 Arduino IDE。会出现一个空白的草图,名称格式为:sketch_<date>。要保存草图,选择文件 ▸ 另存为。在打开的对话框中,选择你要保存草图的位置和文件名。

在为本书中的项目创建新草图时,你有两个选择:可以直接在草图窗口中输入代码,或者你可以从资源文件下载草图文件,访问 www.nostarch.com/arduinoplayground/,然后将代码复制并粘贴到草图窗口中。

我通常喜欢先验证草图——也就是编译它——再尝试上传到开发板,以确保在将草图输入到 IDE 时没有出现错误。验证非常简单,只需点击左上角的勾选标志(参见图 0-7)。当你将鼠标悬停在勾选按钮上时,验证一词会出现在该行五个图标的右侧。

image

图 0-7: 草图窗口,勾选了验证图标,位于图标列表的开头

如果你的代码能够正确编译,那么它就准备好上传到开发板上了。

连接和编程 Arduino Nano

验证草图后,你需要将 Arduino 开发板连接到电脑。在本书中使用的 Arduino 开发板中,Nano 是最容易连接和编程的,因为它内置了 USB 接口。

对于 Nano,找到一根一端是 USB 插头(A 型),另一端是 mini-B USB 插头的电缆;你的开发板可能已经附带了一根。将 USB 端连接到电脑,将 mini-B USB 端连接到 Nano。选择工具 ▸ 开发板,然后选择正确的开发板和微控制器(参见图 0-8)。

你可能还需要选择正确的串口 COM 端口来连接你的 Arduino,尽管某些版本的 IDE 会自动找到一个空闲端口并连接到它。进入工具 ▸ 端口,然后从弹出的菜单中选择一个串口。如果遇到任何问题,可以参考操作系统的个别指南,访问 www.arduino.cc/en/Guide/HomePage/

image

图 0-8: 草图窗口,工具菜单已打开。我选择了带有 ATmega328 的 Arduino Nano

编程 Nano 的最后一步是上传代码。首先,确保开发板仍然通过 USB 线连接到电脑。然后,点击上传按钮,它看起来像一个指向右边的箭头(参见图 0-9)。当你将鼠标悬停在上传按钮上时,上传一词应该出现在五个主图标的右侧。

上传代码到 Arduino 通常不会花费太长时间,但它取决于程序的长度。上传完成后,你可以为电路供电并进行测试。(在使用外部电源供电之前,不要忘记拔掉 USB 连接线。)

image

图 0-9:点击上传按钮的草图窗口

连接和编程 Arduino Pro Mini

Arduino Pro Mini(或其克隆版)的工作方式与 Arduino Nano 非常相似,但它没有内置 USB 接口,而是采用晶体管-晶体管逻辑(TTL)连接。我找到的最简单的方法是移除 Arduino Uno 的处理器芯片,如图 0-10 所示,并使用 Uno 板作为编程器。

不带处理器的 Uno 可以通过 USB 直接连接到计算机,因此它可以为连接的 Pro Mini 板提供电源和编程信号。Arduino Uno 的 USB 电缆是标准 USB 电缆,一端是常规的(A 型)USB 连接器,另一端是方形的(B 型)USB 连接器(见图 0-10)。有关 USB 电缆的更多信息,可以参考www.sparkfun.com/pages/USB_Guide/

image

图 0-10:移除处理器后的 Arduino Uno 克隆板(在板的右侧),USB 电缆,编程电缆组件,以及松动的重置线

按如下方式将 Uno 连接到 Pro Mini:

• 将 Pro Mini 的 Rx 连接到 Uno 的 Rx

• 将 Pro Mini 的 Tx 连接到 Uno 的 Tx

• 将 Pro Mini 的 VCC 连接到 Uno 的 5.0V

• 将 Pro Mini 的 GND 连接到 Uno 的 GND

• 将 Pro Mini 的 RST 连接到 Uno 的 RST

我制作了一根简单的电缆,用于连接正负电压供电以及接收(Rx)和发送(Tx)信号(见图 0-11)。电缆的一端直接插入 Uno 上的插针,另一端的 4 针插头连接到 Pro Mini 的边缘插针。你也可以使用单独的跳线,就像你在面包板上使用的那样。我发现最简单的方法是将 Pro Mini 插入面包板,以便可以使用跳线连接 RST 信号,如图 0-11 所示。

image

图 0-11:准备编程的 Arduino Pro Mini 克隆版,Arduino Uno 克隆版作为编程器,Arduino Uno 的 USB 连接提供电源

在将 UNO 的 USB 电缆插入计算机之前,确保所有连接正确对接。当你编程 Pro Mini 时,从工具菜单的板卡部分选择正确的板卡;即使你将 Arduino Uno 插入计算机,你依然是在编程 Pro Mini。一旦这个设置完成,你可以像上传到 Nano 一样上传程序到 Pro Mini。

虽然使用 Arduino Uno 中介是编程 Pro Mini 的最简单方式,但你也可以购买 USB 转 TTL 设备,如 图 0-12 所示。我在 eBay 上购买了几台,价格在 5 到 12 美元之间,经过一些小调整(端子有时标记不同),它们都能正常工作。

编程 Arduino 只是其中的一部分。要构建一个真正持久的项目,你需要将工作中的 Arduino 电路焊接到电路板上。一个定制的印刷电路板 (PCB),有时也叫做印刷接线板,是保持你的项目干净整洁的最佳方式——如果你愿意投入额外的工作制作一个的话。

image

图 0-12:一种用于编程 Pro Mini 和其他没有自己 USB 接口的控制器电路板的 USB 适配器。这个适配器使用男性 USB (A 型) 插头,并且有一个数据终端准备 (DTR) 引脚,而不是复位引脚 (RST)。大多数 USB 转 TTL 设备可以使用 3.3V 或 5V 供电,但在供电之前要检查一下,因为有些设备只能在 3.3V 下工作

使用 PCB 软件

市面上有许多 PCB 设计程序,它们的复杂度和价格各不相同。许多软件是免费的,目的是吸引客户使用公司提供的设施来制作电路板。因此,在尝试使用这些免费的工具制作 DIY 电路板时,可能会遇到一些问题——例如,软件在免费版本中可能会锁定某些功能。我使用 ExpressPCB (www.expresspcb.com/) 来设计单面和双面电路板。

注意

对于双面 DIY 电路板,我需要手动翻转图像。制作双面电路板的诀窍是正确对齐两面。为了简化许多项目的对齐过程,你可以在传输图像之前,在空白的铜板上做对齐标记并钻对齐孔。偶尔,我也会使用一个叫 TurboCAD 的绘图程序(类似于 AutoCAD)来制作双面电路板

ExpressPCB 提供了我找到的最便宜的电路板制作解决方案。该公司提供了一种 MiniBoard 服务,提供一种标准尺寸的无附加功能的电路板,价格相对较低。此外,随着行业推出更新的软件包,使用包含新 IC 封装的软件包变得至关重要。我使用 ExpressPCB 制作适配器板——从 SOIC 到 DIP,并将 SOIC 集成到成品电路板中,因为该软件非常适用于较小的几何图形。即使我想制作一个“专用”微控制器电路板,可能需要多个层、地平面和 VCC 平面,ExpressPCB 也很可能满足这些需求。

要使用该程序,只需访问 ExpressPCB 网站,下载免费的软件并安装。ExpressPCB 网站上有几个关于如何使用该软件的教程,我建议你利用这些教程。还有一款免费的配套软件 ExpressSCH,它是一个用于编写电路原理图的原理图捕捉程序。虽然它的功能整合度不如理想,但将这两款程序一起使用,有助于电路设计。

注意

本书中的所有 PCB 设计均使用 ExpressPCB 设计软件制作,所有设计文件可以在 www.nostarch.com/arduinoplayground/ 下载。要查看或更改 PCB 图纸,你需要下载该软件。

使用 ExpressPCB 的另一个优点是,你可以将自己为制作电路板所开发的同一文件发送到公司的工厂进行加工。我在书中的一些项目中就这么做了——大多数情况下,在自己制作并希望清理板子后,我发现结果非常令人满意。工厂加工的板提供了电镀孔——如果你制作双面板,就需要在板的两面进行焊接。它们还提供了焊接镀层,并可以制作抗焊接涂层和丝网印刷图像。图 0-13 展示了我用 ExpressPCB 制作的板。

image

图 0-13:一块专业完成的 PCB,具有抗焊接涂层和丝网印刷。我用这块板制作了第八章中的弹道测速仪。

制造多块不同板的技巧

你可以使用 ExpressPCB 的 MiniBoard 服务以非常低的成本制作多块板。为了符合 MiniBoard 的要求并获得折扣,板的强制性尺寸是 3.8×2.5 英寸,启动程序时,黄色引导框会自动显示该尺寸的区域。在准备像图 0-14 中这样的 PCB 时,我将几个较小的板复制并粘贴到 MiniBoard 价格的最大尺寸范围内,从而将它们合并成一块大“板”。

image

图 0-14:为一个 MiniBoard 订单制作的三块不同的板。用于弹道测速仪的是左上角的板,pH 计的是底部的板。右上角是用于光学转速计的板,但未包含在书中。一个价格,你可以获得每块板的三份副本。你所需要做的就是将它们剪开。

制作你自己的 PCB

在设计好 PCB 之后,有多种制作 PCB 的技术。正如我将在第二章中讨论的,最常见的方法是减法方法,通过选择性去除覆铜板上的铜层来留下电路图案。铜可以通过机械铣削去除,但如果你想在家制作 PCB,最常见且最便宜的方法是用化学蚀刻图案。

在进行化学蚀刻时,电路图案通过光敏胶印刷在空白板上,光敏胶是一种化学物质,可以防止铜在受处理区域被蚀刻剂去除。蚀刻剂是一种酸,会攻击覆铜板上未处理的铜。图 0-15 展示了铜板转变为 PCB 的过程。

image

图 0-15:从左到右:未经处理的擦洗过的铜箔板;上面印有光敏胶的板;以及没有钻孔的蚀刻后的板

在过去,制作 PCB 是一项繁琐且混乱的工作——尤其是对于业余爱好者。首先,你需要布置 PCB 图案,直到不久前,这通常是通过在光照台上用胶带在乙酸纸上完成的。然后,你需要清洁铜箔板,并旋转涂布光敏胶。这需要暴露于紫外线下,并用四氯化碳(CCl[4])或三氯乙烯(C[2]HCl[3])显影,而这些对你都不好。之后,你将开始使用氯化铁(FeCl[3])或过硫酸铵((NH[4])[2]S[2]O[8])进行混乱的蚀刻过程。经过所有这些步骤,你通常需要花费大部分时间来制作一块电路板。

今天,所有这些都发生了变化。借助当今的现代 PCB 软件,你通常可以在不到一小时的时间内,设计出一个相对简单的单面或甚至双面板图案,具体取决于其复杂性。从那时起,过程变得更加简便。

应用图案

如果你想学习蚀刻自己的 PCB,可以访问 PulsarProFX 网站(www.pcbfx.com/),该网站提供了将图像轻松转印到铜箔板上的工具。Pulsar 的 PCB Fab-in-a-Box 产品是一个完整的工具包,包含了制作几个电路板所需的一切。一个关键成分是特殊的纸张,你可以用激光打印机打印图像,并利用热量将图像转移到铜箔板上。整个制作过程——钻孔之前——几乎从不超过一个小时,除非你缺少蚀刻剂,这会延长蚀刻时间。

除了 Pulsar 工具包中的物品外,所需的唯一工具是:

• 一台激光打印机

• 一台塑料覆膜机(Pulsar 建议使用 GBC 覆膜机,但我多年来一直使用 Office Depot 品牌的机器,它也能很好地工作。)

• 一个水浴

将 PCB 图案应用到铜箔板上的程序相对简单:

  1. 使用 PCB 布局程序(例如 ExpressPCB)在计算机上设计图案。

  2. 使用激光打印机,而不是喷墨打印机,将图像打印到 Pulsar 提供的特殊纸张上。激光墨水是一种聚合物化合物,当加热时会融化并部分与纸张结合,将图像留在纸上。当纸张重新加热到空白的印刷电路板上时,可以轻松地将图像转移到板上。

  3. 使用廉价的办公室覆膜机,将图像直接从纸张转移到干净的覆铜板上。

纸上的热墨水变成了覆铜板上的抗蚀层。Pulsar 提供了一个额外的薄膜层,热熔与激光打印墨水结合,但单独的墨水也能抵抗蚀刻液。

蚀刻电路板

虽然铜不是一种高度活跃的金属,但有几种置换反应可以有效蚀刻铜。然而,许多由此产生的副产品有一定的毒性,几乎所有副产品都是必须以特殊方式处理或回收的材料,因为它们对环境极其有害。大多数铜盐对多种植物和动物,包括人类,都是强烈的毒药。

对于更好的蚀刻方法,我推荐一个名为“停止使用氯化铁蚀刻液(更好的解决方案)”的 Instructables 页面,你可以在 www.instructables.com/id/Stop-using-Ferric-Chloride-etchant!--A-better-etc/ 找到它。在混合蚀刻液之前,请仔细阅读此教程中的环境和个人安全警告。

本教程中描述的系统使用标准的家用化学品:过氧化氢(H[2]O[2])和盐酸(本质上是氯化氢,HCl)。与旧的氯化铁或过硫酸铵技术相比,这个过程更加环保。你还可以在不丢弃旧溶液的情况下再生所描述的溶液,因为它实际上使用铜——即铜氯化物在水合盐酸溶液中——来溶解铜。

除了蚀刻液,你还需要一个容器来蚀刻电路板。对于非常小型和中型电路板,可以使用圆柱形容器,例如图 0-16 中的烧杯。

将蚀刻液放入安全的容器中,接下来就是将 PCB 放入蚀刻液中,并在不需要的铜层被去除后取出 PCB。在图 0-16 中的情形下,电路板被浸入和取出蚀刻液。请注意,烧杯放置在加热板上。加热溶液可以加速蚀刻过程,但请确保温度保持在 100 到 120°F 之间。

对于较大的电路板,可以使用某种锅具。如果你倾斜锅具,蚀刻液会流过电路板,正如图 0-17 中所示。

image

图 0-16:在烧杯中通过 PCB 蚀刻自动搅拌器搅动蚀刻液进行小板蚀刻,来自第二章。电路板使用塑料线扎固定。

image

图 0-17:在由 PCB 蚀刻自动搅拌器倾斜的容器中蚀刻更大的电路板

平盘可以是玻璃或塑料材质。过去,我曾使用玻璃烤盘,但图 0-17 中的容器是塑料的。如果你使用塑料容器,使用时要小心热量。推荐区域内的温度应是安全的。

在这两种蚀刻情况下,使用基于 Arduino 的搅拌器(见第二章以构建该项目)可以加快蚀刻速度。搅拌器提供了一种简单的机械方式来搅动蚀刻液,加速蚀刻过程。

钻孔电路板

蚀刻只会去除铜,因此,除非你制作的是单面板且全部是表面贴装元件,否则你必须手动为组件钻孔。根据设备和孔数的不同,钻孔 PCB 可能是件繁琐的事。

在我刚开始制作电路板时,我使用 Dremel 工具手工钻孔,钻头是 #66 类型。对于小型项目,手动钻孔可以,但对于更大的项目,使用钻床会更加方便。

如果你已经拥有一台 Dremel 工具,那你真是幸运了。根据购买地点的不同,花不到 40 美元,一款 Dremel 钻床附件可以很好地用于电路板以及其他数百种任务。如果你还没有 Dremel 工具,你可以在网上选购一款大约 30 美元或更便宜的。市场上也有许多其他价格相对低廉的高速钻头和钻床组合。你可以在 Harbor Freight 和其他进口商品供应商处找到这些产品。

如果你计划生产多个 PCB,我建议使用专用的钻床,而不是钻床附件。有一些低压电源的便宜型号,也有一些高价型号,例如图 0-18 中的 Electro-Mechano,这款设备专门设计用于在珠宝和 PCB 上打小孔。只需选择一款适合你需求的设备即可。你还需要小号钻头来打孔。我推荐一套 10 支的钨钢钻头,具有 1/8 英寸的柄部,可以在 Electronic Goldmine(零件编号 #G15421)购买到。亚马逊也有类似的套装,我曾以非常实惠的价格购买了几套。

image

图 0-18:我用于钻孔 PCB 的小型 Electro-Mechano 钻床

本书中使用的连接器

在本书中,我尽量简化连接器的使用,并减少使用的连接器种类。但是无论你是否制作自己的 PCB,你总是需要某种方式将 LCD、I²C 适配器、传感器等模块连接起来;有时你可能需要自己组装连接器。

我经常使用的连接器是一种 0.100 英寸间距的连接器系列,这种标准适用于 PCB 上的男性和女性插座,也适用于某些电缆组件的独立连接器。尽管本书中使用的组件来自 Pololu Robotics and Electronics(* www.pololu.com/ *),但许多其他供应商,如 Jameco、Newark、Mouser、Digi-Key 等,也提供相同或类似的组件。

图 0-19 展示了我使用过的一些基本连接器配置。

image

图 0-19:一些基本的连接器

男性和女性压接连接器是我制作的大多数电缆中的主力。不过,这些连接器必须压接到它们所连接的电线中。要压接一个针脚,你可以使用专业的压接工具(参见图 0-20),这样压接出的效果很好(参见图 0-21)。

image

图 0-20:用于将 0.100 英寸压接连接器压接到 26、28 和 30 号线的压接工具

image

图 0-21:使用压接工具正确压接的男性压接连接器

Pololu 销售的压接工具相对容易使用,能够压接出坚固的连接,但价格有点高,大约 30 美元。如果你不想购买压接工具,也可以使用一把小钳子进行压接。虽然这样得到的连接可能不如专业工具压接得漂亮,但应该同样有效。图 0-22 展示了我用钳子压接的电缆。

image

图 0-22:一个与图 0-21 中相同的男性连接器,使用一把钳子手动压接。两个连接器都牢固地安装在连接器外壳中,效果良好

你可以使用带有女性压接针脚的线缆来插入男性插座。这些对于通过电缆连接 PCB 的各个部分,以及将 Arduino 板连接到扩展板非常有用。

插座和外壳的尺寸从单引脚到 10 引脚、15 引脚甚至更大都有。本书中大多数涉及手工制作连接器的项目使用的是 2 引脚和 4 引脚的连接器。

使用 SOIC

制作通孔插座的连接器没问题,但带有 0.100 英寸间距引脚的通孔集成电路越来越难以获得。虽然制造商继续生产许多老格式的 IC,但新设计往往只有表面贴装元件。这些新封装被称为 小外形集成电路(SOIC)。图 0-23 展示了两个 SOIC 元件与一个 8 引脚的 DIP IC 一起进行尺寸比较。

image

图 0-23:标准的 DIP 封装(上)与两个小型 SMD 集成电路的比较,一个是 5 引脚的 Linear Technology LTC1799,采用 TSOT-23 封装(中),另一个是 3 引脚的 Maxim MAX7375AUR,采用 SOT-23 封装(下),旁边有一枚一角硬币作比例

什么是 SMT 设备?

图 0-23 中显示的两个非 DIP IC 是表面贴装技术(SMT)设备。SMT 设备直接焊接到 PCB 的表面,而不是通过底部的孔将引脚突出。SMT 的优点在于,可以将设备做得更小,并且它们可以彼此靠得很近,从而实现更紧凑的设计。许多 SMT 元件的引脚间距为 0.95 毫米(0.0374 英寸)或更小,这与之前讨论的 0.100 英寸间距的元件不相符。

使用 SMT 组件还可以减少布线长度,这在高频情况下至关重要。许多电路板有多个层(本书中的项目最多有两层),层之间的连接以前是通过 IC 引脚的孔来完成的。这些连接现在更常通过通孔来实现,通孔是板中的小型镀铜孔。自动化贴装设备现在也开始专注于 SMT 元件。未来,电阻器、电容器、电感器、LED、保险丝等很可能仅以表面贴装配置提供,但这可能需要一段时间。

本书中提到的 SMT 封装是有引脚的——也就是说,封装本身有引脚突出,尽管这些引脚并不是为了通过 PCB 上的孔来连接。带引脚的 IC 有多种配置,封装引脚间距不同,从相对稀疏的引脚——比如图 0-23 中的两个 SMT 元件——到引脚数量高达几百的 IC。

注意

本书避免使用某些 SMT 封装类型,例如具有直接连接补丁的超小型封装,其中芯片直接连接到 PCB(称为芯片封装在板上,Chip-on-Board),以及球栅阵列封装,其中连接是封装底部的受控坍塌焊料凸点。

焊锡膏法

使用含铅的 SMT 芯片会留下几个选择。一个选择是设计一个具有正确焊盘的 PCB,以适配 SOIC 封装,并将 IC 直接焊接到 PCB 上。焊接 SOIC 组件涉及涂抹焊锡膏并加热电路板本身。虽然这是可行的方法(网络上有很多相关教程),但填充电路板可能会比较困难,尤其是当电路板同时包含穿孔和 SMT 元件时。除非你有用于涂抹焊锡膏的模板,否则焊锡膏需要手动涂抹,通常使用注射器,有时用尖锐的牙签或牙科钳。图 0-24 展示了我在此过程中使用的一套工具。

几家在线供应商提供价格合理的注射器焊锡膏。大多数焊锡膏的熔点在 300°F 到 470°F 之间(有些较低),因此可以在烤面包炉或热板上的容器中焊接电路板。

image

图 0-24:Chip Quik 焊料、头戴式放大镜、牙科钩、镊子、适配器板和 SOIC(镊子旁的斑点),准备安装

我使用的焊膏是 Chip Quik。它相对便宜,带有一个针管和喷嘴,熔点只有 138°C 或 281°F。尽管喷嘴可能稍微小一些,但它在大多数应用中都能正常工作。Chip Quik 的低熔点使得在烤面包机或加热板上焊接电路板变得非常容易,但在其他情况下可能会成为一个问题:在高电流应用中,焊接点可能会加热到足以熔化焊料的温度。但在本书中的电压、电流和信号水平下,我不认为这是一个问题。

在焊膏涂抹后,可以用一把镊子和稳稳的手将组件小心地放置到焊膏上。我还使用头戴式放大镜,以便能看到连接。当芯片放置到位后,剩下的就是将组件加热到焊料的熔点,哗啦——任务完成。

如果你选择在普通的烤面包机中加热电路板,而不是购买专门的 SMT 烤箱,那么请确保不要使用你用来做饭的烤面包机。许多焊料仍然含有铅,已被认为对健康有害。助焊剂材料(在焊膏中,用于使焊料更容易流动)和粘合剂也含有某些挥发性化合物,如果误食,可能对健康不利。

你还可以将较小的电路板放进一个小而干净的金属罐中。然后将罐子放到加热板上,并在罐子上放一小块钢板(铝也可以)以保持热量。当焊膏熔化后,去掉热源。整个过程通常只需要几分钟。

对于像我这样手指粗的人来说,0.95 毫米还是挺小的,无论是涂抹焊膏、放置组件,还是直接焊接带引脚的 SMT 组件。这个过程有时需要我尝试几次。如果你还不准备在主 PCB 上直接使用焊膏解决方案,可以考虑购买适配器板,将 SMT 组件转换为常规的 0.100 英寸中心孔安装。

一些供应商提供小型适配器板,可以将 SOIC 封装转换为中心间距为 0.100 英寸的 DIP 封装。图 0-25 中的适配器板来自 Futurlec (www.futurlec.com/)。Futurlec 的适配器板每个只售 $0.28,所以我订购了各种不同的,包括适用于 8 引脚、14 引脚、16 引脚和 18 引脚 SOIC 的板子。

image

图 0-25:Futurlec 6PINSO23 适配器板

即使使用适配器,最佳的焊接方案是使用焊膏和烤箱(或者如我刚刚描述的那样使用罐子)。但如果你没有这种技术所需的材料,你也可以直接焊接 SOIC 组件。

直接焊接

直接焊接 SOIC 组件有点棘手。这样做需要一个细尖的焊接铁,尽管我使用的是我平常用的那种焊接铁(我认为我的尖端是 0.7 毫米)。以下是这种方法的工作原理:

  1. 首先,将公头排针放置在面包板上,并将适配器放在顶部,然后焊接它们,形成一个稳定的平台(参见图 0-26)。

    image

    图 0-26:带有插针并插入面包板以焊接集成电路的适配器板。图中的颗粒是焊锡和助焊剂的残留物,稍后我使用酒精和棉签清理干净。

  2. 尽管适配器的铜板上有焊锡,但它的厚度不足以固定集成电路的引脚。需要更多焊锡,因此小心地在一个焊盘上融化一薄层焊锡。(通常,我会放入过多的焊锡,之后用吸锡带去除,但这也没问题,因为它仍然在焊盘上留下了一层薄薄的焊锡涂层。)

  3. 将元件放置在适配器板上,牢牢固定(我使用牙科探针施加压力),然后将热铁放在有焊锡的引脚上。

  4. 一旦第一个引脚固定好,它就能固定元件的位置,然后你可以小心地用热铁焊接其他引脚。

图 0-27 显示了我用这种方法焊接的电路板。它可能看起来不太漂亮,但它能正常工作。

image

图 0-27:一个完成的适配器板,已安装公头排针、集成电路已焊接,且解耦电容焊接在两个引脚之间。这是图 0-26 的清理版。

如图 0-27 所示的完成适配器板可以安装在常规的通孔板上,孔间距为 0.100 英寸。我在本书的弹道计时器(第八章)和方波发生器(第九章)项目中使用了这一技术。

总结思考

凭借本章的知识和一些前期的电子经验,你已准备好应对本书中的任何项目。我将在后续根据需要介绍其他重要技术和信息。

第二章:反应时间机器

image

在本章中,我将向你展示如何制作一个时光机——也就是反应时间机器。我很想说这个项目将带你“回到未来”,但遗憾的是,它做不到。它所看的“时间”是你对刺激的反应时间,这也让它成为一个有趣的游戏。这个项目旨在精确测量个人的反应时间,并为个人的表现提供反馈区域(见图 1-1)。你还可以个性化游戏,使它对你、你的朋友和家人来说更加有趣。

image

图 1-1:完成的反应时间机器

所需工具

焊接铁和焊料

电钻和钻头

安装胶带

剪线钳

零件清单

这个项目的零件数量是本书中最少的,但不要因此小看它的价值。我的家人和朋友们反复享受这个游戏,而且它很便携,所以你可以带着它去聚会和其他活动。

你需要以下材料:

一个 Arduino Nano 或克隆板

两个单刀单掷(SPST)瞬时开关(最好一个带红色按钮,另一个带不同颜色的按钮)

一个单刀单掷(SPST)切换开关

一个红色 LED

两个 10 千欧电阻

一个 470 欧姆电阻

(可选)一个可听见的指示器,Mallory Sonalert 或类似设备

一个 4×20 LCD

一个 I²C 适配器,如果 LCD 未包含(请参阅“将 I²C 板固定到 LCD”,见第 3 页)

注意

我单独购买了一个 16×2 LCD 及其外部 I²C 板,并将两者焊接在一起。不过,许多在线商家提供已焊接好的相同显示器和 I²C 适配器,价格和单独购买两块板差不多,甚至更便宜。特别可以查看 eBay

一个 9V 电池

一个 9V 电池夹

一个 3.5 毫米插孔(如果使用远程开关)

一个 Hammond 1591 BTCL 外壳

28 号或 30 号连接线

22 号固态导线

下载

在开始这个项目之前,请检查本书的以下资源文件,网址是 www.nostarch.com/arduinoplayground/

草图文件 Reaction.ino

外壳的钻孔模板 ReactionEnclosure.pdf

反应与反射

人们常常将反应和反射混淆,所以我会从定义这两者开始。反射是对刺激的非自愿、自动反应。在反射动作中,刺激绕过大脑,直接从刺激源传递到脊髓,再返回控制反应的受体,而不经过任何认知反应。(尽管我知道很多人几乎所有的刺激和信息——似乎都会绕过大脑,经常只是迷失在途中。)想象一下医生用膝盖锤敲击你的膝盖,以触发膝跳反射。

反应则是将刺激信号传递到大脑进行处理,然后通过神经传导返回反应器,产生某种运动行为。这个过程比典型的反射反应稍慢,尽管一些运动员据说拥有极快的反应时间,他们的反应可能更接近反射而不是反应。

注意

《体育画报》在这一领域做了有趣的研究,发表了关于棒球运动员和其他运动员的文章,这些运动员的反应时间似乎异常迅速

游戏是如何运作的?

反应时间机器游戏测量的是个人在看到视觉刺激(在本例中为 LED)后,按下按钮所需的时间。通过一个小的修改,你可以在游戏中加入听觉刺激:只需将 LED 替换为一个可听的提示音装置,如 Mallory Sonalert。反应时间以毫秒或秒为单位(由你选择),它是从刺激激活的那一刻到参与者按下按钮的那一刻之间的时间。

反应时间设备的历史

多年来,出现了许多测量反应时间的设备。我记得其中一个最简单的设备要求你将手指放在由另一个人悬空拿着的标尺两端。当标尺掉落时,你需要看它在你抓住它之前移动了多远。这个距离可以通过代数公式转化为时间。

image

其中S是移动的距离,A是重力加速度,T是反应时间。在完成这个项目后,你可以同时进行标尺测试和反应时间机器测试,看看两个设备之间的时间差距有多小。

使用 Arduino Nano 测量时间

尽管有许多方法可以测量经过的时间,但这个项目利用了 Arduino Nano 保持准确时间的能力。微控制器非常擅长保持时间,它们能够以最小的延迟测量一个输入与另一个输入之间的时间间隔。除了计时你的反应外,Nano 还会在 LCD 屏幕上显示结果。

Nano 几乎完成了这个项目的所有工作;其他组件基本上是被动的。在测试了一些初期版本后,我对草图进行了功能增强,使游戏更有趣且更精准。例如,我最初使用一个简单的按钮来重置 Nano 并启动计时器。参与者会在 LCD 显示时按下红色停止按钮,Nano 测量重置按钮和停止按钮按下之间的时间。然而,我发现玩家可以预见到重置按钮被按下,从而获得一些令人惊叹的反应时间。

为了防止玩家预期刺激何时出现,我让 Nano 延迟启动计时器。书中的版本生成一个从按下重置按钮开始的随机延迟,在随机延迟后激活刺激,并从刺激到玩家按下停止按钮的时刻开始计时。这样解决了一个问题。

然后,其中一位参与者试图提前行动,通过按住停止按钮来提前开始。我通过在草图中设置一个最小反应时间来解决这个问题。任何低于该最小值的反应时间都会触发错误,LCD 屏幕上会显示“Jumped the Gun”,表示玩家按得太快。

我使用了一个相对较大的显示器——4 行,每行 20 个字符——以便有足够的空间显示反应时间以及一些关于玩家相对能力的评论。你可以根据自己的喜好将评论写得幽默或严肃,但必须不超过 60 个字符——也就是说,每行最多 20 个字符,三行总共 60 个字符。虽然我将评论留给你来定制,但该项目的草图中包含了一些我在制作过程中使用的想法。你总可以编辑评论并重新加载草图,以显示适合一组用户(如朋友或亲戚)的评论。

预期的速度范围

根据我测试的小样本,大多数个体的反应时间似乎差异很大。有趣的是,年龄似乎并不是一个因素。平均反应时间大约为 200 毫秒,这也是许多研究人员所确定的平均反应时间。

我测试的样本中,反应最快的人为 105 毫秒;然而,这位个体无法重复这一表现。几位个体的成绩介于 105 毫秒和 125 毫秒之间,但并不稳定。显著更低的反应时间可能是异常的,或者是个体提前预期到刺激的结果。我玩家们未能重复极快反应时间,这一现象可能进一步支持这个观点。(我并不想指责任何人成功地预猜了释放时刻。)

原理图

虽然显示器本可以直接接线,但使用 I²C 互联让事情变得简单得多,且将接口减少为仅四根电线:正极、地线、数据线和时钟线(见图 1-2)。

需要的组件只有 Nano、三个开关(一个电源切换开关和两个短按按钮开关用于激活和重置)、一个 LED、显示器和三个电阻。尽管零件数量相对较少,但该项目运行得非常简洁优雅。

image

图 1-2:反应时间机器的原理图

面包板

就像我大多数 Arduino 项目一样,第一步是准备面包板来验证概念并测试草图。以下是如何接线面包板:

  1. 将面包板上的红色正极轨道连接在一起。

  2. 将面包板上的蓝色负极导轨连接在一起。

  3. 将 Arduino Nano(或克隆板)插入面包板,保持一侧留两行,另一侧留三行。(如果 Nano 板没有焊接插针,请参见“准备 Arduino 板”第 2 页。)

  4. 将 Nano 板的 5V 端子连接到面包板上的红色正极导轨。

  5. 将 Nano 板的 GND 端子连接到面包板上的蓝色负极导轨。

  6. 将电池连接器的负极电线连接到蓝色负极导轨。记住,面包板没有开关,所以你必须断开电池才能关闭它。

  7. 将电池连接器的正极引线连接到 Nano 板的 VIN 端口。(不要将电池的正极端子连接到红色正极导轨,这可能会永久损坏 Nano 板。)

  8. 将 5 英寸的电线连接到两个常开型瞬时按钮开关。(我使用 22 号实心导线,这样它可以直接插入面包板。)

  9. 为 LCD 准备一条电缆束(请参见“将 I²C 板固定到 LCD 上”第 3 页)。

  10. 将 LCD 的红色电线连接到面包板上的红色正极导轨(5V),黑色电线连接到蓝色负极导轨。

  11. 将显示器的黄色电线(SDA)插入 Nano 板的 A4 引脚。

  12. 将显示器的绿色电线(SCL)插入 Nano 板的 A5 引脚。

  13. 将每个按钮开关的一侧连接到蓝色负极导轨。

  14. 将红色反应开关(SW2)的另一侧连接到 Nano 板的 D7 引脚。

  15. 将黄色重置开关(SW1)的另一侧连接到 Nano 板的 D2 引脚。

  16. 从 Nano 板的 D7 引脚连接一个 10 千欧姆电阻到红色正极导轨。

  17. 从 Nano 板的 D2 引脚连接一个 10 千欧姆电阻到红色正极导轨。

  18. 将 LED 的阳极端(较长的引脚)连接到红色正极导轨,阴极端连接到面包板上的一个空行。

  19. 从 LED 的阴极端连接一个 470 欧姆电阻到 Nano 板的 D4 引脚。

Reaction.ino草图上传到 Arduino Nano(请参见“上传草图到你的 Arduino”第 5 页),此时你应该准备好开始使用。图 1-3 展示了面包板上的布局,开关通过电线悬挂。

image

图 1-3:反应时间机器的面包板布局。由于没有开/关开关,你必须断开电池才能关闭它

草图

草图是实际的计算机程序,它告诉 Arduino 做什么以及何时做。它使用自己独特的语言编写,包含结构、变量、数组、函数等,这些构成了微控制器遵循的“食谱”。这个语言会被转换成一串零和一,传递到控制器的不同部分,执行存储、计时、比较、算术运算等功能。

将计算机语言转换为一系列零和一的过程被称为编译。当你点击草图窗口左上角的验证和编译按钮时,Arduino 集成开发环境(IDE)中的编译例程将被激活。

由于在检查分数时可以插入所有的消息,草图变得相当长;然而,基本操作只需要少量代码行。你可以按原样使用评分函数,修改它,或者复制粘贴来创建新的评分函数。正如你在我的消息选项中看到的,我已经玩得很开心了。

以下代码已被截断,以减少行数。然而,你可以简单地访问www.nostarch.com/arduinoplayground/下载完整的草图,其中包含多个消息。

/*
Includes score function, random number generation, false start
"jump the gun" indicator, and multiple messages spaced 10 ms apart

Mod for "jump the gun" gives response if time <70 ms
*/

#include <Wire.h> //Libraries included
#include <LiquidCrystal_I2C.h>

int start_time = 0;
int stop_time = 0;
int reacttime = 0;
int x;
int R;
int randnumber1;
int z;

LiquidCrystal_I2C lcd (0x3F, 20, 4); //Initiate LCD

void setup() {
    Serial.begin (9600);
    pinMode(2, INPUT);
    pinMode(4, OUTPUT);
    pinMode(7, INPUT);
    lcd.init();
    lcd.backlight();
}
//Begin function "score"
void score() {
    lcd.clear();
    lcd.print("Reaction Time ");
    lcd.print(reacttime);
    lcd.print(" ms");
    lcd.setCursor(0, 1);

    if((reacttime >= 105) && (reacttime < 135)) {
       lcd.print("Approaching Superman");
       lcd.setCursor(0, 2);
       lcd.print("but you can still do");
       lcd.setCursor(0, 3);
       lcd.print("a lot better");
    }

    if((reacttime >= 135) && (reacttime < 180)) {
       lcd.print("Superhero Status");
       lcd.setCursor(0, 2);
       lcd.print("but not yet");
       lcd.setCursor(0, 3);
       lcd.print("Superman");
    }

    if((reacttime >= 180) && (reacttime < 225)) {
       lcd.print("You are trying ??");
       lcd.setCursor(0, 2);
       lcd.print("but not hard enough");
       lcd.setCursor(0, 3);
       lcd.print("still a loser");
    }

    if(reacttime > 225) {
       lcd.print("Lost your touch");
       lcd.setCursor(0, 2);
       lcd.print("If you ever had it");
       lcd.setCursor(0, 3);
       lcd.print("on the border of wimpy");
    }
}

//Begin main program
void loop() {
    digitalWrite(4, HIGH); 
    lcd.clear();
    lcd.print("System is Armed");
    delay(1000);
    lcd.setCursor(0, 1);
    lcd.print("     READY     ");
    lcd.setCursor(0, 2);
    lcd.print(" Push Red Button");
    lcd.setCursor(0, 3);
    lcd.print("When Red lamp lights");

    randnumber1 = random(5, 25); //Generate random number between 5 and 25
    R = randnumber1;
    for(x = 0; x < R; x++);
    delay(5000);
    if(x == R) {
       digitalWrite(4, LOW); //Turn on start lamp
       start_time = millis(); //Initiate timer
       lcd.clear();
       lcd.print("Mash React Button");
       lcd.setCursor(0, 1);
       lcd.print("           ");
       lcd.setCursor(0, 2);
       lcd.print("          ");
       lcd.setCursor(0, 3);
       lcd.print("          ");

       while(digitalRead(7) == 1); //Wait for response

       stop_time = millis(); //Complete timing cycle
    }

    reacttime = stop_time - start_time;

    if(reacttime < 70) { //Jump the gun indicator
       lcd.clear();
       lcd.setCursor(0, 0);
       lcd.print("Too anxious. You");
       lcd.setCursor(0, 1);
       lcd.print("(Jumped the Gun)");
       lcd.setCursor(0, 3);
       lcd.print("Could be Fatal!");
    }
    score();

    Halt:
    while(digitalRead(2) == 1);
}

#include行初始化了库:I²C 库,Wire.h,建立了 I²C 通信的规则,液晶显示库允许 Arduino 控制 LCD。接下来,我们定义了七个用于计算反应时间的变量。然后,setup()设置了串行通信——以便你可以调整代码并在串行监视器上查看——并将不同的引脚定义为输入和输出。输入引脚用于复位和停止按钮,输出引脚用于定义 LED,提示玩家何时按下停止按钮。

自定义反应评论

这个项目最有趣的方面之一是有机会在展示玩家反应时间时发挥创意。在setup()之后,草图展示了一个名为score()的函数,根据参与者的反应速度列出可以显示在 LCD 上的不同评论。函数未必是最有效的方式(也可以使用查找表或其他方法),但它足够有效。我在这个版本中只使用了一个评分函数;然而,你可以轻松地定义任意多个,并修改草图来选择其中一个。例如,你可能会编写第二个名为score1()的函数,包含不同的评论和时机。然后,为了在两个函数之间切换,你只需更改调用score()的那一行,改为调用score1()

要自定义草图以包含可以引用你自己朋友或家人的评论,你只需将我的草图中的评论替换为你自己的评论。不要忘记将你想要打印到 LCD 上的文本放在引号内,以便 Arduino 能够识别可打印的字符。

关于反应时间本身的说明:每个评论适用于 5 或 10 毫秒的反应时间范围。我选择这些范围是随意的。在你玩了反应时间机器一会儿之后,你可能希望根据用户的反应集中在某个特定区域(比如从 195 到 225 毫秒)来调整这些范围。我发现许多反应时间在 190 到 250 毫秒之间,但你的朋友和家人的情况可能会有所不同。在这种情况下,你可以将评论之间的间隔设置为 1 或 2 毫秒,以避免玩家一直得到相同的评论。

你可以根据需要添加任意多的评论,最多每毫秒一个评论。如果你不小心重叠了时间,程序可能无法编译。

注意

如果你想了解你的游戏测量结果如何与网络上的反应时间测量工具进行比较,可以在网上找到这些工具。不过,由于 PC 本身的延迟,这些工具的准确性可能存在问题

关于编写代码以设置 LCD 的说明

关于 LCD 设置有几点需要注意。这个示例使用了 LiquidCrystal 库,LiquidCrystal_I2C.h。如果你的 Arduino IDE 没有包含这个库,你可以按照 Arduino 网站上的参考部分的说明轻松下载该库(* www.arduino.cc/reference/ *)。

此外,每个 I²C 设备都有自己的 I²C 地址。这允许多个 I²C 设备通过一条串行线连接。通常设备文档会提供地址——在我使用的 I²C LCD 的例子中,地址是 0x3F。因此,当程序初始化 LCD 时,代码看起来是这样的:

LiquidCrystal_I2C lcd (0x3F, 20, 4);

然而,不同的显示器具有不同的地址。如果你有一个 I²C 设备但不知道其地址,你可以通过将设备连接到 Arduino,下载一个扫描程序并运行它,轻松找到该地址。扫描程序应该会在串行监视器上显示 I²C 地址。

本书中的许多项目都使用类似的代码来操作 LCD,因此每当你需要复习这段代码如何工作的时,可以参考这个框。

循环中发生的事情

现在让我们来看一下程序的循环部分。在void loop()启动程序后,程序调用digitalWrite(4, HIGH)来关闭活动指示灯。然后,LCD 屏幕被清除,并写入文本,表示系统已启动并准备好让玩家在红色 LED 点亮时按下反应按钮。

接下来,生成一个 5 到 25 之间的随机数,程序调用delay(5000)来从零开始每五秒钟计数,直到达到随机数。一旦达到了随机数,三件事会发生:首先,指示灯亮起;其次,Nano 中的内部计时器开始计时;第三,显示器将改变为“按下反应按钮”。

注意

更广泛的随机数范围可能会使这个游戏对玩家来说更加有趣。你可以通过改变随机数的数量、延迟或两者的组合来轻松进行实验

然后,Nano 通过while(digitalRead(7) == 1);等待直到反应按钮被按下。按钮按下后,Nano 计算反应时间,公式为reacttime = stop_time - start_time。这个时间会显示在 LCD 上,并用于选择score()函数中的适当评论。此外,如果玩家的反应时间小于 70 毫秒,条件语句会显示“抢先反应”的相应文字在 LCD 上。系统随后会停止,准备好进行重置。

否则,串口打印模块已经包含在内,以便你在调整代码并在串口监视器上查看时使用。它也有助于调试。

最后,调用score()函数,然后执行Halt命令,系统就准备好重置按钮被按下。

构建

构建反应时间机器可以根据需要简单或复杂。最初,我将所有组件放入了一个柔性手腕支架的塑料包装中。我用 X-ACTO 刀割了一个孔给显示器连接器,并用打孔器和锥形扩孔器打了开关和 LED 的孔。结果有些粗糙,如图 1-4 所示。

image

图 1-4:这是反应时间机器的最初原始包装,虽然能用,但太脆弱。塑料薄膜厚度仅为 0.018 英寸

准备一个坚固的外壳

当然,真实的外壳会让游戏更加坚固,这在竞争激烈的玩家不断按按钮时尤为重要。为了保持尽可能简单,我使用了 Hammond(1591 BTCL)的一款透明 ABS 塑料外壳。外壳的透明顶部让我可以将显示器放在盖子后面,而不是为了让显示器突出而开孔。为了安装组件,我按照图 1-5 中的图纸在盖子上钻了孔。

image

图 1-5:反应时间机器的钻孔模板

四分之一英寸的孔适合瞬时按键开关、切换开关和 3.5 毫米插孔。对于 10 毫米的 LED,我使用了 3/8 英寸的钻头,然后扩孔使其紧密配合。LED 不需要其他安装硬件。

注意

3.5 毫米插孔与执行开关并联。如果你想使用外部独立开关,可以直接插入插孔。然而,我放弃了这个尝试,因为大多数参与者更喜欢手持盒子

硬件安装

为了将显示器安装到外壳上,我使用了 3M 双面室内/室外超重型安装胶带。我裁剪了两段与 LCD 显示器端框相同大小的胶带,并将显示器直接粘贴到盖子上。该胶带难以移除,因此务必第一次就放置准确。我还使用相同的胶带将 Nano 和电池座安装到显示器背面。在安装显示器时,我还使用了剪线钳小心地剪去显示电路板的角落,以便它能足够深入外壳而不碰到盖子的安装支柱。请参见图 1-6,这是从底部看到的完成品。

一旦所有组件到位,剩下的就是将它们焊接在一起,并在需要的地方插入电阻。特别需要注意的是 I²C 适配器,它是位于开关和 LED 下方的黑色小板。虽然我本可以弯曲连接器并使用排针连接,但根据我如何压接连接器,外壳可能无法关闭。因此,我选择将电线直接焊接。只有四根电线,而且焊接时没有太多困难。最后,我打印出来并附上了来自 Brother 标签机的标签。图 1-7 展示了完成的装置。

image

图 1-6:这是安装在 ABS 塑料外壳中的装置背面。注意显示器的角落(左下和右下)已经被剪掉,以适应顶部安装支柱。3.5 mm 插孔未接线,因为我决定在此实现中不使用它

image

图 1-7:安装在 Hammond 1591 BTCL 透明塑料外壳中的完整反应时间机器

定制化的想法

你可以实现许多变化来增加反应时间机器的多功能性和娱乐性。例如,在我开发时,我将霍尔效应开关连接到其中一个模拟输入,并修改了程序,在激活霍尔效应开关时,自动减少一定百分比的反应时间。然后,我在手指上粘贴了一个小磁铁,磁铁与霍尔效应开关正对着,这样我握住盒子时,它就会激活开关。在我玩的时候,我的反应时间减少了大约 20%,而其他人则有一个实际的读数。当然,我并不建议读者去欺骗对手!

还有其他可以进行的修改,例如在草图计数到随机数时添加音调或哔声。通过添加一个提示音和几行代码,便可以轻松实现。如果你足够聪明,还可以添加其他音效,例如在得分较低时播放的粗俗声音。

你还可以锻炼大脑,并为草图添加代码,例如,在你重置之前,将三次尝试后的分数进行平均。我在玩这个设备时尝试了许多变种,但我想提醒你,可能会花费大量时间来获得微小的优势。把游戏组装起来,享受其中的乐趣。

第三章:PCB 蚀刻的自动搅拌器

image

本项目使用 Arduino 微控制器来感应马达电流消耗的变化(即马达使用电力的速率),然后反转马达的方向。电流消耗的测量和应用有许多用途,本项目提供了一种示例方法,未来在电子项目开发中可能会非常有用。

“自己制作 PCB”在第 13 页展示了如何使用现成且环保的家庭产品,以非常低的成本在家设计和制作电路板。这个过程的一部分包括将铜层蚀刻掉。将电路板浸入蚀刻液中并搅动时,过程会更有效,液体在电路板表面会形成层流,双向流动。根据蚀刻液的化学活性和铜的厚度,这一过程可能需要 10 到 15 分钟,甚至超过半小时!站在那里搅拌蚀刻液的确很无聊,但你可以制作一个装置,自动将电路板浸入并取出溶液(参见图 2-1)。

image

图 2-1:展示了用于将电路板浸入并取出蚀刻液的马达、曲轴和蚀刻槽的设置。虽然有许多方法可以搅动电路板,但将其浸入并取出蚀刻溶液效果很好,尤其适用于小型电路板

在本项目中,Arduino 用来测量马达的电流。当马达的旋转到达极限位置时,开始停滞,电流消耗增加。Arduino 通过反应电流的增加来反转马达。

自动马达反转项目的灵感来源

本项目的灵感来源于我的朋友遇到的一个模型火车配件问题。该配件包括一个索道,用来将假想的滑雪者上下小山。原始的机制失败了,于是我制作了一个小电路来驱动直流马达,使滑雪者上下移动。我的想法是,当电车到达轨道的顶部或底部时,马达会减速或停止,从而导致电流消耗增加。这种过高的电流消耗会通过改变极性反转马达,从而使电车反向行驶。到目前为止,滑雪者依旧停留在山脚下,因为我和我的朋友从未安装电路板,但核心电路运作良好,并且预示着其他有趣的应用。

接收输入、处理信息并输出结果是任何微控制器的基本功能。在这个案例中,Arduino 启动电机旋转,等待检测到电机的电流大于正常值,然后反转电机的旋转方向。这个简单的功能有许多不同的应用:你可以利用电压降来为超载电机提供安全关闭机制,创建限制运动的系统等等。

所需工具

一个 6-32 螺纹 tapping 工具

电钻和钻头

一把尖嘴钳

零件清单

一个 Arduino Nano 或克隆板

一个 SN754410 四路 H 桥 IC(如果需要,可以带插座)(注意,如果使用插座,PCB 提供的散热功能将失效。)

一块印刷电路板(PCB)或通孔板

一个限流电阻器(你应该有多个不同值的电阻可供实验,范围从 1 欧姆到 10 欧姆。对于小型电机,1/8 W 电阻即可,但对于较大负载,建议使用 1/4 W 或 1/2 W 电阻。)

两个 330 欧姆、1/8 W 电阻

两个 LED 灯,一个红色,一个绿色

一个 LM7805 电压调节器

一个塑料外壳(我推荐使用 Hammond 1591 XXATBU。)

两个 2 针母头连接器,用于将电机连接到屏蔽板

四个 4 针母头连接器,用于将 Nano 插入

一个小型焊接接头

一个 3.5 毫米、2 导线的插孔和插头

一个单极单投(SPST)拨动开关

一个插头式墙壁适配器,输出 5 至 12V,至少 200 mA

一个齿轮头电机(我使用的是 6V 电机,Amico 20 RPM 6VDC。)

两个 M3×0.5 mm 螺丝,配有螺纹垫片

限位电缆,最好是 0.039 钢琴线或弹簧线

废铜或铝

一个 4-40 或 6-32 螺丝

下载

在开始这个项目之前,检查本书的以下资源文件:www.nostarch.com/arduinoplayground/

草图 Reverse.ino

屏蔽 Reverse.pcb

模板 MotorMount.pdf

自动电机反转原理

Arduino 非常适合这个项目,因为它能够控制整个系统,并且简化了适配不同电流需求的电机的问题。如果用离散组件实现该项目,将需要比等效的 Arduino 电路更多的组件。而且,对于不同电机或不同反转阈值的变化,将意味着需要更换大量硬件,但使用 Arduino,只需简单地更改程序。Arduino 还提供了在运行的两端添加延迟的灵活性。

你将连接到 Arduino 的电机电路使用了一个电阻器,位于电源与电机之间(见图 2-2)。当电机减速或停滞时,电流增大,导致电阻器上的电压降。

image

图 2-2:电阻器两端的电压由正电源与电机输入之间产生。正是这个电压触发了电路的工作

电阻 R 上的电压降是微控制器的实际输入。在这个项目中,电压降被输入到 Arduino Nano 的两个模拟输入引脚,这两个引脚跨越了电压降电阻。微控制器处理这个输入并根据你的程序生成输出。

注意

你可以只使用单个模拟输入来实现电路,但那样会限制电路的一些灵活性——特别是当你使用的电机工作在不同电压下时

原理图

振动器电路将电阻 R1 上的电压输入到 Arduino 的两个模拟输入引脚 A0 和 A1 中,设置了实际的输入(见图 2-3)。

image

图 2-3:本项目的完整原理图显示了 5.6 欧姆电压降电阻(R1)、两个 LED(D)、330 欧姆限流电阻(R2 和 R3)以及四通道 H-Bridge(SN754410),其中一半用于使用

这个电路中的所有地线连接在一起,A0 和 A1 引脚之间的电压是你的程序用来决定何时反转电机方向的电压。请注意,这个电压不是相对于正电源轨或负电源轨的,但它必须在 0 到 5V 之间,以防止损坏微控制器。如果你在连接 H-Bridge 时遇到困难,请参阅“使用 H-Bridge”,该部分在第 48 页。

每个模拟引脚背后的模拟到数字转换器(ADC)提供 10 位分辨率,这意味着转换器最多可以提供 1,024 个不同的值,即 210,从 0 到 1,023,具体取决于输入。

因此,如果电源是 5V,每次增量大约是

5V ÷ 1023 ≈ 0.0048V。

确定反转阈值

为了编写一个程序,让 Arduino 知道何时反转电机,你必须自己确定这个临界点,通过一些数学计算和一点信念。

首先,确定你所使用的电机的电流消耗。通常在电机标签上会标明。我的电机的电流消耗约为 40 毫安(mA),即 40 千分之一安培(见图 2-4)。现在我们进入复杂的数学计算。你需要使用一个称为欧姆定律的公式来确定在程序中设置的电压阈值。

image

图 2-4:我使用了一款亚洲进口电机,如图所示安装了一个限位引脚,证明了其可靠性和性能。螺丝为 M3×0.05

我在电机电路中使用了一个 5.6 欧姆电阻。使用欧姆定律,即电压等于电流乘以电阻(V = IR,其中电压以伏特为单位,电流以安培为单位,电阻以欧姆为单位),我们可以计算出 40 mA 乘以 5.6 欧姆的电阻大约是 0.224V:

image

现在,回到 ADC。它有 1,024 个单位来表示 5V,因此每个单位代表 0.0049V。一点算术可以得出,0.224V 的降压大约代表 1,024 个单位中的 46 个:

image

有些估算你必须相信——至少在你通过测试确认之前是这样。这是其中之一。当电机减速或停转时,电流消耗会增加。根据电机的不同,电流的增加通常是正常电流的两到四倍,但也可能更多。

注意

在没有负载(或负载很小)的情况下,电机的电流消耗最小。正常运行负载下,电流可能是无负载电流的四到五倍。在重负载下,电流可能是无负载电流的 10 倍,具体取决于电机设计

所以根据我们的良好信念模型,设置电机反转阈值的一个好起点是 ADC 的 1,024 单位中的 90 到 100 个单位之间。

或者,你也可以使用数字万用表先测量精确的电流消耗(参见图 2-5)。使用万用表测量电流消耗时,初始时将其指示器设置为 200 mA;如果电机在搭建这里描述的电路时没有动起来,你可能需要将其设置为 10 A。

image

图 2-5:万用表对许多项目非常有用,家里备一个很方便。它们可以从不同的来源购买,价格范围也很广。我使用的是来自 Electronic Goldmine 的便宜款,但如果你计划做高压实验,建议投资一款非常好的万用表。

按照图 2-6 所示搭建电路,然后将万用表的红色探头连接到电源上。将万用表的黑色探头连接到电机的电线,完成电路连接。如果读数为负值,请反转万用表的红色和黑色探头。根据电源电压和电机电压要求,你可能还需要通过电压调节器电路将电机连接到电源,如在“电压调节器”一节中所描述的,见第 58 页。

image

图 2-6:测量电机电流消耗的连接图

要检查电流消耗,请抓住电机的轴以减缓它,并观察万用表上的读数。你可以通过将读数代入欧姆定律,计算电压并转换为步数,像我做的那样,从而得到准确的 ADC 步数指示。

注意

在草图中,我使用了 100 作为反转的阈值。你也可以通过将 100 乘以 0.0049V 来计算电压降的绝对值:

100 步 × 每步 0.0049V = 0.49V

请记住,精确的阈值取决于你使用的电机类型。不同的电机具有不同的电流能力,甚至可能需要不同阻值的电阻。另外,请注意电流消耗的数值并不精确。永久磁铁电机的特性是负载下的电流消耗是一个范围,而不是一个精确的数值。

随着电流的增加,电压降也会增加,直到达到微控制器被指示执行某个操作的点。在此时,A0 和 A1 之间出现的模拟电压差会超过预设的阈值,这将使 Arduino 启动。一旦达到阈值,Arduino 会告诉 H 桥反转电流至电机。

使用 H 桥

在未来的项目中,你可能会遇到 H 桥驱动器,因为它是一个非常多功能的部件,可以执行许多不同的功能。市面上有多种 H 桥芯片可供选择,但我一直在使用德州仪器的 SN754410 四端 H 桥。它很受欢迎,因为它能在宽广的电压范围内工作,非常灵活且价格便宜。逻辑电平为 5V,而驱动电压可高达 36V,持续输出 1A(峰值输出为 2A),因此能够驱动各种爱好用电机、电磁铁,甚至继电器。它采用标准的 16 引脚双排直插封装(DIP)。DIP 封装曾是长期的标准,但现在正逐渐被更新的类型所取代(请参见 “使用 SOIC” 在 第 20 页)。它是传统的“千足虫”式电路。

图 2-7 显示了 SN754410 H 桥的引脚图,而 表 2-1 显示了它的功能表。你可以在德州仪器的数据手册中找到更多信息,链接为 www.ti.com/lit/ds/slrs007b/slrs007b.pdf

image

图 2-7:此项目中使用的 SN754410 四端 H 桥芯片的引脚图。请注意,当从顶部观看时,带缺口指向上的芯片左上角是引脚 1

表 2-1: SN754410 的功能表

输入 输出(Y)
A EN
--- --- ---
H H H
L H L
X L Z

根据数据手册,在此功能表中,H 代表 高电平L 代表 低电平X 表示电平与电路行为无关,Z 表示高阻抗,这会关闭电机。

H 桥是一种优雅的电机控制解决方案,原因有几个。它允许从单一电源反转极性,并且提供不同的逻辑和控制电压。此外,如果双 H 桥的两个输入都为高或低,则没有输出。该草图利用了这一点,在一个函数中编写了停止电机的指令。本书中的其他项目也使用了这个功能。

面包板

对于大多数 Arduino 项目,我建议首先在面包板上搭建电路,以确保你走在正确的方向上,并验证你的初步假设。使用标准面包板和作为配件出售的插头线(参见 图 2-8)。

image

图 2-8:典型的小型面包板和插头线

在你开始在面包板上搭建电路之前,先检查一下你的 Arduino。许多 Arduino 板已经预先焊接好了男性插针。然而,并非所有情况都如此;一些亚洲供应商会将插针与处理器板一起放松在包装里。如果你的板子缺少插针,请参阅 “准备 Arduino 板” 章节,在 第 2 页 找到完整的安装说明。

大多数面包板在每侧的整个长度上都有红色和蓝色条纹;这些条纹旁边的孔分别用于电源(+)和接地(−)。在连接电路之前,使用一根线将右侧的红色列与左侧的红色列连接起来。同样,将蓝色列也连接在一起。

警告

不要 将红色列连接到蓝色列!这会导致短路,并烧坏电子元件

图 2-9 展示了我用于这个项目的面包板,来自 图 2-3 的原理图列出了连接方式。

image

图 2-9:这是我用作概念验证的面包板,确保一切如预期工作

警告

在 Arduino 正在通过电压调节器接收电源时,不要将其插入计算机。这可能会烧坏 Arduino

我建议按以下方式原型化你的电路:

  1. 将 Nano 板插入面包板,留出几行孔在一端。

  2. 从标记为 5V 的 Nano 引脚(引脚 27)引出一根线,连接到面包板上的红色正极轨道。

  3. 从 Nano 的 GND 引脚(引脚 29)引出一根线,连接到面包板上的蓝色负极轨道。

  4. 找到面包板上三个连续的孔,确保它们不会与任何东西连接,然后将 LM7805 的三个引脚插入这些孔。

  5. LM7805 的输入引脚将连接到 9V 电源,LM7805 的接地引脚将连接到蓝色负极轨道,芯片的输出引脚将连接到红色正极轨道。(参见 图 2-10 查看 LM7805 引脚排列图。)

    image

    图 2-10:LM7805 调节器的引脚排列

  6. 将 H-桥插入面包板,缺口朝向 Nano,并且在 H-桥和 Nano 之间留出几行空位。

  7. 使用一根线将 H 桥的第 1 针脚和第 16 针脚连接起来(见图 2-7)。然后,再用一根线将第 1 针脚连接到面包板的正连接端。这条来自第 1 针脚和第 16 针脚的连接为 H 桥提供运行逻辑的电压,并使所用的 H 桥部分启用。

  8. 使用一根线将 H 桥的第 4 针脚和第 5 针脚连接起来,然后将它们连接到面包板的负极端。将第 4 针脚或第 5 针脚通过电线连接到地面即可。

  9. 同样地,将 H 桥的第 12 针脚和第 13 针脚连接起来,并将它们连接到地面。

  10. 使用一根线将电机的一端(哪一端不重要)连接到 H 桥的第 3 针脚,并将 H 桥的第 6 针脚连接到电机的另一端。

  11. 将 Nano 的数字引脚 D12 连接到 H 桥的第 2 针脚。

  12. 将 Nano 的数字引脚 D13 连接到 H 桥的第 7 针脚。

  13. 将 5.6 欧姆电阻(R1)的一端连接到 H 桥的第 8 针脚。

  14. 将电阻 R1 的另一端连接到面包板上的红色正极轨道。

  15. 使用一根线将 H 桥的第 8 针脚与 Nano 的模拟引脚 A0 连接。

  16. 使用一根线将正极(红色)连接器与 Nano 的模拟引脚 A1 连接。

  17. 将一个 LED 的正极(长引脚)插入 Nano 的 D12 针脚。

  18. 将 LED 的负极插入面包板的空白行中。

  19. 从 LED 的负极所在的那一行,连接一根 300 欧姆的电阻(R2)到蓝色负极轨道。

  20. 将第二个 LED 的正极(长引脚)插入 Nano 的 D13 针脚。

  21. 将第二个 LED 的负极插入面包板的空白行中。

  22. 从第二个 LED 的负极所在的那一行,连接一根 330 欧姆电阻(R3)到蓝色负极轨道。

VCC2 电源驱动电机输出。它从电源的正极开始——原理图中的稳压器输出针脚——通过电阻 R1 到达 H 桥的第 8 针脚。VCC2 成为电阻 R1 的低电压端;随着电机负载的增加,它的电压会变低,因为电阻的另一端连接到电源的正极。VCC2 电源电压可以在 5V 的逻辑电压到 H 桥的 36V 极限之间变化。对于这个项目,我直接将电压降电阻连接到 5V 电源,这对于一个 6V 电机来说非常适用。

Nano 的 D12 和 D13 输出引脚驱动 H 桥的 A 输入,而 A0 和 A1 输入则跨接在电压降电阻 R1 上。正是这个电压降值告诉 Arduino 改变输出,以指示 H 桥反转电动机。当输出 D13 为高而 D12 为低时,H 桥的输出引脚 2Y 变为正,而 1Y 保持为负。当 D12 为高而 D13 为低时,反转发生,1Y 变为正而 2Y 保持为负。当两个引脚的输出都是高或低时,它们处于相同的电势(或电压),电动机不会被驱动。(参见 H 桥芯片的数据手册中的功能表,或查看表 2-1。)

草图

以下草图的编写方式是,当电动机达到一个方向的极限时,两个输出都变低;当电动机达到另一个方向的极限时,两个输出都变高。当两个输出都是高或低时,电动机两端没有电压,并且会停止一定的延迟时间。延迟满足后,电动机会开始反向运转。由于 LED 连接到 D12 和 D13 引脚,你还会看到一个视觉指示。当电动机暂停在一个方向时,两个 LED 都亮起,而当电动机暂停在另一个方向时,两个 LED 都熄灭。

     /* Sketch for the Automatic Motor Reversal Project
     */

     //Identify pins that will not change
     const int ledPin1 = 12; //LED1 in schematic
     const int ledPin2 = 13; //LED2 in schematic
     const int analog0 = A0;
     const int analog1 = A1;
     int analogValue0 = 0; //Identify variables for analog inputs
     int analogValue1 = 0;
     int analogdifference = 0;
     int threshold = 100; //The threshold value calculated to stop the motor

     int reading;
     int state;
     int previous = LOW;
     int count = 0;
     int numberstops = 250;
     int time = 0; //The last time the motor reversed

     //Amount of time to wait to get rid of the jitters when the motor reverses
     int debounce = 400;

➊   void setup() { //This is the setup routine
     //Initializes pins as input or output
       pinMode(analog0, INPUT);
       pinMode(analog1, INPUT);
       pinMode(ledPin1, OUTPUT);
       pinMode(ledPin2, OUTPUT);
       Serial.begin(9600); //Was used in setting up the parameters
     }

➋   void loop() { //This begins the processing section
         //Enter an endless do-nothing loop after the counter reaches the limit
         while(count > numberstops) {
             digitalWrite(ledPin1, LOW);
             digitalWrite(ledPin2, LOW);
         }

     analogValue0 = (analogRead(analog0)); //Read the analog values
     analogValue1 = (analogRead(analog1));

➌   //Setting up the analog difference
     analogdifference = analogValue1 - analogValue0; //This is the voltage drop
     //analogValue1 will be greater than analogValue0

     //These were added to view what was happening on the serial monitor
     Serial.print("count =      ");
     Serial.println(count);
     Serial.print("analogdifference =      ");
     Serial.println(analogdifference);
     Serial.println();
     Serial.print("numberstops =      ");
     Serial.println(numberstops);

     //This comparator looks at the difference or drop across the resistor
➍   if(analogdifference > threshold) {
        reading = HIGH;
     }
     else {
        reading = LOW;
     }

     //Toggles the output and includes the debounce
➎   if(reading == HIGH && previous == LOW && millis() - time > debounce) {
        if(state == HIGH) {
           state = LOW;
        }
        else {
           state = HIGH;
        }
        //Increments the counter each time the motor reverses
➏   count++;
        time = millis(); 
     }

     //Writes the state to the output pins that drive the H-Bridge
     digitalWrite(ledPin1, state);
     digitalWrite(ledPin2, !state); previous = reading;
  }

这个草图为项目使用的引脚设置了易于理解的别名,并为引用模拟输入和其他关键值添加了便捷的常量和变量。在草图定义并初始化输入输出引脚之后,开始主循环。

在主循环中,草图会计算电阻上的电压降,并以模拟步长表示 ➌。在 ➍,草图会判断读取值是高还是低。从 100 到 120 的阈值对我使用的 6V、20 转/分钟电动机来说是可靠的,但你可能需要实验以找到适合你电动机的正确值。关于如何估算阈值的更多信息,请参见“确定反转阈值”以及第 46 页。在 ➎ 处的读取值决定是否需要反转电动机。

分压电阻对电流感应至关重要

我已经使用几个类似的电动机测试过这个反转电路,只需要对草图中的阈值做一点微调。然而,对于电流消耗极高或极低的电动机,你可能需要预估一个与模拟差异(analogdifference)完全不同的值,或者使用不同的分压电阻,这在电路图中是 R1。你可能需要将分压电阻的值降低到像 2.2 欧姆这样的数值,这样就需要减小你用来比较模拟差异的值。

对于大多数小电动机来说,分压电阻的值越低(通常在 1 到 10 欧姆之间),模拟差异通常会更稳定,效果越好。对于其他电动机,进行实验以找到最适合的电阻值。

当草图检查reading以查看电机是否需要反转时,还使用debounce值来确保高读数不是由电机换向器或刷子在合法反向期间产生的电噪声造成的。我将debounce设置为 400,但对于不同的电机可能需要进行调整。特别是对于较大的电机,可能需要将其设置得更高。

这个草图还包括一些在将电机作为 PCB 搅拌器时并非必需但在其他应用中可能有帮助的功能。让我们更详细地看看这些项目的方面。

我添加的一项功能是添加一个计数器来跟踪电机反转的次数。在草图中,计数增量显示在➏处为count++。在项目中,当count达到某个值(如果count = numberstops),电机将停止。如果您希望设置一个警报,比如可听到的报警器来告知您完成了,可以通过添加一行代码来轻松实现这一点,以写入其中一个数字输出引脚。我在草图中设置了最大的count值,使用numberstops = 250,所以电机将反转 250 次然后停止。这提供了略多于 15 分钟的蚀刻时间,使用 5V 运行的我选择的电机,这应该足够蚀刻大多数电路板。

当达到最大计数时,草图进入while循环开始,停止搅拌。这基本上使处理器停滞,您必须按电源开关重新启动或重置搅拌器。将此循环放在软件的开始附近只是提醒它的存在。

计数、可选的警报和停止功能的背后思想是提醒您检查电路板是有帮助的。如果电路板已完成蚀刻,继续搅拌会加速线路的削蚀,这是不好的,因为它会削弱(甚至可能断裂!)小铜线迹。另一方面,如果在合理的时间内未完成蚀刻,您可能需要刷新蚀剂。

MOD: 可调停止量

如果在草图中设置一个固定的最大停止数让你不满意,可以尝试在电源和地之间连接一个电位器,将调节引脚(通常是电位器的中间引脚)连接到 Arduino 的 A2 输入引脚。然后,将 numberstops 设置为 A2 的值,该值应在 0 到 1,023 之间,这取决于电位器刮板的位置。

草图的区别在于这里。首先,更改

int numberstops = 250;

int numberstops = setNumber;

然后,添加以下内容:

int setNumber;
int analogPin2 = A2;
int analogValue2;
setNumber = analogRead(analogPin2);

因为时间是相对的,您可以使用一个 270 度旋转的线性电位器,并在外壳上做一些粗略的标记以指示计数的次数。

护盾

对于这个项目,我建议制作一个小型的 PCB护盾,它基本上是一个设计为插入 Arduino Nano 的主板。使用护盾,你的电机反转项目可以保持紧凑,并且你可以以最少的工作量进行设计和制作。

PCB 布局

你可以直接将项目的部件焊接到一块带孔的项目板上,但我相信,制作并组装护盾所需的时间要比将部件放到穿孔板上并手工接线少。通过准备、蚀刻、钻孔和组装自己的 PCB,你还将获得宝贵的经验。而且最终,一些项目足够复杂,手工接线就不再是一个理想的选择。(参考图 5-13 和第 148 页中的示例。)

为了制作我的印刷电路布局,我使用了一款免费的软件程序,叫做 ExpressPCB。图 2-11 展示了我所用的 PCB 布局。

image

图 2-11:这是我在项目中使用的实际 PCB 图案。Arduino Nano 可以直接焊接到板上,也可以通过插针连接器插入。

如果你不想自己设计 PCB,但仍然想制作电路板,可以从www.nostarch.com/arduinoplayground/下载Reverse.pcb文件,并按照第 13 页中“制作自己的 PCB”的说明操作。制作好你的 PCB 后,只需将所有部件焊接到正确的位置,你的护盾就完成了。

护盾设计说明

如果你自己设计护盾,有几个设计因素你必须牢记。

模拟输入

请确保根据图 2-3 中的电路原理图,将 A1 和 A0 输入连接到 R1 电阻器的正确端。A1 应连接到电源侧,A0 连接到 H 桥侧。在草图中,为了比较模拟值,我们计算差值:analogdifference = analogValue1 – analogValue0,其中analogValue1是电阻器高端的输入信号。在这个例子中,analogValue0是 A0,analogValue1是 A1。

接地和散热

引脚 4、5、12 和 13 是 H 桥上的地线,它们也充当散热器以防止芯片过热。在拟议的护盾上包含了一个小区域,用于增加散热器的面积。如果你使用的是相对较小的电机——例如 6V、20 mA 的电机——则不需要更多的散热措施。如果你使用的是更大的电机或驱动较重的负载,可以考虑使用 PCB 的另一面作为散热器。

电压调节器

本项目使用了独立的 5V 稳压器来为 Nano 供电。一个 9V、200 mA 的插头墙适配器连接到板载的 LM7805 稳压器,这将电压从大约 9V 降到 5V。外部稳压器被包括进来,以便使用比 Nano 内置稳压器更强大的稳压器。确保正确连接稳压器的引脚(见图 2-10)。

你可以将 7.5V DC 或 9V DC 墙壁电源直接连接到 Nano 的 VIN 引脚,并使用板载稳压器,这样我的电机就能正常工作。但是,如果你使用更大的电机或高电流 LED,它可能会使板载稳压器负担过重,甚至可能烧坏它。

电源电压越高,稳压器将需要更多的工作来将电压降低到 5V。过度使用稳压器可能会导致其过热并失效。例如,给稳压器输入 12V 可能是 5V 稳压的上限。9V 输入更好,而 7.5V 输入则更优。如果稳压器芯片变热,给其散热片加装散热器。一个小的铝片通常就足够了,但也可以使用普通的散热器。而且,尽管最好将供电电压尽可能接近输出电压,但请记住,稳压器需要至少比稳压输出高 1V 才能正常工作,因此它必须至少接收到 6V,即 5V 稳压输出加上 1V。超过 12V 的输入电压也是可行的,但一定要确保不要超过设备的限制。

MOD: 使用更高电压

如果你为这个项目使用更高电压的电机,它将转得更快,拥有更大的扭矩等等。但是你不能仅仅将更高的电压连接到 H 桥第 8 引脚的降压电阻的高端。那样会导致 A0 和 A1 与地之间的电压超过 5V,这对 Arduino 上的 ATmega328 微控制器的健康有害。(这是唯一一个相对于地的电压很重要的情况。)因此,必须进行修改。查看图 2-12 中的原理图中的 R1。电源首先连接到电阻 R2;R2 与电阻 R3 连接,R3 接地。

image

图 2-12:如果你选择使用更高电压并驱动更快的电机,你将需要通过在 A0 和 A1 输入端前添加电压分压器来修改电路

为了避免损坏 Nano 处理器,你需要确保在接合点处的电压保持在 5V 以下,相对于地面。实现这一点最简单的方法是使用电压分压器。两个电阻对将较高的电压进行分压:第一对是 R2 和 R3;第二对是 R4 和 R5。电阻的值应当使得每一对电阻接合点的输出——R1 和 R2,R4 和 R5——对于任何输入电压值,都略低于 5V。

使用此公式:

image

并且通过图 2-13 中的原理图来确定电压分压电路中应使用的电阻值。

例如,如果你从 9V 开始,并随意选择一个 10 千欧姆的电阻串联,根据计算器,你需要用一个 12.5 千欧姆的电阻将其与地相接。我手头上最接近的电阻是 12 千欧姆,效果很好。如果你找不到适合需要的标准电阻,你也可以使用两个标准电阻并联,以通过这个公式得到你想要的电阻值:

imageimage

图 2-13:一个基本的电压分压器。要找到你应该使用的电阻,将你自己分压器的数值代入公式,就像你的分压器是这个电路一样

如果你不想自己做代数运算,你可以使用一些方便的在线电压分压器计算器,如www.sengpielaudio.com/calculator-paralresist.htmwww.raltron.com/cust/tools/voltage_divider.asp。SparkFun 也有一个关于电压分压的优秀教程,并且提供了自己的计算器:learn.sparkfun.com/tutorials/voltage-dividers/

方向 LED

当然,哪个 Arduino 项目没有闪烁的 LED 呢?正如你在原理图和保护板 PCB 上看到的,我包括了两个 LED:一个红色用于顺时针旋转,绿色用于逆时针旋转。但哪个方向对应哪个 LED 是由你来决定的:只需反转电机引线即可改变 LED 状态。

构建

对于这个项目,你将使用电机反转技术来创建一个加速 PCB 腐蚀的搅拌器。为此,你将用一个 Arduino 驱动的电机将 PCB 悬挂在腐蚀溶液上方,如图 2-1 所示。一个小型外壳将包含 Arduino Nano、保护板、电机与限位电线、方向 LED、电源开关和电源插座。

在组装好外壳后,你只需将它安装在腐蚀设置的上方,并将反转器连接到 PCB 或托盘上。我将我的外壳夹在工作台上方的柜门上,下面放置了一个腐蚀容器(见图 2-14)。整个系统可以快速组装和拆卸。

image

图 2-14:对于较大的 PCB,尝试使用托盘腐蚀,这是一种更传统的方法。只需将电机反转器连接到托盘上,以便摇动电路板,而不是使用反转器将电路板浸入并取出溶液中

本项目其余部分的构建需要一些耐心,也许还需要一些创造力来收集所需的零件。你将需要几颗 M3 螺钉来将电机固定到电机板上——在这种情况下,是一个小型的铝制 L 形支架——以及一些限位电线,最好使用 0.039 的钢琴弦或弹簧钢丝。你还需要一小块废料黄铜或铝块——圆形或矩形都可以——用来连接到电机轴和曲柄上,以及一颗长的 4-40 或 6-32 螺钉作为曲柄,另加一个 M3 垫片和焊接端子,用来将搅拌器线连接到曲柄上。图 2-15 展示了几乎完成的、未安装的产品。

image

图 2-15:在将组件放入外壳之前,先接线并进行最终测试。测试时,我将电机夹住,这样曲柄可以自由转动。调节器散热器遮挡了大部分的屏蔽。

限位电线

限位电线通过与电机曲柄碰撞,实质上限制了电机的旋转。它们与曲柄碰撞的旋转点就是旋转的限制。当曲柄撞到限位电线时,这些电线会阻止电机继续转动,并触发反转。

我推荐使用钢琴弦或弹簧钢丝,这样在曲柄到达旋转极限时,能提供一定的弹性。用一对尖嘴钳将两根限位电线弯成所需的形状(参见图 2-16)。这些电线将固定在电机安装螺钉的外侧,电机安装支架外侧。你可以通过松开螺钉并旋转电线来改变旋转的限位。

image

图 2-16:这是限位销的形成方法。一对好的尖嘴钳可以轻松完成这项工作。

曲柄衬套

曲柄衬套仅仅是将电机的旋转传递给曲柄的部件。图 2-17 详细展示了衬套、垫片和焊接端子的结构。

image

图 2-17:驱动机构的细节,它将电机的旋转转化为搅拌器的升降运动。

虽然在组装这个项目的过程中可能会有许多不同的变体,但这是我用来组装它的步骤:

  1. 在衬套的中心钻一个孔,孔的大小适合电机轴。衬套可以是一个直径约为 0.5 英寸、长度约为 0.75 英寸的小黄铜或铝圆棒。矩形的材料也能很好地工作。使用与电机轴尺寸最接近的钻头。例如,如果你的电机轴直径是 0.157 英寸,就可以使用 11/64 英寸的钻头,差不多就够了。孔的位置不需要精确到中心——只要接近即可。

  2. 在轴承中,与电机轴孔垂直的位置,使用#36 钻头钻孔。然后,攻丝所钻的孔,使得一颗长 6-32 螺钉能够同时作为限位螺钉和曲柄。你也可以使用单独的限位螺钉,将曲柄移得更远,正如我在图 2-18 中所做的那样。

  3. 将曲柄螺钉旋入轴承,使其紧贴电机轴,并使用锁紧螺母固定螺钉位置(参见图 2-18)。

    image

    图 2-18:一张详细展示曲柄头部的照片。注意用于固定电线的焊接片和左侧的鳄鱼夹

  4. 在曲柄的末端,你最终将连接一条线,用于将 PCB 板拉进和拉出蚀刻液。这个接头可以是一个螺母,甚至是一个鳄鱼夹,固定在曲柄上。然而,在细节中,我使用了一个 7 毫米长的 M3 六角公对公间隔套。我从间隔套的一侧平面开始,用同样的#36 钻头将间隔套贯穿钻孔。然后,我用 6-32 丝攻攻丝,并将其旋入曲柄。

  5. 取一个 M3×0.5 mm 机器螺钉,将其穿过焊接片(查看图 2-19 了解焊接片本身,查看图 2-18 了解焊接片的安装情况)。将螺钉完全旋入支架,直到它紧固在曲柄螺钉上。

    image

    图 2-19:用于固定电线的焊接片,这些电线固定了蚀刻板。如果你无法购买类似的物品,可以用一块废金属或塑料轻松制作一个

我本地的 Ace 硬件店提供了我所需的所有配件,除了 M3 间隔套,我从 eBay 上购买了它。你应该能在 Home Depot 或 Lowe’s 找到相同的物品。

包装

屏蔽和 Nano 适配一个标准的塑料外壳(参见图 2-20)。在外壳上钻孔,用于 3.5 mm 电源插孔、作为电源开关和重置按钮的 SPST 开关、指示 LED 和电机线。

image

图 2-20:完成的外壳,包含电机、限位电线、方向指示 LED、电源开关(重置)和电源插孔。LED 会亮起,每个方向一个。当电机在一个方向暂停时,两个 LED 都会亮;当它在另一个方向暂停时,两个 LED 都会熄灭

大多数 3.5 毫米插孔使用约 1/4 英寸的孔,与开关的孔径相同。如果你希望孔更加紧密,15/64 英寸会更合适。使用 5 毫米或 10 毫米 LED 将决定所需孔的尺寸。根据我的经验,不同品牌的 LED 直径略有不同,因此你可能需要先尝试较小的钻头,测试 LED 是否合适。对于 5 毫米和 10 毫米 LED,常用的英制钻头尺寸分别为 3/8 英寸和 3/16 英寸。如果你有一套锥形扩孔器,可以从较小的孔开始,扩孔至适合 LED 的紧密配合。

将电机安装在一小块铝角上,这种铝角在大多数五金店都有售。我购买了一段 1 英寸长的 1.5×1.5 英寸铝角,并用手锯将其切割到合适的尺寸。如果你使用的是我所用的电机,可以参考图 2-21 中的模板,或从* www.nostarch.com/arduinoplayground/* 下载并打印,剪下来,将其贴在铝角支架上,用中心冲或钉子仔细标记支架上的孔位。接下来,钻孔——电机安装孔为 1/8 英寸,中心孔为 5/16 英寸。如果你使用不同的电机,则需要测量并标出安装孔。

image

图 2-21:电机安装模板

如果你认为将来会在另一个项目中使用屏蔽,直接使用一些双面泡沫胶带将其固定在外壳上。否则,可以使用支撑柱和螺丝将其固定在内部,螺丝尺寸可根据需要选择。

蚀刻过程

制作 PCB 有多种技术,最常见的是减法工艺,它从一块铜覆板或粘合到电气绝缘基板上的铜箔开始,通过选择性地去除铜层,在板上留下图案。虽然铜可以通过机械铣削去除,但最常见的方法是通过化学方式选择性地蚀刻板上的图案。

在化学蚀刻过程中,电路图案通过化学阻焊剂打印在空白板上,这样在没有涂覆阻焊剂的区域,铜会被蚀刻剂去除。蚀刻剂是一种具有化学活性的物质,它会攻击未处理的铜层,只留下电路所需的铜。我在《制作你的 PCB》的第 13 页中详细描述了如何逐步蚀刻电路,且该项目使得这一过程变得更加简单。

我们的目标是将一块未蚀刻的电路板悬挂在容器中的蚀刻液上方,并保持电路板在蚀刻液中尽可能长的时间,同时搅拌器上下运动,产生蚀刻液沿电路板表面流动的层流。我建议使用尼龙扎带来固定电路板,因为尼龙对蚀刻液相对不透。你可以将扎带固定在电机轴上,用鳄鱼夹将扎带固定,这样电路板就可以轻松取下(见图 2-22)。

我使用了一个 250 毫升的烧杯作为蚀刻容器。对于非常小的电路板,这种方法效果非常好。对于较大的电路板,我推荐使用一个大量程的量杯,比如一个 2 夸脱的 Pyrex 量杯。一个 600 毫升的烧杯适用于中等大小的电路板。对于更大的电路板,你可以使用托盘,具体见图 2-14。

开关和电源输入位于外壳的左侧。为了固定正在蚀刻的电路板,我通过焊接接头穿入一根线,并用一个小鳄鱼夹将这根线固定在电路板上。在接头的背面,你可以系一个小结,或者用某种夹子固定,以确保线不会掉进接头并进入酸液。在我的设置中,一个夹具(在照片中的电机后面)将外壳固定在悬挂的门上。

image

图 2-22:这个基于 Arduino 的蚀刻搅拌器正在蚀刻电路板。蚀刻液应在蚀刻铜层时变为翡翠绿色。电路板通过一个用鳄鱼夹固定的尼龙扎带悬挂。线通过曲柄上的一个孔,并用另一个鳄鱼夹固定。一个 LED 灯亮起

请注意,蚀刻容器放置在加热板上。虽然蚀刻将在室温下进行,但加热会稍微加速这个过程。小心不要让蚀刻液过热:如果你将加热板设置在低温,使液体保持在约 100 到 120 华氏度之间,这样可以加速蚀刻而不会软化光刻胶。

第四章:可调稳压电源

image

无论你是使用标准的台式电源,还是通过计算机的 USB 端口为 Arduino 供电,迟早你都会需要一个独立的、可调电压的稳压电源。这个项目将教你如何制作一个,只需要少量的廉价零件。可调电源是许多工作坊中最常用的工具之一。这个项目既简单又有趣,你会发现你会一遍又一遍地使用它。

当设定为 5V 或 3.3V 时,可调稳压电源可以轻松为大多数 Arduino 项目供电。你也可以用它为一些附属设备供电,在系统中调整特定电压,而主电源保持不变,或者仅仅用来测试灯电路、LED、电机或其他设备。

电路使用了极其通用的 LM317 调节器芯片。如果你需要一款具有特殊要求的精密电压调节器,可以在网上查找 LM317。JavaScript 电子笔记本上有一篇特别好的文章,标题为“LM 317 电压调节器设计”,作者是 Martin E. Meserve,文章地址是www.k7mem.com/Electronic_Notebook/power_supplies/lm317.html

所需工具

焊接铁和焊锡

电钻和钻头(3/8 英寸和 1/4 英寸)

锯条或钥匙孔锯(剪切工具或其他)

一个十字螺丝刀

(可选)锥形扩孔套件

(可选)压接工具

零件清单

可调稳压电源能够提供从 1.25V 到大约 12V 的可调电压,最大电流可达 1.5A,具体取决于你使用的基础电源。它使用 LM317 单芯片电压调节器来设置电压。要构建这个项目,你需要以下零件:

一个 Arduino Pro Mini 或克隆板

一个 LM317 电压调节器

一个 LM7805 电压调节器

两个 2.2 欧,5 瓦电阻

三个 10 千欧,1/8 瓦电阻

三个 6.8 千欧,1/8 瓦电阻

一个 68 μF 钽电容

三个 0.1 μF 陶瓷电容

一个 1 μF 钽电容

一个 16×2 LCD 显示屏

一个 I²C 适配器(如果 LCD 未附带)

四个 4-40 螺丝

八个 4-40 螺母

一个 5 毫米 LED(用于电源指示)

一个单极单刀开关(SPST)

一个 470 欧,1/8 瓦电阻

一个 10 千欧,1/8 瓦电位器

一个 Hammond 面板/外壳(#1456CE3WHBU)

两个香蕉插头插座

一个 3.5 毫米插孔

一个 12V 2A 交流适配器

一个电源适配器插孔

一个 PCB/屏蔽板

六个 1×4 接头

四个 1×4 接头外壳

四个 1×2 接头

一个重型 TO-220 散热器

一个中等功率的 TO-220 散热器

四个男性压接连接器

四个女性压接连接器

30 号连接线

一个旋钮用于覆盖电位器轴

双面泡沫胶带

关于散热器选择的说明:市面上有各种各样的散热器可供选择。图 Figure 3-2 中展示的是 Futurlec TO220ST 型号,虽然它能正常工作,但当电流接近 1A 时会比较热。一个更大的散热器,如果能放入外壳中,可能会更好。Futurlec TO220SMAL 是 LM7805 的散热器,足以完成任务。

下载

你将在本书的在线资源中找到以下文件,帮助你完成本项目:

模板 PowerSupplyFront.dxf, PowerSupplyFrontBottom.dxf

草图 PowerSupply.ino

扩展板文件 VoltageRegulator.pcb

稳压电源的定义与非定义

本项目中的电源不打算替代常规的实验室电源。它不提供任何电流限制,额定电流为 1.5A,因 LM317 的电流承载能力。然而,针对各种应用——包括本书中的所有项目——它表现得非常好。如果你是 Arduino 新手,它将为你提供稳定的电源,并节省你大量的电池费用(如果你一直使用电池供电的话)。如果你已经拥有一台完整的实验室电源,这个项目将作为第二个电源变得不可或缺。该稳压电源可用于本书中需要辅助电源的多个项目。

我已经在其他应用中使用过该稳压电源,并且在本项目的最后,我将展示一个简化版本,可以作为远程电源使用。有时你可能没有适合某个项目的电压供应,而这个设计正好满足需求。

一个灵活的电压稳压器电路

图 Figure 3-1 中的基础 LM317 稳压器电路是该电源稳压器的核心。尽管它相对简单,但该芯片的简洁掩盖了它强大且多用途的特性。

image

图 3-1:这是稳压电源稳压器组件的原理图,带显示器的完整原理图见 Figure 3-4

我已经在许多应用中使用过这个电路的变种,从独立的可调电源到更大系统的一部分,总是取得了良好的结果。

在商店里,我有时使用一种“电线连接”版本,如图 Figure 3-2(左侧)所示,用于测试 LED 和控制诸如电机速度与灯光强度等设备。我还使用过面包板版本,如图 Figure 3-2(右侧)所示,用于实现稳压器电路。在这两种情况下,我都使用了一个调节电位器,需要调节工具或螺丝刀来进行调整。

image

图 3-2:电压调节器电路的“线搭线”版本,LM317 上安装了散热片(左侧)和电压调节器的面包板版本(右侧)。我在一个功率需求较低的应用中使用了这个电路,因此没有加装散热片

虽然这些调节器电路有效,但使用图 3-1 中更精细的稳压电源格式的一个原因是为了消除笨重的调节电位器,并改用标准的 270 度电位器和旋钮,这样我可以快速、轻松、反复地进行调整。但我构建它的主要原因是希望在工作台上方便地拥有一个具有数字显示的二次可调电压电源。

电路如何工作

这个项目的电路并不复杂。从本质上讲,它通过板载的模拟-数字转换器(ADC)测量 LM317 调节器输出端的电压,并将其与内部参考电压进行比较。结果会发送到 LCD 屏幕。然而,Arduino Pro Mini 5V 版的模拟输入端最大只能接受 5V。因此,我们使用了一个电压分压器来确保模拟输入引脚上的电压不会超过 5V。(确保供给 LM317 的电压不大于 12V。)

在这种情况下,电压分压器由两个串联的电阻组成,它们跨接在 LM317 的输出端和面包板的接地轨之间(参见图 3-4 中的示意图)。来自 LM317 的电压在 R2 和 R3 这两个电阻之间分配。如你在草图中所见,将分压后的电压转换回显示的原始电平,只需反转算术运算即可。

如图 3-4 中的示意图所示,LM317 的输出端连接到 R2-R3 电压分压器以及电阻 R1。R1 与 R9 和负载并联,或者说与任何你希望用电源供电的设备,并可以视为另一个电压分压器。R1-R9 电压分压器的电阻仅为 1.1 欧姆,因此其电压降相对较小。根据欧姆定律(I = V/R),R1 和 R9 上的电压将在最大电流为 1.5A 时降至 1.65V(这是该调节器 IC 所支持的最大电流):1.5A = 1.65V/1.1Ω。

这意味着当 LM317 提供约 12V 且负载电流为 1.5A 时,R1 和 R9 上的电压降为 1.65V,电源输出端剩余的电压为 10.45V。

看图 3-4 中的示意图,我们正在比较 Pro Mini 的模拟输入端 A0 和 A2 上的电压。如果你为 A0 和 A1 使用相同的电压分压器电阻值,你可以省略其中一组电阻,直接将 A0 连接到 A1。

电压分压器电阻值

实现特定电压所需的电阻值是通过以下公式确定的:

image

一个典型的电压分压电路的电路图如图 3-3 所示。

image

图 3-3:典型的电压分压电路

如果你愿意,可以做一些代数计算,但最简单的方式是使用在线计算器,比如* www.daycounter.com/Calculators/VoltageDivider-Calculator.phtml* 上的那个。在这个项目中,目标是实现大约 5V 的输出。我们从 12V 的输入和一个 10 千欧的电阻开始,在公式中表示为 R1,在电路图中标记为 R2。将这些信息填入计算器,计算公式会给出电路图中的 R2 和公式中的 R1 电阻值为 7.1 千欧。最接近的标准电阻值是 6.8 千欧,所以该项目使用 6.8 千欧的电阻和 10 千欧的电阻来构成电压分压器。

那么,为什么要从一个 10 千欧的电阻开始呢?第一个原因是为了避免消耗过多电流。即使整个 12V 压降通过 10 千欧电阻,它也只会导致 1.2 毫安的名义电流消耗。第二,我在零件箱里有很多 10 千欧的电阻,我敢肯定你也有。

在这个电路中,我使用了三组电压分压器。第一组用于测量稳压器输出端的电压,最终显示在 LCD 上。其他两组则分别在电压下降电阻的前后分压,以便根据公式I = V/R测量电流,其中V是电阻 R1 和 R9 之间的电压降,R 是这两个电阻的总值。我是否可以去掉一组电压分压器?是的,通过将 A0 和 A1 连接起来。然而,我认为我可能会在某个时候改变这些值,以通过将其值接近 Arduino 的参考电压来提高安培计的精度,因此我在项目中没有将它们连接。

电路图

虽然我希望稳压电源相对稳健,但我并不想让它过于复杂或难以构建。头发线和面包板版本在临时或紧急应用中表现良好,特别是与数字万用表(DMM)一起使用时,但我希望构建一些更持久的东西,它能够有自己的电压和电流读数,并且能够常驻工作台或放在我的桌面上,成为工具集中的常规部分。图 3-4 展示了稳压电源的完整电路图。

image

图 3-4:稳压电源的电路图

面包板

像我所有的 Arduino 项目一样,我从标准的面包板开始。为了简化操作,我使用了一个标准的电位器,其引脚可以适配 0.100 英寸间距的面包板孔。经过一些努力,一个标准的 16 毫米旋转电位器(原理图中的 R7)带有印刷电路板连接器,几乎能适配面包板上每隔一个孔。图 3-5 展示了安装好之前的面包板的俯视图。

image

图 3-5:稳压电源的面包板。原理图中的电容器—C1、C2 和 C3—不包括在面包板上,但应该包含在完成的单元中

准备 Arduino Pro Mini 和 LCD

Arduino Pro Mini 可能会附带公头针脚,也可能没有。如果没有,你需要自己焊接(请参见“准备 Arduino 板”第 2 页)。确保你的针脚条上针脚的数量与 Pro Mini 上的孔位匹配;如果附带的针脚条太长,你可能需要将其剪短。将两条针脚条修剪到合适的长度,并将两条长针脚条插入面包板,使其间隔合适,以便 Pro Mini 板能放在上面。将 Pro Mini 放置好后,焊接所有的针脚。然后,取两根针脚(使用从长针条中剩余的部分或单独购买),将其插入 Pro Mini 上的 A4 和 A5 孔,并焊接。这些针脚是用于 LCD 的。

最后,在板子的边缘(在 TX0 和 RXI 端)安装五个针脚。某些板子带有直头针脚,其他板子则带有 90 度弯曲的长针脚。在大多数应用中,我发现使用直头针脚更为方便。你可以使用直角针脚,但可能会使得插入编程连接器变得更困难,所以我建议将任何直角针脚替换为直头针脚。你还可以考虑使用一段 1/2 英寸长的 22 号线,将其焊接到 RST 针脚的短端,使其突出。编程时,女性针座连接器将连接到这个突出部分。

现在,你需要准备 LCD/I²C 组件。如果你单独购买了显示器和适配器,你需要将它们组装在一起。请参阅第 3 页的“将 I²C 板固定到 LCD 上”以获取详细说明。如果你购买了带有 I²C 适配器的显示器,它就可以直接组装了。

组装面包板

这是组装面包板的逐步指南:

  1. 插入电线连接两个正极(红色)轨道。

  2. 插入电线连接两个负极(蓝色)轨道。

    警告

    小心不要将两者交叉连接,将正极轨道连接到负极轨道。这样可能会造成短路并损坏硬件

  3. 将 10 千欧旋转电位器插入面包板。

  4. 将 LM317 插入面包板,带或不带散热器,靠近电位器,如图 3-5 所示。(有关 LM317 引脚分布,请参见图 3-6。)

    image

    图 3-6:LM317 调节器的引脚分布

  5. 当电位器轴面朝向你时,将电位器的最左侧引脚和中间引脚连接在一起,然后将这两者都连接到 LM317 的调节(ADJ)引脚。

  6. 将电位器保持相同的方向,连接最右侧的引脚到蓝色负极轨道(地)。

  7. 将一个 470 欧姆的电阻器从输出引脚连接到 LM317 的 ADJ 引脚。

  8. 将一个 1.2 欧姆的电阻器(图 3-4 中的 R1——我使用了两个 2.2 欧姆电阻器并联)从 LM317 输出引脚连接到你选择的负载上。为了测试,我使用了一个 1/8 W 的电阻器,并连接了一个 5V,30 mA 的白炽指示灯作为负载。(你可能想使用在最终装置中将使用的实际 R1 和 R9 电阻器,这样你就可以在完成装置之前调整草图。)

  9. 将 LM317 的输入引脚连接到 12V 系统输入电压。这是从 LM317 到图 3-5 中上方鳄鱼夹的导线。

  10. 将蓝色负极轨道连接到输入电源的负极(可能是墙插)。

  11. 将 LM7805 插入面包板,如图 3-5 所示。(有关 LM7805 引脚分布,请参见图 3-7。)

    image

    图 3-7:LM7805 调节器的引脚分布

  12. 将 LM7805 的输出引脚连接到面包板上的红色正极轨道。

  13. 将 LM317 的输入引脚连接到 LM7805 的输入引脚。这是连接来自电源输入电压的点。

  14. 将 LM7805 的接地引脚连接到面包板上的蓝色负极轨道。

  15. 插入一个 6.8 千欧姆的电阻器,并将一端连接到蓝色负极轨道。这是电阻器 R3;另一端将连接到电阻器 R2。请参见图 3-5 中的面包板俯视图。

  16. 将一个 10 千欧姆的电阻器(R2)插入面包板,一端连接到 LM317 输出引脚,另一端连接到第 15 步中的电阻器 R3。

  17. 将第 8 步中的电阻器 R1 从 LM317 输出引脚连接到面包板中的一个空孔。这一行将作为调节器的输出。

  18. 连接电压分压器:首先,将一个 10 千欧姆的电阻器(R4)插入面包板。然后,将电阻器 R4 的一端连接到与 R1 相同的行(你需要使用跳线),另一端连接到面包板上的一个空行。

  19. 将一个 6.8 千欧姆的电阻器(R5)插入面包板,一端连接到 R4 的开路端,另一端连接到蓝色负极轨道。

  20. 将 Arduino Pro Mini 插入面包板,使其跨越中央断开部分,如图 3-4 和图 3-5 所示。

  21. 使用跳线将 Pro Mini 的 VCC 端口连接到红色正电源轨。

  22. 使用跳线将 Arduino Pro Mini 的 GND 引脚连接到蓝色负电源轨。(至少有两个可供选择,一个位于 RST 和 D2 之间,另一个位于 RAW 和 RST 之间。任选其一。)

  23. 使用跳线将 R4 和 R5 的连接点连接到 Arduino Pro Mini 上的 A1 和 A0 引脚。

  24. 找到 R2 和 R3 的交点,并使用跳线将该交点连接到 Arduino Pro Mini 上的 A2 端口。

  25. 将草图上传到 Arduino Pro Mini。(我通常会完全从电路中取下 Pro Mini 来编程,这样稍微不那么混乱。)

  26. 通过将 VCC 和 GND 分别连接到面包板上的红色正电源轨和蓝色负电源轨,连接 LCD/I²C 显示屏。

  27. 将 SDA 连接到 Arduino Pro Mini 上的模拟引脚 A4,SCL 连接到模拟引脚 A5。

  28. 将 LM7805 电压调节器的输入连接到将接入+12V 的引脚。

  29. 将 LM7805 的输出连接到红色正电源轨,将接地连接到蓝色负电源轨。

一旦这些连接都完成,您就可以开始了。上传草图并测试电路。

草图

稳压电源草图尽可能简化。唯一的难点是,尽管我全程使用 1%容差的电阻,但我发现电阻值有所不同。因此,请注意,您可能需要调整草图以适应这一点。

这是草图:

// Regulated Power Supply with volt and current read

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); //Check your library for specific LCD
                                    //code both here and in setup.

float low_side_res = A0;
float volt_two;
float volt_three;
float volt_disp;
float low_side_res_2 = A1;
float hi_side_res = A2;
float volt_drop_1;
float amp;
float amp_3;
float amp_4;
float amp_disp;

void setup() {
    lcd.init();
    lcd.backlight();
}

void loop() {
    volt_two = analogRead(low_side_res);
    volt_three = (volt_two*5)/1024.0;
    volt_disp = volt_three*(10000+6800)/6800;  //Actual voltage reading
    amp_3 = analogRead(low_side_res_2);
    amp_4 = analogRead(hi_side_res);
    amp = amp_3 - amp_4;
    amp_disp = amp *5/1024*(10+6.8)/6.8/1.22*.9; //Calculation of amperage I=V/R
    //*0.9 = adjustment for random error in ref voltage in pro mini

    lcd.setCursor(1,0);
    lcd.print("Volt ");
    lcd.setCursor(12, 0);
    lcd.print(volt_disp);
    lcd.setCursor(1, 1);
    lcd.print("mA ");
    lcd.setCursor(11, 1);
    lcd.print(amp_disp*1000,2);
}

首先,这个草图导入了一些库,并设置了 LCD(参见 “编写代码以设置 LCD” 在第 36 页)。接着,它定义了一系列变量,都是浮动类型,用于设置电压、从模拟引脚读取数据、计算要显示在 LCD 上的值等等。setup()循环非常简短:它只有两行代码用于初始化 LCD。主loop()读取电池电压和电流,并执行必要的计算来显示在 LCD 上。volt_disp值是要显示在 LCD 上的电压。

屏蔽板

尽管电路并不复杂,使用屏蔽板会简化许多连接,尤其是驱动 LCD 和构建电压分压器的部分,它将使稳压电源的组装比点对点接线更加方便。图 3-8 展示了我设计的屏蔽板,当然你也可以自己设计。PCB 文件可在 www.nostarch.com/arduinoplayground/ 获取。

虽然我使用了两层来构建屏蔽板,但通过一点努力和稍微大一些的电路板,电路完全可以放置在单层板上。

image

图 3-8:在稳压电源中使用的 PCB 屏蔽。黑色是顶层,深灰色是底层,浅灰色是丝网印刷层

扩展板的元件不需要按特定顺序安装,但某些元件在其他元件之前安装会更容易。我建议按以下顺序焊接:

  1. 首先,将 2.2 欧姆、5 瓦特的电阻 R1 和 R9 插入 PCB。这些是降压电阻,为安培计(mA)提供电压,提供总电阻(原理图中的 R1)为 1.1 欧姆,功率为 10 瓦特。这些电阻比板上的配置稍长,所以你需要弯曲引脚以使其适配。当稳压电源接近其最大额定功率时,预计这些电阻和 LM317 本身都会变得有些热。

  2. 电容 C1 是一颗 68μF 的钽电容,安装时会比较紧凑。为了确保它不会干扰 LM317,先安装电容。然后,再安装 LM317,确保为散热器留出空间。记住,散热器可能会变得相当热。

  3. 确保按照图 3-6 中的引脚排列和图 3-4 中的原理图正确安装 LM317 的引脚。如果你使用提供的扩展板文件,LM317 丝网图上的粗线对应 IC 上的金属标签。如果将元件安装方向错误,系统将无法工作,并且该元件可能会烧坏,而且拆除起来会很麻烦。

  4. 将 LM7805 稳压器安装在 PCB 的右上部分,并确保它与图 3-7 中的引脚排列及图 3-4 中的原理图匹配。你可以使用 PCB 丝网图中的粗线作为参考。

  5. 尝试将两个稳压 IC 和散热器一起安装在扩展板上(至少暂时安装),确保它们不会与任何活动元件接触。记住,散热器是活动的:LM7805 的散热器(标签)为接地电位,而 LM317 的散热器(标签)为输出电位。

  6. 安装电阻 R2、R3、R4 和 R5。在安装 Arduino Pro Mini 的女性插针之前,先安装这些会更容易。

  7. 然后,焊接 C1、C2 及将 Arduino Pro Mini 与电位器 R6 连接的导线,电位器 R6 将安装在外壳上。你可以将导线留长一些,等安装扩展板到外壳时再修剪。按照原理图中的指示安装电容 C4 和 C5,参见图 3-4。

  8. 接下来,焊接包含 Pro Mini 支架和 LCD 连接器的女性插针。LCD 的连接为 SDA、SCL、−和+,位于 PCB 的右下角。我使用了男性插针和一根女性对女性连接线,将 LCD 与扩展板连接。(要了解如何制作自定义连接器,请参见本书中使用的连接器,第 18 页。)

对于 LCD 和 Arduino Pro Mini,我通常将针脚插入板中,先焊接一个引脚,然后用手指按住上面,加热该引脚并推动连接器,以确保其与板面平齐。对于 Pro Mini 的针脚,我只使用女性针脚连接到那些有铜迹的引脚。我还喜欢在 Pro Mini 的最后一个引脚(通常是 1×4 针脚)上放置一个针脚,以便对准。这些引脚对应 RAW、GND、RST 和 VCC。此外,我还喜欢至少放置两个对角线排列的针脚,以增强机械稳定性。这将对应 Pro Mini 上的 D8 和 D9 引脚。Pro Mini 上的 A4 和 A5 引脚位于 A2、A3 和 VCC 的上方,属于主连接行的一部分。

构建

当稳压电源全部焊接完成后,您需要准备一个外壳并将电路装入其中。我选择了一个外观不错的粉末涂层金属外壳,约为 2 1/4 × 3 1/4 × 4 3/4 英寸。图 3-9 展示了完成的设备,驱动着几个白炽灯面板灯。

image

图 3-9:完成的稳压电源

不过,请记住,虽然外壳不脆弱,但漆面容易划伤,因此要小心。它也有点贵——大约 20 美元——但因为它将一直放在我的工作台上,我认为值得。当然,您也可以使用您选择的其他外壳,并根据本书提供的模板进行修改。

准备外壳

如果外壳的前面板是倾斜的,您需要在需要打中心点和钻孔的地方放一块废木板,以帮助固定位置。确保仔细测量、打中心点并钻孔。

本项目的模板见图 3-10 和 3-11,可从www.nostarch.com/arduinoplayground/下载。

image

图 3-10:稳压电源外壳的倾斜面

image

图 3-11:稳压电源外壳的前面和底部

以下是我建议您准备外壳的方法:

  1. 为电位器、开关(1/4 英寸)和电源指示 LED 打中心点并钻孔。有关前面板的尺寸,请参见图 3-10。

  2. 在面板后部打中心点并钻孔,用于电源输入插孔(见图 3-10)。

  3. 在外壳前面钻孔,用于输出绑定器和 3.5 毫米插孔,如图 3-11 所示。

  4. 小心测量并标记 LCD 的切割区域,如图 3-10 所示。用中心冲打标记并钻孔 1/2 英寸的孔在 LCD 屏幕区域的四个角落,帮助启动锯切。你可以根据图 3-10 中的示意图大致判断,或者下载模板的 PDF 文件。可以使用碳纸将图像描摹到机箱上,或者仅用中心冲打标记角落并连接这些打孔点。

  5. 小心切割 LCD 的开孔。你可以使用多种工具来完成这项工作。我首先钻了 A 和 B 两个孔,然后使用细齿锯条的钥匙孔锯(可在本地五金店购买)在这两个孔之间切割。记住,切割是在外推时进行的,因此在回程时无需对锯片施加压力。可以用锉刀清理毛刺。

  6. 小心地将显示器安装到窗口中,如有必要,可以打磨以确保其紧密安装。由于背光在显示器的一侧突出,为避免挤压背光,您可以使用螺母作为垫片,使其与面板分开。

  7. 钻孔 F、G、H 和 I,并固定显示器。在此过程中,仔细检查垫片螺母的宽度是否足够(4-40 螺母有不同尺寸),如果需要,可以使用两个螺母或一个螺母和一个垫圈来为背光提供空间。

安装电路板

完成护罩组装并测试 LCD 后,安装电位器、开关、LED 和电源插孔。然后就是将护罩安装到机箱中的时候了。最初,我在电路板上钻了四个孔,方便将其固定到机箱中,但我发现 3M 双面胶带也能达到同样的效果。我用 1 1/4 英寸长、3/4 英寸宽的双面胶带将整个电路板(包括散热器)固定住。(制造商声称它能承受 2 磅的重量。)

该粘合剂相对较强,因此在使用之前,请确保仔细计划好安装电路板的位置,以避免它阻碍其他组件。我将电路板倒置安装在机箱的顶部部分,这样所有的组件和连接都位于同一平台上(见图 3-12)。

image

图 3-12:已完成的(倒置)组装,电路板、LCD、输出连接器、电位器、开关、LED 和输出电源插孔都安装在机箱顶部内部。

最后一步是根据项目原理图将开关、LED 指示灯、LED 限流电阻、电位器、电源输入插孔和输出连接器连接到 PCB。我使用了 28 号连接线将所有组件连接在一起。两个接线柱/香蕉插头插孔和 3.5 毫米插孔是并联连接的。图 3-12 展示了我如何安装护罩。请注意,我使用了小型线扎带(可选)来保持电线整洁。

在关闭外壳之前,确保没有可能导致短路的区域。例如,我在 LCD 屏幕和金属屏蔽之间放了一小块绝缘胶带。它们在组装时可能不会接触,但在你合上外壳时可能会接触。你可以使用绝缘胶带来防止这种短路。

在测试短路之后,只剩下将外壳的两部分组装在一起。输出连接—绑定端子/香蕉插孔和 3.5 毫米插孔—是并联的。最后一步是将两个部分用螺丝固定,你就可以开始使用了。我在电位器上装了一个指示旋钮,尽管外壳上没有标记。如果你想加上刻度盘也可以,但我觉得数字显示已经足够了。

最后的点睛之笔:去掉一些橡胶脚底部的保护纸,并将它们安装到外壳底部。完成!

完整的稳压电源项目将占用相当大的工作台空间,但你会发现数字显示和香蕉插孔非常有用。如果你觉得冒险的话,你也可以制作一个更小的版本,去掉插孔和 LCD,见图 3-13。

image

图 3-13:这是快速简易的电源,顶部已拆开。我是在决定制造完整的稳压电源之前做的这个简易版

你可以在 www.nostarch.com/arduinoplayground/ 找到如何构建迷你稳压电源的说明。

第五章:一只手表上链器**

image

如果你是自动机械手表或自上链手表的收藏者,你可能已经熟悉手表上链器及其功能。那么,为什么在一本关于 Arduino 微控制器项目的书中会有手表上链器呢?这个问题的答案随着我们深入了解本项目的技术将逐渐明朗。而且,在本项目的过程中,我们将快速了解一些自动手表的历史以及这些看似过时的设备如何在数字时代得以生存和繁荣。即使你不收藏这些珍贵的时计,这个项目也许会激发你开始自己的收藏。

为什么选择手表上链器?

因为作为一个收藏者,你拥有的不止一只自动机械手表,你可能想要考虑把那些不在手腕上的手表保持上链状态。如果你阅读过有关机械手表和上链器的资料,你会发现使用手表上链器有许多优缺点(可能优点更多)。一个大的优点是,如果多功能手表停下来,重新设置可能需要很长时间。也有一种观点认为,如果一只机械手表保持静止不动,润滑油会向低点迁移。手表上链器的定期运动,或佩戴时的运动,有助于保持润滑油的均匀分布,并保持在轴承中,防止润滑油流失。虽然很多人赞同这一观点,但实际上并没有确凿的证据。

还有一个很有说服力的理由支持使用手表上链器。作为一个收藏者,能够展示更多的收藏品,而不仅仅是单独戴在手腕上的那一只,感觉很好。许多市售的上链器都配有珍稀木材的外壳,以展示手表。但便宜的上链器往往不可靠,而贵的上链器则,嗯,价格不菲。

我冒险购买了其中一款更经济实惠的手表上链器,并把我的两只机械手表——一只真劳力士和一只假劳力士——放了进去,想着就这样搞定了。但不到六个月,这个上链器就坏了。我把它拆开,发现设计和做工非常差。即使我更换了坏掉的电机,其他的机制也可能不太可靠。在使用上链器时,那只假劳力士没有完全上链,而且也没能保持准确的时间。

当时的问题是,是否要从口袋里掏出 400 或 500 美元,购买一个承诺可靠性的上链器(甚至有些型号的售价超过 1500 美元、2000 美元或更多),还是尝试做得更好。所以,隐喻地说,挑战已经提出。挑战是设计并制造一个可靠的手表上链器,它不仅能作为我的手表展示平台,还能在坚固的机械结构中提供我所需要的时间控制和灵活性。Arduino 是控制手表旋转频率的显而易见的选择,而机械部分则围绕这一点展开。

在构建你的手表上弦器时,你会发现无论是在机械结构还是草图方面,都有很多个性化的空间。尽管手表上弦器是一个用于保持手表上弦的实用设备,但这个版本为你的时计提供了一个优雅的展示平台——它本身也是一件艺术作品,一座动感雕塑。你可以在图 4-1 中看到最终效果。

因为我选择了 Arduino 作为逻辑计时元件,我不得不围绕这一点规划其他电子元件和软件。我们将重新审视 PCB 蚀刻机中的 H 桥电路(参见“使用 H-Bridge”,见第 48 页),以便使电机能够双向驱动,并且我们将使用晶体管来增强高功率 LED 的驱动能力。我们还将使用霍尔效应传感器来测量手表的旋转。

image

图 4-1:完成的手表上弦器。遗憾的是,这张黑白图片无法体现其美感:鲜艳的 LED 灯光通过丙烯酸材料作为光导,将各种颜色的 LED 光传送到设备上

该项目的草图使用函数和数组以重复的模式闪烁 LED。草图还指示控制器读取霍尔效应传感器的状态,该状态为零或一。知道这一状态可以让控制器决定何时为手表上弦,并保持旋转次数的计数,以确保手表不会上弦过度或不足。

自动手表的神秘感

自动手表是在 1920 年代初期发明的,并在几年后开始商业化。在接下来的几年里,许多改进相继出现,直到它达到了今天仪器的精密水平。自动手表通过一个连接到棘轮装置的摆锤来运作:当摆锤摆动时,棘轮装置会为手表的主发条上弦。内置的滑动离合机制防止了过度上弦。请参见图 4-2,了解这些手表的内部结构。

image

图 4-2:一只自动手表,背面已移除,暴露出摆锤和支点(中心的螺钉),它们与棘轮装置一起工作,给手表的主发条上弦

几乎所有手表制造商的自动手表都在几十年间享受了广泛的成功。然而,在 1960 年代初期,宝路华(Bulova)开发了其 Accutron 调谐叉电子手表,随后 Pulsar 推出了数字石英电子手表。1

尽管电子手表(现在包括智能手表)涌现,但领先的机械手表制造商依然在这个时代存活下来,并且甚至有所繁荣。今天,自动手表的价格从不到 100 美元到数万甚至数十万美元不等。

为什么有人愿意为一款不特别准确、沉重、经常笨重且在不使用时需要保持上链的手表支付高价呢?我敢肯定每个收藏者的答案都不相同,但我猜他们和我一样,喜欢那种优雅、声望、复杂性、历史感和精密机械感,这是电子表无法比拟的——尽管 iWatch 在某些方面接近。就像任何收藏品一样,一只自动手表永远不够——这也引出了手表自动上链器。


1。从机械表到电子表的过渡被描述为托马斯·库恩在其 1962 年的著作《科学革命的结构》中提出的“范式转变”的典型例子。

必备工具

钻头和钻头套件

锥形铰刀套件

小型压线钳

中心冲孔器

Weld-On 4 和 Weld-On 16 丙烯酸粘接液

各种砂纸,包括 220 到 600 目数的砂纸以及用于最终抛光的 1500 目砂纸

珠宝抛光粉或其他液体塑料抛光剂

(可选)圆锯

(可选)螺纹锁固液

(可选)线圈工具

(可选)旋转工具(例如,你可以购买一款带有磨料切割轮的德瑞姆工具。)

零件清单

如果你想制作一款像图片中的手表自动上链器,你将需要几块丙烯酸材料以及其他硬件,详细内容我会在本节中说明。

丙烯酸

以下丙烯酸部件可以轻松从标准丙烯酸板中切割而成。除非购买独立的圆盘(我建议你单独购买),其余部分都可以从两块 12×12 英寸的丙烯酸板中切割(其中一块厚度为 3/8 英寸,另一块为 1/4 英寸厚)。如果你愿意,你也可以找到提供激光切割丙烯酸定制尺寸的供应商。(例如 ZLazr,其他许多商家也提供此服务。)虽然价格会比自己动手稍贵,但它会使切割和抛光更加简单。

四块尺寸为 1/4 × 2 × 1 1/2 英寸的材料(手表篮子的长边;可以是 3/8 英寸)

四块尺寸为 1/4 × 1 × 2 英寸的材料(手表篮子的短边;可以是 3/8 英寸)

两块尺寸为 3/8 × 3 × 2 英寸的材料(轴承盒的轴承支架)

两块尺寸为 3/8 × 2 × 1 1/2 英寸的材料(轴承盒的安装面)

一块尺寸为 1/4 × 1 × 2 英寸的材料(电机支架)

两个圆形部件,厚度为 3/8 英寸,直径为 5 英寸(手表篮子的两端)

两块尺寸为 1 1/2 × 5 × 1/4 英寸的材料(支架侧支撑)

一块尺寸为 3/8 × 3 × 5 1/2 英寸的材料(支架底座)

一块尺寸为 3 × 1 1/2 × 3/8 英寸的材料(灯条)

一块尺寸为 2 1/2 × 2 1/2 × 3/8 英寸的材料(屏蔽支架)

两个 3.5 毫米的立柱,带有 M/F M3-05 螺纹(电机支架)

三个 1.5 毫米的立柱,带有 M/F M3-05 螺纹(屏蔽支架)

有几个在线商家可以购买这个项目所需的亚克力材料;只需在 Google 上搜索acrylic sheet,就能找到离你最近的商家。在美国,* www.zlazr.com/*似乎不错。在我写这篇文章的时候,我与商家老板亲自交谈过,他表示他可以轻松处理这个项目所需的切割工作。

其他硬件和电路组件

一个 Arduino Nano 或其克隆版

一个霍尔效应开关,例如 Melexis US5881LUA(侧支撑的尺寸应为 1 1/2 × 5 × 1/4. 参见《搭建支架》,见第 115 页)

一根 8 英寸长,直径为 1/4 英寸,28 牙螺距的驱动轴(我建议使用黄铜,因为它易于加工)

两个球轴承(R4A-2RS)

六个 1/4 英寸-28 的六角锁紧螺母

两个装饰性螺栓,1/4 英寸-28,长度 1 英寸(我使用的是镀铬的内六角螺栓)

十个 ZTX649 晶体管

一个 SN754410 四路 H 桥

十个 470 欧姆电阻

一个 10 千欧,1/8 W 电阻

一个 0.1 μF 的陶瓷电容器(C1)

一个 10 μF 的钽电容器(C2)

一个如《定制屏蔽板》中所描述的定制屏蔽板,或孔板(你也可以选择让 ExpressPCB 定制屏蔽板;有关详细信息,请参见《制作你自己的 PCB》,见第 13 页)

一个齿轮头电机(我使用的是一个 6V、20 RPM 的电机,型号为 Amico 20 RPM 6VDC 0.45 A)

一个 LM7805 电压调节器

十四个 LED,颜色多样(我购买了清晰和磨砂版本。输出较高的通常是清晰版本)

各种连接线和线缠绕线

十个 LED 线缆缠绕或焊接用的钉子(可尝试 Pololu 的#966 商品或 Electronic Goldmine 的#G19870 商品)

一根直径为 3/8 或 1/2 英寸,长度约为 3/4 英寸的黄铜圆棒(我使用的是直径 3/8 英寸的黄铜棒。黄铜材料常见,长度为 6 英寸和 12 英寸,可以用锯子裁剪成所需的尺寸)

一根直径为 0.39 英寸的 6 英寸长钢琴弦

一个铌或钕磁铁,直径约为 3/8 英寸,厚度约为 1/8 英寸

一个 4-40 平头螺钉

六个 M3×3/8 英寸螺丝

七个 M3-05×1/2 英寸螺丝

(可选)一个 Amico H7EC-BCM 计数器

(可选)八个 270 欧姆电阻(如果你选择遵循我在《面包板》中的具体说明,可以在面包板原型中使用这些电阻,见第 98 页)

下载

在开始构建之前,请访问https://www.nostarch.com/arduinoplayground/,下载本书的资源文件,并查找以下第四章所需文件:

模板    MotorMountAndBearingBox.pdf, BaseAndLightbar.pdf, WatchBasket.pdf

机械图纸    MotorAssembly.pdf

屏蔽板    WatchWinder.pcb

草图    WatchWinder.ino

基本的手表上链器要求

一些初步研究表明,为了保持手表的最佳状态,手表上链器每天应该旋转 600 到 1200 次。但这并不完全正确。我随后发现,这个范围实际上要宽得多,至少根据两个领先的自动手表网站,手表是不能被过度上链的,因为它们有内置的保护系统。我还了解到,手表应该同时朝顺时针和逆时针旋转,以保持润滑油在正确的位置,并避免长时间内出现不均匀的磨损。关于这个主题,网络上有丰富的信息,包括手表制造商的官方网站以及手表上链器网站。

显然,总的转动次数才是关键,而不一定是转动的顺序或每个方向上转动的次数完全相同。(如果手表在长时间内被过度上链,可能会有负面影响。)听起来不是很棘手,对吧?我也这么认为。

使用 Arduino 控制上链器旋转

一个纯粹实用的上链器只需要完成其功能,旋转手表以使摆锤摆动。但拥有额外功能的上链器更加有趣。正如在《为什么使用上链器?》一节中提到的,第 90 页上,一些上链器装饰有精美的异国木材盒子,用来展示手表。

然而,这是一个 Arduino 项目,额外的技术特性和 LED 应体现平台的灵活性和多样性。在一个开发模型中,原始草图指示电子设备先将电动机朝一个方向转动,然后再转向另一个方向,使用延迟确保每天进行 600 到 1200 次的旋转。

但事实证明,一些手表需要比最小的旋转次数更多,而有些手表则可以少一些。改变旋转次数最简单的方法是根据需要调整草图中的各种延迟。你甚至可以向电路中添加硬件,通过一个电位器来调整每天的转动次数,正如我在《设计说明》一节中描述的,见第 124 页。

为了驱动电动机,我使用了一个 H 桥集成电路。它接受来自 Arduino 的控制逻辑,并允许你通过单一电源反转电动机的极性,从而使电动机可以在两个方向上旋转。

注意

欲了解更多关于 H 桥的信息,请参阅《使用 H 桥》一节,见第 48 页

使用霍尔效应传感器监测旋转

然后,就涉及到如何测量设备转动的次数,以协助计时并为草图提供更多信息。每单位时间的转动次数是电动机的一个函数,虽然我为指定电动机提供的计时方法理论上可行,但它可能并不适用于所有电动机。

例如,我在相同电压下测试了三台相同型号的电机,每台电机的转速略有不同。此外,如果你选择替换一个转速不同的电机,旋转计数也会不同。在 Beta 测试中,一位用户在 5V 电源下运行 6V 电机时遇到了困难。(参见“电机电压”在第 126 页)。由于每单位时间的转动次数与电机有关,因此如果仅凭计时来确定总的旋转次数,这些不一致性可能会成为问题;需要一种机制来监控旋转次数。

为了确保一致的计时,我决定测量设备的转动次数。因此,我将一个小磁铁固定在旋转手表的轴上,并将一个霍尔效应设备,或者说一个能够检测磁场的传感器,安装在与磁铁对齐的位置。如果你愿意,可以用一个小型簧片开关来替代霍尔效应传感器。

当手表和磁铁旋转时,霍尔效应开关只有在靠近磁铁时才会开启,使开关在每次旋转时开关一次。每次霍尔效应开关状态改变时,Arduino 会递增一个内部计数器。结合草图,这确保了无论电机速度如何,每天的转动次数都能正确计算。与簧片开关不同,霍尔效应开关不需要任何缓冲或去抖动,如在“草图”中讨论的那样,在第 102 页,因为设备电路中包含了施密特触发器。如果你选择使用簧片开关,可能需要在草图中添加去抖动功能。

使用带有永久磁铁的霍尔效应开关时,你只需要小心如何移动磁铁。某些机械手表因靠近强磁场而受损,因为发条被磁化,导致物理特性发生变化,从而使计时出现偏差。尽管指定的磁铁很小,不太可能造成问题,但我强烈建议你将任何磁铁至少保持在距离手表一英寸的地方——无论是机械表还是电子表。

原理图

图 4-3 展示了用于手表上链器的电路原理图。请注意,霍尔效应设备的输出端连接了一个上拉电阻,连接到正电源。这使得 Arduino 的 A0 引脚在霍尔效应开关或簧片开关遇到足够强的磁场时保持高电平,关闭开关并将引脚拉低。霍尔效应设备的输出本质上是一个开路集电极,因此没有上拉电阻时,集电极会处于浮空状态,可能会导致误触发。

这两个电容器防止 LM7805 调节器自行振荡并消耗过多的电力。尽管我用示波器检查了调节器的输入和输出并没有看到振荡,但我决定添加这些电容器作为预防措施。我根据以前的项目选择了这些电容器,它们表现得很好。

我试图为时钟上链器(Watch Winder)设计一种壮观的外观,以匹配它所容纳的一些时计,因此我使用了高功率的 LED,如在“零件清单”中描述的,位于第 93 页。这些 LED 的光输出可以达到 100,000 到 200,000 甚至更多的毫坎德拉(MCD)。但这引发了另一个问题。Arduino Nano 的处理器芯片 ATmega328 每个输出引脚只能提供或吸收 40 mA 电流。此外,整个芯片的最大电流消耗仅为 200 到 300 mA。因为这些 100,000+ MCD 的 LED 每个大约需要 30 到 60 mA 的电流,所以必须采取措施。

image

图 4-3:时钟上链器电路。晶体管连接到 Nano 的数字输出,而 A0 通过 10 千欧电阻连接到高电平

每个 LED 都有一个 1 A 的晶体管来承担负载。NPN 晶体管的集电极—正极—连接到 VIN,而不是为 Nano 和 H 桥供电的 5V,因此 LED 不会对电压调节器造成负担,即使发射极跟随基极并将 5V 送到 LED。

面包板

就像我们讨论过的其他项目一样,时钟上链器最初是一个面包板,如图 4-4 所示。这让我能够测试技术并进行草图的初步调试。

image

图 4-4:时钟上链器面包板被用作项目的概念验证。在这里,我使用第三章的调节电源为其供电

我建议首先为这个项目建立一个面包板,这样你可以看到每个部件的连接位置以及原因。使用面包板,你还可以在不需要每次都重新焊接的情况下玩转草图和 LED。我使用了一块 6.5 英寸长的面包板来容纳所有组件。我在面包板上确实采取了一些捷径,这些都在说明中注明;你也可以直接按照电路图来构建。

为了接线面包板,请按以下步骤操作:

  1. 将面包板右侧的红色条带连接到左侧相应的红色条带。这些是你的正极轨道。

  2. 将面包板右侧的蓝色条带连接到左侧相应的蓝色条带。这些是你的负极轨道(地线连接)。

  3. 将 Arduino Nano 插入面包板的一端。

  4. 将 Nano 的 5V 引脚连接到红色正极轨道。

  5. 将 Nano 的 GND 引脚连接到面包板上的蓝色负极轨道。

  6. 插入 LM7805 调节器,并将输出引脚连接到红色正极轨道。(图 4-5 展示了调节器的引脚排列。)

    image

    图 4-5:LM7805 稳压器 TO-220 封装引脚排列

  7. 将稳压器的地端连接到蓝色负极轨道。

  8. 稳压器的输入端将连接到面包板上的一个空行,这一行将连接到+7.5V 到 9V 的电源。

  9. 将电容 C1 从稳压器的输入连接到地线。

  10. 将电容 C2 从稳压器的输出连接到地线。

  11. 将 SN754410 H-桥插入距 Nano 几行的地方,跨过面包板中间的凹槽。(图 4-6 显示了 H-桥的引脚排列。)

    image

    图 4-6:SN754410 H-桥 DIP 封装引脚排列

  12. 将 H-桥的 4 号、5 号、12 号和 13 号引脚连接到地。

  13. 将 H 桥的 8 号、9 号和 16 号引脚连接到红色正极轨道。

  14. 将 H-桥的 14 号和 11 号引脚连接到电机,电线至少要 10 到 12 英寸长。除非使用鳄鱼夹或夹子引线,否则必须将连接电机的引脚焊接起来。

  15. 将大约 8 英寸的电线连接到霍尔效应传感器的三个引脚。将霍尔效应传感器连接到红色正极轨道和蓝色负极轨道的引脚分别接到正负极。

  16. 将连接到霍尔效应传感器第三个引脚的电线连接到 Nano 的 A0 引脚。霍尔效应传感器将用胶带(我用了 masking tape)固定在电机外壳上(由于引脚是绝缘的,这样做是可行的),使设备的活动部分靠近与轴旋转时附着在轴上的磁铁。

  17. 将一个 10 千欧姆电阻从 Nano 的 A0 引脚连接到红色正极轨道。

  18. 将 H-桥的 10 号引脚连接到 Nano 的 D13 引脚。

  19. 将 H-桥的 15 号引脚连接到 Nano 的 D12 引脚。

  20. 在面包板的一侧插入五个 ZTX649 晶体管,每个晶体管使用三行。(图 4-7 显示了晶体管的引脚排列。)

  21. 将每个晶体管的集电极连接到红色正极轨道。

    image

    图 4-7:ZTX649 晶体管 TO-92 封装引脚排列

    这些晶体管连接与最终的原理图不同,其中集电极将连接到 9V 输入电压。

  22. 取五个 LED,并将每个 LED 的正极连接到每个晶体管的发射极。

  23. 将每个 LED 的负端通过一个 270 欧姆电阻连接到地。

  24. 在面包板的另一侧以类似步骤 20-23 中连接的五组方式,连接三个额外的晶体管、LED 和 270 欧姆电阻。

    注意

    步骤 20-25 与原理图不同,因为 LED 直接由 Nano 驱动,便于实验。在原理图中,它们是通过晶体管连接的。使用 470 欧姆电阻代替 270 欧姆电阻限制了 Nano 的电流。

  25. 将另一个 LED 的正极连接到 Nano 的 D12 引脚。

  26. 将 D12 引脚的 LED 负端连接到面包板上的一个空行。

  27. 将一个 470 欧姆电阻的一端连接到 D12 引脚 LED 的负端,将电阻的另一端连接到地面。

  28. 将另一个新 LED 的正端连接到 Nano 的 13 引脚。

  29. 将 13 引脚 LED 的负端连接到面包板上的空排。

  30. 将一个 470 欧姆电阻的一端连接到 13 引脚 LED 的负端,将电阻的另一端连接到地面。

  31. 将 Nano 上的 D4、D5、D6、D7、D8、D9、D10 和 D11 引脚连接到为 LED 供电的晶体管的基极。

因为面包板仅用于示意,所以连接的顺序并不重要,除非你希望在电路处于面包板上的时候重新编程 Arduino。

磁铁是通过双面胶泡沫胶带安装到电机轴上的插头上的。对于插头,你几乎可以使用任何东西——如软木塞、橡胶塞等——只要它能将磁铁放置到一个位置,使磁铁旋转时大约距离传感器 3/8 英寸。

完成面包板连接后,将WatchWinder.ino草图上传到 Arduino。只需按照第 5 页中“将草图上传到 Arduino”的说明操作。

草图

Watch Winder 利用函数和数组显示不同的闪烁序列在 LED 上,而无需每次都重写序列。也有一些漫长的延迟:大约 24 小时内 829 次旋转,相当于 20 转/分钟的马达大约运行 32.5 分钟,在 1,400 分钟的一天中。这意味着如果草图处理整整一天的旋转,它将每天闲置 1,367.5 分钟。

但你可以将旋转分配开来,这样草图就可以重复,并且只需要 24 小时中的一小部分时间来完成。例如,如果选择一小时作为草图循环完成的时间,那么电机必须旋转 24 次。它可以每次 12 次,或者其他的组合。

在以下的草图中,我还努力使灯光和马达的运动尽可能地具有视觉吸引力,几乎没有发生什么的空闲时间——这是一种艺术选择。

      /*This gives about 829 revs/day*/  

      const int HallPin = A0; //Identify those things that will not change  
      const int CWpin = 12;  
      const int CCWpin = 13;  

      const int LED11 = 11;  
      const int LED10 = 10;  
      const int LED9 = 9;  
      const int LED8 = 8;  
      const int LED7 = 7;  
      const int LED6 = 6;  
      const int LED5 = 5;  
      const int LED4 = 4;  

      int autoDelay = 1000;  
      int timer = 500;  
      int timer2 = 3000;  
      int repeats = 10;  

      int previous;  
      int HallValue = 1; //Response from the Hall effect sensor  
      int time = 0;  
      int state;  
      int count = 0;  
      int q = 0;  
      int i;  
      int j;  

      int ledPins[] = {  
        11, 4, 7, 6, 8, 10, 5, 9,  
      };  
      int pinCount = 8;  

      void blinkIt() {  
        //Initiate rapid blink sequence  
        for(int thisPin = 0; thisPin < pinCount; thisPin++) {  
          //Turn the pin on:  
          digitalWrite(ledPins[thisPin], HIGH);  
          delay(timer2);  
          //Turn the pin off:  
          digitalWrite(ledPins[thisPin], LOW);  
          delay(timer2);  
        }  

        //Loop from the highest pin to the lowest:  
        for(int thisPin = pinCount - 1; thisPin >= 0; thisPin--) {  
          //Turn the pin on:  
          digitalWrite(ledPins[thisPin], HIGH);  
          delay(timer2);  
          //Turn the pin off:  
          digitalWrite(ledPins[thisPin], LOW);  
          delay(timer2);  
        }  
      }  

      void flashIt() {   
        //Initiate rapid blink sequence  
        for(int thisPin = 0; thisPin < pinCount; thisPin++) {  
          //Turn the pin on:  
           digitalWrite(ledPins[thisPin], HIGH);  
           delay(timer2);  
           //Turn the pin off:  
           digitalWrite(ledPins[thisPin], LOW);  
        }  

        //Loop from the highest pin to the lowest:  
        for(int thisPin = pinCount - 1; thisPin >= 0; thisPin--) {  
           //Turn the pin on:  
           digitalWrite(ledPins[thisPin], HIGH);  
           delay(timer2);  
           //Turn the pin off:  
           digitalWrite(ledPins[thisPin], LOW);  
        }  
      }  

      void allatOncefast() {  
        {  
          digitalWrite(LED4, HIGH);  
          digitalWrite(LED5, HIGH);  
          digitalWrite(LED6, HIGH);  
          digitalWrite(LED7, HIGH);  
          digitalWrite(LED8, HIGH);  
          digitalWrite(LED9, HIGH);  

          digitalWrite(LED10, HIGH);  
          digitalWrite(LED11, HIGH);  

          delay(500);  

          digitalWrite(LED4, LOW);  
          digitalWrite(LED5, LOW);  
          digitalWrite(LED6, LOW);  
          digitalWrite(LED7, LOW);  
          digitalWrite(LED8, LOW);  
          digitalWrite(LED9, LOW);  
          digitalWrite(LED10, LOW);  
          digitalWrite(LED11, LOW);  

          delay(500);  
        }  
      }  

      void allatOnce() {  
        {  
          digitalWrite(LED4, HIGH);  
          digitalWrite(LED5, HIGH);  
          digitalWrite(LED6, HIGH);  
          digitalWrite(LED7, HIGH);  
          digitalWrite(LED8, HIGH);  
          digitalWrite(LED9, HIGH);  
          digitalWrite(LED10, HIGH);  
          digitalWrite(LED11, HIGH);  

          delay(4000);  

          digitalWrite(LED4, LOW);  
          digitalWrite(LED5, LOW);  
          digitalWrite(LED6, LOW);  
          digitalWrite(LED7, LOW);  
          digitalWrite(LED8, LOW);  
          digitalWrite(LED9, LOW);  
          digitalWrite(LED10, LOW);  
          digitalWrite(LED11, LOW);  

          delay(2000);  
        }  
      }  

      void setup() {  
        pinMode(HallPin, INPUT);  //Identifies inputs and outputs  
        pinMode(CWpin, OUTPUT);  
        pinMode(CCWpin, OUTPUT);  

        Serial.begin(9600);  

        for(int thisPin = 0; thisPin < pinCount; thisPin++)  {  
          pinMode(ledPins [thisPin], OUTPUT);  
        }  
      }  

        void loop() {  
          int HallValue = (digitalRead(HallPin)); //Sets value of initial Hall effect  

          if(HallValue == HIGH  previous == LOW) {  
            if(state == HIGH)  
              state = LOW;  
            else  
              state = HIGH;  

            //Increments counter each time the Hall effect sensor passes the magnet  
➊          count++;  
        }  

        /* The "Serial.print" line was used in development. I left it in so that   
           you can experiment and look at some of the values on a serial   
           monitor. You might even want to change the parameters of what you   
           are looking at in the monitor.  
        */  
        Serial.print("HallValue       ");  
        Serial.println(HallValue);  
        Serial.print("count                      ");  
        Serial.println(count);  
        Serial.print("CCW                             ");  
        Serial.println(" ");  

        if(count == 1) {  
           digitalWrite(CCWpin, HIGH);  
           digitalWrite(CWpin, LOW);  
        }  

        if(count == 3) {  
           digitalWrite(CWpin, HIGH);  
           digitalWrite(CCWpin, HIGH);  
        }  

        if(count == 3) {  
           for(i = 0; i < repeats; i++) {  
            allatOncefast();  
          }  
          count = count + 1;  
        }  

        if(count == 3) {  
           digitalWrite(CWpin, LOW);  
           digitalWrite(CCWpin, HIGH);  
        }  

        if(count == 4) {  
           digitalWrite(CWpin, HIGH);  
           digitalWrite(CCWpin, HIGH);  
        }  

      if(count == 4) {  
         for(q = 0; q < repeats; q++) {  
           blinkIt();  
         }  
         count = count + 1;  
      }  

      if(count == 5) {  
         for(j = 0; j < repeats; j++) {  
          allatOnce();  
         }  
        delay(50);  
         count = count + 1;  
      }  

      if(count == 6) {  
         digitalWrite(CCWpin, LOW);  
         digitalWrite(CWpin, HIGH);  
      }  

      if(count == 7) {  
         digitalWrite(CWpin, LOW);  
         digitalWrite(CCWpin, LOW);  
      }  

      if(count == 7) {  
         for(i = 0; i < repeats; i++) {  
           flashIt();  
         }  
         count = count + 1;  
      }  

      if(count == 8) {  
        digitalWrite(CCWpin, HIGH);  
         digitalWrite(CWpin, LOW);  
      }  

      if(count == 10) {  
         for(i = 0; i < repeats; i++) {  
           allatOncefast();  
         }  
         count = count + 1;  
      }  

      if(count == 11) {  
         digitalWrite(CCWpin, LOW);  
         digitalWrite(CWpin, LOW);  
      }  

      if(count == 11) {  
         for(i = 0; i < repeats; i++) {  
           blinkIt();  
         }  

         delay(2000);  
         count = count + 1;  
      }  

      if(count == 12) {  
         digitalWrite(CCWpin, LOW);  
         digitalWrite(CWpin, HIGH);  
      }  

      if(count == 13) {  
         digitalWrite(CCWpin, HIGH);  
         digitalWrite(CWpin, HIGH);  
      }  

      if(count == 13) {  
         for(i = 0; i < repeats; i++) {  
           flashIt();  
         }  
         count = count + 1;  
      }  

      if(count == 14) {  
         for(i = 0; i < repeats; i++) {  
          allatOnce();  
         }  
      }  

      if(count == 14) {  
         digitalWrite(CWpin, LOW);  
         digitalWrite(CCWpin, HIGH);  
        delay(autoDelay);  
      }  

      if(count == 17) {  
         digitalWrite(CWpin, HIGH);  
         digitalWrite(CCWpin, HIGH);  
      }  

      if(count == 17) {  
         for(i = 0; i < 20; i++) {  
           blinkIt();  
         }  
      }  

      {  
         for(i = 0; i < repeats; i++) {  
           allatOncefast();  
         }  
         count = count + 1;  
      }  

            if(count == 18) {  
              digitalWrite(CCWpin, HIGH);  
              digitalWrite(CWpin, LOW);  
               delay(2000);  
               digitalWrite(CCWpin, LOW);  
               digitalWrite(CWpin, HIGH);  
               delay(2000);  
            }  

            if(count > 20) {  
➋          count = 0;  
            }  
            previous = HallValue;  
     }

首先,草图创建几个常量、整数和数组,通过读取霍尔效应传感器并计算旋转次数来帮助计时旋转。接下来,定义几个函数:blinkIt()flashIt()以不同的模式闪烁 LED,而allatOnceFast()allatOnce()则在不同的延迟下同时闪烁所有 LED。

和往常一样,setup()函数告诉 Arduino 哪些引脚是输入和输出。在loop()函数的开始,读取霍尔效应传感器,并根据需要在➊处增加计数器,同时在串行监视器中打印一些有用的调试值。这个程序使用count值来开启或关闭不同的序列,并限制重复次数。然而,由于count在➋处在序列结束时被重置,它不能作为总计器使用。

最后,对于不同的计数,程序使用if语句来硬编码不同的模式,用于打开手表和闪烁 LED;我在这里展示了一些,但我鼓励你设置你自己的模式。这个程序编写了许多函数,你可以按原样使用或在for循环中重复以进行多次迭代。

盾牌

与一些其他 Arduino 项目一样,这块盾牌并不是非常复杂,但看起来有点繁忙。为了简化,这块盾牌采用单面板设计。电路使用 LM7805 电压调节器来处理由于使用不同电机可能产生的过多电流。Nano 上内置的调节器仅适用于 300 mA 以下的电流。

注意

在这个项目中,我使用了最高可达 500 mA 的调节器,但调节器会变得相当热,我在这个电流下使用它并不感到舒服

你也许可以省略调节器;为高输出 LED 供电的晶体管的集电极被配置为发射极跟随器,并直接连接到正 9V 电源,因此它们并没有对稳压后的 5V 产生负载。

图 4-8 显示了盾牌的铜箔图案(左)和丝印层(右)。

image

图 4-8:盾牌的铜箔图案(左)和丝印层(右)。手表上链器的丝印层显示了 Nano、H 桥、外部计数器的接点、霍尔效应传感器、可调电阻、LED 连接、跳线、输入电压(VIN)和地(GND)的大致位置。PCB Express 文件可以从www.nostarch.com/arduinoplayground/下载。

请注意,板子顶部标有Hall的霍尔效应开关接点。我将连接霍尔效应器件的线缆直接焊接到 PCB 上,不过如果你更喜欢的话,也可以使用连接器。

在板子的中央,我留出了连接可调电阻(POT)的位置,用于外部调整周期,这一选项我在“总旋转调整”中进行了描述,见第 124 页。数字输出的编号标注在左侧。

如果你选择组装 Watch Winder 屏蔽板,请注意 Nano 板应插入焊接到屏蔽板上的女性插头,并且晶体管位于 Nano 板的下方。在焊接晶体管之前,请将它们按足够深的位置按下,以确保插入 Nano 板时它们不会阻碍其安装。我必须将晶体管放得相当靠近,以便将所有连接都安排在 PCB 布局中。我选择的 ZTX649 晶体管足够适合 Nano 脚印所允许的 0.100 英寸间距。

你还需要添加一些跳线,以完成屏蔽板上的连接。它们在丝网印刷图案上标明了。在图 4-8 中,这些以五条黑色线条显示。在接线板时不要忘记将它们包括在内。我还省略了 LM7805 稳压器输入和输出到地面的电容器;在完成的电路板上,它们是外部焊接的。如果你需要这些电容器,只需直接将一个 10.0μF 的钽电容和一个 0.1μF 的陶瓷电容焊接到稳压器的引脚上,正如图 4-3 中的电路图所示。

电机组件概览

当你玩够了看面包板上 LED 灯闪烁、观察电机启动和停止,以及玩弄草图时,接下来就是解决该项目的机械部分,这部分有一些特殊的挑战。这个上链器在电机没有东西可以转动之前是无法运作的;请参见图 4-9,其中有电机、电机支架、传动装置、轴承盒和传动轴的详细图示,它们构成了转动组件。

image

图 4-9:该结构需要制作一个小盒子,用以固定通过轴承安装的传动轴,并通过锁紧螺母将其固定到位。电机安装在支架上,并与传动轴连接,手表篮将连接到传动轴的另一端

传动轴需要通过轴承进行安装,两者可以用锁紧螺母固定在一起。我选择了一个相当标准的 R4A-2RS 轴承,这是一个比较常见的部件,外径为 3/4 英寸,内径为 1/4 英寸,厚度为 9/16 英寸。我建议使用滚珠轴承,因为我购买的预制上链器仅使用了电机的铜套作为唯一的轴承,而这正是故障的原因。由于轴承的内径是 1/4 英寸,我决定使用标准的螺纹杆,规格为 1/4 英寸×20 tpi(每英寸转数)或 1/4 英寸×28 tpi,而不是尝试将 1/4 英寸的杆强行压入轴承中。

注意

我使用锁紧螺母将杆固定到轴承上,因为它们比常规螺母更薄且外观不那么显眼,但你也可以使用标准螺母

构造

卷轴的制作提供了许多挑战,特别是处理亚克力材料——这是我在这个项目之前不熟悉的材料。虽然有一些困难需要克服,但通过反复试验,我学会了如何完成这项工作。图 4-10 展示了完成的手表卷轴侧面。

image

图 4-10:完成的手表卷轴侧面,显示了底座制作、轴承盒、电机安装架和手表篮。

最难的部分是切割亚克力和钻孔以安装球轴承。切割亚克力的方法有很多种,但没有一种特别容易。如果你选择一个能为你激光切割亚克力部件的供应商,这会容易很多。一些公司提供这种服务,价格略高于原材料成本。我之前提到过其中一个供应商,ZLazr。

如果你能使用圆锯,这将是最简单的 DIY 方法之一。否则,任何锯子都可以使用。我使用过钢锯,如果你耐心点,效果比大多数锯子要好。(如果操作太快,亚克力会过热并开始融化,导致锯子卡住。)我还知道一些人通过刻划并断裂亚克力板来成功切割。只需使用最适合你的方法即可。

请参阅 第 93 页的“亚克力”章节,了解制作轴承盒、手表篮和支架所需的亚克力形状。如果你还没有切割这些部件,请现在开始,并按照以下步骤制作这些部件。

准备电机安装架和轴承盒的亚克力材料

首先,打印出本章文件夹中的电机安装模板(见图 4-11),将其剪下,并使用中心线将其对齐到亚克力板上,用于电机安装。

image

图 4-11:电机安装架和轴承盒的模板。你可以在 www.nostarch.com/arduinoplayground/ 下载模板。

将模板贴到亚克力板上,使模板的中心线与亚克力板的中心对齐,并标记 A、B、D、E 和 F 孔的位置。标记孔的位置时,只需使用中心冲或钉子打出中心点。现在,开始钻孔;对于 A、B、D 和 E 孔使用 1/8 英寸的钻头,F 孔使用 3/8 英寸的钻头。

然后,将这块部件放在一旁,收集用于轴承盒的亚克力材料。最终的轴承盒将看起来像图 4-12 所示,等我们把所有部件装配在一起后。

image

图 4-12:完成的轴承盒,未经过最终修整和抛光。一个轴承暂时放置在位。

使用轴承箱模板标记一个轴承安装件上的 A、B、C 孔的钻孔中心。C 孔是轴承孔,A 和 B 孔是用于电机安装支架的。用中心冲击工具打标记,并使用 2.5 毫米(或#39)的钻头钻孔,再用 M3-05 螺纹 tap 攻丝。这些孔将用于安装电机的支架。使用相同的模板仅在有机玻璃的另一侧标记轴承孔(C)。然后,拿起那两块不承载轴承的轴承箱有机玻璃,按对角线标出中心。用中心冲击工具打标记,钻 1/4 英寸的孔以便安装到支架上。

警告

在钻任何尺寸的孔时,务必将工件牢牢夹住,如图 4-13 所示。不要手持工件。如果钻头或孔锯卡住了,有机玻璃可能会旋转。无论如何,请保持钻机转速较慢,并非常缓慢地将钻头推进到工作中。

image

图 4-13:在有机玻璃上钻大孔。请注意,有机玻璃已被牢牢固定住。

我找到的最好的方法是先钻一个相对较小的孔——可能是 1/4 英寸或 3/8 英寸——然后用锥形扩孔器将孔扩大到最终尺寸(参见图 4-14)。这是迄今为止最安全、最简单的方法,也是我强烈推荐的做法。

当你用扩孔器扩大轴承孔时,确保从两侧都进行扩孔。这将导致孔的中心部分直径略小于外部部分。扩孔直到轴承紧密配合,然后,如果需要,你可以使用厌氧粘接剂填充孔边缘。

有机玻璃的最终准备阶段是打磨和整理。你最初切割有机玻璃的方法将决定需要多少整理工作才能将边缘处理好。如果是激光切割的,几乎不需要打磨。对于所有的整理工作,我使用了逐渐增大的砂纸,开始时用 220 目,逐步升到 1500 目——也就是说,220、320、400、600,最后是 1500 目。自动砂光机——如轨道式、带式、振动式等——往往太粗糙,如果不小心使用,会融化有机玻璃。如果使用,请先在废料上试验。打磨过程效果良好,尽管对于粗糙切割的部分需要额外的打磨。对于另一块工件的打磨也需要额外的工作,以确保两块工件拼合成矩形——如果是轴承箱的情况,则是拼成正方体。

image

图 4-14:使用锥形扩孔器将轴承孔扩大到最终尺寸

使用液体抛光剂或珠宝师抛光膏进行最终抛光。确保在粘接之前,将抛光剂上的所有蜡都清除干净。尽量避免圆滑各部分的边缘,这样薄粘合剂(Weld-On 4)才会有效。你需要确保粘接面有足够的接触面积,以确保粘接牢固。

轴承盒的丙烯酸粘接

现在,是时候使用粘合剂将轴承盒的各个部件连接起来了。幸运的是,粘接丙烯酸板实际上比我预想的要容易一些。

在边缘平滑但没有过度圆角的地方,Weld-On 4 薄粘合液应该能很好地工作。它部分溶解丙烯酸并形成实际的焊接。最困难的部分是防止粘合液流到不该流的地方。如果你有较大的缝隙,或者边缘被圆滑化,可以尝试使用 Weld-On 16,它具有更高的粘度和透明丙烯酸填料,必要时用来填补缝隙和空隙。

在这两种情况下,你应该按照产品上的说明进行操作,但丙烯酸焊接的一般过程是这样的:首先将干燥的丙烯酸件夹紧,然后使用粘合剂随附的针头涂抹器,在每个接缝处涂上一层薄薄的丙烯酸水泥。毛细作用会将水泥吸入接缝处。对于表面稍微不平整的接缝,你可以将较厚的 Weld-On 16 涂抹在一面表面,然后将其与另一面连接。夹紧只需几分钟,但最终固化需要几个小时。

这个系统不需要太强的强度,但它在触碰时不应散架。对于节俭的人来说,像 Klean Strip 这样的油漆去除剂也可以很好地粘合丙烯酸。(Weld-On 中的粘合剂背后的化学物质是氯甲烷,这也是油漆去除剂的关键成分。)Klean Strip 的价格不到 Weld-On 的四分之一。

注意

网上也有一些关于粘接丙烯酸的教程。如果有疑问,可以查阅其中的一个,并先用一些废料试验,之后再尝试在你辛苦制作的部件上操作

粘接完轴承盒后,如图 4-9 所示,粘接侧板到底部,然后检查对齐情况。将螺纹杆穿过轴承,并把止动螺母放好,但不要过度拧紧。确保轴承不会卡住。如果轴承没有很好地居中,可能会出现这种情况,但通常在你稍微拧紧止动螺母时,它们会自动对齐。如果对齐不正确,可能需要用扩孔器稍微调整孔位,并用一些丙烯酸水泥修补,但我从来没有遇到过这个问题。目前,先从轴承盒中取出传动轴。

搭建支架

底座是这个项目中最简单的部分。它包括两个侧支撑,尺寸为 1 1/2 × 5 × 1/4 英寸,以及底座,尺寸为 3/8 × 3 × 5 1/2 英寸。我还将光条(3 × 1 1/4 × 3/8 英寸)和屏蔽安装(2 1/2 × 2 1/2 × 3/8 英寸)包括在内(参见图 4-15)。

首先,在每个侧支撑的上方 1/2 英寸处钻 1/4 英寸的孔,左右居中。然后,将两个侧支撑与底座粘接,位置距底座边缘 1 1/2 英寸,背面朝外。接下来,钻光条上的 LED 孔。我使用了五个 LED(红色、蓝色、白色、黄色和绿色),每个大小为 10 毫米。你可以选择任何你喜欢的颜色组合。

最后,钻孔并安装屏蔽。要找到零件的中心,从角落到角落标记。然后,在中心处钻一个#43 的孔,并为 4-40 螺钉攻丝。在底座的后边缘 2 英寸处,钻一个对应的孔并居中。接着,使用屏蔽本身,或者从 ExpressPCB 打印图纸中提取的图纸,作为模板钻孔以安装三个固定螺钉。在设计电路板时,我没有留出足够的空间来放置第四个螺钉。但三个螺钉已经足够,因为电路板上没有任何机械应力。我使用了 2.5 毫米(#39)钻头,并为 M3-05 螺钉攻丝,立柱将适合这个螺钉。图 4-15 展示了零件的尺寸和部分组装好的底座,包括支撑、光条和屏蔽安装。

image

图 4-15:表盘和灯条的组件及配置

准备电机和传动轴

尽管我们尽力精确标记并钻孔,但仍然可能会出现电机与传动轴之间的错位问题,因此这个构建的目标是保持联轴器的灵活性。我的解决方案可能不会受到工业工程师们的推崇,但我使用了一段乙烯基管将电机和传动轴连接起来。这个联轴器已经使用超过一年,且没有出现任何磨损或问题。

一段 1 英寸长、壁厚的乙烯基管,外径 7/16 英寸,内径 3/16 英寸,应该能够胜任这个工作。

不过,它可能无法直接适配电机轴或 1/4 英寸的螺纹轴,稍微需要一些加工。(我把 Lowe’s 的销售员弄得快疯了,买了他们库存的每种尺寸六个。)我们只需将螺纹轴的直径减小,并为电机轴制作一个小的衬套。

修剪螺纹轴

首先,修剪螺纹轴的直径。将手持电钻夹紧在台钳或平行夹具中,使用折叠的毛巾保护电钻不被损坏,并将螺纹轴放在通常钻头的位置(参见图 4-16)。然后,打开电钻,并使用锋利的锉刀修剪轴。

image

图 4-16:减少螺纹轴的直径

将轴直径缩小到略大于 3/16 英寸,这样就能紧密地配合塑料管,应该只需要一到两分钟。

制作电机衬套

接下来,取一小段圆形金属料,大约 3/4 英寸长,直径为 3/8 到 1/2 英寸。(我使用了直径为 3/8 英寸的材料,因为它需要的工作量较少。)在端部钻一个 11/64 英寸(#21)的孔,深度大约为 3/8 英寸。衬套孔需要尽量靠近中心,所以你可能想先用中心冲打一个标记(参见图 4-17)。

image

图 4-17:将用作衬套的零件的轴夹在台钳或台钳夹具中,在钻孔之前先用中心冲打一个标记。尽量靠近中心。

然后,像处理带螺纹的轴一样,将你切割的短料放入钻床中,使中心孔朝向钻床。将没有孔的一端打磨平整。将直径减少约 1/4 英寸,使其大致与传动轴打磨后的端部相等。

接下来,在衬套上钻一个 0.041 英寸的孔,距离衬套边缘大约 3/8 英寸。

同时,在传动轴上钻一个相应的孔。为了中心打孔并钻传动轴和衬套孔,先将端部打平,以便中心冲能找到一个支点(参见图 4-18)。这些孔将用于通过塑料管穿过钢琴线。

image

图 4-18:钻螺纹杆和衬套上的孔最简单的方法是将轴端打磨平整并使用中心冲。

最后,在衬套上钻一个 2.5 毫米(#39)孔,并在与电机轴孔垂直的方向上攻一个 M3-05 的螺纹孔。这将用来安装电机轴的锁紧螺钉。如果你愿意,也可以钻一个#43 的孔并攻一个 4-40 的锁紧螺钉。这个锁紧螺钉将把衬套固定在电机轴上,另外,在传动轴和电机衬套上分别钻的两个 0.041 英寸的孔,将通过钢琴线将塑料管固定到位。

切割钢琴线销钉并完成电机组件

切割两段宽度为 0.039 英寸,长度为 1/2 到 5/8 英寸的钢琴线。这可能会稍微费点力气。我使用了 Dremel 工具上的砂轮切割片。使用固定在钻床上的小磨轮角可以在钢琴线上打出槽口。一旦在钢琴线上打出槽口,你就可以用手折断它。你也可以用任何磨刀石来刻划钢琴线,应该能轻松折断。

完成这些步骤后,剩下的组装过程应该会很容易。首先,将轴承安装到电动机上;在紧固前,在锁紧螺钉上滴上一些螺纹锁定液。然后,将乙烯基管的一端套在轴承上,并将钢琴丝穿过轴承上的 0.041 英寸孔。用一把小钳子(小型自锁钳效果很好)牢牢夹住钢琴丝的一端,将其穿过乙烯基,进入电动机轴承中的孔,并穿过另一侧的乙烯基。如果这变得困难,可以尝试用小火焰加热钢琴丝,之后它应该就能轻松穿过。图 4-19 显示了乙烯基管套在电动机轴承上。

image

图 4-19:电动机轴和轴承组成了传动装置的一半,另一半是经过减速的驱动轴,通过轴承并固定手表篮

使用 M3×3/8 英寸螺钉将电动机支架固定到电动机上。接下来,将电动机支撑柱拧入轴承笼中;请参见图 4-20 了解如何安装它们。然后,将电动机组件(即电动机、支架、轴承和乙烯基管)与轴承支撑柱对接,使用 M3-05×1/2 英寸螺钉将其固定到轴承笼上。

要在乙烯基上制作驱动轴的孔,只需将驱动轴安装到轴承箱中,不加卡紧螺母,将乙烯基管套上,然后按照前面部分所述安装钢琴丝销。如果你担心钢琴丝销会脱落,可以用线扎将其固定或用胶带覆盖它们。(我从未遇到过问题。)目前,先从驱动轴上取下钢琴丝销,并将驱动轴从轴承箱中取出,直到准备进行最终组装。

image

图 4-20:电动机和电动机支架通过支撑柱与轴承箱连接。支撑柱拧入轴承箱,而电动机支架则用 3 毫米×1/2 英寸的螺钉和垫圈固定。轴承箱用 1 英寸长、1/4 英寸×28 的螺钉和螺母固定在支架上

制作手表篮

制作固定手表的部分有很多方法。我选择用丙烯酸材料制作我的手表篮。制作过程相对简单,但需要一些耐心。首先,取两个 5×3/8 英寸的丙烯酸圆盘,并在每个圆盘上仔细标记中心位置。然后,在每个圆盘的中心钻一个 1/4 英寸的孔。接下来,在将作为顶部圆盘的圆盘上,标出图 4-21(左侧)所示的矩形区域。

如果你还没有做,按照我在“零件清单”中描述的方式,切割用于手表盒的矩形亚克力件,并按照“粘合轴承盒的亚克力”中的说明在第 93 页组装它们。(在我制作的大多数样品中,我使用了 1/4 英寸的亚克力;不过,3/8 英寸的亚克力也能很好使用。)然后,小心地在圆盘上标出开口的位置(见图 4-21)。现在,将手表篮子粘合到一个圆盘上,如图 4-22 所示。接着,切割开口,使其与手表篮子的内部对齐。

image

图 4-21:为手表托篮切割尺寸。该图案可以作为 PDF 文件从 www.nostarch.com/arduinoplayground/ 下载

image

图 4-22:手表托篮安装在亚克力圆盘上的样子。它们上方是完全组装好的电机、轴承盒和传动轴

切割矩形块最简单的方法是在角落钻孔,注意不要钻到手表篮子里,然后使用钥匙孔锯或弯锯(或者,如果你小心的话,也可以使用弯曲锯)来切割开口。这些开口只需在一个圆盘上切割,这将是顶部。你可以用锉刀或砂纸稍微清理切口的边缘,但不要花太多时间,因为安装手表和垫圈后,这些边缘并不会显得很明显。

最后,将篮子安装到传动轴上。首先,将两个螺母拧到传动轴上,并将它们锁紧——也就是将一个螺母拧紧到另一个螺母上。然后,加入一个垫圈,接着是篮子的底盘、上部组件和手表篮子、一个垫圈,最后是顶部的螺母。如果你愿意,可以去五金店找一个装饰性的螺母来完成这个项目。

注意

如果按照我描述的方式使用锁紧螺母并将篮子紧固,则不需要粘合底部圆盘。我没有将盒子粘合到底圆盘上,这也没有造成任何问题

到了这个阶段,你可以使用两个装饰性的 1/4 英寸 × 28 螺栓和螺母将完成的组件安装到支架上。你也可以用亚克力水泥将灯条粘合到底座上,并钻孔安装盾牌安装板。

添加 LED

你差不多完成了。将 LED 灯安置在亚克力上,放置的位置可以随你喜欢,并将其接线到盾牌上。你可以在图 4-1 中看到我放置的位置。(亚克力传导光线的方式能产生一些很酷的效果。)你可能想要钻一些盲孔来安装 LED。只需钻一个 LED 直径大小的孔,但不要完全穿透亚克力。如果你小心的话,可能会做得很整洁,连线几乎看不见。

由于 LED 对自动上链器的最终外观至关重要,因此它们的安装和位置是成品的重要组成部分。钻孔以安装 LED 可能有点棘手,因为如果你购买了不同种类的 LED,它们的直径可能会稍有不同。作为起点,尝试为 5 毫米 LED 钻 3/16 英寸的孔,为 10 毫米 LED 钻 25/64 英寸的孔。我发现获取正确尺寸的最佳方法是在废料上钻一个样品孔,并在钻进成品之前进行试验。如果孔稍微小了一点,使用倒角扩孔器稍作修整应该能解决问题。如果孔稍微大了一点,可以尝试用丙烯酸水泥(如 Weld-On 16)填补。

如果你有一些线包线和线包工具,你可以使用线包技术将 LED 与屏蔽罩连接,而不是焊接。这样可以保持 LED 背部的连接整洁,而且由于线材直径较小,连接相对不显眼。它还允许你将电线靠近 LED 连接,如图 4-23 所示。如果你进行了焊接,可能会有过热 LED 连接点的风险。

使用线包或焊接将 LED 的引脚连接到屏蔽罩上。我在屏蔽罩上焊接了一个插座,这样就可以轻松地将 LED 的引脚直接线包或焊接到屏蔽罩上。你确实需要将电机的引脚焊接到屏蔽罩的另一端,但这应该不是问题。

霍尔效应传感器的电线可以焊接到屏蔽罩和传感器的引脚上。测量电线的长度,使其适合你计划安装霍尔效应传感器的位置。你可以使用连接器,但我们保持简单。传感器本身和磁铁通过双面泡沫胶带机械安装。

image

图 4-23:LED 上的线包线。这些电线非常细(30 号线)且绝缘层薄,因此不显眼。使用小型线缆扎带可以整理电线。我建议提前标记 LED 的正极端子,像我在这里做的那样,之后可以擦掉

展示组件

那么,屏蔽罩和纳米板该怎么办呢?本项目的主题一直是透明性,因此我建议让所有东西都暴露出来:将裸板直接安装在支架上,背面放置开关和电源插座(见图 4-24)。

image

图 4-24:完成的自动上链器上安装的纳米板和屏蔽罩。屏蔽罩上仅使用了三个支架

我将电子元件直接放置在轴承盒下方,位于支撑整个组件的立柱之间。然后,我将电路板安装在一块单独的丙烯酸板上,该板通过 4-40 平头螺钉固定在基座上。

将手表保持在篮子里

为了固定手表在手表篮里,我简单地剪了一块细致的泡沫海绵,效果很好。如果你想要比海绵更有格调一点的东西,你可以缝制一些小枕头,把手表带缠绕在上面。我没有缝纫能力,所以我就选择了海绵。

注意

开放框架总体上效果不错,但可能会积灰。如果你比较讲究,你可以用 3/16 英寸厚的亚克力板制作一个盒子来覆盖整个上链器。或者你也可以像我一样买一罐除尘喷雾。有些人还建议我,可以将整个上链器安装在一块硬木上,比如胡桃木或其他装饰性硬木,以增加一点点完美的收尾效果

设计说明

现在你已经看到我如何制作手表上链器了,我将带你走过一些关键的设计决策,可能有些你会选择不同的方式来做。

总旋转调整

通过不修改草图,可能会改变手表上链器的总转数,尽管我选择不这样做。

你可以使用电位器来创建一个可变电压,并将其输入到 Arduino 的一个模拟输入端口。然后,你可以用这个值替代草图中某个延迟的值,以改变每日的转数。以下是如何安装电位器以及你需要对草图做的修改。

硬件更改

将电位器的上端和下端接到系统的正负电源轨上。为了这个目的,扩展板上已经提供了焊接点。你不需要使用全尺寸的电位器;一个小型的可调电位器(10 圈最好)就足够了,并且能节省很多空间。将电位器的中间引脚(在扩展板上)连接到 Nano 的一个模拟引脚。由于霍尔效应开关使用的是 A0 引脚,我建议使用模拟输入 A1。扩展板上已提供焊接点。

软件更改

在草图中,你需要做几个操作。首先,告诉 Nano 输入 A1 正在使用。在草图顶部添加如下代码:

const int revSet = A1;

然后,再稍微往下,识别电位器设置的值,如下所示:

int revNumber = 0;

revSet是我给输入 A1 取的任意名称,revNumber是我给草图中替代延迟的数字取的任意名称。

电位器将输出从 0 到 5 伏的值。由于模拟输入 A1 连接到一个 10 位的 ADC,它将生成 0 到 1,023 之间的 1,024 个数字值。在其他应用中,通常需要将这 1,024 个值映射到其他一组值。然而,在这个特定情况下,最简单的做法是直接使用这些值。

在草图文件中,移动到void loop() {之后的那一行,并将 A1 的值赋给revNumber,如下所示:

revNumber = analogRead(revSet);

回到我们定义草图中某些延迟的地方。修改

int timer = 500;

int timer = 0;

最后,回到你输入revNumber = analogRead(revSet);的地方,在那之后输入如下内容:

timer == revNumber;

现在,每次草图调用定时器值时,revNumber 值应该自动使用,这会带来延迟的广泛变化。最终的变化范围从每天 200 次到 1,200 次不等。

使用多少个 LED 和放置位置

我最初设想 Watch Winder 只有两个 LED 来指示旋转方向。第一版使用了连接到 Nano 的电机方向引脚 D12 和 D13 的 LED(见 图 4-2)。一个引脚在旋转一个方向时保持亮起,反之亦然。红色和绿色的 LED 用来指示绕发器的旋转方向,就像船上的跑道灯一样。

但这还是很无聊,而且还有那么多引脚没做任何事。此外,如果你邀请朋友来看你的绕发器,它会大部分时间什么都不做——你的朋友也是。所以我决定为这个项目增加一些装饰性的 LED。我还决定通过让草图提供一些动画来增加更多的变化,要求手表转动不同的次数——有时转动较少,但更频繁。我甚至加入了一个“乒乓效果”。

由于负责艺术事务的大脑半球显然没有得到很好的发展,我将 LED 的放置位置留给你自己。在 图 4-1 中,轴承盒里有四个 LED,灯条中有五个 LED,但你可以把它们放在任何地方。

我随意选择了九个 LED 通道,在某些情况下,我为每个通道使用了两个 LED。我为电机的每个方向都用了两个 LED——D12 和 D13 这两个通道既驱动 LED,也驱动电机。D2 和 D13 各自为两个 LED 供电。D4 到 D10 为其他 LED 供电,包括位于手表篮子后面的两个 LED——D9 和 D10,每个都有两个 LED——以及位于灯条前面的五个 LED——D4–D8。D11 保留给你未来可能想要添加的开发。

电机电压

一位 Watch Winder 的测试员在使用 5V 电源驱动 6V 电机时遇到困难。投诉是扭矩不足。如果你遇到这个问题,解决方法是将 H-桥的第二个电源(VCC[2])直接连接到 9V 电源。为此,你需要切断连接到第 8 引脚的线路,或者移除该引脚并将其单独焊接到 9V 电源上。由于电机是间歇性运行的,烧坏电机的风险很小。虽然这不是一个优雅的解决方案,但它确实有效。顺便提一下,在大约 20 个不同的电机中,只有这个电机出现了该问题。而且正如之前所提到的,电机在较高电压下的更高速度对转动次数几乎没有影响。

手表自动绕发器转动多少次?

如果你真的需要知道手表上链器的旋转次数,这里有一个解决方案。内部计数器用于排列草图,但并不准确反映电机的总旋转次数。虽然我们本可以在内部计数旋转次数,但那样需要额外的显示装置或将其连接到串行监视器。但如果你需要保持计数,可以添加一个小型外部计数器。因为你只会在更改旋转次数时偶尔需要它,所以你可以在需要时插入它——保护板中已有预留——不需要时可以将其保存起来用于其他项目。图 4-25 中的外部计数器是自供电的,价格不到$8。有关详细信息,请参见“零件清单”和第 93 页。

外部计数器并非必须,但它可能是一个不错的配件,可以在此项目及其他项目中使用。它未包含在设计中,因为它只在偶尔使用时需要插入。我在保护板上使用了一个双引脚母头——连接端口标记为GNDX-ctr,并为计数器的连接线配备了一个双引脚插头。计数连接从地线接到计数器的引脚 4,再从霍尔效应传感器接到引脚 1。你可以为计数器添加一个复位按钮,将其从地线接到引脚 3。计数器来自制造商,附带的信息很少,因此图 4-25 显示了计数器背面的视图,复位按钮位于右侧。

image

图 4-25:增加复位按钮的外部硬件计数器

即使这个手表上链器不能保持我的手表上链,我认为它依然会是一个很棒的雕塑。当你完成这个项目后,也许你的下一个 Arduino 项目将正是这样:一个充满动感、闪烁和运动的艺术作品。

第六章:Garage Sentry 停车助手

image

这个项目是一个可靠的电子设备,用于测量你需要将车开进车库的距离。如果你停车在车库里,可能会遇到这个问题:你应该把车开到车库多远,才能确保前面有足够的空间放置物品,后面又有足够的空间让车库门关上?有些人会在天花板上悬挂一个网球,并在网球接触到挡风玻璃时停车。这种方法有效,但网球的安装和调整很麻烦,且如果你想将车库用于除停车外的其他用途时,网球常常会妨碍你。

Arduino 提供了更好的解决方案。这个 Garage Sentry 项目是经典的“网球挂绳”装置的电子版,只是做得更好。Garage Sentry 准确地检测你的车是否到达车库的正确位置,并触发一个警报,闪烁的灯光提示你何时踩刹车。

此外,在本章末尾,我将展示如何将基本的 Garage Sentry 改造为豪华版,当你接近完美停车位置时,它会发出警报。

Garage Sentry 背后的灵感

这个项目来源于我玩 超声波收发模块 的经验,该设备发出声波并在声波到达物体后被反射回来,模块接收到反射波。模块的输出使得微控制器能够测量声波的往返时间,进而根据已知的声速来计算距离。为了测试超声波收发器的灵敏度和极限,我使用了在车库中的电池供电面包板版本,那里有足够的空间可以测试不同的距离。事实证明,汽车是超声波能量的极好反射体。通过这些实验,我受到了启发,将测试设备转化为 Garage Sentry。

必需工具

这个项目不需要太多工具或材料,但无论是标准版还是豪华版,你都需要以下工具:

配备 3/8 英寸或 1/2 英寸夹头的电钻(可由电池驱动,或通过 110/220V 电源)

用于电位器(9/32 英寸)、电源输入(1/4 英寸)和 LED(3/8 英寸)的钻头

焊接铁和焊锡

锥形扩孔器套件

十字螺丝刀和一字螺丝刀

钳子(我推荐使用尖嘴钳。)

(可选)1/4 英寸螺纹 tapping

零件清单

你将需要以下零件来构建基本版 Garage Sentry:

一块 Arduino Nano(或克隆版)

一只 HC-SR04 超声波传感器

两个高强度 LED(>12,000 MCD)

两个 270 欧姆、1/4 W(或更多)电阻(用于限制 LED 的电流)

一只 20 欧姆、1/8 W 的电位器

两个额定集电极电流至少为 1.5 A 的 NPN 信号晶体管(我使用了 ZTX649 晶体管。)

一个外壳(我推荐使用蓝色的 Hammond 1591 ATBU,透明的 1591 ATCL,或类似的外壳。)

(可选)一条 0.80 英寸的铝条用于安装支架

(可选)两颗 1/4 英寸×20 英寸×3/4 英寸的螺栓和螺母

一块大约 1×1 英寸的打孔板(可以在一侧包含铜箔环)

一个 3.5 mm 插孔

两颗 2-56×3/8 英寸螺丝和螺母

两颗额外的 2-56 螺母,用作垫片

一个 9V、100 mA 插头式墙壁适配器电源(任何 7.5V 至 12V DC,100 mA 或更大都应能正常工作)

一段大约 3 英寸长的双面泡沫胶带

一个 LM78L05(TO-92 封装)调节器(仅适用于面包板版)

28 或 30 号连接线

(可选)线包工具和线材

因为基础版不需要太多额外组件,我建议在标准打孔电路板上构建电路,而不是使用扩展板。为了为电路供电,您可以使用一个 9V、100 mA 的墙壁适配器,通过 3.5 mm 插孔连接(参见图 5-1)。您应该不需要开关。

image

图 5-1:我使用的是 Magnavox 的交流适配器,但任何类似的 7.5V 至 12V 的直流输出电源都可以使用。这些电源在网上很容易买到,价格从不到 1 美元到大约 3 美元不等

请确保使用两颗明亮的 LED,即使在汽车前灯开启时也能清晰可见。亮度较高的 LED 范围从 10,000 MCD(毫坎德拉)到超过 200,000 MCD。亮度越高越好;不过要记住,亮度更高的 LED 需要更多的电力,因此限流电阻器需要有更高的功率额定值来配合更亮的灯。使用 270 欧姆的限流电阻器,在 5V 时,我使用的 12,000 MCD 的 LED 电流消耗大约是 30-40 mA。(功率等于电压乘以电流,或者P = VI,所以在 40 mA 和 5V 的情况下,功率就是 0.20 W。)即使您可以用更小的功率值(如 1/4 W)轻松应对,因为 LED 仅间歇性亮起,还是最好使用 1/2 W 或更大功率的电阻器。

豪华版配件

除了基础版车库守卫的组件外,如果您想要构建豪华版,还需要以下额外组件:

两颗高亮度绿色 LED

两颗高亮度琥珀色 LED

两颗额外的 270 欧姆、1/4 W 电阻器

两个额外的 NPN 信号晶体管,一个 Hammond 1591 BTCL 外壳(替代 1591 ATCL)

一块 PCB(扩展板)

下载

程序文件    GarageSentry.inoGarageSentryDeluxe.ino

钻孔模板    Transducer.pdf

机械图    Handle.pdf

豪华车库守卫的扩展板文件    GarageSentryDeluxe.pcb

原理图

图 5-2 显示了车库守卫的原理图。R1 和 R3 是 LED 的 270 欧姆电阻器,应该是 1/4 W 或更大功率。如果没有更大功率的电阻器,可以将几个电阻器并联使用来达到所需的功率。首先,使用公式找出正确的电阻值:

image

你还可以使用自动计算器,例如 www.1728.org/resistrs.htm,这比自己做数学计算要容易得多。

image

图 5-2:车库哨兵的示意图

为了避免额外的计算,选择相同值的电阻器。这样,相同数量的电流会通过每个电阻器。例如,两个 1/8 W 的电阻并联将得到 1/4 W 的值。

如果你使用不同值的电阻器,你将不得不计算每个电阻器通过的电流以及总的功耗。

这个原理图还为你定制报警提供了空间。虽然该版本的项目使用 LED 来创建视觉报警,但只需稍作修改,你也可以轻松创建可听到的报警。只需将红色或蓝色 LED 替换为可听设备,例如 Sonotone Sonalert,报警就会响起。要替换 LED,你需要将 Sonalert 连接到该 LED 的两端;只需确保极性正确。或者,你可以保留两个 LED 并为第三个警告添加可听设备。

注意

在这个项目中,Nano 利用了其板载电压调节器,这就是为什么原理图中没有外部调节器的原因

计算距离的基础

这个项目测量声音从起点发出、反射回物体并重新传回起点所需的时间,并利用该时间计算物体与传感器之间的距离。

基本的距离计算与通过计算闪电和雷声之间的秒数来确定暴风雨的距离差不多。每一秒钟代表 1,125 英尺的距离,约合 0.2 英里。由于声音在海平面上的传播速度为每秒 1,125 英尺,如果闪电和雷声之间有五秒钟的延迟,你可以确定暴风雨大约离你 1 英里远。在车库哨兵的情况下,一旦你知道声音来回所需的时间,并知道声音的传播速度,你可以根据时间-速度-距离公式计算出距离:

距离 = 速度 × 时间

车库哨兵的工作原理

这个项目利用了超声波,它与雷声不同,超出了大多数人的听力范围。如果你的听力很好,你可以检测到约 30 Hz 到接近 20 kHz 之间的声音,尽管听力在超过 10 kHz 或 15 kHz 后会迅速衰退。

注意

作为参考,钢琴上的中央 C 是 261.6 Hz。幼儿(以及大多数狗)通常能够听到高频声音,但随着年龄的增长,听力,特别是高频部分,会迅速下降

本项目中使用的超声波收发模块以大约 25 kHz 的频率发出脉冲,并通过麦克风监听回声。如果信号碰到物体反射回波,系统会接收返回的回声,并告知微控制器已接收到信号,并进行距离计算。对于 Garage Sentry,该模块被放置在车库前方,信号会发射并反射到汽车的前部——如果你是倒车,则是反射到后部。为了计算汽车距离超声波收发器的距离,Arduino 会测量信号从收发器到目标并返回的往返时间。例如,如果 Arduino 测得时间为 10 毫秒(0.010 秒),你可以这样计算距离:

image

啊,但别急。记住,信号是先到达汽车再返回到麦克风的。为了获得正确的车辆距离,我们需要将测得的时间除以二。如果控制器测得 10 毫秒,那么到汽车的距离就是:

image

HC-SR04 超声波模块在 Arduino 的指令下发送信号(见 图 5-3)。然后,草图指示发射器关闭,麦克风监听回声。

image

图 5-3:超声波传感器模块。模块的背面(底部)有连接端子

如果有物体让信号反射,麦克风就会接收到反射的信号。Arduino 记录信号发送和接收的准确时间,然后计算延迟。

HC-SR04 模块不仅仅是一个扬声器和麦克风。该模块包含换能器——扬声器和麦克风——以及大量电子元件,包括至少三个集成电路、一个晶体和若干个无源元件。这些元件简化了其与 Arduino 的接口:25 kHz 的音调实际上是由模块生成,并通过微控制器打开和关闭。一些组件还增强了接收器或麦克风的灵敏度,使其具有更好的探测范围。

HC-SR04 超声波换能器的范围大约是 10 到 12 英尺。返回的信号总是比发送的信号要弱,因为一些声波能量在空气中散失(见 图 5-4 中的虚线)。

image

图 5-4:在本项目中,声音从发射器传出,碰到物体后反射并被接收

计算发射器与物体之间的距离并不困难。你只需要拿到信号返回所需的微秒数,除以声音在 1 英寸中传播所需的 73.746 微秒,然后再除以 2,因为信号是先出去再返回的。这个完整的计算方法将在“确定距离”一节的第 141 页中详细介绍。

这个草图提供了一个以英寸或厘米为单位的响应,具体取决于你的偏好。我们将使用英寸来设置报警的距离,但转换为厘米只需要重新映射模拟输入,并略微调整数字。这个草图还会为你执行基本的算术运算,以确定厘米的测量值。

在高层概述之后,让我们深入了解如何接线 Garage Sentry。

面包板

整个 Garage Sentry 可以放在一个小型面包板上,你可以将它搭建好,进行编程,用电池供电,并四处走动进行测试。随着你玩这个项目,我相信会想到超声波技术的其他应用。

我组装的面包板,如图 5-5 所示,使用了 9V 电池供电。通常,你可以将电池直接接到 Nano 的 VIN 引脚,并使用 Nano 内置的电压调节器。但在第一次编程和测试时,你将通过 USB 电缆为 Nano 供电,所以在面包板上,你需要为 Nano 和超声波模块分别设置 5V 的正负轨。为了避免损坏 Nano 或模块,并避免使电路过于复杂,我加入了一个单芯片外部电压调节器(LM78L05),使整个面包板都能稳定在 5V 电压下工作。请查看图 5-6,看看它是如何接线的。

image

图 5-5:这是已经接线的面包板。我使用了一块 9V 电池,这样可以在不同环境下进行实验。由于相机曝光时间的长度,两颗 LED 都显得亮着。

image

图 5-6:这是 LM78L05 TO-92 电压调节器在面包板上的接线方式。旁路/滤波电容器不是必需的。

下面是接线面包板的详细步骤列表:

  1. 首先,将超声波模块放置在面包板的下端,面向外侧,然后将 Nano 插入面包板,确保其上方留出四行连接。

  2. 确保左侧和右侧的正负轨(红色和蓝色条纹)连接正确——红接红,蓝接蓝。如果将红色连接到蓝色,将会导致严重的问题。

  3. 将红色正轨连接到 5V 电源(Nano 的引脚 27,标记为5V)。如果你通过 USB 连接供电,这一步是必要的。

  4. 将 Nano 的引脚 4(标记为GND)连接到面包板的蓝色负轨。

  5. 将 HC-SR04 传感器的 VCC 引脚连接到红色正轨。

  6. 将 HC-SR04 传感器的 GND 引脚连接到蓝色负电源轨。

  7. 将 HC-SR04 传感器的 TRIG 引脚连接到 Nano 的第 15 号引脚(D12)。

  8. 将 HC-SR04 传感器的 ECHO 引脚连接到 Nano 的第 14 号引脚(D11)。

  9. 将两只 ZTX649 晶体管插入面包板中。选择一个区域,使每只晶体管的三个引脚都有自己的行。

  10. 将 Nano 的第 12 号引脚(D9)连接到晶体管 Q1 的基极。

  11. 将 Nano 的第 13 号引脚(D10)连接到晶体管 Q2 的基极。

  12. 将两个晶体管的集电极连接到红色正电源轨。

  13. 将晶体管 Q1 的发射极连接到一个 270 欧姆电阻的一端。

  14. 将连接到晶体管 Q1 发射极的 270 欧姆电阻的另一端连接到面包板上的一个空白行。

  15. 将晶体管 Q2 的发射极连接到另一个 270 欧姆电阻的一端。将连接到晶体管 Q2 发射极的 270 欧姆电阻的另一端连接到面包板上的另一个空白行。

  16. 将 LED(D1)的+(长端)连接到 270 欧姆电阻,并将另一端连接到蓝色负电源轨。

  17. 将 LED(D2)的+(长端)连接到第二个 270 欧姆电阻,并将另一端连接到蓝色负电源轨。

  18. 将一个 20 欧姆电位器的一端连接到红色正电源轨。

  19. 将电位器的另一端连接到蓝色负电源轨。

  20. 将电位器的滑动端(中间引脚)连接到 Nano 的模拟引脚 A0(26)。

image

图 5-7:78L05 稳压器的引脚图

你应该准备好开始了!如果使用交流电连接,只需将其连接到 Nano 的 VCC 引脚。

要添加电池连接,需将 78L05 的中心引脚连接到地(负电源轨),输入端连接到电池的正极,输出端连接到正电源轨(参见图 5-7)。将电池的负极连接到负电源轨。

草图

一旦面包板完成,草图可以加载到 Nano 上。下载GarageSentry.ino文件,地址为www.nostarch.com/arduinoplayground/。要将文件加载到 Nano 上,按照“上传草图到你的 Arduino”中的说明操作,详见第 5 页。记得选择正确的板类型。加载完成后,设备即可进行实验。

Garage Sentry 的草图有多个功能。它告诉超声波传感器生成一个波,并检测回波返回的时间。然后,基于该时间计算距离,并在必要时通过点亮 LED 发出停止警报。以下是完整的草图;接下来我会详细讲解。


      /* Garage Sentry  
      */  

      int ledPin = 10;  
      int ledPin1 = 9;  
      int count;  
      int analogPin = A0;  
      int val;  
      int y;  

      void setup() {  
        Serial.begin(9600);  
        pinMode(ledPin, OUTPUT);  
        pinMode(ledPin1, OUTPUT);  
        pinMode(analogPin, INPUT);  
      }  

      void loop() {  
        val = analogRead(analogPin);  
        long duration, inches, cm;  
        //Give a short LOW pulse beforehand to ensure a clean HIGH pulse:  
➊   pinMode(12, OUTPUT);  //Attach pin 12 to TRIG  
        digitalWrite(12, LOW);  
        delayMicroseconds(2);  
        digitalWrite(12, HIGH);  
        delayMicroseconds(5);  
        digitalWrite(12, LOW);  

        pinMode(11, INPUT);  //Pin 11 to receive ECHO  
        duration = pulseIn(11, HIGH);  

        //Convert the time into a distance  
        inches = microsecondsToInches(duration);  
        cm = microsecondsToCentimeters(duration);  
        val = map(val, 0, 1023, 0, 100);  
        if(inches == 0)  
          digitalWrite(ledPin, LOW);  

        if(count == 0  inches > 0  inches < val) {  
➋      for(y = 0; y < 200; y++)  
         {  
           digitalWrite(ledPin, HIGH);  
           digitalWrite(ledPin1, LOW);  
           delay(100);  
           digitalWrite(ledPin, LOW);  
           digitalWrite(ledPin1, HIGH);  
           delay(100);  
         }  

        count = count + 1;    
      }    

      digitalWrite(ledPin1, LOW);    
      if(inches > 10) {    
        //delay(1000);    
        count = 0;    
      }    
      Serial.print(inches);    
      Serial.print("   inches ");    
      Serial.print(count);    
      Serial.print(" count   ");    
      Serial.println();    
      Serial.print(" Val       ");    
      Serial.println (val);    
      delay(100);    
  }    
  long microsecondsToInches(long microseconds) {    
    return microseconds / 74 / 2;    
  }    
  long microsecondsToCentimeters(long microseconds) {    
    return microseconds / 29 / 2;    
  }

首先,我们定义几个变量,设置参数,并加载库(如果有的话)。在此情况下,定义ledPinledPin1,它们将作为警报。其他定义(int)包括cmcount(一个将在内部使用的变量)、analogPin(作为 A0)、val(用于存储限制信息)和y(用于循环中)。

在 setup() 函数内部

接下来是 setup() 函数。在这里,你设置你可能需要使用的 Arduino 特性;这个草图包括串口监视器,尽管你可能在最终产品中不需要它,但它在调试代码时通常非常有用,尤其是当你想修改代码时。这个草图将监视器的速率设置为 9600 波特,这是许多应用程序中的标准设置。它还定义了你将使用的引脚模式,设定为输入或输出。你可以在代码中的几乎任何位置设置 pinMode 的值,包括在 setup 之前或其中;它们也常常在主循环中定义,特别是当这些定义预期会发生变化时。

在 loop() 函数内部

loop() 函数是所有操作真正发生的地方。循环会不断执行,除非被命令延迟或暂停。所以即使看起来什么也没发生,控制器也会不断循环执行代码。在这个应用程序中,控制器在循环中的第一项任务是设置变量 val 来存储来自连接到模拟引脚(analogPin)的电位计输入。

为了启动超声模块的发送/接收功能,草图首先会调用低信号发送给发射器(TRIG),清除模块以确保接下来的高信号是干净的。你可以在从 ➊ 开始的几行代码中看到这一点。

接下来,会有一个延迟,让系统稳定下来,然后草图会向传输引脚写入高电平,命令发射器发送超声波信号。紧接着是另一个延迟,然后草图将数字引脚 12 设置为低电平,关闭发射器,并通过调用 pulseIn() 方法激活接收器。

确定距离

如果没有回声——也就是说,如果 inches == 0 或者英寸接近无穷大——控制器会继续运行代码,直到它到达结束位置,然后从头开始。如果检测到回声,微秒数(duration)会从发射器开启到接收到信号的时间,这个值会转换成英寸和厘米。这给了我们一个测量值,表示收发器距离物体的距离。请注意,在整个解释过程中,我将使用英寸单位,但你也可以使用厘米单位来理解。

microsecondsToInches()microsecondsToCentimeters() 命令根据“车库哨兵工作原理”一节的算式,将时间测量值分别转换为英寸和厘米,详见 第 134 页。使用 long 数据类型,而不是 int,是因为 long 提供 4 字节的数据存储,而不是仅有的 2 字节,并且微秒数可能会超过 2 字节的限制 32,767 位。到目前为止,一切顺利。

在常规公式中,距离的计算看起来是这样的:

imageimage

在任一情况下,我们首先除以 2,因为信号从换能器传到目标再返回,正如之前所讨论的那样。在英寸函数中,我们将折半后的微秒数除以 74,在厘米函数中,我们除以 29。(信号传播 1 英寸需要 74 微秒,传播 1 厘米需要 29 微秒;我通过遵循“时间与距离转换系数”中的算式得出了这些数字,详见第 142 页)

时间与距离转换系数

你可以直接相信我的数学计算并复制时间到距离的转换代码,但你也可以将这段算式应用到任何使用类似超声模块或其他传感器的项目中,因此我鼓励你自己计算一下。

如我在“车库监控器工作原理”中所述,声音速度大约是每秒 1,125 英尺。将其乘以每英尺 12 英寸,得到每秒 13,500 英寸。

要得到每英寸的秒数,只需将此值除以 13,500 英寸:

image

声音传播 1 英寸大约需要 74 微秒,即 0.000074 秒。要计算厘米的距离,可以进行相同的操作,但使用 343 米每秒的声音传播速度,乘以每米 100 厘米,并取倒数。

触发警报

草图还没有完成。现在我们需要查看测量的英寸(或厘米)数,并将其与预定的值——在此案例中是val——进行比较,以确定是否应激活警报。为了将变量val设定为数值,取一个跨越电源的电位器(R2),将刮片连接到 A0 引脚(见图 5-2)。因为 A0 是一个 10 位模拟到数字转换器的输入,它将电压(介于 0V 和 5V 之间)转换为介于 0 和 1,023 之间的数字值。使用analogRead()命令读取该值时,结果将在 0 到 1,023 之间,具体取决于电位器的位置。

然后将该值用于设定警报的触发点。但允许所有 1,024 个值实际上会使距离范围从 0 到 1,023 英寸。由于控制器仅旋转 270 度,因此调整例如 40 到 42 英寸之间的距离将代表一个非常微小的旋转——超出了大多数电位器的分辨率。

为了将此应用于电位器,草图将该值映射,使电位器的整个旋转表示大约 100 英寸的距离,代码如下:

val = map(val,   0,   1023,   0,   100);

映射电位器的值会将最大距离从 1,023 英寸缩小到 100 英寸,同时保持最小距离 0 英寸不变。你可以映射任何一组值,这样车库卫士的目标距离可以从XY,电位器完全旋转时,设置好车库卫士后,你可能需要测试这个范围,直到它适合你的车库。

一个条件控制结构设置了警报的限制。这个结构确保当测量的距离为 0 时,无论草图使用的是英寸还是厘米,LED 都会关闭。首先,inches的值会与val进行比较,表达式如下:

count  ==  0 && inches  >  0  &&  inches  <  val

如果该语句为真,警报会被触发,且➋处的for循环会被激活(见第 139 页),该循环交替闪烁 LED 200 次,直到超时并将 LED 关闭。

for循环仅从 0 数到 200,但可以很容易地修改。每次计数后,它会打开一个 LED,短暂延迟后关闭该 LED,再稍微延迟打开第二个 LED,再稍微延迟关闭该 LED,然后进入下一个计数。在 200 次计数结束时,系统会关闭 LED,程序继续到下一行,重新开始。也就是说,程序会从头开始。

结构

图 5-8 显示了车库卫士的外壳。

image

图 5-8:基础车库卫士使用导线包绕进行最终连接

车库卫士最棘手的部分是将超声波模块安装到外壳上。由于该模块只能沿直线发射声波,因此你需要能够调整其方向,以便超声波传感器能够击中目标并接收回波。但该模块仅包括两个对角安装孔,因此没有简单的方法将其固定到一个灵活的安装架上。我们将首先解决这个问题。

为电子设备钻孔

为了解决这个问题,我将收发器直接安装到外壳上,并根据需要调整外壳的方向。为了安装模块,需要在外壳上钻 5/8 英寸的孔,并使用支撑柱牢固地固定电路板。可以参见图 5-9 中的模板来进行钻孔测量。本书的在线资源中有该模板的 PDF 文件,网址是www.nostarch.com/arduinoplayground/,如果你想打印它并将其作为指南放在外壳上,可以访问该网站。推荐使用的外壳是聚碳酸酯塑料,比苯乙烯或有机玻璃更不容易开裂;但它容易卡住钻头,所以要小心。

image

图 5-9:钻孔模板,用于安装传感器孔

有几种方法可以钻出 5/8 英寸的孔。如果你擅长钻孔,可以直接使用 5/8 英寸的钻头钻孔。但是我发现,通过先钻一个直径约为 1/4 到 3/8 英寸的孔,然后用锥形扩孔器扩大孔径,可以安全且轻松地钻孔。亚马逊上不到 15 美元就能买到锥形扩孔器套件,里面较大的扩孔器可以将孔扩展到 7/8 英寸直径,对于其他项目也很有用。使用 1/8 英寸的钻头钻孔,用作支撑垫的孔,可以参考图纸来作为模板。

如果你扩孔时要确保从两侧进行扩孔。将孔扩大到一个能够紧固换能器元件的大小,但不要过于紧密。虽然这不是一种非常精确的打孔方式,专业的机械师可能会对这种方法不以为然,但在这里效果还不错。

警告

无论孔的大小如何,钻孔时不要用手直接握住工件。始终将其固定在夹具中。如果钻头卡住,工件会想要旋转或向上攀升。钻孔时应使用较慢的速度,轻轻操作

接下来,钻孔以安装电位器、电源插孔和两个 LED 灯。根据你使用的电源插孔和电位器选择合适的钻头尺寸。我使用了 9/32 英寸的钻头用于电位器,1/4 英寸的钻头用于 3.5 毫米插孔,以及大约 25/64 英寸的钻头用于 LED。10 毫米 LED 的尺寸可能会因制造商不同而有所不同,因此我建议你选择一个较小的钻头,比如 3/8 英寸,然后逐渐扩孔直到 LED 能够紧密安装。由于 LED 是锥形的,最好从外壳的后部扩孔,这样 LED 会更好地适应。

电位器和电源插孔的位置并不重要,但要确保它们不会挤压换能器或 Nano。你希望它们位于外壳的底部,这样在外壳安装后可以方便访问(见图 5-12)。

安装选项

在将 Arduino、超声波传感器和打孔板电路塞进外壳之前,先弄清楚你想如何安装 Garage Sentry。有几种方法可以将外壳安装到你需要的表面上。

魔术贴条

如果你有一个平整的表面来安装组装好的设备,可以直接使用粘性魔术贴将外壳固定(见图 5-10)。我车库里已经用这种方式安装了两个警戒器几个月,没有出现滑动或老化的迹象。

image

图 5-10:使用粘性魔术贴条安装 Garage Sentry 外壳

一个可以调节的 U 型支架

如果你没有合适的表面并且需要将模块以一定角度进行调节,可以将其安装在一个 U 型支架上,这样传感器就可以上下或左右摆动。在这一节中,我将描述如何构建图 5-11 所示的 U 型支架安装架。

image

图 5-11:此图说明了可选的 U 型支架把手的大小和形状,以及它如何连接到外壳。当你看到一个维度有两个测量值时,较小的适用于基本车库警卫,而较大的适用于豪华版本

为了制作适用于 1591 ATCL 2×4 英寸外壳的基本车库警卫 U 型支架,取一条 3/4 英寸×0.080 英寸×5 1/2 英寸长的铝条(可在 Ace Hardware、Home Depot 或 Lowe’s 购买),并在铝条的两端 5/16 英寸处钻 1/4 英寸孔。然后,在外壳的侧面钻对应的孔,使用 7 号或 15/64 钻头,并在孔中螺纹加工 1/4 英寸-20 螺纹。对于标准版本,将铝条在每端 1.5 英寸处弯曲,而豪华版则在每端 2 英寸处弯曲(参见图 5-11)。使用台钳弯曲金属是最简单的方法,但如果不方便,也可以将铝条夹在工作台和金属板之间,夹紧后手工弯曲。

为了制作适用于 1591 BTCL 2.2×4.4 英寸外壳的豪华车库警卫 U 型支架,使用一条 6 3/8 英寸长的相同材料条,且在距两端 1/2 英寸的位置钻 1/4 英寸孔。然后,在距离每端 3/4 英寸的位置将铝材弯曲成直角,以适应标准版本;对于豪华版,则在每端 1 英寸处弯曲。

要将 U 型支架固定到任何外壳上,可以先在外壳每端的中心钻孔。最简单的方法是分别在外壳的两端钻一个 7 号孔——15/64 号也足够接近——为了准确定位孔位,最好在两端沿对角线画一条线,交点即为中心。接着,将孔螺纹化,使用 1/4 英寸-20 螺纹 tap,这样你就可以直接将外壳固定到 U 型支架上。由于薄 ABS 塑料的螺纹强度不高,请小心避免过度拧紧螺栓。

完成将支架安装到外壳上后,外观应与图 5-12 相符。

image

图 5-12:基本车库警卫的外壳可以通过支架安装,从而使其能够倾斜或旋转,将传感器指向正确的方向

焊接晶体管和限流电阻

在面包板上测试完电路并决定如何安装车库警卫后,将驱动晶体管和限流电阻焊接到一小块打孔的酚醛板或 FR-4 预钻孔板上。使用图 5-2 中的原理图或“面包板”中的说明,参考第 136 页作为焊接和布线元件的指南。

按照原理图进行连接,除此之外,组装打孔板没有对错之分。我推荐使用带有铜垫的打孔板,这样可以简化焊接。在尝试将板子安装到外壳内之前,先焊接好电源、可调电阻、Nano 板、超声波模块和 LED 的连接线。

完成焊接后,将打孔板安装在外壳中任何有足够空间的地方。我使用了双面泡沫胶粘剂,效果很好。接下来,安装 Nano 板、LED 和超声波模块。

连接各部分

最后,使用 30 号连接线根据图 5-2 中的原理图,将 Nano 板、超声波传感器、打孔板电路和 LED 连接起来。你也可以选择使用线绕线和线绕工具来连接各部分,但这不是必需的,如果你没有工具和线,可能会比较昂贵。连接组件并将其安装在外壳内可能会有些杂乱,但这样可以省去做外壳的步骤。

豪华车库守卫

就这样!或者说,这就完了吗?

我在车库里使用标准模型已经好几个月了;它能做到它应该做的事,并且做得很好。但是似乎少了点什么。当你到达车库里指定的位置时,警报会响起,但为什么不在你到达之前就给你一个小警告,这样你就可以在接近停靠点时慢下来呢?

这个设计的想法是让系统在停靠点的预设距离内发出警告,这样你就不需要突然停车了。增加两个 LED,让它们在不同距离时亮起,并不会增加太多的额外工作。图 5-13 展示了豪华车库守卫。

image

图 5-13:豪华车库守卫设置了三个阶段的警报

现在,让我们讨论如何组装豪华车库守卫。

豪华原理图

手工焊接标准版的所有组件非常繁琐。所以,在豪华版中,我开发了一个集成板(PCB),它可以容纳 LED、可调电阻、Nano 板、晶体管和限流电阻。增加 LED 和额外晶体管需要对电路做一些修改。图 5-14 展示了修改后的原理图。

请注意,这个电路是以发射极跟随器的方式驱动晶体管。因此,基极显示出较高的电阻,因此不需要在 Arduino 与 Q1 至 Q4 的电阻之间添加电阻。如果使用共射极驱动,则需要电阻,因为电流会流经基极-发射极结,导致驱动器短路并烧毁晶体管。

image

图 5-14:豪华原理图在右侧增加了 LED、驱动晶体管和限流电阻

注意

为了进一步改进车库哨兵,你也可以考虑使用特殊的换能器和电子设备将范围加倍或以其他方式增加,但在此应用中,10 英尺的工作范围已经足够。

豪华版草图

在构建豪华版车库哨兵之前,从本书的资源文件中下载 GarageSentryDeluxe.ino,并根据 “将草图上传到你的 Arduino” 中的说明,在 第 5 页 上传到你的 Arduino Nano。该草图与基本的车库哨兵草图基本相同,但已更新以包含新的 LED。

        /* Deluxe Garage Sentry: goes with the shield PCB      
       */  

        int ledPin = 8;  
        int ledPin1 = 7;  
        int ledPin2 = 10;  
        int ledPin3 = 9;  
        int count;  
        int analogPin = A0;  
        int val;  
        int y;  

        void setup() {  
          //Initialize serial communication:  
          Serial.begin(9600);  
          pinMode(ledPin, OUTPUT);  
          pinMode(ledPin1, OUTPUT);  
          pinMode(ledPin2,OUTPUT);  
          pinMode(ledPin3,OUTPUT);  
          pinMode(analogPin, INPUT);  
        }  

        void loop() {  
          val = analogRead(analogPin);  

          long duration, inches, cm;  

          pinMode(12, OUTPUT);  
          digitalWrite(12, LOW);  
          delayMicroseconds(2);  
          digitalWrite(12, HIGH);  
          delayMicroseconds(5);  
          digitalWrite(12, LOW);  

          pinMode(11, INPUT);   //Attached to ECHO  
          duration = pulseIn(11, HIGH);  

          //Convert the time into a distance  
          inches = microsecondsToInches(duration);  
          cm = microsecondsToCentimeters(duration);  

          val = map(val, 0, 1023, 0, 100);  
          //Map the value of the potentiometer to 0 to 100  

          if(inches == 0)  
            digitalWrite(ledPin, LOW);  

  ➊   if(count == 0  inches > 0  inches < val + 15)   
             digitalWrite(ledPin2, HIGH);  
          else digitalWrite(ledPin2, LOW);  

  ➋   if(count == 0  inches > 0  inches < val + 7.5)  
             digitalWrite(ledPin3, HIGH);  
          else digitalWrite(ledPin3, LOW);  

       if(count == 0  inches > 0  inches < val) {  
  ➌     for(y = 0; y < 200; y++) { //Repeating blink sequence  
           digitalWrite(ledPin, HIGH);  
           digitalWrite(ledPin1, LOW);  
           delay(100);  
           digitalWrite(ledPin, LOW);  
           digitalWrite(ledPin1, HIGH);  
           delay(100);  
        }  
        count = count + 1; //Turn off instruction  
      }  

            digitalWrite(ledPin1, LOW);  

         if(inches > 10) { //Reset if inches > 10  
              delay(1000);  
              count = 0;  
         }  

         Serial.print(inches);  
         Serial.print("   inches ");  
         Serial.print(count);  
         Serial.print(" count   ");  
         Serial.println();  
         Serial.print(" val       ");  
         Serial.println(val);  
         delay(100);  
      }  

      long microsecondsToInches(long microseconds) {  
          return microseconds / 74 / 2;      
      }  

      long microsecondsToCentimeters(long microseconds)         {        
          return microseconds / 29 / 2;  
      }  

豪华版草图和标准版草图的最显著区别在于,在 ➊ 和 ➋ 处的两个 if-else 语句中,绿色和琥珀色的 LED 在不同的距离处被激活,取决于停止点。例如,如果停止点设置为 36 英寸,或者草图中的 Val,那么绿色 LED 会在 VAL + 15,即 52 英寸时亮起,琥珀色 LED 会在 VAL + 7.5,即 43.5 英寸时亮起。这样,当汽车距离最终停止点 15 英寸时,绿色 LED 会亮起,而当汽车距离停止点 7.5 英寸时,琥珀色 LED 会亮起。这些数字是随意选择的,你可以更改它们。

当汽车到达停止点时,红色和蓝色的 LED 开始闪烁。你可以在 ➌ 处看到 LED 的闪烁方式。

豪华版屏蔽

图 5-15 显示了豪华版车库哨兵的屏蔽。如果你想制作这个屏蔽,下载本书的资源文件,找到文件 GarageSentryDeluxe.pcb,按照 “制作你自己的 PCB” 中的蚀刻说明,在 第 13 页 上操作,并将你的组件焊接到电路板上。你也可以将文件发送给服务机构,让他们为你制作电路板。

电位器直接焊接到屏蔽上,尽管你仍然需要将电线焊接到电源插口和超声波模块上。如图 5-15 所示,超声波传感器的连接位于左侧。

image

图 5-15:这是豪华版车库哨兵的屏蔽,它简化了早期版本中必须焊接的各个电线。

绿色 LED 位于最外侧,琥珀色 LED 紧随其后,闪烁的红色和蓝色 LED 位于中间。电位器的连接位于右下方,靠近前两个连接端口,分别是地线和 VIN(从左到右)。电位器帮助将屏蔽固定在外壳内。

这个版本使用了高功率 LED,这些 LED 需要相当大的电流。由于哨兵使用了 Nano 上的 5V 电压调节器,驱动 LED 的晶体管直接与 9V 输入电压连接,这样该设备就不需要单独的电压调节器。LED 与驱动晶体管配置为发射极跟随器,因此 LED 的电压将“跟随”晶体管基极的电压——即 5V,而不会给 LED 提供 9V 电压。

这个扩展板上需要几个跳线,包括用于电源的跳线,它连接到晶体管的集电极并将原始输入连接到 Nano 的(VIN)端口。还需要跳线将地线连接到 LED。

我将晶体管和限流电阻器安装在 Nano 板下方以节省空间。另外,注意标准版中的超声波模块连接使用了一个直角女性头,而在豪华版中这样做会导致公头部分的长度挡住 LED,因此我直接将连接焊接到 PC 板和超声波模块上,以避免电线干扰。

更大的盒子

绿色和琥珀色 LED 作为一对工作,因此每对 LED 只需要一个驱动晶体管。但由于所有这些新的电路,豪华版的电路板不容易适应与标准版相同的外壳。

你需要为豪华版找到一个更大的外壳,这样可以带来一些额外的好处。使用更大且透明的聚碳酸酯外壳,比如 Hammond 1591 BTCL,LED 可以保持在外壳内并且仍然可见,这样你就不需要在 PC 板上钻孔来安装 LED。你只需要钻四个孔:两个大孔用于超声波传感器,一个孔用于电源插座,一个孔用于电位器。这些孔使得可以使用双面泡沫胶带将超声波传感器安装在 Nano 板上,并且 Nano 板又被安装到扩展板上(见图 5-16)。换句话说,你需要将 Nano 板夹在中间,底部是扩展板,顶部是超声波模块。这个设计消除了第一版中使用的安装螺丝的需要。

image

图 5-16:与基本版的车库哨兵相比,豪华版几乎没有手工接线。驱动 LED 的晶体管和限流电阻器位于 Nano 板下方

只需使用标准版中使用的相同模板,钻(和/或扩孔)两个 5/8 英寸的孔用于两个超声波元件。屏蔽本身可以用小型平头螺钉和螺母或更多的双面泡沫胶带固定到底部。当你将电位器固定在外壳上时,它应该会把电路板固定到位,因为它的引脚已经焊接到屏蔽上。图 5-16 显示了豪华版;请注意它比图 5-8 中的基础版要整洁得多。

在为电位器钻孔之前,仔细测量电位器孔的高度,并稍微钻一个较大的孔,以便轴和螺丝可以以角度插入外壳。你还会注意到,在图 5-16 中,印刷电路板的角落已经被剪去,以免妨碍外壳顶部螺丝使用的螺柱。

我建议将电源连接安装在与电位器相同的外壳表面——即底部。在这里,电源连接和电位器在安装后可以方便接触,而顶部可以紧密贴合在架子上。该单元也可以轻松地倒置安装,将调整和电源插孔置于顶部。

图 5-17 显示了安装在我车库工作台上的完成版豪华车库哨兵,车子已经到位。

image

图 5-17:安装在我车库工作台上的完成版豪华车库哨兵,车子已经到位

完整的哨兵单元运行完美无缺。根据你特定的车库以及单元放置的位置,你可能需要调整草图,使得绿色和琥珀色的灯在不同的距离上亮起。图片中的单元已经完美运行了近六个月,我简直无法想象没有它,我怎么把车开进车库。

第七章:电池保护器

image

这个项目实际上起源于 1970 年代,当时我第一次制作了一个非常类似的装置。其目的是在电池因不经意的电量消耗而导致车辆无法启动时,切断车辆的电池。在计算机化汽车出现之前,驾驶员常常会停车并忘记关灯,结果回来时发现电池没电。那时,他们必须找到办法呼叫服务站(因为没有手机),并启动电池。更糟的是,如果电池死掉且车辆放置时间过长,电池就会变得无法使用,必须更换。在 12 到 18 小时之间处于放电状态后,大多数铅酸电池会完全放电,无法恢复。

但那是过去的事了。现在,许多车辆,尤其是配备了自动照明系统的车辆,已经通过自动(通常是延迟)断电功能来防止这种不便情况的发生。然而,仍有几种类型的车辆没有自动关机系统或报警装置来提醒你灯光还开着。这个项目,如图 6-1 所示,对于这些车辆特别有用。

image

图 6-1:完成的电池保护器,包装好准备使用(上),以及内部构造(下)

船只、拖拉机和其他车辆

许多适合上路的车辆都能从电池保护器中受益,但这个项目主要面向那些电池意外放电可能带来麻烦且昂贵的系统。船只尤为容易受到影响。即使是我的小型跑船也遇到过类似问题。曾多次在白天忘记关掉导航灯,直到几天后才发现。电池完全没电,必须更换。

留下导航灯开着并不是唯一一种会意外耗尽船只电池的方式。大多数内舱船只都配备有排气系统,用于安全地排出可能爆炸的气体和燃油蒸气。常识(以及海岸警卫队)建议,在启动引擎前保持排气扇运转,船只运行时一直开着,并且至少在关闭引擎后再运行 10 分钟。很容易忘记排气扇还在开着,结果下次使用船只时发现需要更换电池。

注意

在为像船只排气扇这样的安全系统构建电池保护器之前,请阅读《注意事项》中的内容,见第 158 页。有一些需要注意的事项,可能会要求对电气系统做一些小的布线更改

船只并不是唯一易受影响的车辆。骑行割草机和拖拉机也有三种原因容易面临风险:

• 它们通常只是间歇性使用。

• 停车和/或前照灯开关通常放置在容易碰撞到的位置,尤其是在上下车时。开关也可能会被飞溅的碎片或崎岖的地面损坏。

• 它们通常在白天使用,因此有时很难判断灯光是否开启。

电池节能器还可以保护电动工具,如拖车喷雾器。使用这些工具后,容易忘记关掉它们,尽管大多数喷雾泵的电流消耗不大,但如果让它们开着一整天或两天,电池很可能会耗尽。

所需工具

电钻和钻头

中心冲

4-40 螺纹攻丝

锯条

400 目砂纸

沉头钻(几乎任何 82°的沉头钻都可以使用。被加工的材料相对较软,因此不需要特殊的材料。)

针形锉(参见图 6-20。虽然只需要一把,但通常它们是成套出售的。)

三角锉

注意事项

如果你按照本章所述制作电池节能器,它应该能够正常工作。然而,仍然有可能发生墨菲定律带来的问题,因此在制作之前,请考虑以下几点。

如果电池节能器发生故障,可以进行重置,但在此期间,它将切断车辆电气系统的所有电源。不要将电池节能器用于任何电气故障可能导致灾难性后果的系统(如飞机上),或可能导致人身伤害或财产损失的系统。话虽如此,我已经在一辆汽车、三台农业拖拉机和两艘船上使用了这个设备超过一年(以及更早版本使用了好几年),没有发生过任何故障。

电池节能器包含一个非常高电流的开关。在某些条件下,可能会产生一定的电阻,当电流流过时,开关可能会变得非常热——甚至可能会热到成为火灾隐患。(值得一提的是,即便是原型版本,也从未发生过这种情况。)我们已经尽一切努力消除类似问题——例如,电池节能器铜触点所用的模块是由耐火和耐熔的酚醛材料制成的——但过热仍然是一个潜在的危险。在触碰电池节能器之前,请始终检查它的温度,确保它不热到足以烫伤你。如果车辆或电池节能器出现故障,重置按钮也可能变得足够温热以致烫伤。

最后的这一条警告专门针对船员。如果你将船停在水中,它很可能配备了内置的舱底泵和自动浮漂开关,以确保在你不在船上的时候船能保持浮力。如果你有多个电池,请确保舱底泵接到与电池节能器电路无关的电池上,如图 6-2 所示。否则,找到为舱底泵/开关供电的电线,并简单地绕过电池节能器。

image

图 6-2:船上电池节能器的接线

零件清单

这个零件清单看起来可能有点像寻宝游戏,但所有东西都可以从各种来源轻松找到。然而,获取特定尺寸或数量可能会有些困难,因此在开始之前,仔细阅读清单,确保你拥有所有物品。在购物前,还请查看图 6-13 以及第 170 页,看看一些不常见的零件,比如铜触点。

一块 Deek-Robot Pro Mini Arduino 克隆微控制器板(有几种不同的版本,其中一些有不同的引脚排列,特别是 A4 和 A5 引脚)

图 6-3 显示了我使用的引脚排列。其他具有不同引脚排列的设备应该也能工作,但需要更改扩展板上的连接。)

一个 LM7805 电压调节器

12V 电磁铁(此项目使用的是 Electronic Goldmine G19852。)

一个 10 千欧的电阻

一个 5.6 千欧的电阻

一个 4.7 千欧的电阻

一个 470 欧的电阻

一个 4.7V 的齐纳二极管

一个 1N4002 二极管或等效品

两个 ZTX649 晶体管

一块 1/2 英寸的酚醛板

一根 6×3/4×3/16 英寸的铜条,是高电流开关的一部分(这实际上是一块常用于大型电气安装的铜母线。请参见图 6-4 的示例。要找到这个,你可能需要通过在线搜索铜母线进行一些挖掘。我买了一根长 3 英尺的铜条。)

image

图 6-3:Deek-Robot Pro Mini Arduino 克隆的引脚排列

image

图 6-4:用于电池节能器的铜母线

一个 ABS 塑料外壳,类似于 Hammond 1591 STCL

两个 1/4 英寸的黄铜圆棒(你将使用其中一个作为支柱。)

一小块金属片,用作释放部件

一个 e 型卡环

四个 1/2 英寸、4-40 型号的平头螺丝

一个 3/8 英寸、4-40 型号的圆头螺丝

3 盎司的 Permatex 硅胶 RTV 密封剂

一对匹配的内联连接器(你可以在线购买简单、便宜的内联连接器,或者自己制作。我使用了 Pololu 的 1×2 连接器外壳和男、女性压接针脚,如图 6-5 所示。请参阅《本书中使用的连接器》部分,在第 18 页了解压接技巧。如果能找到电话式的“小鸡头”连接器,也可以使用。)

image

图 6-5:用于连接电磁铁的配对连接器

28 号连接线

一个焊接端子(如果找不到,你可以绕过它,方法是将 Arduino 的电源线缠绕在螺钉的头部,如图 6-7 所示。)

一条电池电缆,一端适配你的储电池,另一端有接线端子用于连接电池节能器

下载

草图 BatterySaver.ino

模板 ReleaseLever.pdf, BatterySaverEnclosure.pdf

扩展板 BatterySaver.pcb

电路图

尽管电路相对简单,如图 6-6 所示,但有几个关键设计元素需要注意。

image

图 6-6:电池保护器的原理图

请注意,电路使用了 LM7805 稳压器。理论上,Pro Mini 板上包含的小型稳压器应该足够,因为负载相对较轻。但是在汽车引擎盖下以及高电流系统和高压电子设备周围,存在大量的杂散电磁能量。虽然这种能量不太可能对电池保护装置造成问题,但这种情况完全有可能发生。更为强大的 1.5A LM7805 稳压器为 Pro Mini 提供了额外的保护。此外,还包括了电容 C1 和 C2,用于旁路进入电路的交流信号,并防止不必要的振荡。同样,4.7V 稳压二极管(D1)保护 Arduino 输入免受 12V 电源电压尖峰的影响,这种尖峰非常可能发生。它将 A0 的电压限制为 4.7V。

电阻 R1 和 R2 的配置可能在其他项目中也很熟悉。它们构成了一个电压分压器,将 12V 电源降低到 Arduino 输入能够承受的 5V 最大值以下。为了安全起见,我选择了 R1 为 10 千欧,R2 为 5.6 千欧,这两个值都是标准值。这个设计应该允许电池电压在达到稳压二极管启动的点之前,跳升到 14V。

二极管 D2(1N4002 或等效型号)提供了另一个保护层级:它保护免受反向电流的影响,这种电流可能在电磁线圈的磁场坍塌时产生。这是铁芯电感器中的标准保护装置,它能够储存磁能并迅速将其释放到线圈中。反向电压可能达到相对较高的水平,并产生显著的电流,这可能会损坏驱动晶体管及系统中的其他组件。

晶体管 Q1 和 Q2 都是 ZTX649 硅 NPN 晶体管。我选择这些晶体管是因为它们具有足够的驱动能力,并且价格低廉且容易获取。我在其他项目中也使用了相同的型号。Q2 的高端连接到红色正极轨(VCC),因为 LM7805 稳压器提供了足够的电流。(你也可以将 Q2 的高端或集电极连接到 12V 电源,因为 Q2 是按发射极跟随器接线的,发射极的电压将只跟随基极电压。)R4 是一个 470 欧姆电阻,限制 LED1 的电流。

LED1 指示装置是否在运行。包含 Q2 和 LED1 的电路提供了一个短周期闪烁的 LED,这与本章目标一致,即尽可能频繁地闪烁 LED。

注意

Deek-Robot Pro Mini 还配备一个红色 LED,指示其是否打开。这个附加的小的常态电流消耗可能会对电池的放电产生影响。在我安装的设备中,我将 Pro Mini 的 LED 的一端焊接了,这是一项相对精细的操作

晶体管 Q1 以共发射电路的方式提供驱动电流给电磁铁。电阻 R3(4.7 千欧姆)驱动晶体管并起到保护作用——如果直接连接,基极-发射极结将会通过过多电流,可能导致损坏。电磁铁的高端连接到正 12V,以允许最大电压和电流流过电磁铁线圈,而不会对电压调节器造成负担。

电池保护器如何防止电池过度放电

电池保护器包括一个能够断开电流的高电流开关和一个传感器电路,用于检测电池是否面临耗尽的风险。高电流开关是必需的,因为它会中断电池的主电源,其中包括给启动电机供电的部分,启动电机可能会消耗数百安培的电流。

高电流开关——也可以认为是一个继电器——由三块铜母排组成:一个释放条,一个电磁铁和一个释放杠杆。当铜母排连接时,电池与其电路正常连接。当电磁铁被吸入时,电源被断开。

传感器电路使用 Arduino 微控制器的电力。Arduino 不断监控电池,如果它检测到电力正在减少,它会触发高电流开关(继电器)。有许多方法可以判断电池是否快耗尽,这个项目简单地查看电池中的剩余电压。表 6-1 显示了标准 12V 铅酸蓄电池的电压与剩余电量之间的关系。

表 6-1: 电池充电状态与电压的关系

电池充电水平 电池电压
100% 12.7V
90% 12.5V
80% 12.4V
70% 12.3V
60% 12.2V
50% 12.1V
40% 11.9V
30% 11.8V
20% 11.6V
<10% 11.3V

电池电量迅速下降,但电压仅有最小的减少。为了确保电池至少剩余 40%到 50%的电量,必须在 11.9V 到 12.2V 之间某个位置停止电池的耗电(如表 6-1 所示),我以后将这个电压称为触发点。在实际应用中,经验数据显示,即使电池电压降至 12.0V、11.90V,甚至更低,仍然有足够的电量。一块处于良好状态的电池,在理想情况下可能会以不到 30%容量的电量运行,但这取决于负载、环境温度等因素,因此我持一个非常保守的看法,认为 12V 以上是合理的。新设计的电池通常表现更好。

虽然电量状态是电池剩余容量的良好指示,但其他因素——如内阻、电池放电速率等——也可能影响电池剩余的可用电量。更准确的电池剩余容量测量方法可能是当前使用的电流,如果已知电池中的总能量,就可以计算。例如,如果电池的容量为 1100 安培小时(A·h),你可以计算出剩余 550 A·h 并在此时断开电池。但是,由于这个项目针对的系统电池容量差异很大,因此我决定通过测量电池电压来满足需求,足以满足项目需求。

Arduino 来拯救

Arduino 微控制器负责测量电池电压,并在适当的电压下触发断电开关,但如果它只做这些,可能会出问题。启动车辆时,启动电机会消耗大量电流。根据电池的状态(如内阻等)和环境条件(例如温度),在启动过程中,电池电压可能会跌破关键的关机电压。电池节能器依赖 Arduino 给车辆足够的时间来启动电机。

此外,如果系统因意外耗电而关机,你需要确保在重置电池节能器时,它不会立即检测到电池电压临界值并再次关机。所有这些功能都由微控制器根据程序指令来处理。虽然可能有多种不同的处理方式,但该程序实现了时间序列——即在某些情况下采取特定行动的规则——以便在发动机启动时电压下降时使用。类似的时间规则也为用户在重置电池节能器后重新启动发动机提供了时间。

面包板

尽管这个项目不需要很多额外的组件和外围设备,我仍然认为通过面包板接线的练习是有用的。一个工作原型可以为概念提供明确的证明,并且让你在最终版本完成之前,先体验硬件和软件。与面包板一起工作时,我测试了与成品中使用的电磁铁类似的电路(参见图 6-7)。

image

图 6-7:我用来测试电池节能器概念并组装软件的面包板。使用电磁铁测试电路不是必需的

图 6-8 显示了面包板操作高电流开关的示意图;“构建”在第 170 页描述了如何构建这个开关。若不先构建高电流开关进行电路测试,或者仅使用电磁铁(参见图 6-7),你可以将灯泡、LED、继电器或其他元件替代开关进行连接。记住:如果使用 LED 或其他极性元件,确保正确连接极性。

image

图 6-8:高电流开关组装完成后,面包板电路操作电磁铁的示意图。请注意使用夹线将电池节能器连接到面包板。二极管 D1 和 D2 以及电容 C1 和 C2 没有包含在面包板中,主要是因为它们只在项目使用时才需要

基本的面包板连接非常简单。只需按照以下说明组装:

  1. 将面包板上的红色正极轨连接在一起,并将蓝色负极轨连接在一起。不要将正极轨与负极轨连接,因为那样会导致直接短路。

  2. 插入 LM7805 电压调节器,使三个引脚跨越三行不同的排针。(参见“原理图”在第 160 页,了解为何使用外部电压调节器,而不是 Pro Mini 板载的调节器。)

  3. 将调节器的输入端连接到正 12V 电源。(参见图 6-9,了解 LM7805 的引脚图。)

    image

    图 6-9:LM7805 调节器的引脚图

  4. 将调节器的中间引脚连接到蓝色负极轨,将输出引脚连接到红色正极轨。当你为电路供电时,正极轨应从调节器的输出端获得 5V 电压。

  5. 将 Pro Mini 微控制器板插入面包板。其位置并不关键;放在图 6-7 所示位置附近的任何地方都可以。

  6. 将电阻 R1(10 千欧姆)和 R2(5.6 千欧姆)插入面包板。最方便的做法是将它们插入靠近稳压器的地方。然后,将 R1 的一端直接连接到稳压器(输入引脚)。R1 和 R2 的连接点应该位于板上的独立位置,R2 的另一端直接接地。

  7. 将跳线从 R1 和 R2 的连接点连接到 Pro Mini 的 A0 引脚。

  8. 将晶体管 Q1(ZTX649)插入面包板,在有三个开放排的区域(请参见图 6-10 了解引脚排列)。

  9. 将电阻 R3 从 Q1 的基极连接到 Pro Mini 的 D9 引脚。

  10. 将 Q1 的发射极连接到地面。

  11. 将 Q1 的集电极连接到负载(电磁铁或其他)。

  12. 将负载的另一端连接到 12V 正电源。

  13. 将晶体管 Q2 插入面包板,并将其集电极连接到红色正电源轨道之一。

  14. 将 Q2 的基极连接到 Pro Mini 的 D12 引脚。

  15. 将 Q2 的发射极连接到 LED1 的正极。

  16. 将 LED1 的负极连接到 R4(470 欧姆)。

  17. 将 R4 的另一端直接连接到蓝色负电源轨道。

  18. 将 12V 电源的负极连接到蓝色负电源轨道。

现在,将草图加载到 Pro Mini 上(请参见“连接和编程 Arduino Pro Mini”第 8 页),并进行测试。如果你有带电压读数的可调电源,设置电压会很简单;如果没有可调电源,我建议你参考第三章中的“稳压电源”进行构建。如果你使用没有读数的可调电源,只需使用万用表来监控电压,并观察触发点。

将电源开启到 13V(对于充满电的 12V 铅酸蓄电池,12.7V 是正常值),此时监控 LED 应缓慢闪烁。逐渐降低电压,记下从慢闪到快闪的电压。该电压即为触发点,应该在 11.9V 到 12V 之间。

image

图 6-10:ZTX649 晶体管引脚图

草图

在开发电池节能草图时,我经历了几个迭代过程,以确保其可靠的功能性。一个难点是避免当引擎或附件(如液压倾斜装置)启动时,由于电压波动而产生误触发。

我使用了函数来调整不同的操作序列,这些操作序列独立于主程序运行。这并不是一个复杂的草图,但编写简单的函数是一种有用的技巧,当你想避免重复代码时特别有效。我本可以在最终草图中避免使用函数,但我让它们保留了下来,因为它们工作得很好,而且这种写法也为我提供了关于使用函数的好经验。

/*The Battery Saver sketch, which uses multiple functions
  to create timing sequences */

int led = 12;
int Battin = A0;
int Relay = 9;
int volts = 0;
int volts2 = 0;
int volts3 = 0;
int B = 387;    //Threshold trigger set point

void timer3() { //Shut off timer function
  delay(200);
  volts = analogRead(Battin); //Reset trigger point
  volts3 = map(volts, 0, 1023, 0, 500);
  if(volts3 > B) {
    digitalWrite(Relay, LOW);
  }
  else {
    digitalWrite(Relay, HIGH);
  }
}

void timer2() { //Fast blink timer function -- low voltage
  if(volts2 < B) {
    for(int j = 1; j < 1800; j++) {
      digitalWrite(led, HIGH);
      delay(10);
      digitalWrite(led, LOW);
      delay(90);
    }
  }
}

void timer() { //First timer function -- high voltage
  if(volts2 > B) {
    digitalWrite(led, HIGH);
    delay(200);
    digitalWrite(led, LOW);
    delay(1000);
  }
}
void setup() {
  Serial.begin(9600);
  pinMode(Relay, OUTPUT);
}
void loop() {
  delay(1000);
  volts = analogRead(Battin);
  volts2 = map(volts, 0, 1023, 0, 500);

  timer();
  if(volts2 < B) { //Set trigger point
    timer2();
  }
  if(volts2 < B) {
    timer3();
  }
}

在这个草图中,timer()timer2()timer3()是使用的三个函数。timer()函数用于在电池电压高于触发点时的正常操作。触发点是电池节能器进入超时模式并准备关闭的电压值。timer2()函数在达到触发阈值时启动一个快速闪烁序列,并提供超时前的定时——快速 LED 序列。一旦timer2()完成,若电压仍低于阈值,则调用timer3(),此时通过激活电磁阀切断电池。如果在超时期间,电压在任何时刻超过触发点,则在timer3()超时后,电池节能器会恢复正常操作。此草图中的许多变量也可以更改,以调整闪烁和延迟序列及阈值;这些内容在《操作电池节能器》中讨论,详见第 180 页。

扩展板

正如你从面包板上可以猜到的那样,扩展板也很简单。不过,与手工接线相比,我认为这样做更容易、更快捷。

PCB 布局

图 6-11 展示了我完成的 PCB, 图 6-12 展示了布局图,丝印显示了元件的位置。你可以在 www.nostarch.com/arduinoplayground/ 下载扩展板的 PCB 布局。

image

图 6-11:未安装元件的电池节能器电路板。RLY 连接处是你连接电磁阀的位置

image

图 6-12:电池节能器上扩展板的铜箔图案。丝印图像为灰色

大多数元件都放置在 Pro Mini 下方,以节省空间。除此之外,填充扩展板没有什么特别之处。与其他项目一样,并不需要为所有 Pro Mini 的引脚都配备排针。只需使用与板上走线连接的引脚,以及足够的其他引脚来增加机械稳定性。我通常会为第一个引脚使用至少一个排针,以便在插入时对齐电路板。

LED 可以直接安装在电路板上,也可以通过长线安装在远离电路板的位置。只需确保遵守极性。电池节能器可能位于操作员无法看到 LED 的位置,因此将其放置在远离电路板的地方是一个实际的解决方案。

准备扩展板和 Pro Mini 控制器

如果你想使用 PCB,可以根据本书提供的资源文件中的布局制作屏蔽层,无论是自己蚀刻还是将其交给专业制造。你也可以设计自己的屏蔽层 PCB,如果你有雄心壮志,或者仅仅是将所有组件焊接到原型板上,但如果你使用了零件清单中的其他所有部件,只需确保你的电路板与提供的屏蔽层布局尺寸相同。

如果你使用我提供的 PCB 设计,请接下来钻孔。我通常使用#66 钻头。将一根 2 英寸的电线焊接到屏蔽层的正 12V 端,并将电线的另一端焊接到一个小焊接端子。将一根 15 英寸的电线焊接到接地端子,然后将两根电线连接到电磁铁的连接端。我使用了一种小型内联连接器——由 Pololu #1950 压接连接器外壳、#1931 男型压接针脚和#1215 女型压接针脚制作——这样,如果需要的话,我可以轻松地拆下电路板。几乎任何连接器都可以使用。

两个晶体管位于屏蔽层下方,因此在焊接时,确保将它们按压到足够的位置,使其清除 Pro Mini 的底部。请参见图 6-11 和图 6-12 了解 PCB 上的晶体管放置位置。

我将监视 LED 直接焊接到电路板上,这样它可以通过外壳看到。不过,你也可以将电线焊接到电路板上,并将监视 LED 放置在一个可能更容易在车辆外部看到的位置。

构建

完成电池节能器的其余部分涉及一些机械挑战,并且需要一定的拾荒技巧。图 6-13 展示了电池节能器的所有组件布局。任何组件都不复杂。

image

图 6-13:电池节能器的组件,完全拆解。外壳的盖子位于透明盒子下方。请注意用于固定间隔器与电磁铁的短螺钉,以免损坏电磁铁线圈

电池节能器中只有少量组件:外壳、酚醛接触支撑、屏蔽层和 Pro Mini 控制器、铜接触组件、电磁铁和安装件、释放杠杆和支架、释放杆、弹簧和电子夹。以下的组装说明有些复杂,但如果卡住了,只需参考图 6-13,这样就能理清思路。完成后,电池节能器应该像图 6-14 一样。

image

图 6-14:完整的电池节能器,盖子已拆除,开关处于工作位置。在这一版本中,酚醛块上为正极和接地线刻有凹槽

准备外壳

因为外壳——Hammond 1591 STCL——是设计的一个重要部分,我建议从那里开始。除了外壳上加工的几个孔和槽口,几乎没有其他要做的工作。图 6-15 详细展示了我所切割的孔;一个模板包含在本项目的资源文件中。其实只需要切几个孔,因此,如果你仔细按照这些说明操作,应该不需要模板也能完成。

在外壳的长边上,从顶部大约量出 1 1/8 英寸的位置——这是重置活塞将要穿过的地方。这应该大致位于第四个安装肋的位置。在该肋的中心,钻两个 #30 的孔——大约 1/8 英寸——距离每个边缘 3/8 英寸,并且要将孔倒角,以便安装 4-40 的螺钉。两边都要做。

在每一侧,紧靠下一个肋的顶部(朝外壳顶部方向),切一个深度为 1 英寸的槽,用于放置铜触点组件。图 6-15 的侧视图中阴影部分显示了槽的切割位置。ABS 塑料外壳可以用钢锯轻松切割。去掉外壳盖,从外壳的开口向后切割。每个槽需要做两次切割,这样当你去掉它们之间的材料时,就能得到一个宽度为 3/16 英寸的通道。切割时,离开口大约 1 英寸就可以了,但不需要切到外壳的背面。你甚至可以同时切割两侧,只要确保通道正好位于对面即可。如果切割稍有偏差也不用担心,稍后可以用锉刀修正。完成切割后,取下中间的材料,并用小三角锉或平锉清理通道。

image

图 6-15:电池节能器外壳中的孔和槽

现在,在外壳顶部钻一个 1/4 英寸的孔,这是重置按钮的安装位置,正好位于顶部表面中心。按照图 6-15 中所示,从角落到角落画出对角线,然后在交点处钻孔。这个孔是安装重置活塞的黄铜释放杆的地方。

联系我们支持

接触支架可能是最容易制作的部分。首先,将酚醛片切割成 3×1 3/8 英寸的块。用钢锯轻松切割酚醛材料。将块插入外壳中,使得你通过肋条钻的两个孔位于块的中心。标记孔的位置,分别在两侧钻孔,使用#43 钻头,并为 4-40 螺钉攻丝。在制作酚醛接触支架时,你可以在两侧切割两个槽或通道,用于电源和接地线(稍后在图 6-18 中展示)。这个位置不太关键,因为这些槽仅用于放置屏蔽的正负电线。我使用图 6-16 中的小 Dremel 工具切割槽。每侧使用两个 4-40×3/8 英寸的平头螺钉将酚醛块固定到位。

image

图 6-16:带小圆锯片的 Dremel 工具

在酚醛接触支架固定到位后,将钻头尽量垂直地握住,定位于接触块最大面的中心位置。钻一个 1/4 英寸的孔,使其与之前在外壳顶部钻的 1/4 英寸孔对齐。最简单的方法是将接触支架固定好,然后使用外壳顶部的孔作为引导来钻接触块中的孔。钻孔后,将接触支架放在一旁,直到你准备好铜接触组件。

注意

外壳并不是一个完美的矩形,因为它包含了一些缓解区域,便于从模具中取出。钻孔对准中心孔时,需要考虑这一点。在我钻孔时,我将外壳固定在台钳中,以消除缓解区域的影响

准备铜接触组件

铜接触组件只需要几个孔。切割一段 4 3/4 英寸长的 3/16×3/4 英寸铜条,并按图 6-17 所示在 3/4 英寸尺寸的中心位置钻孔。

image

图 6-17:铜接触组件的基座,显示孔和间距

对于孔 A 和 G,使用 9/32 英寸的钻头。孔 B、C、E 和 F 应使用#30 钻头钻孔;确保它们被深度沉孔,以适应 4-40 平头螺钉。最后,使用 1/2 英寸的钻头钻孔 D。为孔 A 和 G 攻丝,使用 5/16×18×3/4 英寸的螺栓,这将用于固定电池电缆。

警告

虽然铜不硬,但它容易抓住钻头并沿着钻头攀爬。在钻孔时,始终将铜件夹在台钳中、夹具里或用钳子固定。绝不要用裸露的手持铜件

当七个孔都钻好后,将铜接触的底部放置在酚醛接触支撑上,使铜条中的 1/2 英寸中心孔尽可能精确地对准酚醛支撑中的 1/4 英寸中心孔,并且铜条在接触支撑的整个长度上居中。确保铜条两侧的距离相等,牢牢地将两件配件固定在一起,并标记 B、C、E 和 F 孔。用中心打孔器打出刚才标记的孔,在接触支撑上用#43 钻头钻孔,并攻丝为 4-40 螺丝,再次将接触支撑放到一边。

现在,标记铜接触的精确中心,中心应当恰好平分 1/2 英寸的孔。根据这个标记将铜条剪成两段;锯条应该能很好地完成这个工作。接着,用剩余的 3/16×3/4 英寸的铜条切割出一个 3/4×3/4 英寸的正方形,并通过从角到角画对角线来标记中心。在交点处居中打孔,钻一个 1/4 英寸的孔。这个铜方块将成为实际的接触部分。

铜接触组件中需要打的最后一个孔位于 E 和 F 孔之间,条形的外缘上;请查看图 6-18(已圈出),寻找从接触条上突出的小螺丝。钻一个#43 的孔并攻丝以适应 4-40 螺丝。这就是连接到 Pro Mini 的开关正电压的来源。图 6-18 显示了所有接触和安装硬件的钻孔情况。

image

图 6-18:准备组装的接触和支撑硬件

电磁铁的安装材料

根据你的电磁铁,安装过程可能会有所不同。我使用的电磁铁框架底部有两个孔,已攻丝适合 4-40 螺丝。然而,框架和线圈之间的空间非常狭窄,因此我决定寻找一种替代的安装方法——一种非常强力的双面胶。如果你还是希望用螺丝安装电磁铁,仔细判断螺丝的长度。无论采用哪种安装方式,电磁铁都没有足够的高度与释放机制对接,因此我不得不添加一个平台。

准备释放杆、弹簧和 E 型卡簧

和电池节能器的其他机械组件一样,重置接触的释放杆只需要一点点关爱。从一段 1/4 英寸的黄铜棒开始,将其切割成 4 1/4 英寸长。从一端量起 1 1/8 英寸,制作一个槽以便春季固定夹的安装,如图 6-19 所示。

为了切割槽口,我将条形件安装在电钻的夹头中,然后将电钻固定在工作台上,使用锯条小心地在材料上开槽,手指引导锯条。锯条的齿距有些宽,但槽口的深度,而不是宽度,才是最重要的。话虽如此,槽口不需要太深。我建议你逐步切割槽口,并不断试装保持夹子,直到它牢固地合适为止。

图 6-19 也展示了弹簧的配置。最底部的弹簧将放置在酚醛块上,直到释放杆被压下时,才会将铜触点从触点区推开。它的大小应足够小,以免碰到铜触点的两侧。(记住,方形触点的孔宽为 1/2 英寸,所以弹簧的大小需要小于此。)当释放杆被按下时,顶部弹簧会覆盖住下部弹簧,并保持开关的上半部分与下半部分牢固接触。你可以在小型磨床上微调弹簧长度,或者使用德美工具(Dremel)或手动磨石。

image

图 6-19:释放条的上半部分。条上有两个槽;下部槽是错误做成的。用于释放杆的弹簧是从 Ace Hardware 的标准弹簧套件中选出的,并裁剪到适合项目的大小。

现在,从同一端量取 4 英寸,并使用小针锉在 1/4 英寸的释放条下半部分锉出释放槽。图 6-20 展示了使用的针锉以及释放槽的形状。(你可能想先用锯子锯出槽口,然后用锉刀修整上面部分。)

image

图 6-20:释放杆底部释放槽的特写(上图),以及用来制作槽的针锉(下图)。

释放槽的形状并不十分关键,但确保上侧有轻微的倒角。你在轴上看到的漩涡是我用 400 目砂纸磨光杆子所留下的,以便它能平滑地滑过酚醛块、机壳中的孔以及触点件。

制作释放杆和塔架

释放杆由一小块轻型钢板制成,厚度大约为 0.060 英寸。使用图 6-21 中的图样切割杠杆。在本书的在线资源文件中,你可以找到杠杆模板的 PDF 文件。由于模板相当小,你可以尝试将模板粘贴到一块大小相似的空白材料上,夹住它(活络钳效果不错),然后在磨石上塑形。将模板粘贴到材料上后,你也可以使用锉刀来修整它。

image

图 6-21:释放杆模板

使用一把锡剪,我首先剪出一个矩形,然后剪出释放杠杆的形状。我将零件牢牢夹在台钳中,这样我就可以用锉刀完成它的成形。软钢用锉刀锉削时手感很好。(您也可以使用小型磨轮或带有磨砂轮的 Dremel 工具来塑形。)首先根据模板制作略大一些的零件,因为在最终组装时可能需要进行一些调整。杠杆应该受到弹簧的压力,并能牢固地固定释放杆,使得方形铜件紧密接触底部铜接触组件的两侧。杠杆上的两个铰链孔——一个用于连接电磁铁,另一个用于连接释放支柱——都用#30 号钻头打孔。

这个支柱用于将释放杠杆安装到外壳上,您可以使用任何手头有的废铜或铝材来制作支柱。图 6-22 中的支柱是用直径为 3/8 英寸的黄铜棒做成的。我缩小了顶部部分的直径,因为我不希望支柱与释放杆摩擦,但那可能并不是必需的。

image

图 6-22:释放杠杆、支柱和两个螺丝

将支柱切割到大约 0.61 英寸长,这样当它安装在外壳内部时,连接到释放杠杆的一端将刚好撞击释放杆的直径中心下方。这个尺寸取决于释放杆孔是否准确地钻到外壳顶部的中心。将释放杆穿过孔,测量它距离外壳背面的中心有多远。支柱应该比这个长度稍短一些。

您可以通过将支柱的顶部夹入钻机中,像钻头一样旋转并用锉刀修整它,使其变得更小。在最终组装电池节省器时,如果孔没有钻得完全垂直,您可能还需要稍微调整支柱的高度,以适应释放杠杆的厚度和释放杆的高度。

在支柱的中心附近钻一个#43 号大小的孔,贯穿支柱两侧,并从两面攻丝以适配 4-40 螺丝。一个螺丝将用于安装到外壳背面,另一个将固定释放杠杆。为了确保螺丝不会拧得太紧并卡住释放杠杆,我仅攻丝约 3/16 英寸,这样螺丝就会到底并卡住。图 6-23 展示了攻丝后的支柱样子。

image

图 6-23:支柱内部

您可以调整攻丝孔的长度或螺丝的长度,确保释放杠杆能自由移动但又稳固,用螺丝头作为支撑表面。为了固定释放杠杆的轴承螺丝和支柱安装螺丝,我建议使用厌氧胶粘剂(如 Loctite Threadlocker)来确保螺纹牢固。

组装所有零件

现在,我们准备将图 6-13 中的所有部分组合在一起,并将它们固定在适当的位置。组装顺序并不非常关键,更多的是依靠常识。我将逐步进行说明:

  1. 从将铜接触件拧入酚醛支架开始。确保螺钉头部低于铜的表面。这对于确保与接触条的良好接触至关重要。在组装之前,为了提高接触面积,我用 400 目砂纸打磨了铜接触件和接触帽。为了确保平整,我将砂纸放在平面上,并将铜件在上面摩擦。

  2. 将酚醛支架滑入外壳,并用四个 4-40×1/2 英寸的螺钉将其固定。

  3. 将释放杆穿过外壳,然后将其穿过压力弹簧,再穿过铜接触件,最后穿过释放弹簧并下穿酚醛基座。插入 E 型卡簧。这可能有些棘手,你需要用一把尖嘴钳固定卡簧。

  4. 测量塔柱的位置,并用 4-40×1/2 英寸的平头螺钉将其固定到外壳上。塔柱应该位于外壳内部,螺钉应从外部拧入。

  5. 将释放杠杆拧到塔柱上,并手动检查它是否与释放槽啮合,并固定释放杆。这有点棘手,可能需要通过打磨或修整释放杠杆来调整它,以适应释放杆的槽。一旦杠杆到位,你可以用手指操作它,确保它牢牢地锁定在释放杆槽中。

  6. 将垫片安装到电磁铁上。

  7. 临时将电磁铁安装到外壳上,并将释放杠杆固定到电磁铁上。为此,我首先将释放杠杆从塔柱上解开,并将另一端固定到电磁铁活塞上。接着,我在垫片底部贴上双面胶带,将所有部件调整到位,并将螺钉松动地放入释放杠杆,并拧入塔柱。

  8. 在保持电磁铁固定的位置的情况下,操作释放机制。一旦释放杆牢固地按下了顶部开关接触点,就标记电磁铁垫片的位置。

  9. 在外壳上钻孔并攻丝,以牢固地将电磁铁和垫片固定到外壳上。或者,也可以使用双面胶带(如 3M 户外双面胶带)将电磁铁固定。

  10. 将连接电磁铁到 Pro Mini 电路的电线从释放杆下方穿过,并使用连接器将其连接到电磁铁。

  11. 将 Pro Mini 电路的接地线从释放杆下方引出,并通过铜条的槽口开口穿出。(它是图 6-14 中从外壳左侧突出出来的黑色电线。)您可能需要在酚醛块上钻小孔给电线留出通道,或者使用 Dremel 工具和小圆锯片(如图 6-16 中所示)雕刻小槽来让电线通过。您也可以使用锉刀或钢锯锯条制作槽口。

  12. 将红色正电压线与接头连接到第 173 页中《准备铜接触组件》最后一个孔的铜开关极上。使用 4-40×3/8 英寸的圆头螺钉。

  13. 使用小间隔垫安装屏蔽板。如果找不到焊接接头,您可以先对电线进行焊锡处理,然后将其形成适合螺丝的形状,紧固螺丝。

将您的电池保护器与图 6-14 中的完成设备进行比较,以确保一切正常。当电池电压达到触发点时,Arduino 会触发电磁铁,从而释放杠杆。杠杆释放后,杆子从下弹簧的弹力中弹出。下弹簧将接触片保持在铜片上方,铜片被安装在酚醛块上,从而切断电路。要重置电池保护器,只需将杆子重新推下。进行最终测试之前,请多次检查释放杠杆和杆子的卡扣情况。

将电池保护器安装到车辆中

将电池保护器连接到车辆上只需要几分钟。首先,断开电池的正负极接头。然后,从电池的正极接一个短电池线到电池保护器的输入端。再将电池保护器的输出端连接到原先连接到电池的电缆上。将黑色电线连接到将要重新接回电池的负极端子。

安装整个外壳的方式将取决于您的车辆电池和/或电池箱的位置及安装方式。在许多情况下,电池保护器可以直接挂在电池电缆上。在其他应用中,我使用了重型电缆扎带,将其绕在整个电池和电池保护器周围,以固定位置。在某些情况下,双面魔术贴也能很好地起到固定作用。

操作电池保护器

在操作中,一旦电池保护器安装完成(见图 6-24),恢复电池的接地连接,并将该接地连接挂接到电池保护器。然后,通过按下重置按钮——也就是释放杆的顶部——来设置电池保护器,直到设备被激活。当您按下重置按钮并且释放杠杆卡住时,应该能听到或感觉到“咔哒”一声。

image

图 6-24:安装在我波士顿 Whaler 小艇上的电池节能器。电池连接到电池端子,并与电机及配件的正极连接。电池的地线穿过电池盒的背部。重置按钮非常容易接触到

正常操作

只要电池充满电并且电压高于阈值电压,"开"指示灯将以timer()函数中设定的速率闪烁,约每 2.2 秒闪烁一次。当电池电压低于阈值时,指示灯将开始快速闪烁。阈值电压大约设置在 11.9V,通过电路图中的可变B进行调整。当 LED 序列完成,即大约 3 分钟后,电压将再次被检查。如果电压仍然低于阈值,电池将被断开;否则,系统将恢复正常操作。

当你在电池节能模式关闭后重置它时,系统将恢复运行。重置后,如果电池电压高于阈值,指示灯将按照每 2.2 秒闪烁一次的正常速率闪烁。通常,当电池从某个放电水平移除负载后,电池会在相对较短的时间内自行恢复。然而,如果电压低于阈值,指示灯将按照超时周期快速闪烁,如前所述,以允许操作员启动船只、拖拉机或其他车辆。你可以通过更改timer2()函数中j的值来设置超时周期。

j变量的最大值在初始电路图中设置为 1,800,增减j的值将分别增加或减少 100 毫秒的总超时周期。因此,要将超时周期设置为 5 分钟,你可以将j的最大值设置为 3,000。

设置阈值电压

阈值电压由电阻 R1 和 R2 决定,分别为 10,000 欧姆和 5,600 欧姆(参见图 6-6 中的原理图)。它们被设置为电压分压器。根据电压分压计算,无论是使用计算器还是根据公式计算,12V 输入下的电压大约为 4.31V。因此,你可以通过设置阈值触发点,即电路图中的B,来计算你希望设备关闭电池电流时的确切阈值电压。虽然我计算了理论阈值,但通过实验我发现将B设置为 387 时,关闭电池电流的阈值大约为 11.9V。

电池类型

我通过几块电池和负载进行了实验,发现将B设置为 387 时,关机后电池至少还剩下一半电量,用于重新启动发动机。在几种不同的电池上,从便携式发电机的小电池到用于启动卡车的大容量电池,设置相同的值似乎都能很好地工作。

话虽如此,我对深循环电池了解甚少,知道它们具有非常不同的放电参数。如果你想尝试将电池节省器用于这类电池,请查看它们的放电速率和电压,并相应地调整阈值。

防护环境

不幸的是,电池节省器并不防水,而大多数应用场景要求它在某种程度上能够适应恶劣环境。然而,也有一些可能的解决方案。在各种车辆上,包括船只和拖拉机,我将设备包裹在塑料袋中,并将电缆进入和退出设备的地方用电缆扎带紧紧固定。

但那样看起来不太美观,我还因此受到了家族中女性成员的一些责备,于是我在所有铜条穿过的开口周围涂上了 Permatex 硅胶 RTV 密封剂——但不包括重置(黄铜)杆的穿过处——并封住了所有的螺丝。

对于重置按钮,我很难找到合适的保护套(你会对我在网上找到的东西感到惊讶),所以我最终用硅胶密封剂将一个滴眼液瓶的顶部固定在外壳上。这样也可以防止重置条——当按下时,带有 12V 电压——短路。

应用 Cool Amp

尽管铜对铜接触良好,我还是在组装前用非常细的砂纸(400 目)进行了打磨。即使未处理的接触点已在多个版本的电池节省器中使用且从未失败,但我决定在这一版本中使用 Cool Amp,这是一种易于使用的银镀合金。

通过非常低的成本,我成功地对接触条和接触板的接触区域进行了银镀,从而降低了它们的电阻。图 6-25 和 6-26 显示了未镀和镀银铜的差异。

image

图 6-25:电池节省器接触点在打磨后,但在使用 Cool Amp 处理前的状态

image

图 6-26:电池节省器接触点在使用 Cool Amp 银镀后的效果

尽管这种额外降低电阻的措施可能并非必要,但车辆的所有电流都必须通过这个接触点,因此我认为在安全方面多做一些准备并不会有坏处。此外,我在海洋环境中使用过电池节省器,接触点周围的铜部件已经获得了绿色的铜绿,而银镀部分则没有。

我已经在多个接触点上使用了 Cool Amp,从电动机启动接触点到重型继电器接触点,它的效果很好。你可以在www.coolamp.com/了解更多关于 Cool Amp 的信息。

注意

铜不会迅速氧化,铜的最常见氧化物具有高度的导电性,这也是铜常用于电流开关的原因之一。银具有相同的性质——只不过更好

我的原始想法

我持有一项美国专利(4,149,093,现已过期),该专利涉及与电池节能器类似的设备。专利图纸见于图 6-27。注意,即使是在几十年前制造的,它与这个项目的相似程度仍然很高。尽管当时还没有发明微控制器,它的功能基本相同!

image

图 6-27:电池节能器前身的专利图纸

第八章:定制 pH 测量仪

image

微控制器被广泛应用于许多,甚至大多数商业和科学仪器中。它们精确且多功能,使得它们成为解决各种测量需求的低成本方案。本项目将 Arduino 微控制器与商业探头和一些模拟电路结合,构建了一个精确的仪器来测量 pH,即溶液的相对酸性或碱性。

测量 pH 值的方法有三种基本方式。这个项目涉及使用 pH 测量仪和探头。其他方法包括石蕊试纸指示剂(你可能还记得它们在高中化学课上用过)和比色计,后者通常是游泳池维护工具包的一部分。比色计通常是一套化学试剂和比较色卡。在这三种方法中,pH 测量仪无疑是最准确的。

那么,pH 值到底测量的是什么呢?pH 值描述的是水溶液中氢离子的活性。氢离子的活性越高,溶液越酸性,pH 值越低。氢离子的活性较低(而氢氧根离子的活性较高)时,pH 值较高。

pH 值的刻度是对数的。每增加一个 pH 单位,代表氢离子活性在溶液中增加或减少十倍。这解释了为什么溶液的攻击性会随着 pH 值从中性点的距离迅速增加。

图 7-1 显示了完成的定制 pH 测量仪,如果你想知道为什么测量 pH 值是有用的,“为什么要测量 pH?” 在 第 187 页 提供了多个答案。

image

图 7-1:定制 pH 测量仪在实际测量环境中的应用

为什么要自己制作 pH 测量仪?

商业 pH 测量仪的价格从不到 $60 的低成本便携型设备到几百或几千美元的全功能实验室仪器不等。相对低成本的 pH 测量仪可以完成任务,但它们都有一些缺点,例如精度有限、使用寿命较短、校准问题和一致性问题。

还有许多 pH 测量仪套件可供选择,包括许多印刷电路板,有些是为 Arduino 设计的。(印刷电路板 是一块小电路板,包含执行某些功能所需的关键电路,但没有处理器。)我还没机会尝试这些套件,但它们通常比较昂贵,接近或超过 $100。而且它们仍然需要电源和包装。

虽然这个项目并未提议提供一款完整的实验室仪器,但它提供了一款不错、可用的 pH 测量仪,并且对 pH 测量仪的组成部分提供了很多有价值的见解。我已尽力调试电路以达到最佳性能,但你可能会觉得进一步的调整会有所帮助,所以如果你在查看电路后想尝试不同的方法,尽管去做吧。

为什么要测量 pH 值?

过去,pH 是一个相对晦涩的测量,局限于实验室工作台和工业环境(用于质量控制、过程控制、废水排放监测与控制等)。然而,越来越多的人开始在那些传统上依赖死记硬背或试错实验的方法的领域使用科学测量,比如家庭酿酒和啤酒酿造、水培、家庭农业、水养殖和烘焙。所有这些应用都能从精确的 pH 测量中受益,而且它们甚至不包括管理游泳池、锦鲤池、喷泉或水族馆化学成分这一更为平常的任务。

例如,在烘焙中,面团需要低 pH 才能发酵。食物的 pH 值也影响四种味觉中的两种:低 pH,或酸性食物往往味道酸,而较高 pH,或碱性食物则味道苦。柠檬汁是酸味的例子,西兰花或黑巧克力则可以视为苦味。在家庭园艺中,pH 是特定作物的重要土壤特性。简单调整 pH 可以使水族箱水清澈,并减少玻璃壁上的污垢沉积,而池塘中的平衡 pH 维持鱼类健康,并减少藻类生长。类似的例子还很多。

所需工具

焊接铁和焊料

电钻和钻头

锯孔锯

中心冲孔器

文件

2-56 螺纹刀

热风枪或吹风机(用于热缩管)

零件清单

构建定制 pH 计需要以下零件:

一个 Deek-Robot Pro Mini Arduino 克隆板(其他 Arduino 一般也适用于本项目,但不能与本书提供的屏蔽模板兼容。我在面包板上使用了一个 Arduino Nano 克隆板,因为它自带 USB 接口。在完成的设备中,我换用了 Pro Mini 以节省空间。)

一个 LM35(D)温度传感器

一个 Texas Instruments TL072 双运算放大器(引脚图见图 7-2)

image

图 7-2:TL072 引脚图

一个 10 转,1 兆欧 调节电位器(R7)

一个 10 转,10 千欧 调节电位器(R4)

一个 BNC 公头连接器

一个 LM7805 电压调节器

一个 LMC7660 电源逆变器(引脚图见图 7-3)

image

图 7-3:LMC7660 引脚图

一个 16×2 LCD 显示器

一个 I²C 适配器,如果 LCD 没有自带的话

一个 5.1V 稳压二极管

一个 1 μF 陶瓷电容(C2)

五个 0.1 μF 陶瓷电容(C1,C6,C7,C8,C9)

一个 0.01 μF 陶瓷电容(C5)

一个 22 μF 钽电容(C10)

两个 10 μF 钽电容(C3,C4)

一个 10 千欧,1/8 W 电阻(R5)

三个 10 千欧,1/8 W 电阻(R1,R2,R10)

两个 1 千欧,1/8 W 电阻(R8,R9)

一个 pH 探头

四个 4-40×1/2 英寸螺丝

八个 4-40 螺母和垫圈

四个 2-56×1/2 英寸螺丝

28 或 30 号导线

一个 Hammond 1591 BTCL 塑料外壳

热缩管

下载

草图   pHMeter.ino

封面模板   pHCover.pdf

侧面模板   pHBoxSide.pdf

屏蔽   pHMeter.pcb

关于 pH 探头

自定义 pH 测量仪的核心是 pH 探头。它测量溶液中氢离子的活性,从而决定该溶液的酸碱性。一个基本的 pH 探头,如图 7-4 所示,包含两个元件:参考电极和测量电极。我不会深入探讨探头的化学原理或 pH 探头的具体工作机制,但我会描述它的输出以及与电路的接口,电路提供显示读数。

pH 探头产生的电压与探头浸入溶液的 pH 值成正比。pH 范围从 0 开始,最酸性,到 14,最碱性。探头输出的电压大约在 -420mV 到 +420mV 之间,表示每个 pH 单位大约增量为 60mV。中性 pH 7.0 位于从 0 到 14 的中间值,表示为 0.0mV。

探头输出的特性使得本项目中的自定义 pH 测量仪的基本功能相对简单:它需要读取并显示电压。但自定义 pH 测量仪电路还需要考虑其他一些问题。首先,虽然商用探头是按照最高标准制造的,但它们可能存在一定的误差,需要调整。其次,我们处理的是相对较小的值,因此为了保持准确性,组件和电路必须精心挑选。此外,随着探头的使用和老化,它们通常会发生轻微变化,需要重新校准。

image

图 7-4:pH 探头的简化图

最后,pH 探头具有非常高的电阻值——可能是 10 到 100 兆欧姆或更高。从实际角度看,高电阻意味着尽管电压水平较高,但几乎没有能量能够改变其他设备的状态或条件,因此电路需要放大这个信号。这需要一个专门的输入电路,通常会涉及运算放大器(op-amp),其设计目的是在处理高阻抗信号时尽量减少噪声。今天的半导体技术已经能够满足这一需求,正如我在《集成电路选择的一些注意事项》中提到的,第 196 页里,我检查了几种运算放大器,找到了最适合性能与价格平衡的型号。当然,虽然选择一款好的运算放大器很重要,但输入电路同样需要尽可能高效,以便在不引入噪声的情况下,准确读取 pH 探头的敏感输出。

如何保养你的 pH 探头

虽然你的 pH 探头可能附带了使用说明书,但有一些方法可以延长其使用寿命。首先,当然,按照制造商的说明进行操作。其次,除非制造商另有说明,存储探头时,应将探头的工作端浸入 3 摩尔浓度的氯化钾(KCl)溶液中,如图 7-5 所示。你应该能在购买 pH 缓冲溶液的地方以相当低廉的价格购买到这种溶液。(缓冲溶液是由相对弱酸性和碱性化学物质混合而成的溶液,能保持特定的 pH 值。)你也可以通过将约 22 克 KCl 溶解在 100 毫升蒸馏水中来自制这种溶液。

image

图 7-5:我在本项目中使用的 pH 探头。探头尖端被浸泡在含有橡胶密封的 KCl 溶液的小瓶中

即使是相对较短的存储时间,最好将探头存放在 pH 7 缓冲溶液中,而不是在空气或水中。在每次样品之间,或将探头转移到不同的缓冲溶液时,务必小心冲洗探头。大多数制造商建议使用蒸馏水冲洗。你可以轻轻地将多余的水分拍掉,但大多数制造商警告不要擦拭或擦干电极球,以免由于极化效应而导致测量误差。

在测量之前对探头进行校准时,即便是顶级 pH 计的制造商也建议使用最接近预期样品 pH 值的缓冲溶液进行校准。例如,如果你怀疑样品的 pH 值约为 9,那么应使用 pH 10 的缓冲溶液来校准仪器。

原理图

图 7-6 和 图 7-7 所示的定制 pH 计电路包括一个双运算放大器、一个电压反转器(为运算放大器提供 ±5V 电压)、一个电压调节器、一个温度集成电路、一个 Arduino 和一个 I²C LCD 显示屏。你可以选择使用 Arduino Nano 或 Arduino Pro Mini 来构建你的定制 pH 计。我在使用 Nano 构建面包板时更为顺利,但我的最终产品(因此,本章节提供的扩展 PCB 文件)使用 Pro Mini 来节省空间。

本节的其余部分将介绍在设计此原理图时做出的决策及其背后的原因。

image

图 7-6:使用 Arduino Nano 的定制 pH 计基本原理图

image

图 7-7:使用 Deek-Robot Pro Mini 的定制 pH 计基本原理图

集成高阻抗探头

请记住,pH 探头输出的直流电压范围从–420mV 到+420mV,大约每个 pH 单位对应 60mV。此输出具有非常高的阻抗,电路必须接受探头的高阻抗输入而不引入杂散信号,降低阻抗到可管理的水平,并放大输入信号,以便 Arduino 的模拟输入能够读取。电路还必须提供一种方法来调整送往显示器的电压,以便在偏置和增益方面校准探头(请参见“偏置和增益”在第 194 页的快速教程)。

为了处理高阻抗探头输出,运算放大器的输入必须具有非常高的阻抗,通常在太赫(1×10¹²欧姆)范围内,才能读取任何电压。运算放大器的输入还必须具有低输入电流(这两者是相关的);通常约为 10 皮安(1×10^(−12)安培),尽管一些运算放大器的输入电流低于 25 飞安(1×10^(−15)安培)。如果运算放大器具有非常低的漂移(即在输入不变的情况下输出发生变化的倾向),那将是非常好的。

一般设计注意事项

定制 pH 计设计为使用 9V 电源,可以通过电源开关在电池和插入模块之间选择(请参见图 7-6 和图 7-7 中的原理图)。由于交流电源的输入可能不稳定,定制 pH 计使用外部电压调节器,而不是 Pro Mini 内建的调节器。一个 LM7805 电压调节器,输入和输出端都带有旁路电容器,在以前的项目中效果良好,本项目也使用了同样的调节器。该调节器为逆变器、运算放大器电路和 Arduino 提供+5V 电源。电源开关是一个三位置开关,中间是关闭位置,一个位置选择电池,另一个位置选择交流电源。

由于 pH 探头提供的输出为±420mV,因此该电路必须能够处理双极性(高于和低于地面)电压。实现这一点的最简单方法是使用一个具有正负电源和中间接地的运算放大器,这就需要一个能够提供这些电压的电源。LMC7660 电压逆变器是解决方案:它将来自电压调节器的+5V 转化为+5V 和–5V,并且中间有地面。这样,运算放大器就能处理输入信号,只要它不超过+5V 或低于–5V。

注意

大多数电压逆变器与 LMC7660 非常相似,且所需的外部组件最小—在这种情况下,仅需两个电容器。该电路使用钽电容器,因为它们体积小且可靠,但也可以使用电解电容器

偏置和增益

为了演示偏置和增益如何工作,图 7-8 展示了本项目中使用的电压范围,从–5V 到+5V。

image

图 7-8:改变增益和偏移量时自定义 pH 计中电压变化的示意图

想象一下,当 pH 探头的电压被放大时,会有一个电压范围 A。在这个示例中,电压 A 代表供电电压的一半,范围从–2.5V 到+2.5V,总共是 5V。如果增益被调整,电压范围仍然会以 0V 为中心,但会增加或减少到某个电压范围 B。调整增益时,所选电压范围的最低和最高端将始终以相同的幅度增加或减少,前提是原始电压范围在总电压范围内。

通过调整偏移量,整个电压范围也可以在连续体内移动,如图 7-8 所示。电压范围 A2 仍然包含与范围 A 相同的总电压,但其最小电压和最大电压不同。在这种情况下,电压范围的中心从 0V 移动到 2.5V,使得电压 A2 的范围从 0V 到 5V。

这个偏移量可以是供电范围内的任何电压,但实际上最好不要将电压推到电压轨(即供电电压的最大值和最小值)。相反,应在电压轨和项目所需的电压范围之间留出一些缓冲区。

“电路图”在第 205 页中显示,自定义 pH 计将电压映射到 Pro Mini 的供电限制内(0V 到+5V),并使其成为所选增益的平均值。本项目的最终增益和偏移调整是通过使用预先准备的缓冲溶液和电路中的电位器来完成的。

自定义 pH 计使用 Deek-Robot Pro Mini Arduino 克隆板,因为该克隆板体积小且价格便宜;不过,如果自己制作印刷电路板,Nano 也可以使用。虽然 Pro Mini 没有 USB 接口,但有多种方式可以轻松地对其进行编程。如果你以前从未使用过这款 Arduino,请参阅第 8 页的“连接和编程 Arduino Pro Mini”章节。

显示器的 I²C 接口仅包括两根线——时钟和数据,此外还有电源和接地。如果需要,I²C 协议也可以与多个 I²C 设备同时使用。

运算放大器电路详细介绍

在运算放大器电路中,使用了电阻和电容来最小化杂散信号的影响,并对电路进行耦合。放大电路有两个阶段,两个阶段都包含在运算放大器的单一封装中:第一个阶段处理来自探头的高阻抗并提供增益调整,第二个阶段是缓冲器,提供偏移量,既用于校准,也为了适应 Arduino 所需的 0 到+5V 模拟输入。每个阶段都有一个 10 转的调整电位器。第一个阶段的电位器为 1 兆欧,它设置增益;缓冲阶段的电位器为 10 千欧,用于调整偏移量。

第一级提供了大部分增益(输出大约是输入的六倍),增益可以通过一个负反馈电阻(R2)和一个电位器(R3)进行调节。调整范围比实际需要的稍宽,但效果还是很好。最初,我对范围进行了收紧,但发现对于某些探头来说,较小的范围会使校准变得困难。

第二级运算放大器电路使用了一个固定的反馈电阻(R5),值为 10 千欧,而非反相输入使用了两个 10 千欧电阻(R1 和 R2)和一个 10 千欧的可调电位器(R4)来提供偏移调节。该阶段除了提供偏移调节外,还提供了少量增益,使得 pH 探头电压能够集中在 0mV(pH 为 7)并在–420mV(pH 为 0)和+420mV(pH 为 14)之间波动。此外,该缓冲阶段将电压范围从正负电压转换为仅正电压,供 Arduino 使用。

使用缓冲阶段同时提供校准偏移和转换正负电压范围是非常方便的,几乎没有什么明显的缺点。可选择生成单独的参考电压,但这会增加额外的组件,并且相比于从缓冲阶段偏移电压并将电压参考接地,几乎没有优势。

在缓冲器的输出端,添加了一个齐纳二极管(D1)和电阻(R9)来保护 Pro Mini 免受过电压影响。没有添加保护来防止负电压对模拟输入引脚的影响;然而,在初始设置和实验过程中,模拟引脚多次意外接收到负电压,但没有出现不良反应。

一些关于 IC 选择的说明

在为任何项目选择集成电路(IC)之前,最好测试多个 IC,以查看哪个最适合你的情况。在采样芯片时,我建议记录每个芯片的优缺点。例如,这些是我对定制 pH 计的运算放大器选择的记录:

TL072   表现良好;是一个不错的全能解决方案

TLC2262   一个不错的全能解决方案;和 TL072 之间难以抉择

OPA129   表现良好,但没有 DIP 封装

LMC6001   表现良好,但没有优势,价格有点贵,大约 20 美元

LMC6042   可能会有效,但设置起来较为困难

LMP7702   可能会有效,但价格有点贵,且设置起来较为困难

在尝试了多个公共领域的运算放大器电路并且大多结果令人失望之后,我使用了一个通用电路逐一测试这些运算放大器,并且每次测试都需要对电路进行一定的调整。调节包括改变电路以稳定增益并最小化杂散信号和杂散电压。德州仪器的 TL072P 运算放大器证明是最佳选择,一旦我做出了这个选择,我进一步调整了电路以优化定制 pH 计。TLC2262 也会表现得很好,我在一些原型样品中使用过它。

我试用的其他运算放大器可能也能发挥作用,或者在像 TL072 那样优化后,几乎能达到相同效果;然而,这样做会非常耗时,而所得增益则微乎其微,甚至为零。最终定制的 pH 计电路是在自我设限下的最佳努力,例如预算。例如,一款顶级运算放大器,如德州仪器的 OPA627/637,可能会很好地工作,但仅芯片的价格在 25 美元到 50 美元之间,具体取决于版本。这将使项目的总预算超过 100 美元,超出了自设的预算限制。继续进行该项目本身就已经很有问题,因为探头的成本(在写作时为 36 美元);然而,我相信探头的性能是值得花费这笔钱的。

准备 LCD

在你将电路搭建在面包板上之前,确保 LCD 已经准备好进行原型制作。尽管本项目使用的 LCD 可以与 I²C 适配器板一起购买,但我经常需要将 LCD 和适配器板分开购买,就像这次一样。当你单独购买时,适配器板通常会带有插针,您只需将它们插入显示器并进行焊接即可。 “将 I²C 板固定到 LCD 上”在第 3 页中描述了这个过程。

关于 LCD 背光

当我最初将 I²C 板连接到定制 pH 计的显示板时,我切除了显示板上的阴极(K)插针。阳极和阴极插针可以为显示器的背光提供电压。切断连接的想法是加入一个单独的开关来控制背光的开关,以节省电池电流。结果发现,显示器在没有背光的情况下几乎无法读取,除非在极其明亮的光线下,因此我放弃了这个想法,并手动重新接线了背光。你可以尝试使用其他显示器,看看是否能找到一种适合环境光下阅读的显示器。

面包板

像我大多数 Arduino 项目一样,定制 pH 计项目从面包板开始(见图 7-9)。尽管外观有些凌乱,但面包板版本运行良好。

image

图 7-9:这块面包板上的电路作为定制 pH 计的概念验证原型。

除了基本的定制 pH 计电路外,我还在面包板的左上区域(在图 7-9 中可见)增加了一个单独的电路,以提供一个连续的、可变的±500mV 测试电压,这样我就可以在使用探头之前检查电路并进行一些初步的校准。这个测试电路,如图 7-10 所示,由一个独立的电压逆变器、一对电压分压器和一个调节电压的电位器组成。你可能希望将这个小电路设置在一个单独的面包板上,并用它来对完成的单元进行初步调整。

image

图 7-10:此电路为定制 pH 计提供了测试电压

在图 7-9 中,pH 探头被一个廉价的滴定管夹固定在一个旧的机床磁性量规支架上。探头太细,无法直接安装在支架上,因此我在探头周围包裹了一些泡沫来夹紧它。

准备这个面包板比平常更加凌乱和复杂,因为面包板上有很多元件。如图 7-9 所示,我使用了一个包含四个垂直面包板和一个位于顶部用于正负轨道的条形面包板的大型面包板。最初,我使用了一个 Arduino Nano 克隆板在面包板上构建定制 pH 计。然而,在完成的版本中,我建议使用 Deek-Robot Pro Mini 板,以减少尺寸。两款 Arduino 都使用相同的 5V、16 MHz 的 Atmel 328 处理器及其他组件。为了满足与运算放大器输入连接尽可能短的要求,BNC 连接器被设置在能够提供相对直接连接到运算放大器的非反向输入的位置。电压调节器 LM7805 位于面包板的右上方,并通过 9V 碱性电池或 7.5V 至 12V 的壁式适配器供电。

下面是我构建面包板的步骤:

  1. 将所有垂直方向的正负轨道(分别用红色和蓝色条纹标记)连接到面包板顶部的水平正负轨道。

  2. 将电源逆变芯片(LMC7660)安装在面包板的左上方。

  3. 将电容器 C3(10 μF)安装在 LMC7660 的 2 脚和 4 脚之间。(请确保观察极性:将正极连接到 2 脚,负极连接到 4 脚。)

  4. 将电容器 C4(10 μF)安装在 LMC7660 的 5 脚和蓝色负极轨道之间。(请确保观察极性:电容器的正极连接到蓝色负极轨道。)

  5. 将 LMC7660 的 3 脚连接到蓝色负极轨道。

  6. 将 LMC7660 的 8 脚连接到红色正极轨道。

  7. 将电压调节器(LM7805)插入面包板的右侧区域。

  8. 将 LM7805 的 1 脚连接到一个空白行,该行将接收输入的 9V 或 7.5V 电压。(如原理图所示,它可以接受+7V 至+12V 的输入电压。)

  9. 将 LM7805 的 2 脚连接到蓝色负极轨道。

  10. 将 LM7805 的 3 号引脚连接到红色正电源轨。

  11. 将电容 C2(1 μF)的一端从 LM7805 的 1 号引脚连接到蓝色负电源轨。

  12. 将电容 C1(0.1 μF)的一端从 3 号引脚连接到蓝色负电源轨。

  13. 将 TL072 集成电路插入面包板;我将其放置在第二个垂直区域。在操作芯片时,务必遵循所有防静电预防措施。

  14. 尽可能缩短与 TL072 的连接,以消除可能的杂散信号。

  15. 将电容 C5(0.01 μF)的一端从 TL072 的 8 号引脚连接到蓝色负电源轨。尽量将连接做得靠近芯片,以最小化杂散信号的影响。

  16. 将 TL072 的 8 号引脚连接到红色正电源轨(再次使用尽可能短的跳线)。

  17. 将电阻 R5(47 千欧姆)从 TL072 的 2 号引脚连接到蓝色负电源轨。

  18. 将 BNC 输入插孔的中间引脚通过尽可能短的电线连接到 TL072 的 3 号引脚。

  19. 将 BNC 的地线连接到蓝色负电源轨上最靠近的位置。(我使用了面板安装型 BNC 连接器,并将一根硬线拧到法兰上,这样我就能将其安装得非常接近。)

  20. 将 TL072 的 4 号引脚连接到 LMC7660 的负电压(5 号引脚)。

  21. 将电容 C6(0.1 μF)的一端插入 TL072 的 4 号引脚,尽量靠近芯片。

  22. 将电容 C6 的另一端插入蓝色负电源轨上最靠近的位置。

  23. 将电位器 R7(1 兆欧姆)的外侧引脚插入 TL072 的 1 号和 2 号引脚之间。

  24. 从电位器 R7 的 2 号引脚插入一根短跳线连接到 3 号引脚。该电位器仅使用两个引脚(中间和一个端点)工作。为了规范性和稳定性,我通常将中间引脚连接到不调节的引脚。

  25. 将电容 C7(0.1 μF)的一端从 TL072 的 1 号引脚连接到 2 号引脚。

  26. 将电阻 R8(1 千欧姆)插入 TL072 的 1 号引脚和 6 号引脚之间。

  27. 将电容 C8(0.1 μF)的一端连接到 TL072 的 6 号引脚,另一端连接到地线。

  28. 将电阻 R10(10 千欧姆)连接在 TL072 的 6 号引脚和 7 号引脚之间。

  29. 在面包板的空旷区域(尽量靠近 TL072),插入电位器 R4(10 千欧姆)。

  30. 将电阻 R2(10 千欧姆)的一端连接到电位器 R4 的 1 号引脚。

  31. 将电阻 R2 的另一端连接到负 5V(LMC7660 的 5 号引脚)。

  32. 将电阻 R1(10 千欧姆)的一端连接到电位器 R4 的 3 号引脚。

  33. 将电阻 R1 的另一端连接到红色正电源轨。

  34. 将电位器 R4 的 2 号引脚(中间引脚或滑动端)连接到 TL072 的 5 号引脚。

  35. 将电容 C9(0.1 μF)的一端连接到 TL072 的 5 号引脚(尽量靠近引脚),另一端连接到蓝色负电源轨。

  36. 将 Arduino Nano 插入面包板。我将其放置在面包板从左数的第二排,以便 USB 连接易于访问。

  37. 将 Nano 的 5V(27 号引脚)连接到红色正电源轨。

  38. 将 Nano 的地线(29 号引脚)连接到蓝色负电源轨。

  39. 将电阻 R9(1 千欧姆)的一端连接到 TL072 的 7 号引脚。

  40. 将电阻 R9 的另一端连接到 Nano 的 A0(第 26 脚)。你可能需要在面包板上找一个空位,然后使用跳线。

  41. 将齐纳二极管(D1)的阳极连接到 Nano 的 A0 引脚。

  42. 将齐纳二极管的阴极连接到蓝色负极轨道。

  43. 将电容 C10(22 μF)的正极引脚连接到 Nano 的 A0 引脚。

  44. 将电容 C10 的另一引脚连接到蓝色负极轨道。

  45. 为 LCD 制作一条四线电缆,包括正极、负极、SDA 和 SCL 线。(如果你从未制作过电缆,请参阅本书中使用的连接器,见第 18 页。)

  46. 将 LCD 线束的正负线分别连接到红色正极和蓝色负极轨道。

  47. 将 LCD 的 SDA 引脚连接到 Nano 的 A4(第 22 引脚)。

  48. 将 LCD 的 SCL 引脚连接到 Nano 的 A5(第 21 引脚)。

在图 7-9 中,板子左上角会看到四个电阻和一个通过三条线连接的电位器。这是图 7-10 中的探针电压模拟电路。要接线模拟电路,进行以下连接:

  1. 将电阻 R5(10 千欧)的开口端连接到负 5V(LMC7660 的第 5 引脚)。

  2. 将电阻 R1(10 千欧)的开口端连接到红色正极轨道。

  3. 在电阻 R1(10 千欧)和电阻 R2(1 千欧)的连接处,连接电位器 R3(20 千欧)的第 1 脚。

  4. 在电位器 R4(1 千欧)和电阻 R5(10 千欧)的连接处,连接电位器 R3(20 千欧)的第 3 脚。

  5. 将电位器 R3(20 千欧)的中间引脚(第 2 脚)连接到 TL072 的第 3 脚。

温度传感器不包含在面包板中。

最后,校准自定义 pH 表。我建议先使用模拟电路进行校准,然后再使用实际探针,具体步骤见下一节。

自定义 pH 表的校准

第一次校准自定义 pH 表可能会有点困难,但一旦熟悉了操作,就不需要太长时间,之后应该会运行得很好。首先,将标度电位器和偏置电位器都调整到其范围的中间位置。因为 pH 7 是中性,所以从 pH 7 开始,将探针放入 pH 7 溶液中,并调整偏置电位器,直到显示屏显示为 7.00。

接下来,清洁探针,将其放入 pH 4 溶液中,并调整标度微调器,直到显示屏显示为 4.00。之后,再次清洁探针,重新测试 pH 7 溶液;读数应该接近中心。如果偏离中心,则再次调整偏置,使其精确为 7.0,并重复此过程。这一次,调整标度到 pH 4.0 只需要很小的调整。现在,将探针放入 pH 10 缓冲溶液中,检查显示,看看读数偏离多少,并相应调整标度微调器。重复这一过程,直到读数与所有三个缓冲溶液匹配。(大约三到四次尝试,调整标度和偏置后,我将其完美校准。)

当你确认仪表工作正常后,我建议你重置它并重新校准以进行练习。第二次我做得更快,只用了两次重复。我在大约三周的时间里多次检查了我的 pH 计,发现它似乎保持了良好的校准状态;你应该也能获得类似的结果。

注意

作为初步测试,我还使用了图 7-10 中的测试电压电路进行初步校准。你还需要一个数字电压表。我从 0V 开始,调整偏置电位器,直到 LCD 显示 pH 为 7。接下来,我调整测试电压电路,使其在数字电压表上输出 180mV,并转动刻度电位器,直到 LCD 显示 pH 为 10。我然后将测试电压调整为-180mV,并调整刻度,直到 LCD 显示 pH 为 4。经过几次尝试后,我得到了不错的结果,于是我断开了测试电源并替换成了探头。这一次,我只用了一个尝试就成功校准了仪表

当你的仪表搭建并校准好后,试着用一些常见的家庭产品进行测试,比如这些:

• 可口可乐经典:pH 2.5

• 橙汁:pH 2.8

• 咖啡:pH 5.0

• 5%氨水溶液:pH 11

• 漂白水:pH 11.9

从模拟思维角度看

我们这些老古董仍然喜欢模拟读数,对于那些仍徘徊在 20 世纪的坚持者,我在图 7-6 和 7-7 的原理图中、草图以及最终的屏蔽 PCB 文件中包括了使用模拟读数的设置。这是一个稍微的后期想法,是可选的,因此屏蔽板中没有包括仪表的串联电阻器;然而,Pro Mini 与读数器的引脚连接是有的。所需的单个电阻器可以安装在仪表表头的背面。在图 7-11 中,我只是将仪表连接到面包板电路中。

image

图 7-11:定制 pH 计面包板电路,包含数字显示和 20mA 表头

多年来,我收集了模拟表和表头;所示的仪表是一个 Simpson 20mA 表头。为了驱动该仪表,我简单地使用了 Pro Mini 上引脚 5 和 6 的 PWM(脉宽调制)输出,直接连接到仪表,并串联一个电阻器。在草图中,我将仪表居中在 0V,因此它使用正负电压。

最终,我使用了一个可变电阻器,将模拟表的最小值和最大值分别设置为-420mV 和+420mV。这样解决了尝试设置增益和偏移以匹配数字读数的问题。然而,这并不会影响任何读数的准确性,数字和模拟读数是匹配的。它们也在整个 pH 范围内完全一致。

对于许多仪表,可以拆卸外壳以方便更换不同的刻度,如图 7-11 中所示。本项目的仪表面板是用激光打印机制作的,以使刻度反映 pH 值并显示用于参考的 mV 刻度。你可以使用 Corel Draw 或 Adobe Illustrator 等绘图程序制作一个精美的刻度,并购买带有粘性背面的标签纸,将其粘贴到原始仪表板上。只需小心操作,避免在过程中损坏指针或机芯。

关于温度的影响

到目前为止,我还没有处理温度问题,但溶液的 pH 值是温度依赖的,正如图 7-12 所示。

image

图 7-12:pH 值如何随温度变化

温度对 pH 值的影响在接近室温(25°C)时是微不足道的。实际上,根据图表,从 25°C 到 0°C 的 pH 差异在两端的 pH 值极限处仅为半个 pH 单位。然而,在 100°C 时,差异更加明显,可能达到 1.5 个 pH 单位。

有了这些信息,问题就变成了如何处理温度对 pH 值的影响。

添加温度传感器

解决温度影响的第一步是将一个温度传感器包含在电路中,这样自定义 pH 计就能知道温度是多少。在 Arduino 平台上,最简单且应用最广泛的温度传感器之一是 LM35,根据数据表,该传感器在 25°C 时输出线性 10mV/°C,并具有半度的准确度。你可以在图 7-6 和 7-7 的电路图中看到这个传感器。

我连接了芯片并将其包含在电路图中,但我有些担心其准确性。不幸的是,我没有国家标准与技术研究院(NIST)的温度标准可以参考,于是我将 Arduino 传感器的读数与玻璃科学温度计、双金属拨盘温度计以及 Radio Shack 数字温度计进行了比较。结果是这些设备的读数彼此不一致,也与 Arduino 的读数不符。

检查准确性

校准温度传感器的显而易见方法是将其与我非常了解的两个温度值进行比较:蒸馏水的冰点和沸点(在海平面上)。因为我住在海平面以上大约 12 英尺的地方,所以海拔高度不成问题。冰水和沸水测试的结果表明,传感器的读数确实偏差了大约 2%。这可能是外部电路中的某些因素造成的,例如参考电压,这在电路图中已有补偿。温度 IC 和连接部分被热缩管保护,以避免水分进入连接部分,具体内容可以参见《构建》章节中的第 211 页。

根据我在此项目中使用的玻璃电极制造商的说明,温度引起的误差可以按以下方式计算:

pH 误差 = 0.003 × (校准温度 − 当前温度) × (中性 pH − 实际 pH)

例如,如果电极在室温(25°C)下校准,并且测量的样本 pH 值约为 4,温度约为 5°C,则误差计算如下:

  1. 计算温差:25°C – 5°C = 20°C

  2. 计算 pH 值与中性 pH 值的差距:7 pH – 4 pH = 3 pH

  3. 总误差为:0.003 × 20 × 3 = 0.18 pH。

截至目前为止,我还没有尝试将温度读数集成到草图中以自动调整 pH 值。然而,定制 pH 计在 LCD 屏幕上显示温度,因此你可以决定是否值得进行调整。正如你在图 7-12 中看到的,温度对 pH 值的影响是微小的,可以通过图表近似,或者用类似我的测试方法计算出来。

你的大多数测量值很可能会在室温下或接近室温。温度补偿通常只在恶劣的环境和工业环境中需要。如果你在极端温度下进行 pH 测量,你可能想在草图中加入该公式。

注意

如果你感兴趣,可以阅读更多关于如何补偿由于温度导致的 pH 探头读数误差的内容,网址为 www.qclscientific.com/electrochem/phtemp%20comp.html

草图

定制 pH 计草图,像本书中的许多草图一样,包含了其他草图和示例的部分。我在整个代码中加入了注释,描述了最重要的部分是如何工作的。该设备是在 Arduino IDE 版本 1.0.5-r2 上进行测试和使用的。

//Custom pH Meter Sketch
//Smoothes both temperature and pH

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
/* Visit http://playground.arduino.cc/Main/I2cScanner for code
  you can run to figure out your LCD's I2C address if 0x27 doesn't work. */
LiquidCrystal_I2C lcd(0x27, 16, 2); //16x2 display
//There are a couple of libraries out there. The one I used was
//simply Liquid Crystal_I2C for a generic type display.
const int numReadings = 10;
const int numReadings2 = 20;
const int meterOut1 = 5;
const int meterOut2 = 6;

float readings[numReadings];         //The readings from the analog input
float readings2[numReadings2];

int index = 0;                       //The index of the current reading
int index2 = 0;
float total = 0;                     //The running total
float total2 = 0;

float average = 0;                  //The average
float average2 = 0;

int pHpin = A0;
int tempPin = A1;
int meterdrive1;
int meterdrive2;

int pHvalue = 0;
float val;
float val2;
float tempC;
float temp2;
void setup() {
  lcd.init(); //You may have to use a different command, depending on the
             //library you use
  lcd.backlight();
  pinMode(meterOut1, OUTPUT);
  pinMode(meterOut2, OUTPUT);

  //Initialize serial communication with computer:
  Serial.begin(9600);

  //Initialize all the pH and temperature readings to 0:
  for(int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
  for(int thisReading2 = 0; thisReading2 < numReadings2; thisReading2++) {
    readings2[thisReading2] = 0;
  }

  //Configure the reference voltage used for analog input to 1.1V
  analogReference(INTERNAL);
}

void loop() {

  tempC = analogRead(tempPin);
  temp2 = tempC/9.31; //My calibration factor was 9.31, as determined
                     //by the boiling water and ice tests

  pHvalue = analogRead(pHpin);

  val = map(pHvalue, 0, 1023, 0, 1400);
  val = constrain(val, 0, 1400);

  val2 = val/100;

  meterdrive1 = map(average, 0, 14, 0, 255);
  meterdrive2 = map(average, 14, 0, 0, 255);

  analogWrite(meterOut1, meterdrive1);
  analogWrite(meterOut2, meterdrive2);

  //Subtract the last reading:
  total = total - readings[index];

  //Read from the sensor:
  readings [index] = val2;

  //Add the new reading to the total:
  total = total + readings[index];

  //Advance to the next position in the array:
  index = index + 1;

  //If we're at the end of the array…
  if(index >= numReadings)
    //…wrap around to the beginning:
    index = 0;

  //Calculate the average:
  average = total / numReadings;

  //Subtract the last reading:
  total2 = total2 - readings2[index2];

  //Get readings from the temperature sensor:
  readings2 [index2] = temp2;

  //Add the temperature reading to the total:
  total2 = total2 + readings2[index2];

  //Advance to the next position in the array:
  index2 = index2 + 1;

  //If we're at the end of the array…
  if(index2 >= numReadings2)
    //…wrap around to the beginning:
    index2 = 0;

  //Calculate the average:

  average2 = total2 / numReadings2;

  delay(1);                   //Delay between reads for stability

  lcd.setCursor(0,0);
  lcd.print("pH");
  lcd.setCursor(4,0);
  lcd.print("               ");
  lcd.setCursor(7,0);
  lcd.print(average,2);      //Truncate to two decimal places
  lcd.setCursor(0,1);

  lcd.print("Temp ");
  lcd.print(average2*.98,1); //Error calculated from empirical measurement
  lcd.print((char)223);      //Print the degree symbol
/* This may vary depending on display. One display used ((char)178) for the
degree symbol.*/
  lcd.print("  C");

  delay(600);  

}

基本的 pH 测量功能非常简单:它从运算放大器电路的模拟输出读取一个模拟值,并将该值传输到 Pro Mini 的模拟输入引脚。每次主循环运行时都会读取 pH 值和温度,然后分别将它们存储在 pHvaluetempC 中。我第一版的草图直接将这些值打印到 LCD 屏幕上。

但是,当我在面包板上布置电路并调整组件时,我注意到输出有些跳动。pH 值波动大约两到三十分之一的 pH 单位,围绕某个核心值上下波动。例如,读数可能从 pH 4 跳到 4.1,再到 3.9,然后回到 4。

平滑 pH 和温度输出

我重新回到设计图板前。调整电路,试图找出跳动的原因,但未能解决。然后,因为 pH 值不太可能快速变化,我决定对几个读数进行平均。虽然这稳定了读数,但缺点是,我取样越多,读数的速度就越慢。

然而,我认为这不是问题,因为我使用过的一些昂贵的商业 pH 仪表也需要一些时间才能稳定,很可能是由于相同的原因。但仍然有改进的空间。

幸运的是,Arduino 网站上有一个由 David Mellis 编写,后来由 Tom Igoe 修改的有用草图,使用数组来平滑信号。(你可以在 www.arduino.cc/en/Tutorial/Smoothing/ 上看到完整的原始草图。)我将这个示例作为模型,在本项目的草图中平滑 pH 电压。我尝试了几种不同的值,发现 5 到 10 个样本之间的值效果最佳。我将 numReadings 设置为 10,这样就减少了稳定期的拖延,并且平滑效果相当好。书中显示的草图将平滑后的结果存储在 average 变量中,并在主循环结束时打印到 LCD 屏幕。此外,我继续微调电路,使得草图需要的平均值越来越少。

请注意,在处理来自温度传感电路输入的草图部分中,也采用了相同的平滑技术。(average2 变量包含平滑后的温度读数结果。)这是必要的,因为平滑 pH 电压时需要做同样的事情:即使是温度传感器输出也有些许波动。我最初的怀疑是,可能是 Arduino Pro Mini 及其电压参考导致了 pH 和温度电压的波动。然而,我将温度传感器直接连接到我的万用表,并使用过滤良好的电源,结果还是出现了同样的干扰。最终,平滑方法解决了这个问题。

注意

虽然这个草图中使用的平滑方法效果很好,但这并不是唯一的选择。例如,移动平均法也可以很好地工作

居中一个模拟仪表

如果你选择使用模拟仪表,Arduino 需要驱动仪表的正负两端。草图将仪表驱动映射到两个引脚的 PWM 值反转,如下所示。

meterdrive1 = map(average, 0, 14, 0, 255);
meterdrive2 = map(average, 14, 0, 0, 255);

为了获得 meterdrive1,将平均值(测量的 pH 值的平均值)从 0 映射到 14,而 meterdrive2 是将相同的平均值从 14 映射到 0。两个映射都使用了 Arduino 预加载库中的 map() 函数。

map() 函数是一个有用的工具,它允许你将一个数字从一个范围映射到另一个范围。其语法如下:

map(value, fromLow, fromHigh, toLow, toHigh)

map() 函数可以用于调整一组值,或者像在此案例中,将值从 0 到 14 反向映射至 14 到 0。如果你想使用模拟仪表并且不想将指示器重置到中心位置,你可以简单地使用输出引脚 5 或引脚 6(将不使用的引脚留空),并改变电阻的值以获得正确的读数。

关于有效数字的说明

以下这行代码将 pH 值显示到 LCD 上,显示两位小数:

lcd.print(average,2); //Truncate to two decimal places

草图的早期版本中调用了lcd.print(average,1),只显示一位小数,但当我试图最小化自定义 pH 计的抖动时,我更改了显示代码,加入了两位小数,以便实现更精细的分度。大部分时间,pH 读取值即使到第二位小数也保持极其稳定。

在最终的草图中,我保留了两位小数,但老实说,我不确定第二位小数的意义或准确性有多高。当探头浸入溶液中时,它有轻微的漂移倾向,我认为这是正常现象。我认真研究并学习了比我想知道的更多关于有效数字(测量中具有实际意义的数字)的知识,但仍然没有得到一个确切的答案。

结论是:我阅读的所有关于 pH 值的文献都讨论了整数形式的 pH 值——或者在最好的情况下,只有到十分位。只有在一些科学和工业应用的参考中,才会涉及到百分位。

对于大多数实际应用,如果你愿意,可以将草图更改为只使用一个有效数字。我也强烈建议你在初步校准期间只使用一个有效数字,因为额外的数字可能会造成混淆。如果你非得要使用第二个有效数字(也许更多的是出于自尊心),你可以重新添加它,但要知道它的准确性存疑,并且根据我的经验,它实际上并没有带来什么额外的好处。

屏蔽层

本项目中显示在图 7-13 中的自定义 pH 计屏蔽层旨在最大限度地减少 pH 探头对输入的噪声。Pro Mini 和 LCD 会产生一些电噪声,因此,所有活跃的模拟输入组件都位于 PCB 的一端,而 Pro Mini 和显示器的接口则位于板的另一端。反相器 IC 及相关组件位于 Pro Mini 下方,以节省空间。

image

图 7-13:屏蔽层 PCB 上仅为本项目在 Pro Mini 上使用的引脚焊接了插头。电压反相器和电容器位于 Pro Mini 将要插入的位置下方

对于这个项目,我决定使用双面电路板。这使得 PCB 布局比试图将所有东西挤到一面上简单得多,并且它允许放大器、缓冲阶段 IC 及相关组件紧密排列。你可以在图 7-14 中看到这个屏蔽层的布局文件,你可以与本书的其他资源文件一起下载。

image

图 7-14:屏蔽层中的顶部走线最暗,底部走线次之,丝网印刷层最浅。请注意,丝网印刷层显示了围绕各种组件的框

图 7-15 展示了完成的印刷电路板,显示了装配前后的情况。在装配这块板时,要采取预防措施防止静电损坏 TL072 芯片。由于该芯片具有非常高的输入阻抗,因此对静电放电特别敏感。我使用了一个插座来固定运算放大器,这样万一它损坏,更换起来就不需要大费周章。

image

图 7-15:装配前后屏蔽 PCB 的情况。电压逆变器及其相关组件位于 Pro Mini 下方。装配后的版本显示了与显示器连接的情况

还要注意,许多电阻器在这个 PCB 上是垂直安装的,以节省空间并减少引线长度和电路板布线长度。我使用了 0.100 英寸的女性针脚头来安装 Pro Mini,这样就为下面的组件留出了充足的空间。并不需要完全填充所有针脚头来适配 Pro Mini 的所有引脚;只需要足够的针脚头来机械支撑 Pro Mini 并提供必要的电气连接。我发现,将针脚头放在至少一侧的最末端可以对齐引脚,简化将 Pro Mini 板插入时的对准工作。

构建

确保草图已经加载到 Arduino 中,并且现在将所有组件焊接到你的 PCB 上,包括电源和接地的线缆以及(可选的)温度传感器插座的线缆。现在也将运算放大器插入其插座,但要弯曲运算放大器的第 3 针,使其突出。你需要在后续的构建过程中访问第 3 针。

当定制 pH 计电路已焊接完毕并将草图加载到 Arduino 时,实际构建过程只剩下最后一步:将一切放入保护外壳中。本节描述了一些关于外壳和如何将电路板安装到外壳中的建议。图 7-16 展示了完成的外壳。

image

图 7-16:完成的定制 pH 计放入外壳中。此特写图说明了偏移(标注为Ofst)和增益(标注为Scale)校准调整孔的位置

定制 pH 计外壳

你选择外壳的方式将取决于你如何使用定制 pH 计,是否选择包括模拟仪表,以及所需的便携性。我选择了一个标准的 ABS 透明塑料盒,外部尺寸大约为 1.3×2.45×4.4 英寸。空间比我预期的要紧凑一些,但我还是能够将印刷电路板、显示器、开关、连接器和电池挤进盒子里。

为显示器腾出空间

这个项目的外壳是 Hammond Manufacturing 公司生产的 1591 BTCL 型号的盒子。图 7-17 展示了塑料盒顶部的图纸,标明了切割显示孔和钻孔位置的线条。

image

图 7-17:外壳盖的模板,显示 16×2 显示器的开口(阴影区域)和钻孔位置

你可以下载本书的资源文件(见 www.nostarch.com/arduinoplayground/),并将其作为打孔模板使用。

我需要尽可能多的垂直空间来容纳电池,因此需要切割外壳的顶部。但要小心:有些显示器的尺寸可能略有不同,所以在切割之前请先测量你的显示器并与图纸对比。如果有差异,请调整测量值。

外壳所用的 ABS 塑料容易切割,因此切割显示孔应该不会遇到重大问题。在开始之前,请将外壳牢固地夹在一块附着在工作台或桌子上的废木板上。

警告

当你使用较大的钻头钻入薄层 ABS 塑料时,钻头容易抓住塑料。请勿手持外壳进行操作

要遵循此模板,首先在显示区域的对角线两端的角落中钻两个大孔,使用冲击标记作为中心。我发现 1/2 英寸的孔大小刚好合适,但只要孔足够大,能容纳你用来切割的锯片就可以。你可能希望先用小钻头钻一个 1/2 英寸孔的中心,以确保孔的位置正确。然后,使用钥匙孔锯切割出较小的矩形。

为了确保电池有足够的空间,我建议将显示器安装在偏离中心的位置,如图 7-16 所示,并按照图 7-17 中的尺寸进行安装。当显示孔切割完成后,用#30 或 1/8 英寸的钻头钻小孔,用于安装 LCD 显示器,并配合 4-40 螺丝。

钻孔用于其他硬件

一旦顶部准备好,根据图 7-18 中的模板,在外壳主体的两个较小的侧面上钻孔,用于 BNC 连接器(A)、开关(B)、电源输入开关(C)和可选的温度插孔(D)。BNC 连接器的孔为 3/8 英寸,而开关和温度插孔的孔均为 1/4 英寸。

image

图 7-18:外壳左侧 BNC 连接器(A)孔和右侧开关(B)、电池/交流开关(C)以及可选的 3.5 毫米温度传感器输入插孔(D)孔的近似布局

安装电路板

最后,选择将印刷电路板安装到机壳内的位置。对于我制作的两个 pH 计,我将一个没有元件的盾牌 PCB 放置在外壳内,标记了塑料上四个安装孔的位置;如果你愿意,也可以使用本书资源文件中的板布局打印图纸作为模板。标记好四个孔后,轻轻用中心冲击器打点并钻孔。小心不要弄裂塑料外壳,并确保它们与 PCB 上的安装孔对齐。我建议使用#41 钻头(大约 3/32 英寸)来钻这些孔。

如果你使用本书附带的盾牌设计,可能还需要将电路板的安装孔钻孔至正确的大小。传统的制造方法建议使用垫片、螺丝和螺母将电路板固定在外壳内,但我选择了直接在电路板上钻孔并攻丝。我使用了#50 钻头在四个角落钻孔,并使用 2-56 攻丝器进行攻丝。然后,我用 2-56 螺丝将电路板固定到位。虽然这种做法并不适用于所有应用场景,但由于电路板比较轻,这种方法效果不错。

此外,我并不认为制作完成的 pH 计会遭受过多的物理冲击。考虑到这一点,我只是在电路板的无元件一侧放了一条泡沫条,并将电路板轻轻地固定在外壳侧面——但是不要太紧。如果你预计该设备将经历反复且剧烈的震动,可以在组装前在螺纹上涂抹一小滴 Thread-Lok 或其他厌氧胶粘剂。

一旦电路板安装好,标记增益和偏置微调电位器的接入孔位置。将外壳盖放在外壳上,直视盖子,使用马克笔标记两个微调孔的位置。移除外壳顶部后,钻出 1/4 英寸的孔,对应微调电位器上的螺丝头(见图 7-16)。

安装其他硬件

现在你可以安装 BNC 连接器、开关、电源开关和(可选的)温度插口。我发现最好先将开关和插口安装到外壳内,然后再将线缆焊接到它们上面。同样的技巧也适用于 BNC 连接器,虽然你可能希望提前将接地线焊接好。我取了一根 22 号实心线,将它绕在连接器底座上三分之四圈,用固定螺母拧紧,然后将它焊接到 PCB 上的接地点(见图 7-13)。

注意

虽然我没有为个人制作的设备引出模拟仪表的信号,但如果你制作这块盾牌,你会看到两个信号连接点,它们周围有一个小方框标记

连接探头到运算放大器

“高阻抗探头集成”在第 193 页中描述了使用 pH 探头作为定制 pH 计输入时的特殊注意事项。事实证明,即使是高质量的 FR-4 电路板材料,也可能由于表面污垢或潮气等污染而导致一些电流泄漏。为了最小化泄漏,将 IC 的输入直接连接到探头。为此,将 IC 放置在接近外壳内 BNC 连接器的位置。然后,代替将运算放大器的第 3 针焊接到电路板上或插入插座,将其弯曲并直接接线到 BNC 连接器(见图 7-19)。

image

图 7-19:为了最小化杂散信号,从 BNC 连接器到 IC 引脚的连接直接焊接。

因为这是电路中唯一的高阻抗部分,运算放大器数据表中提到的其他一些预防措施(例如在其他输入周围使用接地隔离环)并不需要。然而,这个项目的屏蔽 PCB 确实保持了关键信号线尽可能短,并将组件放置得很近。

连接温度传感器

对于可选的温度传感器,你需要在外壳内安装一个 3.5 毫米的三导体插孔;该孔的位置在图 7-18 中标记为 D。将这个插孔与 PCB 上温度 IC 的连接端子连接,这些端子位于图 7-20 中显示连接器和调节 IC 之间的三个孔。插头的套筒为接地,环为正极,尖端为温度传感 IC 的输出。

image

图 7-20:温度传感 IC 的三个连接就在“Therm”字样的上方。

你可以通过将 IC 封装在一段短的热收缩管内并加上密封剂来保护 IC 免受液体侵入,如图 7-21 所示。这种热收缩管可以在网上轻松购买。管内的密封剂应能为 IC 提供完全防水的密封。封装 IC 时,只需将其插入管内,并使用热风枪或高温的吹风机加热,直到完全封住。

image

图 7-21:这个 LM35 温度 IC 完全包裹在一段短的热收缩管内,里面填充了密封的热凝胶。热凝胶几乎不可见,只能在电线进入管道的地方看到一些。

一旦所有硬件都安装在外壳内,所有组件都焊接到 PCB 上后,将 LCD 固定在盖子上并封闭,完成组装。你可能还需要像图 7-16 所示那样标记你的电位计和开关,以便日后操作更加方便。

第九章:两种弹道测速仪**

image

这个项目是用来测量弹丸速度的设备。最初它是用来测量气枪和彩弹枪的子弹速度,后来它发展为能够测量 BB 枪和弹丸枪的弹丸速度,最终能测量高达每秒 3,000 英尺(fps)以上的高功率武器的速度。这个项目的主要目标不是测量传统火器的速度,但它确实具备这个能力,本章的最后部分将介绍如何使用它来测量 9 毫米子弹的速度。

弹道测速仪本来设计得很简单,但结果比原计划稍微复杂了一些。最终产生了两个项目:完整的弹道测速仪和一个更小巧、更简单的设备,我称之为 Chronograph Lite(见图 8-1)。

image

图 8-1:附有弹丸加速度通道的 Chronograph Lite,连接到 0.177 口径的弹丸枪

我尽力让每个弹道测速仪系统既灵活又精确。灵活性来自于将传感器元素与读数分开,并允许不同类型的传感器用于测量不同设备——并且使用相同的加速度通道产生不同的读数。

在这个项目中,你将使用一些在 Arduino 项目中不常见的元件,如晶体振荡器来提供精确的定时(与 Nano 中使用的晶体振荡器不同)、红外 LED、光电晶体管、逻辑门、12 级数字计数器和数字-模拟转换器(DAC)来帮助执行计数功能。

警告提示

本着对 Jean Shepherd 的《圣诞故事》的敬意(在其中每个人都警告 Ralphie,“你会把眼睛射瞎!”),请记住,任何火器本身都具有危险性,许多气动武器也能发射致命力量。无论你测试的是气动设备还是使用高能子弹的武器,都要格外小心。完整的弹道测速仪和 Lite 版本主要是为使用 CO[2]和气动装置加速弹丸的低功率武器开发、测试并制造的。虽然该设备能够测量传统火器的子弹速度,比如前面提到的 9 毫米手枪,但它并未为此应用进行开发或测试。我强烈建议你不要尝试将本章中构建的设备用于此类应用。

什么是弹道测速仪?

用于测量从火器中发射的高速弹丸速度的设备通常被称为弹道测速仪。术语测速仪是从钟表学领域借用过来的,现在广泛用于描述用于测量子弹、箭、飞镖等速度的仪器。

本章介绍了两种版本的弹道计:一种能够准确测量高速弹丸的版本,以及一种提供稍低精度但实现更加简便的轻量版。尽管我将较简单的版本称为“轻量版”,但它绝不是不成熟的设计。

商业弹道计

市面上有多种商业弹道计,大多数是为高功率手枪和步枪设计的。弹道计通常被放置在射手前方的地面或桌面上。大多数流行的商业设备依赖于环境光照进行工作,因此它们无法在室内或阴天使用。虽然这些设备价格适中,但并不算便宜。

弹道计的种类从简单的双线设备(至今仍在使用,并且被一些人认为是最准确的)到相对复杂的设备,这些设备具有数字存储、平均速度计算及其他功能。双线方法仅使用两根细线(36 号或 40 号线即可),将它们拉伸并精确地放置在两组接触点之间。弹丸发射后,首先打断第一根线,启动计时器;然后,如果瞄准准确,打断第二根线,停止计时器。根据两次线断裂之间的时间,计算出以英尺或米为单位的速度。最早的弹道计是用时钟构建的,通过一排 LED 显示的数字 1 和 0 进行读数。这个二进制数需要转换为十进制数,然后与线之间的距离一起计算出速度。

测量枪口速度

现在你知道了市面上有哪些现成的弹道计,我们来看看该设备的物理原理。离开武器枪口的弹丸由某种推进剂(如空气、CO[2],或是火药快速氧化产生的气体)赋予它速度。弹丸沿枪管前进并离开枪口。弹丸离开枪口时的速度称为枪口速度

空气动力枪的枪口速度会因多个因素而有所不同,包括推进剂的装药量、枪管的清洁度和弹丸与枪管的匹配。某些空气步枪的压力可以被充至近 3000 psi(每平方英寸磅),以便发射较大的弹丸,且射速相对较高。这些大口径空气枪的枪口速度相对较低,通常在 1000 fps 以下,但威力十足。与常规空气步枪(通常发射直径为 0.177 英寸的弹丸,提供 15 到 25 英尺磅(ft-lbs)动能)相比,这些大口径步枪提供 500 到 700 英尺磅的动能。

理想情况下,你希望尽可能靠近枪管的末端测量速度。然而,这可能比较困难,一些计速器制造商声称,在前几英尺(甚至几码)的飞行中,速度变化不大。另一方面,毫无疑问空气阻力是一个显著的因素,飞行物在前几英尺内会至少有一定的减速,特别是对于较大的飞行物来说。

本项目的做法

就像两线式弹道计速器系统一样,我们尝试测量飞行物穿越固定距离所需的时间。但与打断细线不同,该项目利用了红外光源和光敏接收器,如图 8-2 所示。

image

图 8-2:测量飞行物速度的基本原理是让飞行物打断光束启动计时器,然后打断另一个光束停止计时器

两对 LED 和红外传感器被布置成红外传感器通常能够检测光源。但是当飞行物穿过第一对传感器的光束时,传感器会变暗并改变其电气状态。处理器检测到这一变化并启动定时器。当飞行物中断第二对源/接收器的光束时,定时器停止。这两组光源和接收器之间的距离被精确设置,因此可以相对容易地计算出飞行物的速度。

举个简单的例子,假设光束的间距是 1 英尺。当飞行物打断第一个光束时,计时器开始;当飞行物打断第二个光束时,计时器停止。如果微控制器的计时器测得是 1 秒,那么速度就是 1 英尺每秒,或 1 fps。

该系统可以用于各种飞行物,并在 LCD 上提供数字读数。与其他方法不同,该设备将传感器组与电子设备分离开来,因此,如果需要,可以为不同的枪械或甚至不同的应用场景更换不同的传感器。例如,你可以设置一个传感器通道,通过它做一些基础的物理实验,记录小物体掉落的速度。

Chronograph Lite

首先,我们来看一下 Chronograph Lite,它非常容易构建,并且只有少量部件。

所需工具

焊接铁和焊料

电钻和钻头(1/2、1/4 和 1/8 英寸)

十字螺丝刀和平头螺丝刀

锯子(钥孔锯或伐木锯)

零件清单

一块 Arduino Pro Mini 或其克隆版

两个红外 LED,波长约为 650–850 纳米;两个红外光电传感器(我使用了霍尼韦尔 Optoschmitt SA5600 型)。

注意

有些用户在将红外 LED 与 Optoschmitt 光传感器匹配时遇到了问题。如果你碰到这个问题,可以尝试使用霍尼韦尔 SE3450/5450 或同等产品。另一种选择是使用两个 Adafruit IR Break Beams(零件号 #2167),而不是单独的 LED 和传感器。IR Break Beams 适用于 Chronograph Lite,但需要对输出进行反向处理,以便适配完整版。)

一个 270 欧姆、1/8 W 电阻(可选)两个 10 千欧姆、1/8 W 电阻(如果使用光电晶体管而非 Optoschmitt 光传感器)

一个包含两对 LED/传感器的通道 一个 16×2 LCD 屏幕

一个 I²C 适配器,如果 LCD 没有包含的话 一个 x4 适配器外壳(见“本书使用的连接器” 在 第 18 页)

四个母头插针(见“本书使用的连接器” 在 第 18 页)

一个 SPST 开关 一个瞬时 NO 开关

一个 9V 电池连接器

一个 9V 电池

一个 Hammond 1591 BTCL 外壳或同等产品

两个 7 1/2 × 1 1/2 × 0.06 英寸铝片

一块 1 3/8 × 7 1/2 英寸的 1 3/8 英寸丙烯酸板

两个 #10-24×1 英寸尼龙螺钉

两个 #10×24 尼龙螺母

四个 4-40×1/2 英寸螺钉

八个 4-40 螺母

四个 4-40 螺母垫圈

各种 28 号连接线

下载链接

草图 ChronographLite.ino

模板 PanelCutoutLite.pdf, PanelCutout.pdf, AccelerationChannel.pdf

原理图

在 Arduino 主板外,项目的电路并不复杂。图 8-3 中的原理图使用 I²C 总线为 LCD 提供电源,两个光电传感器的连接以及两个清除开关的连接。

image

图 8-3:Chronograph Lite 的原理图。主原理图显示了光电晶体管,而备用部分则显示了霍尼韦尔 Optoschmitt 传感器(左下角)

构建测试平台

图 8-4 展示了用于验证概念并开发草图的测试平台。我建议你先自己动手制作一个,并将 LED 和光电传感器安装进去,然后再搭建面包板。

对于这个测试平台,我剪切了两块约 2×6 英寸的纸板,并打孔使其适配两个红外 LED 和光电晶体管的对接位置,两个传感器之间间隔为 3 英寸。然后,我将纸板用螺丝固定到一块 1 英寸厚的木板上,你也可以选择用胶水或钉书钉固定。制作时,确保每个光电晶体管与红外 LED 在通道中直接对面。

安装红外 LED 和光电晶体管到测试平台后,我建议按照以下方式为面包板做准备:

  1. 用一根电线将两个红外 LED 的正极连接起来,可以通过焊接或绕线方式进行连接。

  2. 将一根 24 英寸长的电线焊接到组合的 LED 正极。如果你使用的是适合面包板的实心线,只需将 24 英寸电线的另一端剥皮即可。如果你使用的是绞线芯电缆,则需要将一个男性压接针连接到电线的末端。

  3. 使用电线将两个红外 LED 的阴极连接起来,可以通过焊接或包线方式连接。

  4. 使用电线将两个光电晶体管发射极连接起来,可以通过焊接或包线方式连接。

  5. 将合并后的红外 LED 阴极连接到合并后的光电晶体管发射极;我建议焊接一根长线。

  6. 将一根 24 英寸的电线焊接到合并的 LED 阴极和光电晶体管发射极上,并像第 2 步那样在电线的另一端做上公端压接针。

  7. 将一根 24 英寸的电线焊接到每个光电晶体管的集电极上,并像第 2 步那样在电线的另一端做上公端压接针。

在图 8-4 中,LED 和光传感器(根据选择,这些将是光电晶体管或 Honeywell Optoschmitt 传感器)被放置在加速通道纸板上打的孔中。

image

图 8-4:我最初用来验证测速仪概念的测试台

我使用了一个相对较小的打孔器,以便利用摩擦力将它们固定到位。你也可以使用热熔胶或接触胶将它们粘在一起。我使用了一根 24 英寸长的四导线电话线来连接通道和面包板,但任何电线都可以。在完成的版本和其他原型中,我只用了四根 30 号铜线,因为它们更灵活。或者,你现在也可以构建最终的传感器通道。

LED 和光电晶体管需要按照图 8-3 中的电路图连接到 Arduino 上。我将 LED 的正极通过一个 270 欧姆电阻(R3)连接到电源上。对于光电晶体管,我将它们设置为发射极接地,每个集电极通过 10 千欧电阻(R1 和 R2)连接到电源的正极,以实现开集电极配置。因此,如果光束被中断,光电晶体管将导通,集电极的电压会下降。

注意

如果使用 Honeywell Optoschmitt SA5600/5610,则不需要 10 千欧电阻(R1 和 R2),因为它们已经包含在 SA5600/5610 芯片中。Optoschmitt 传感器的接线如图 8-3 所示,位于电路图的左下方。

我并没有用活弹丸、BB 弹或子弹把办公室弄得一团糟,而是将设备垂直设置,这样可以让一个飞行物穿过光束来测试系统。这种方法意味着所测得的速度不会接近武器枪管发射物体的速度,但对于初步的概念验证实验已经足够。目标从更高处掉落时,记录的速度会更高——当然,前提是你的瞄准准确。(记住,s = (1/2)at²,其中s是位移或距离,a是重力加速度,t是时间,初始速度为零。)

如果环境光在测试中造成问题,可以将额外的纸板粘贴到两个纸板的顶部(侧面)以遮挡传感器,尽管在我进行的所有实验中我没有发现这是个问题。

面包板

下一步是构建一个面包板,如图 8-5 所示。为此,我们将使用图 8-3 中的 Chronograph Lite 电路图。电路中最复杂的部分是连接光传感器和 LED,这些组件并没有直接插入面包板,而是需要安装在传感器通道中,正如前一部分所描述的。

image

图 8-5:早期原型中,光传感器和 LED 通过离散电线连接到面包板。为了测试该单元,将一枚硬币掉入通道中

无论您是否已经制作完成了通道,还是正在使用纸板原型,您都需要将通道中的传感器和 LED 连接到面包板上——或者,实际上,连接到已完成的单元——使用四根电线:正极、地线、第一传感器和第二传感器。

以下是如何接线面包板:

  1. 将红色正极轨道和蓝色负极轨道分别连接起来。绝对不要将红色正极轨道和蓝色负极轨道连接在一起——这样会导致短路并损坏组件。

  2. 将 Arduino Pro Mini 或其克隆板插入面包板,留出一定的空间——大约四五行——在一端。

  3. 将 Mini 上的 VCC 引脚连接到红色正极轨道。

  4. 将 Mini 上的 GND 引脚连接到蓝色负极轨道。

  5. 取两个 10 千欧电阻(R1 和 R2),将每个电阻的一端连接到红色正极轨道。(注意,如果您使用的是 Optoschmitt SA5600 光传感器,则无需使用这两个电阻。)

  6. 使用跳线将电阻 R1 的另一端连接到 Mini 的 D4 引脚。

  7. 使用跳线将电阻 R2 的另一端连接到 Mini 的 D2 引脚。(如果您使用 Optoschmitt 光传感器,可以直接将 D2 和 D4 引脚连接到光传感器的输出引脚,如图 8-3 左下角所示。)

  8. 使用附带的 24 英寸电线,将光电晶体管 Q1 的集电极引脚连接到 Nano 的 D2 引脚。

  9. 使用附带的 24 英寸电线,将光电晶体管 Q2 的集电极引脚连接到 Nano 的 D4 引脚。

  10. 将一个 270 欧电阻 R3 的一端连接到红色正极轨道。

  11. 使用其中一根 24 英寸的电线,将电阻 R3 的另一端连接到面包板上的一个空行。

  12. 将 LED 1 和 LED 2 的共同阳极通过附带的 24 英寸电线连接到第 9 步中连接电阻 R3 的行。请参考图 8-3 查看 LED 是如何连接在一起并接入面包板的。

  13. 将 Mini 上的 5V 引脚和 GND 引脚分别连接到 LCD 上的 VCC 和 GND 引脚。

  14. 将 Mini 上的 A4 引脚连接到 LCD 的 SDA 引脚。

  15. 将 Mini 的 A5 引脚连接到 LCD 的 SCL 连接端口。

现在你已经准备好输入草图了。

草图

现在编写草图使其正常工作。以下是 Chronograph Lite 的草图:


     //Lite version of chronograph, using Optoschmitt sensors

     #include <Wire.h>
     #include <LiquidCrystal_I2C.h>

     unsigned long start_time = 0;
     unsigned long stop_time = 0;
     unsigned long time_of_flight = 0;
     float velocity = 0;
     LiquidCrystal_I2C lcd(0x3F, 20, 4);
      void setup() {
       Serial.begin(9600);
       pinMode(2, INPUT);
       pinMode(4, INPUT);
       lcd.init();
       lcd.backlight();
     }
     void loop() {

➊   while(digitalRead(2) == 1) {
         //Waiting for first sensor to trip
     }

➋   start_time = micros();

➌   while(digitalRead(4) == 1) {
     }

➍   stop_time = micros();

➎   time_of_flight = stop_time - start_time;

     Serial.print(" time of flight        ");
     Serial.println(time_of_flight);

     velocity = 1000000*.25/(time_of_flight);

     lcd.clear();
     lcd.print("tm of flt  ");
     lcd.print(time_of_flight);
     lcd.print(" us");
     lcd.setCursor(0, 2);
     lcd.print("Speed FPS    ");
     lcd.print(velocity);
  } 

草图非常直观。在设置了变量和输入后,一个while循环会等待第一个传感器被中断,通过检查条件digitalRead(2) == 1 ➊。触发时,时钟通过start_time = micros(); ➋开始,另一个while循环会继续,直到第二个传感器被激活(由于第二个传感器插入了 D4 引脚,这个while循环检查是否digitalRead(4) == 1 ➌)。当第二个传感器激活时,时钟通过stop_time = micros() ➍停止。

草图会计算从第一个传感器到第二个传感器之间的时间,通过time_of_flight = stop_time – start_time公式在➎位置计算。一旦草图完成计算,它会提供指示,显示结果在 LCD 屏幕上。

现在你需要做的就是加载草图,将测试通道竖立起来,如同在图 8-4 中所示,并通过纸板通道掉落像弹珠这样的投射物。首先,用编程器为 Mini 供电。或者,你可以使用一个单独的调节后的 5V 电源,连接到 Mini 的 5V 端口,或者你可以连接一个电池到 Mini 的 VIN 端口,并使用 Mini 的板载调节器。不要将 9V 电池连接到 5V 电源轨道——这可能会烧毁所有电路。

当你确认传感器正常工作后,如果想进一步测试电路,你可以将临时传感器通道连接到真正的气手枪上(参见图 8-6)。

image

图 8-6:早期原型中的光电传感器,安装在 Crossman 0.177 口径气手枪上。设置显然是原始的,使用 C 夹将通道固定在武器上。由于测试通道非常简单,我将其设置在了我的桌子上

如果这已经足够满足你的需求,你可以将其打包,并跳过第 233 页中“完整弹道测速仪”的内容。Chronograph Lite 应该适用于游戏以及低速和中速武器(低于 600 fps),如气枪、BB 枪、气软枪等。

尽管表现令人满意,但我仍然困扰于这样一个事实:虽然 Arduino 可以计算微秒,但它只能提供四的倍数结果,因此实际上分辨率只有 4 微秒。这就是我开发完整弹道测速仪项目的原因。如果这也让你感到困扰,并且你不打算将 Chronograph Lite 打包,你可以现在跳到第 233 页的“完整弹道测速仪”章节。

使用投射物模拟器测试 Chronograph Lite

为了测试 Chronograph Lite 或 Full Ballistic Chronograph 是否有误,我做了一个模拟器来模拟投射物穿过两个传感器的效果,而不是用子弹或彩弹射击我的工作区。在开发过程中,我主要使用了这个模拟器——它对于本章中任何计时器的完成或使用都不是必需的——但是它提供了如何开关相对高速信号的一些见解。

我使用了一个方波发生器(如果你想自己制作,见第九章),并制作了一个非常简单的面包板模拟器。模拟器的电路图,显示在图 8-7 中,仅包括开关功能,并由方波发生器驱动。

image

图 8-7:用于模拟 Optoschmitt 传感器顺序触发的模拟器示意图。它与方波发生器一起使用。电阻 R1 和电容 C1 可以调节以达到满意的去抖效果,但所示的数值已经很好。(续)

模拟器从方波发生器接收时钟信号。启动时,按下模拟器上的开关(在图 8-7 中标为 SW)开始从 CD4017 十进制计数器发出的起停信号序列。一个手动开关(SW)在 NE 555 定时器的去抖作用后触发模拟器。模拟器的功能是像投射物穿过起始和停止 LED/光传感器对一样,打开和关闭连接到光传感器的电路。图 8-8 显示了一个用于模拟器的面包板,展示了完成的电路板和方波发生器。

image

图 8-8:模拟器面包板和方波发生器连接到完成的 Full Ballistic Chronograph 原型板上。模拟器与 Chronograph Lite 或 Full Ballistic Chronograph 一样工作良好。

构建

为了完成 Chronograph Lite 项目,你需要做的就是将 Mini、显示屏、电池和适当的开关安装到一个外壳中,并留出一个连接器,以便将设备连接到传感器通道。与本书中大多数其他项目不同,我没有为 Chronograph Lite 使用保护板,因为 Mini 的接线已经足够。

它简单到不需要额外说明。我使用了 Hammond ABS 塑料外壳 1591 BTCL,正如部件清单中所示。见图 8-9 了解完整的 Chronograph Lite。

image

图 8-9:完成的 Chronograph Lite 的正视图。外壳右侧切了一个孔,以便为背光突起提供空间

图 8-10 展示了外壳的模板。你可以从* www.nostarch.com/arduinoplayground/* 下载该图纸的 PDF 文件,并用它来标记并中心打孔外壳上的孔。

image

图 8-10:Chronograph Lite 的孔和显示器模板

我为 Chronograph Lite 准备了外壳,步骤如下:

  1. 小心地标记、中心打孔,并钻 1/2 英寸孔用于显示器(A)的角落,1/8 英寸孔用于显示器的安装孔(B),1/4 英寸孔用于开关(C),以及 1/4 英寸孔用于清除开关(D)。

  2. 对于 LCD 屏幕,标记 1/2 英寸孔(A)的边缘。画线连接这些边缘,这样你就有一个矩形可以切割。 (你可以使用 Sharpie 马克笔,稍后用酒精清除多余的标记。)钻孔并沿着这些线用钥匙孔锯或弯锯切开开口。

  3. LCD 右侧(面朝上)有一个轻微的凸起,这是背光组件的一部分。你可以像我在图 8-10 中所做的那样切一个孔来适应这个凸起,或者你也可以保持边缘平直,并使用垫片防止凸起碰到外壳。

  4. 安装显示器,并用 1/2 英寸长的 4-40 安装螺丝和螺母将其固定。如果你已经为 LCD 背光凸起切割了孔,你可以直接安装显示器。如果没有,使用额外的 4-40 螺母将显示器从外壳面向后移。如果需要,添加额外的垫圈;4-40 螺母的厚度可能有所不同。

  5. 按照图 8-9 中所示安装清除开关。

现在接线 Pro Mini。没有扩展板,因此我们将直接焊接到 Pro Mini 板上,步骤如下:

  1. 焊接 I²C 连接的电线。为了让你的工作更轻松,使用彩色电线并为自己创建一个编码。将连接焊接到 Nano 板上的 5V(一些克隆板可能标为 VCC)和 GND 引脚。然后,将 3 英寸的电线焊接到 Nano 上的 A4 和 A5 引脚。将这些电线的另一端连接到一个四针母连接器。(详见“本书中使用的连接器”第 18 页了解如何制作 Pololu 连接器。)将 Nano 上的 5V 和 GND 引脚连接到 LCD 上的 5V 和 GND。将 Nano 上的 A4 引脚连接到 I²C 板上的 SDA,将 A5 引脚连接到 I²C 板上的 SCL。

  2. 将电池连接器的正极(红色)电线连接到 SPST 开关的一侧。将开关的另一侧连接到 Nano 板上的 VIN 端口(一些克隆板可能标为 RAW)。

  3. 将电池连接器的黑色(负极)电线焊接到 Nano 板上的 GND 引脚。

    最后,将 Nano 板连接到传感器通道,步骤如下:

  4. 准备一个四导线女性 Pololu 连接器,带有大约 3.5 英寸长的四根彩色编码导线。将两根导线(建议使用红色和黑色)从此连接器连接到 Nano 的 VCC 和 GND 引脚。

  5. 将剩余的两个连接器连接到 Nano 板上的 2 号(D2)和 4 号(D4)引脚。

  6. 在外壳的一侧开槽或打孔,并将带有传感器通道连接器的 Pololu 连接器穿过孔洞(见图 8-11)。

    image

    图 8-11:外壳上的一个槽口,用于穿过四针传感器通道连接器。该连接器使用双面胶粘贴安装

  7. clr按钮的一端连接到 GND,另一端连接到 Nano 的 RST(重置)引脚。

  8. 最后,连接电池,拧上外壳顶部,插入传感器通道,翻转开关打开设备。

你应该准备好使用你的 Chronograph Lite 了。请参考“最终设置与操作”(ch08.xhtml#ch08lev1sec5)),获取关于如何使用 Chronograph Lite 的说明。

全弹道测速仪

虽然 Chronograph Lite 工作良好,并且我成功地用它测量了投射物的速度,但我一直有一种感觉,它还可以做得更好。如果你用这个设备测量低速投射物——即 600 fps 或更低——Chronograph Lite 的准确度完全足够。但由于分辨率限制在 4 微秒,在更高速度下,精度出现了我认为有一定误差的情况(单位为英尺每秒 fps),因此我决定构建全弹道测速仪。

所需工具

烙铁和焊锡

电钻和钻头(1/2、1/4 和 1/8 英寸)十字螺丝刀和平头螺丝刀 锯(钥匙孔锯或军刀锯)

零件清单

组装全弹道测速仪相对简单。你需要以下材料:

一个 Arduino Nano 或克隆板

一个 16×4 LCD

一个 I²C 适配器(如果 LCD 中未包含) 一个 PCB 保护板

一个外壳(Hammond 1591 BTCL)

四个 1/2 英寸×4-40 螺丝 四个 4-40 螺母

一个 3PDT 拨动开关

两个瞬时按钮开关 四个 0.100×4 的女性接头

四个母座 X4 外壳

十六个(八个公头,八个母头)适配器引脚 一个 4 MHz 晶体

一个 TI SN 74LVC1GX04 晶体振荡器驱动器 一个 SOT23 适配器板

一个 HCT 4011 四输入 NAND 门 一个 CD4013 双 D 触发器

一个 CD4040 12 级二进制计数器 一个 ADC DAC8562 数字模拟转换器 一个 LM7805 电压调节器

一个 NPN 晶体管 2N5172(或等效) 四个 5 千欧姆、1/8 W 的电阻器

一个 1 兆欧姆、1/8 W 的电阻器

一个 1 千欧姆、1/8 W 的电阻器

一个 1.5 千欧姆、1/8 W 的电阻器

一个 270 千欧姆、1/8 W 的电阻器

一个 4.7 μF 钽电容器 两个 33 pF 电容器

一个 0.01 μF 电容器

一个 5 毫米 LED

两个 IR 探测器(我使用了 Honeywell Optoschmitt SD5610) 两个 850–950 纳米的 IR LED 28 号或 30 号连接线

注意

对于完整的弹道计时器,你需要使用芯片的反向版本 SA5610,或者外部反转信号。请参见 图 8-3 底部的说明

下载

草图 FullBallisticChronograph.ino

模板 ChronoCover.pdf, AccelerationChannel.pdf

PCB ChronoPCB.pcb, LEDHolder.pcb, SensorHolder.pcb

提高准确性

改进计时器准确性有几种可能的解决方案。Arduino Nano 使用的是 16 MHz 时钟,但在使用 Arduino Nano 平台和 IDE 配置时,其分辨率为 1 微秒(±2 微秒),尽管 16 MHz 时钟的周期——即周期之间的时间——是 1/16,000,000 秒,或 0.063 微秒。虽然处理器无法精确到自身时钟速度,但它可能远超 1 微秒的精度。显然,目前项目中存在一些开销——可能部分来自硬件(Arduino 板上的组件)和部分来自软件(IDE 的编译器和固件部分)——这些都限制了性能。以下是我提出的一些提高准确性的想法,从一个未能进入最终项目但我认为具有教育意义的想法开始。

深入研究机器代码

一种可能的解决方案是深入研究基础的 Atmel 机器和 AVR 代码。不必详细讲解,AVR 汇编语言是 Atmel 芯片的功能性语言。Arduino 社区为其提供了特定的代码,使 AVR 能够在 Arduino 环境中运行。

根据 ATmega328 的数据手册,可以直接访问 ATmega328 上的各个定时器,以获得所需的分辨率。然而,经过研究,我发现这种方法可能会过于复杂,认为一定还有其他方式。

创建高速窗口

我们希望查看的弹丸飞行时间范围大约是 90 微秒(在 3 英寸距离内约为 3000 fps)到 950 微秒(在相同的 3 英寸距离内约为 260 fps),从最快到最慢。与一些时钟的高频率(如处理器的 16 MHz 时钟)相比,90 微秒已经算是相当长的时间。

测量速度的一种方法是在第一个光束被中断时打开一个定时窗口,允许高速信号通过,直到第二个光束被中断。在窗口打开时,信号中的脉冲将被计数;当窗口关闭时,计数值将表示窗口打开的时间。

例如,假设窗口打开,一个每秒 10 个周期(cps)的信号通过,直到窗口关闭;此时计数了 100 个周期。在这个例子中,Arduino 的时钟就是高频信号。当你知道了投射物的行进距离后,可以使用简单的算术来确定行进时间和速度:10 cps 下的 100 个周期给出了 10 秒。如果距离是 1 米,而窗口打开时计数了 100 个周期,那么速度就是 1 米/10 秒,即 0.1 米/秒。

一个单一的 NAND 逻辑门可以用来制造一个可以打开和关闭的窗口。逻辑门只是一个电子控制的开关,仅在特定条件下输出电压,对应于布尔逻辑方程式。NAND是“非与”的布尔表达式,当两个输入不相同的时候,NAND 门会输出电压。

我测试了 74HC00 高速 NAND 门和标准 CD4011BC 门,标准部件工作良好。还有一些其他部件也可以使用——你需要的是一个传播延迟(T[PD])小于 100 纳秒的部件。

选择计数器

在决定采用窗口方法后,接下来要考虑的是需要计数的最大值。例如,如果你要从 1 计数到 100,你将需要一个能够计数到 100 的计数器,这样的计数器将提供 100 的分辨率。如果你将这个范围扩大,计数器的范围可以是 10 到 1,000,或者是 100 到 10,000。如果这个范围是 fps 计算的结果,那么你将只有 1,000 fps 的分辨率(每次增加将等于 100 fps),加上任何可能的误差,我们稍后会详细讨论。

那么接下来该怎么做呢?当然是去零件箱看看有哪些计数器可以用来计数通过该窗口的信号。当选择计数器时,你需要考虑它需要多快以及需要计数多少脉冲。经过验证的 CD4040,12 位,串行输入,平行输出数字计数器似乎能够完成这项任务。(CD4040 的工作频率为 4 MHz,但你总是可以使用更快的计数器,如 74HC4040 或 74HCT4040。)CD4040 将提供从 0 到 4095 的数字计数,或 2¹²。

选择时钟频率

接下来,考虑需要什么样的信号频率来适应投射物速度的范围。我假设我想要实现一个目标。

大致范围从 300 fps 到 2,500 fps,尽量在两端保留尽可能多的宽容度。

此外,尽管计数器理想情况下会从零计数到最大值 4,095,但也存在一定的误差。因此,我有些随意地选择了查看从 400 到 4,000 之间的总数字计数,以考虑可能的误差。

给定计数的周期数、信号频率和行进距离,可以通过以下计算得出投射物的速度:

image

让我们来计算一下一个弹丸在 4,000 个 2 MHz 信号周期内行进 0.25 英尺(3 英寸)的情况:

image

对于 4 MHz 的时钟,一个完整的 4,000 周期计数将在速度范围的低端大约为 281 fps。在高端,考虑到计数了 400 个周期并且使用 2 MHz 时钟信号,你将测量到 1,250 fps,而在 4 MHz 时,你可以测量到 2,500 fps。

你可以对频率进行创意性设计。如果你选择使用 2 MHz 的时钟,它将在非常低速范围内提供最大分辨率。另一方面,如果你选择 4 MHz 的时钟,它将位于分辨率范围的中间。8 MHz 的时钟将在快速范围内提供非常好的分辨率(比任何常规武器都快),但会在低速范围内限制性能。

由于我预期我需要测量的大多数速度都将在计数范围的中间,因此大约 4 MHz 的时钟听起来是合适的。我并未预见到很多速度会低于 300 fps,而在高端,看来精度可以保持在 5,000 fps 以上(数字计数接近 200,可能有点超出,但在模拟中似乎效果不错)。

如果你的弹丸仍然处于低于 300 fps 的范围,我建议重新考虑使用 Chronograph Lite。如果因为某种原因,你想保持在较低的 fps 范围内,但又需要最大精度,可能需要多个数字,那么可以构建一个时钟速度较慢的完整弹道计时器。你只需要将 4 MHz 的晶体换成 2 MHz 的晶体,并调整程序代码,将范围滑动到较低区域。

调整时钟速度

为了处理时钟的速度(即传递到计数器的信号),迄今为止最准确的方法是使用晶体控制振荡器,这种振荡器通常只有低于 50 万分之一的误差。我使用了一个 4 MHz 的晶体和 TI SN 74LVC1GX04 晶体振荡器驱动器进行实验配置,它表现得非常好,因此我在最终项目中使用了它。

尽管我查看、评审并测试了单芯片振荡器,如 Maxim 独立振荡器(7375),它的稳定性不如晶体控制版本。

设计完整的弹道计时器

现在,我们已经有了将信号传递到 4040 计数器的手段,但我们需要弄清楚如何在 LCD 上显示速度。一种方法是使用一个具有串行输出的不同计数器,直接将其时钟信号传输到 Nano 上。另一种可能的方法是将来自 CD4040 的并行数据通过移位寄存器串行化,然后将结果传递给 Nano。

然而,我采取了不同的方向,如图 8-12 中的框图所示。我决定使用一个 12 位的数模转换器(DAC)来接收并行数字信号,并将其转换为单一的模拟值。DAC 和其对应的模数转换器(ADC)广泛应用于数字音乐、电视以及其他许多需要将模拟输入数字化、处理、传输、存储,最终输出以返回模拟信号的领域。我认为这是一个很好的机会来介绍数模转换器的功能。

image

图 8-12:全弹道计时器的框图

图 8-12 中的过程展示了使用模拟器的计时器操作。在实际操作中,模拟器将被两个 LED 传感器对所替代。在发射开关的控制下,模拟器启动一个启动信号,该信号会保持激活状态,直到第二个停止开关在由方波发生器确定的时间间隔后被激活。这基本上模拟了弹丸通过第一个传感器对,再通过第二个传感器对的过程。

当启动开关最初被激活时,它会打开触发器——一个双稳态设备,随着启动开关的激活而打开,并保持开启,直到停止开关被激活。触发器向门的触发端输入信号。当触发器(T)未激活时——即,当其设为逻辑 0 时——来自振荡器的信号(A)无法通过门传递到输出(B)。当触发器被激活(设为逻辑 1)时,门允许来自振荡器(A)的信号通过门传递到输出(B),并最终传递到二进制计数器的输入。二进制计数器计数通过门传输的脉冲数,并在门关闭时停止计数。

二进制计数器的输出被送入 DAC,它们表示从 0 到 4,095 的二进制数——即 0 到 2¹² - 1。DAC 将这些数字值转换为单一的模拟值。这个转换的技术取决于使用的 DAC 类型;例如,在此处使用的 DAC8562 中,切换 R-2R 电阻梯形网络,并使用晶体管来产生输出。(要获取完整信息,请查阅来自 Analog Devices 的 DAC8562 数据手册。)

DAC 的输出范围为 0V 到 4.095V,且与数字输入值对应。然后,该输出被导入 Arduino Nano 的一个模拟输入,Nano 提供 DAC 的逆向功能,将模拟信号转换回 Nano 能够处理的数字格式。Nano 接收该信号,并根据草图中的指令,调整该值以表示弹丸在 3 英寸距离内所需的速度(fps)。最后,Nano 将该数据发送到 LCD 显示器,显示弹丸的速度和旅行时间。

原理图

图 8-13 和 8-14 展示了完整的全弹道测速仪原理图。注意底部的额外门电路。我将它们包含在原理图中,因为它们在为这个项目建议的 NAND 门和触发器 IC 封装中是可用的,但我的设计并没有使用它们。如果你想增加功能,它们是可以使用的。

image

图 8-13:全弹道测速仪的原理图

我们还没有讨论的是原理图中包含的复位按钮。在全弹道测速仪中,我添加了一个按钮来触发复位,而不是让它自动复位。我本可以设置为在系统复位之前,结果会在 LCD 上显示一段固定时间,但这样可能会导致数字在用户有时间记录之前就被擦除,或者用户可能会发现自己在等待超时时什么都不做。我决定使用复位按钮会更加方便。

因为复位微控制器不会打乱事物的顺序,所以我选择通过晶体管 Q1 对控制器进行硬复位。为了复位 CD4040 和 DAC,我使用了复位信号,并通过 CD4011 的四个 NAND 门之一反转该信号,将两个输入接在一起。SW2 手动关闭第二组传感器,以防第一组传感器触发而第二组没有触发,SW3 是电源和电池开关。

image

图 8-14:如果使用 SA5600 而不是 SA5610,针对 Optoschmitt 或 Adafruit 传感器的反相器电路。该电路使用 CD4011 NAND 门的未使用的门作为逻辑反相器。它们没有在 PCB 中布局,所以你需要手动接线

原理图草图

全弹道测速仪的原理图相对简单:


      //Full Ballistic Chronograph 

      #include <Wire.h>
      #include <LiquidCrystal_I2C.h> 
      LiquidCrystal_I2C lcd(0x27, 16, 2); 
      int DACpin = A0; 
      float DACvalue = 0; 
      float FPS; 
      float Time; 

      void setup() {
        lcd.init();
        lcd.backlight();
      }

 void loop() {
➊   DACvalue = analogRead(DACpin);
      Time = DACvalue*5/1023/4*1000;
      FPS = .25/Time*1000000;
      lcd.setCursor(0,0);
      lcd.print("Speed  ");
      lcd.print(FPS,0);
      lcd.setCursor(11,0);
      lcd.setCursor(0,1);
      lcd.print("Time  ");
      lcd.print(Time); 

      lcd.setCursor(11,1);  
      lcd.print(char(0XE4)); //To display the mu symbol, use 228 or 0XE4
      lcd.print("s");
  }

在这个草图中,软件接收来自 DAC 在 X 点的模拟信号,并将其转换为数字值。然后,它经过几个快速的数学运算来得出飞行时间(Time),计算每秒英尺速度(FPS),并最终将这些值导出到 LCD 显示器。

在设计电子电路时,硬件和软件之间总是存在权衡。这些很多都与时序问题和软件方法中的内建延迟有关。在这种情况下,权衡在于需要更高的精度,而这在使用直接的 Arduino IDE 方法时是无法获得的,除非转向某种本地代码。为了避免使用本地代码,全弹道测速仪比 Chronograph Lite 有更复杂的硬件。

电路板

与 Chronograph Lite 不同,Full Ballistic Chronograph 最好在一个扩展板上构建。这个扩展板比书中其他一些扩展板稍微复杂一些,但不要被吓到。图 8-15 展示了扩展板的实际走线,而图 8-16 展示了带有元件位置和孔位配置的丝印图像。对于这个项目,我选择了双面电路板,因为电路比其他一些电路复杂,并且它能让我最小化所需空间。完整的 PCB 文件可以在 www.nostarch.com/arduinoplayground/ 上下载。

image

图 8-15:扩展板的走线图。深灰色是上层铜层,浅灰色是下层铜层

image

图 8-16:扩展板上的元件放置图

我尽量将扩展板的占地面积保持在最小,以便用户可以将系统放入一个小型便携外壳中。完成后的 Full Ballistic Chronograph 可以轻松放入一个 11×8×4 厘米的盒子里。

这是另一个我选择将 PCB 制造外包的案例,在我自己制作并完善了第一个样品,确保所有关键连接都能在电路板的两面焊接后,图 8-17 展示了从服务机构收到的原始电路板。

image

图 8-17:Full Ballistic Chronograph 电路板在元件放置前的状态

焊接 Full Ballistic Chronograph

一旦你有了所有的元件,按照这个指南来构建 Full Ballistic Chronograph:

  1. 准备振荡器适配板,先将引脚头焊接到位。使用“使用 SOIC”中建议的方法之一,将芯片焊接到适配器上,第 20 页提供了详细步骤。

  2. 开始填充 PCB。我通常喜欢从放置在 Nano 下方的组件开始——在这种情况下,是振荡器适配板、电阻器、晶体和 CD4011\。将它们按图 8-15 所示放置到 PCB 上。接下来,我喜欢加入 Nano 插入的引脚头。再次强调,不必完全填充所有的 Nano 引脚头。虽然偶尔我会使用完整的引脚头,但我通常只填充有连接的那些引脚头,以及顶部的一个对,以简化在插入 Nano 时的对准。此外,还应该有足够的引脚头来机械支撑 Nano。现在将这些引脚头焊接到位。

  3. 填充板上的其余部分,包括 I²C 显示器和传感器通道的接头。将电线引线焊接到板上的复位开关、清除开关、LED 和正负电源的连接处。引导传感器——即第一个被投射物体打断的传感器——应连接到 4013 的第 6 脚,无论是否使用反相器电路;另一个传感器应连接到第 4 脚。

构建

图 8-18 显示了外壳中孔和切割孔的位置。你可以从www.nostarch.com/arduinoplayground/下载图 8-18 并将其作为模板使用。

image

图 8-18:外壳盖上的孔和 LCD 切割孔

按照以下步骤准备全弹道计时器的外壳:

  1. 按照图 8-18 所示,准备外壳盖,钻出 1/2 英寸的孔用于切割 LCD(A);钻出 1/8 英寸的孔用于安装 LCD(B);用扩孔器将 1/8 英寸孔扩大,以便 5 毫米 LED(F)紧密安装;以及钻出 1/4 英寸的孔用于瞬时清除开关(D)、瞬时复位开关(E)和开/关开关(C)。

  2. 标记 1/2 英寸孔(A)的边缘,并连接切线——你可以使用马克笔,稍后用酒精清理多余的标记。

  3. 使用钥匙孔锯或弯锯切开显示屏的开口。

  4. LCD 的右侧中央(面朝上)有一个轻微的突起部分,这是背光组件的一部分。你可以像我在全弹道计时器和 Chronograph Lite 上做的那样切一个孔以容纳它,或者保持边缘直线,并使用垫片防止突起部分接触到外壳。即使我为突起部分切割了空间,我仍然使用了一个单个螺母垫片,以便将显示屏顶部的连接从外壳前部隔开(参见图 8-19)。

    image

    图 8-19:四导线母连接器通过双面胶粘贴在外壳侧面

  5. 将 LCD 的 I²C 组件安装到外壳的前面。

  6. 将开关安装到外壳上。按照图 8-13 中的原理图连接开关和 LED。按照"焊接全弹道计时器"中第 3 步的说明使用带引线的电缆(见第 244 页)。

  7. 准备电缆组件,将屏蔽板连接到 I²C 适配器以及连接全弹道计时器与传感器通道的 4 针母连接器。(如果你以前从未制作过连接器,请参见本书中使用的连接器,可在第 18 页查阅。)

  8. 使用双面胶将屏蔽板粘贴到外壳底部。

  9. 使用 4-40 平头螺丝或双面胶固定电池架。

  10. 在外壳的一侧切一个口子,将电线穿过连接器连接到传感器通道。单根钢锯片的宽度足以容纳 28 号电线。

  11. 使用双面胶将传感器通道的连接器固定到外壳上,如图 8-19 所示。

传感器通道

我们在本章早些时候建立了一个传感器通道测试台,但现在我们将构建一个更为永久的传感器通道,并查看我们将在其中使用的传感器和 LED 配对。

构建传感器通道

传感器通道是一个 U 形隧道,固定在武器的枪口上,容纳处理开关的光电探测器/LED 配对。这个通道可以由多种材料构建。我使用了 3/8 英寸厚的亚克力和两块 0.060 英寸厚的铝片(见图 8-20)。

image

图 8-20:从上方(正面朝上)看到的完整传感器通道。注意亚克力上为 LED 的正负电源连接所开设的通孔(标框)。还注意到 PCB 上用于 LED 的限流电阻(标圈)。交叉纹理区域是泡沫胶带,用于保护武器的滑块免受刮擦

你也可以使用轻型钢板作为侧面部件。顶部部件,如图 8-20 所示,可以采用任何轻质材料,如酚醛塑料、Lexan 或其他塑料,以支撑侧面部件。我选择了透明亚克力,因为它让我能看到枪支内部,而不必看枪管。你可以在图 8-21 中看到更宽的视角,整个通道,包括传感器电缆。

image

图 8-21:连接电缆并安装好 PCB 的通道,确保连接器面朝后方(武器连接处)

有两块 PCB,分别用双面胶带固定在通道的两侧,用于容纳 LED 和光电传感器。这些 PCB 彼此略有不同,如图 8-22 和图 8-23 所示。这些电路板的 PCB 文件可以在www.nostarch.com/arduinoplayground/下载。

image

图 8-22:用于容纳 LED 并安装到传感器通道上的 PCB 图案。注意限流电阻

image

图 8-23:传感器通道光电晶体管一侧的 PCB 图案。注意每个光电晶体管的三个引脚。边缘的接触点是用来焊接连接头的,连接头通过脐带电缆与主处理和显示板连接

传感器通道的亚克力顶部尺寸为 1 3/8 × 7 5/8 英寸。我使用了一根直木棒将枪管与传感器/LED 对齐。请注意,在亚克力顶部有一个小的凹痕,这是用 1/2 英寸钻头打出来的,以便让 Crossman T4 气手枪的光学瞄准器能够对准。

用于侧面的铝板尺寸为 1 3/8 × 7 5/8 英寸。我用 #30 钻头钻了孔,将铝侧面固定到亚克力顶部,孔距为 1 英寸。亚克力使用 #43 钻头钻孔,并进行了 4-40 螺钉攻牙。有关亚克力和铝件钻孔的规格,请参见图 8-24。亚克力的孔是穿过宽度方向钻孔的。

image

图 8-24:传感器通道的亚克力顶部和铝侧面孔位的尺寸。此模板可以下载并作为标记和中心打孔的模板使用

此外,作为 LED 侧到光电传感器侧的线缆穿过孔,我在亚克力和铝件上的第四个安装孔两侧各钻了两个 #43 的孔。这些孔的具体位置不是特别关键。

除了用于固定亚克力的孔外,铝板还需要在每侧钻两个孔用于安装 LED 和光电传感器对,以及在一侧再钻两个孔用于将其安装到枪管(滑套)上(如 图 8-24 中的 A 和 B),使用 #25 钻头钻孔并攻牙为 10-24 螺钉。看看 IR LED 的大小。大多数是 5 毫米,3/16 英寸的孔通常适合。Optoschmitt 传感器也能紧密适配 3/16 英寸的孔。LED 和光电传感器的孔可以精确地间隔 3 英寸,或者你也可以自行测量,以便与安装在侧面的 PCB 匹配。

根据你打算使用的武器,你可能需要调整图 8-24 中 A 和 B 孔的位置。传感器通道还可以容纳更多的攻牙孔,以适配多个武器。为了将传感器通道安装到枪的顶部,我使用了带锁紧螺母的尼龙螺丝。尼龙螺丝能够紧固在手枪的蓝钢表面上,而不会损伤其表面。

用于安装枪支的螺丝在 Crossman T4 上以及在旧款 Crossman 气枪上都能很好地工作(见 图 8-25)。

image

图 8-25:安装在旧款 Crossman 气枪上的传感器通道。这个角度展示了通道的顶部(亚克力)部分

在通道内部,我放置了一些双面胶泡沫带(如果你能找到单面胶泡沫带,那就更好了),以便更紧密地适配,并保护武器免受损坏。我保留了泡沫另一面的保护膜,这样它就不会粘到武器上或损伤表面。

根据你使用的武器,你可能需要在通道中增加一层泡沫,以便将枪管的中心靠近通道的中心。但是,只要枪管没有偏离到足以让弹丸击中 LED 或光电探测器的位置,完美地将枪管居中并不是至关重要的。

然而,确保垂直调整的居中是至关重要的,以便 LED/探测器对能够与弹丸的轨迹对齐。为了设置这个对准,我使用了一根直木棒,直径与枪管的孔径相同,部分插入到武器的枪管中,然后调整位置,使其与 LED/探测器对齐。一旦对准好,就用尼龙螺丝将通道固定在武器上。

Optoschmitt 光传感器和紫外线 LED

在准备传感器通道时,我测试了几种不同类型的 LED 和探测器,看看哪种在价格和性能上最好。通过 eBay 购买的单元(紫外 LED 和光电晶体管组合)效果很好,我在早期的原型版本中使用了它们。然而,我继续寻找一个我确信足够快速且能在狭窄的领域内提供良好灵敏度的传感器,这有助于排除环境光。经过多次筛选,我选择了霍尼韦尔的 Optoschmitt SD5610 探测器——大概因为它包括了施密特触发电路(见图 8-26)。

image

图 8-26:我在测速仪中使用的 Optoschmitt SD5610 探测器的示意图。请注意,10 千欧的上拉电阻已包括在内,但示意图中没有包括反向器功能

Optoschmitt SD5610 传感器稍显昂贵,但它具有 6 度的接收角度,适用于各种大小的弹丸,包括非常小和非常大的弹丸。它还有效减少了环境光的影响。

根据制造商的说法,光电探测器由光电二极管、放大器、稳压器、施密特触发器和一个带有 10 千欧(标称)上拉电阻的 NPN 输出晶体管组成(见图 8-26)。内部的上拉电阻消除了电路中外部电阻的需要。需要注意的是,这个设备有两个版本:SD5600 和 SD5610。SD5610 包括一个反向器,因此当环境光超过开启阈值时,输出为低电平。由于我需要反向输出,我使用了 SD5610。它的光谱灵敏度在 800 到 850 纳米波长范围内最大,这是大多数常见红外 LED 的波长范围。有关 SD5600 系列的更多信息,可以访问霍尼韦尔网站。

对于 LED,我使用了声称输出在 850–950 纳米范围内的普通红外 LED。我只是通过 eBay 买了一袋 50 个单位的 LED,它们工作得很好。或者,SparkFun 也非常便宜地提供单个 LED。

LEDs 和光传感器应焊接到为它们设计的 PCB 上,并应紧密适配到孔内。我使用一些标准的 3M 双面胶带将 PCB 固定在加速通道的两侧。

传感器脐带电缆

我用来将传感器通道连接到全弹道测速仪 PCB 的电缆由四根 30 号电线扭在一起,使用胶带固定,并在每端连接一个四芯的 Pololu 母接头。这些接头没有极性,也没有定位槽,因此可以相对容易地拔出或插反。在插入之前,确保对齐彩色电线。

注意

我最初尝试使用一根四芯电话线,但它太硬,导致了一些问题

通道和完成的测速仪可以轻松连接。如果你使用了彩色电线,你会知道插头连接正确,因为它没有极性。

最终设置与操作

完成单元和传感器通道的组装后,是时候将其带到射击场试试了。Chronograph Lite 和全弹道测速仪都设计为由电池供电,因此无需插电。将脐带电缆连接传感器通道与测速仪单元,然后将通道牢固地安装到武器上(见图 8-27)。

image

图 8-27:完成的全弹道测速仪,传感器通道安装在 Crossman 0.177 口径气枪上

一旦通道连接到武器上,通过使用与枪管孔径相同直径的直木棍或制作一个简单的适配器,利用一段直管将武器的枪管与通道中的 LED/传感器对齐(见图 8-28)。

image

图 8-28:使用小直径的黄铜杆和特氟龙端部设置 Crossman T-4 CO[2]手枪的枪管与传感器/探测器之间的正确对准

警告

操作武器时请始终小心。不要直接看着枪管对齐。请通过传感器通道的透明有机玻璃顶部观察

使用全弹道测速仪

在尽可能对齐枪管后,打开全弹道测速仪并按下复位按钮。小心瞄准目标并射击。弹丸的速度(以每秒英尺为单位)以及弹丸在传感器间移动 3 英寸所需的时间应显示在 LCD 屏幕上。要进行另一次测量,只需按下复位开关并再次射击。

如果不小心未能正确地将武器对准通道,可能会导致弹丸中断第一个光电传感器组,而非第二个光电传感器组。在这种情况下,你可以按下清除开关,然后按下重置开关,再次尝试。清除开关仅仅是断开第二组光电传感器的连接。

全弹道计时器应提供从约 300 fps 到超过 2,000 fps 的精确读数。

使用 Chronograph Lite

Chronograph Lite 的操作方式与此类似,只是它会自动重置,因此无需重置按钮。然而,如果弹丸未能中断第二组传感器/探测器,则需要通过按下清除按钮来清除显示。实质上,这和中断第二个传感器/LED 对的作用相同,但你应该始终使用清除按钮,而绝不应尝试用外部物体——尤其是你的手指——去中断第二组传感器/探测器。如果武器不小心发射,你可能会受到严重伤害。Chronograph Lite 可以提供从约 200 fps 到超过 1,000 fps 的精确测量,但其精度在接近 700 fps 时会有所下降。

高功率武器测试

除非你有丰富的枪械使用经验,否则我强烈建议不要使用 Chronograph 来测量高功率武器。尽管如此,我还是在一些高功率武器上测试了全弹道计时器。

图 8-29 显示了安装在史密斯菲尔德 XP/M 9 毫米半自动手枪上的传感器通道。我用多种弹药测试了全弹道计时器,测量结果与制造商提供的子弹规格误差仅在几 fps 之内。例如,雷明顿 JHP 声称子弹速度为 1,155 fps,而我测得大约为 1,152 fps。其他武器的测量结果也接近公布的速度。

image

图 8-29:一把配备全弹道计时器传感器通道的史密斯菲尔德 XP/M 9 毫米手枪。为了安全起见,弹匣被故意倒插。

第十章:方波发生器**

image

信号发生器,也叫波形发生器或函数发生器,产生交流(AC)电压,可用于各种电子测试和诊断程序。像你将在本章中构建的方波发生器(如图 9-1 所示)是一种电子实验室仪器,它产生一系列等间隔的电脉冲,这些脉冲在一定时间内保持开启,随后关闭相同的时长,再次开启,循环往复。

image

图 9-1:完成的方波发生器

为什么要构建方波发生器?

像这样的信号发生器常用于执行诊断任务,从评估组件和子系统的频率响应到为正在开发的系统提供激励信号。信号发生器的一些具体用途包括:

• 观察放大器、衰减器或其他设备的完整性

• 测量电路的时间特性

• 模拟现实世界的开/关事件

本项目中的信号发生器部分主要是方波发生器。

什么是方波?

你问,什么是方波,它有什么用?方波是一种电信号,从零电压开始,升高到某个电平(其幅度),在该电平上保持一段时间,回到零电压,然后以对称的模式重复这一过程。

方波是电子学中最基本的波形之一,并且在许多方面是最有用的,部分原因是它同时具有直流成分和交流成分。直流成分指的是它在一段时间内保持在某个电压水平,然后几乎瞬间过渡到另一个电平。交流成分则是它以规律的周期重复这种过渡。图 9-2 展示了一个方波。

image

图 9-2:典型的方波

方波有一个幅度和周期。周期是一个完整周期的持续时间,单位可以是秒、分钟、毫秒、微秒等。频率是指在一定时间内(标准单位为一秒)发生的周期数,因此是周期的倒数。对于周期T,计算频率的公式为f = 1/T

方波的应用价值

方波在开发和测试电子产品时特别有用。例如,微控制器系统中的时钟本质上就是一个方波。在一些诊断和测试过程中,可以断开微控制器的内部时钟,并用信号发生器生成的外部信号替代——在这种情况下,方波或正弦波都能很好地工作。你可以在不同频率下测试微控制器。对于某些处理器,通常在测试过程中减慢处理器时钟是很有价值的,这样可以准确地看到软件故障发生的位置。

其他用途包括向被测试的设备发送信号,以便将电路调节到正确的值,或者检查设备的频率响应或完整性。方波发生器也可以作为脉冲发生器,用于测试各种数字电路。你会发现在第八章的弹道计时仪中,这个应用非常有用。

由于方波的电压从零开始并几乎瞬间上升,它也可以作为开关电压,在方波的频率下开关电路。在本章中的方波发生器的频率范围从 1 kHz 到约 30 MHz(包括分频开关后,可以降到 100 Hz)。通过电位器可以调节这个频率范围,因此你可以以不同的速率开关设备。这使得方波发生器几乎可以模拟任何重复的开关操作,这对于进行寿命测试应用时开关设备也非常有用。

其他有用的波形

方波只是常见波形中的一种。最常见的波形可能是正弦波,即正弦波形,其中波形是一个连续的曲线,一个周期代表 360 度。另一种在电子学中经常遇到的波形是三角波。图 9-3 中展示了这两种波形。正弦波和三角波的振幅和周期的测量方式与方波相同。

image

图 9-3:正弦波(上)和三角波(下)

这些波形各自具有特定的特点,使它们在不同的应用中发挥作用。例如,正弦波和三角波在电子音乐项目中都很重要。然而,本项目聚焦于方波,随着你在本章的学习进展,你会发现它可以以多种方式应用。

一个频率计

除了提供信号发生器,本项目还包括一个频率计,它可以读取波形频率,因此你可以在数字读数上显示发生器的输出频率。你还可以将频率计作为独立仪器,测量来自外部源的频率并显示它。这个项目还显示波形的周期或脉冲时间。

在操作过程中,频率计接收一个交流输入信号并计算每个脉冲。计算了一定数量的脉冲后,计数器将其与一个时钟信号进行比较,这个时钟信号有时被称为时间基准,并显示单位时间内的脉冲数量——例如,每秒的脉冲数或周期数。

为了确保准确性,计数器将脉冲与时钟进行比较,通常时钟是基于晶体的。对于需要最高精度的仪器,晶体时钟组件是一个精密的子系统,通常放置在温控环境中。这个项目中的频率计使用的是 Arduino Pro Mini 上的 16 MHz 晶体。实际上,Pro Mini 几乎具备了实现完整频率计所需的大部分电路,所需的额外组件非常少。它包括用于计数的时钟寄存器以及几乎所有频率计所需的其他组件,无需外部组件。

注意

专业的实验室和台式仪器,售价几百(或几千)美元,通常提供非常宽的频率范围,从低于 1 Hz 到几 GHz,并且提供从 6 位到 10 位的精度。它们的显示器还可以切换为读取频率或时间(脉冲间的时间)

为了完成这一切,方波发生器利用了 Arduino AT328 16 MHz,5V Pro Mini,它是 Arduino Nano 的一个更小、更便宜的版本。发生器还包含了特殊电路来分频,使你能够在一端提供非常低频率的输出,并允许频率计读取非常高的频率——超出了 Pro Mini 通常能够处理的范围——在另一端。

方波发生器的不足之处

虽然这个项目制作了一个方波发生器和一个在许多应用中表现良好的频率计,但与专业实验室和台式仪器相比,它仍有一些缺点。发生器的频率误差不到 1%,这对于爱好者项目来说是足够的,但无法达到实验室级别和直接数字合成器(DDS)发生器单元的容差。这些单元的误差通常以百万分之一(PPM)来衡量。而频率计使用的是 Arduino 的时间基准,尽管它准确,但无法与高价单元中的晶体烤箱和其他特殊电路相匹配。

这个发生器也没有提供多个数字的分辨率。许多实验室和台式仪器的分辨率可以达到多达 10 位数字。尽管如此,这个仪器在我进行的各种 Arduino 和其他项目中表现得很好,而这些项目并不需要更高的分辨率。

所需工具

电钻和钻头

锯孔锯

烙铁和焊锡

锉刀

零件清单

除了 Arduino Pro Mini 之外,你还需要一个线性技术公司的振荡器芯片和一些其他小组件。以下是完整的零件清单:

一个 Arduino Pro Mini 或克隆板(有几种可用,且一些具有不同的引脚配置,尤其是 A4 和 A5 引脚。图 9-4 显示了我使用的特定克隆板的引脚配置。其他具有不同引脚配置的单元也可以使用,但可能需要更改屏蔽板上的连接。)

image

图 9-4:Deek-Robot Pro Mini Arduino clone 的引脚配置图

一个 LTC1799 振荡器芯片和面包板兼容适配器板,类似于图 9-5 所示的 5-SOT-23 适配器板(有关如何使用这种表面贴装芯片的提示,请参见使用 SOIC 页面 20)

image

图 9-5:此适配器板包含一个完整的可调频率振荡器(1 KHz 到 30 KHz)和 CMOS 缓冲电路

一个 250 千欧的碳质电位器

两个 0.1 μF 陶瓷电容

一个 LM7805 电压调节器

两个 SPDT 中间开关

两个 SPDT 拨动开关

一个 HCT4017 十进制计数器 IC,类似于图 9-6 所示的 CD4017 B

image

图 9-6:CD4017 B 是一个 CMOS 计数器/分频器,由一个 5 级 Johnson 计数器和 10 个解码输出组成。在此作为 10 分频计数器使用

一个 1 μF 电解电容

一个 10 μF 电解电容

一个 20×4 LCD

一个 I²C 适配器(如果 LCD 未包含该适配器)

一个 PCB 屏蔽板(如果不想自己设计,请参见下载页面 262 上的页面 262)

一个 Hammond 1595C 斜面前端外壳(或同等产品)

一个电池座

一个旋钮

四个 4-40×1/2 英寸的螺丝和垫圈

八个 4-40 螺母

一块双面泡沫胶带

一个 9V 电池

各种 28 或 30 号连接线

(可选)四个香蕉插头插座 三个 BNC 连接器

(可选)一个 3.5 毫米插孔

(可选)一个 9V, 100 mA, 110V 墙壁电源适配器(更多信息请参见电池电源页面 278)

请注意,我选择在前面板上使用香蕉插头插座,尽管这有点过时,可能不是最佳做法。你可以用 BNC 连接器替换两个输出连接器,就像 pH 计项目中使用的那样,虽然价格稍贵,但它消除了对接地的需求,因为 BNC 连接器有一个中心导体和一个围绕它的屏蔽地。香蕉插座每个只有一个导体。

下载

草图 SquareWave.ino

前面板模板 SquareWaveEnclosure.pdf

PCB 铜箔图案 Generator.pcb

原理图

图 9-7 中的方波发生器电路所需的元件并不多。然而,在开始构建之前,请注意,Arduino Pro Mini 的引脚配置与 Nano 有很大不同。还需要注意的是,Pro Mini 有许多版本可供选择,因此购买时要检查所选版本的引脚排列。建议在零件清单中列出的特定 Arduino,其引脚排列在图 9-4 中有详细说明。有关主要差异的描述,请参见“关于 Pro Mini 的重要说明”(第 263 页)。

在原理图中,请注意开关:SW1、SW2、SW3 和 SW4。SW2 提供了 10 倍分频显示功能。SW3 允许你使用外部信号源代替信号发生器与频率计连接。SW1 连接主时钟的 1、10、100 分频器(该开关具有一个中位“关”位置,处于此位置时没有连接)供 LTC1799 振荡器使用。SW4 是电源开关;其中心位置为关,另外两个位置用于外部电源或电池。

image

图 9-7:方波发生器原理图

关于 Pro Mini 的重要说明

在搭建面包板之前,请注意,Pro Mini 板之间的一个主要引脚差异是 A4、A5、A6 和 A7 的布局。一些版本将所有四个模拟输入放置在板子的短边上,而本项目使用的 Deek-Robot 则将它们分开(见图 9-8)。它将 A4 和 A5 放置在其他模拟引脚附近,但不与它们对齐,A6 和 A7 则位于板子的短边。引脚 A4 和 A5 用于驱动显示器的 I²C 总线。

Pro Mini 和 Arduino Nano 之间有一些其他的小差异,但最显著的一点是 Pro Mini 没有 USB 接口,因此你必须使用外部串口接口进行编程。市场上有几种基于 FTDI 技术的串口适配器。(FTDIFuture Technology Devices International的缩写,是一家专注于 USB 技术的苏格兰半导体公司。)

使用基于 FTDI 的专用串口适配器的替代方案是使用另一块微处理器板来为 Pro Mini 编程。我使用一块 Arduino Uno 克隆板来为 Pro Mini 编程,因为它价格便宜,允许我移除处理器芯片,这样就不会编程两个板子,而且使用起来很方便。我使用一个简单的面包板设置进行编程。有关连接详情,请参见“上传草图到你的 Arduino”(第 5 页)上的内容。

image

图 9-8:Deek-Robot Pro Mini 与一把厘米标尺放在一起。其引脚排列与类似的 Arduino 克隆板略有不同。例如,引脚 A4 是 A2 和 A3 之间未标记的焊盘,而 A5 是 A3 和 VCC 之间的焊盘

方波发生器的开发过程

这个项目是为了应对在创建第八章中的弹道计时器时出现的一个需求。开发计时器时,我需要一种方法来测试它,确保它正常工作,而不需要使用带有实弹的武器,也不需要在我的车间里打洞。

方波发生器是我解决问题的方法。通过它和一些其他的小零件,我能够模拟出当一个弹丸打破一系列光束时,计时器应接收的信号。我决定从弹丸在 3 英寸(约 7.62 厘米)距离内所需的时间开始,这个时间在 50 到 1,000 微秒之间,具体取决于弹丸的速度。然后,我使用方波发生器生成频率在 20,000 Hz 到 1,000 Hz 之间的信号,这些频率是这些时间的倒数。一旦我弄清楚了计时器需要什么,方波发生器项目便发展出了它自己的生命,最终版本就是你在本章看到的样子。

决定如何生成信号

首先,我寻找了一种简单的方法来满足我的时间要求。有几款 DDS(直接数字合成)产品和板卡可以轻松解决这个问题,但我找到的所有解决方案都比我期望的要贵一些,而且很多还有其他缺点。在放弃 DDS 后,我查看了几种替代方案,其中一些让我回到了我的旧无线电爱好者时代。一种解决方案是使用晶体振荡器并通过分频器将基本频率分割,从而获得接近我需要的频率。这带来了几个问题,其中一个最大的就是电路可能需要多个分频芯片。

另一种解决方案是从零开始创建我自己的可调频率振荡器(VFO)。虽然这也是一个可行的选择,但这一解决方案需要比我当时准备做的更多的设计工作,所以我又回去查阅了数据表。

我发现 Linear Technology 的 LTC1799 单芯片精密振荡器几乎完全符合要求——而且还多了一些。根据数据表,这款芯片提供从 1 KHz 到 33 MHz 的方波信号,只需一个可调电阻和一个开关来将基本振荡器频率分频 1、10 或 100 倍。它的稳定性也相当好:名义上误差不到 1%。而且,它的价格远低于 DDS 解决方案,仅为不到 4 美元。

问题的最后一部分是要查看发生器生成的频率。如果没有外部频率计或经过校准的示波器,即使是接近的频率也很难获得。因此,项目扩展到了包含一个内建频率计。由于频率计反正已经在了,我还加了一个开关,允许我将频率计作为独立的仪器使用。

如何规划显示频率

现在我可以生成方波了,但仍然有一些其他问题需要解决。例如,我该如何读取外部频率呢?我可以通过标记电位器位置来进行校准——就像许多旧式发生器所做的那样——但在今天的数字时代,这种方法充其量也只是笨拙且不准确。内置的频率计数器和亮显示器似乎是最实用的选择。

我回到了绘图板——并且回到了 Arduino 库。我在网上找到了几种 Arduino 频率计数器的实现方式,包括至少两个独立的频率计数器库。对于这个应用来说,最简单和最方便的库是FreqCount.h,由 Paul Stoffregen 开发。我如何使用这个库将在“草图”中进一步讨论,见第 271 页。有关该库的更多信息或获取最新更新,您可以访问*github.com/PaulStoffregen/FreqCount/

初步的面包板原型表明频率计数器工作良好。我使用一个 20×4 的 LCD 显示器,并通过 I²C 接口将其连接起来,制作了面包板。在显示器上标注了Frequency字样,并在其下方显示了频率(以 Hz 为单位),我仍然剩下两行 20 个字符(见图 9-9)。

image

图 9-9:方波发生器的显示,显示频率和脉冲时间

我常说“浪费不得”。因为我计划使用方波发生器的至少两个项目需要均匀间隔的脉冲(差不多就是一个脉冲发生器),我决定使用显示器的后两行来指示脉冲的时间。在草图中计算时间相对容易,因为时间(以秒为单位)是频率的函数(T = 1/f)。

信号完整性

如果不深入信号组合的高级数学,方波可以被认为是无限多个正弦波谐波相加的结果。随着频率的增加,波形的复杂性和脆弱性也在增加。如果你将面包板电路连接到示波器,你可以亲自观察到这一点。

这个项目最初是作为一个方波发生器/频率计数器开发的,能够在 1,000 Hz 到 1 MHz 的范围内工作。这个发生器表现得非常出色,但其基本的振荡器芯片的工作范围远远超出了这个范围。

在开发这个项目时,我有两个选择。第一个是故意将设备的性能限制在最初提出的范围内,或者将其扩展到接近振荡器的极限,并在高频段遭受一些退化。我选择了后者。虽然方波在大约 15 MHz 时开始变得不规则,但在较低频率——即原定频率——下的性能完全不受影响。图 9-10 显示了不同频率下的四个示波器波形图,以作示范。

在 1 kHz 时,波形几乎完美无缺,你可以从我的老式模拟示波器的显示屏上看到这一点(见图 9-10A)。在图 9-10B 中,5 MHz 时,方波的边缘有一点点妥协,显示出上升沿有轻微的超调。当频率提高到 12 MHz 时,信号开始显得有些凌乱,失真更严重(见图 9-10C)。波形的一些失真是由调谐或某些元件的寄生电容和电感效应引起的。这是一个可以避免的现象,我之所以提到它,主要是让你了解波形的形状。我怀疑你大多数应用这个发生器的场景会是在低频区,低于 1 MHz,在这个频率范围内产生的波形可以说是最完美的。此外,我也在更高频率下使用过该发生器,稍微失真的波形几乎对结果没有影响。

image

图 9-10:四个示波器波形图,显示了方波发生器在 1 kHz (A)、5 MHz (B)、12 MHz (C) 和 20 MHz (D) 下的输出。很快就能看出,方波信号在约 12 MHz 时开始失去完整性

当频率超过 20 MHz 时,波形继续失真(见图 9-10D),但它们仍然可以完全识别为方波,并且仍然有效。在 30 MHz——方波发生器的工作范围极限——下,信号波形看起来越来越像正弦波,但对于大多数测试目的来说,它仍然完全有效。

听方波

一个有趣的实验,可以让你了解方波中存在的谐波,就是将方波发生器设置为可听频率范围,并将其输出连接到放大器和扬声器的输入。仔细聆听声音的质量。你听到的“噪音”是方波产生的丰富谐波的结果,这些谐波本质上由频率范围内所有其他正弦波的合成组成。

使用十进制计数器进行微调

在设计系统时,我最终决定添加一些功能,以提高系统的实用性和性能。频率计数器组装完成后,频率范围大约为 100 Hz 到最大约 10 MHz。LTC1799 振荡器的频率范围从 1 kHz 到约 30 MHz,对于大多数应用来说,这已经足够。但我考虑到的一些应用需要一个低至 100 Hz 的交流信号源。

嗯,结果证明有一种方法可以用一颗芯片“杀死两只鸟”:一个除以 10 的计数器——在这个例子中,是一个 HCT4017 或 CD4017 十进制计数器和几个开关。

十进制计数器接受一个交流信号,计数到 10,然后重新开始。通过查看其中一个计数器输出,它基本上是除以 10 的。

可以通过将振荡器的输出信号送入除以 10 的计数器,并在 LCD 上显示输出频率,而实际输出频率将是显示频率的 10 倍。这个变通方法允许方波发生器在 LCD 上显示高于 10 MHz 的频率,只要你能在脑中将小数点向右移动一位。另一方面,开关(SW2)可以被移动,以直接获取振荡器的输出,除以 10,使得最小输出频率可低至 100 Hz,或者是 1 kHz/10。

振荡器详细信息

这个项目的振荡器部分几乎完全由 LTC1799 单芯片完成,只需要一个外部可变电阻、一个旁路电容和一个用来将基本振荡器频率除以 1、10 或 100 倍的开关。频率除以多少,取决于你连接到 4 脚的组件。当将 LTC1799 的 4 脚或 DIV 脚连接到地(GND)时,频率除以 1;当 4 脚悬空或开路时,频率除以 10;当 4 脚连接到 5V 时,频率除以 100。这样,设备可以覆盖从 1 kHz 到 30 MHz 的频率范围。

此外,虽然我选择在 LTC1799 的 1 脚和 3 脚之间使用一个 250 千欧的电位器,但任何 3 千欧到 1 兆欧之间的电位器都是可以接受的。当电阻值增加时,频率会降低,反之亦然。

根据制造商的说法,LTC1799 在其频率范围内输出的方波相当清晰。然而,随着频率的增加,有许多因素会影响波形的完整性。这些因素包括由于电路布局引起的寄生电容和电感,如输出位置、可调电位器的连接、开关和其他元件。由于我考虑的大多数应用位于 LTC1799 提供的频率范围的低端,因此我没有严格关注布局,因此在较高频率下可能会出现某些完整性问题。请参阅图 9-10 查看实际信号轨迹。

面包板

就像我几乎所有的 Arduino 项目一样,在设计过程中,我总会制作一个面包板布局。图 9-11 展示了方波生成器的原型。

image

图 9-11:方波生成器的面包板

为测试接线面包板并不困难,唯一的例外是,当使用较长的互联导线时,振荡器在较高频率下会变得有些不稳定。

这是连接方式:

  1. 将所有的红色正极轨道和蓝色负极轨道连接在一起。务必小心,绝不要将红色轨道和蓝色轨道连接在一起。

  2. 将 LTC1799 振荡器模块尽可能靠近面包板的一端插入。请参见图 9-11 的最左侧。振荡器必须安装在适配板上,以便其适应面包板的 0.100 英寸间距,如图 9-12 所示。

  3. 将 Arduino Pro Mini 插入面包板。将 Pro Mini 的 5V 端子连接到面包板的红色正极轨道。

  4. 将 Pro Mini 的 GND 连接到蓝色负极轨道。

  5. 将 HCT4017 十进制计数器插入面包板。(它位于图 9-11 中的 LCD 左侧。)

  6. 将 LTC1799 和其适配板插入面包板。

  7. 将三位置(中断)开关 SW1 的一端连接到地。将另一端连接到 VCC,并将开关的中间引脚连接到 LTC1799 的第 4 引脚。

  8. 将开关 SW2 的一端连接到 LTC1799 适配板的第 6 引脚(或 LTC1799 的第 5 引脚)。

  9. 将电位器 R1 的一端连接到 LTC1799 的第 3 引脚。将 LTC1799 的第 1 引脚与电位器的另一端及其滑动端(即电位器的中间引脚)一起连接到红色正极轨道。

  10. LTC1799 的第 6 引脚将是振荡器的输出,连接到 HCT4017 的第 14 引脚和开关 SW2 的一只脚。

  11. 电容器 C1 应如描述那样安装在适配板上。

  12. 将 HCT4017 的 13 引脚和 15 引脚连接到地。

  13. 将开关 SW2 的另一端连接到 HCT4017(CD4017)的第 12 引脚。

    image

    图 9-12:SOIC 已焊接到适配板上,这样它就可以适配面包板的 0.100 英寸间距。该芯片只有 5 个引脚,但我使用了一个 6 引脚适配器

  14. 将开关 SW2 的中心连接到面包板上的空行。(我使用的是 Pro Mini 和 HCT4017 之间的一行)。

  15. 将开关 SW3 的一端连接到你在第 8 步中使用的相同空行,该行应与开关 SW2 的中心相连。

  16. 将开关 SW3 的中心连接到 Pro Mini 的数字引脚 5(D5)。

  17. 如果你在仅使用频率计模式下使用面包板,则开关 SW3 的第 3 引脚将作为输入。

    注意

    SW4,AC/电池开关,无需在面包板上配置,因为在编程 Arduino 时,电路可以从计算机获取电源。由于同样的原因,LM7805 在面包板配置中没有使用

  18. 检查你的 LCD。如果它已经焊接了 I²C 子组件板,你可以继续。如果没有,按照 “将 I²C 板固定到 LCD” 在 第 3 页 中的描述,将 I²C 板焊接到显示器上。

  19. 当你的 LCD 准备好后,你将需要四根公对母连接线来连接它。(在最终版本中,你可以为它做一个小的线束,包括 VCC、GND、SCL 和 SDA 的线。)我通常用红色和黑色表示正负电源,用绿色表示 SCL,用黄色表示 SDA。将 VCC 线插入红色正极轨道,将负极插入蓝色负极轨道,将 SDA 插入 Pro Mini 的 A4,将 SCL 插入 Pro Mini 的 A5。

最后,构建你的编程电路或插入 FTDI 适配器,将草图加载到 Pro Mini 上,你就可以开始了。

草图

随着项目的迭代,方波生成器的草图做了一些简化。得益于 LTC1799 和 FreqCount.h 库的集成(可以从 Arduino IDE 的库管理器部分获得),最终结果是一个相当简洁的程序。


/* Square Wave Generator Sketch. Gives a proper reading with multiplier.  
 * Parts of this sketch are derived from Paul Stoffregen's public domain  
 * example code.  
 */ 
#include <FreqCount.h>
#include <LiquidCrystal_I2C.h> 
#include <Wire.h> 

unsigned long freq = 0; 
float impulse; 

LiquidCrystal_I2C lcd(0x27,20,4);

 void setup() {
  lcd.init();
  lcd.backlight();
  FreqCount.begin(1000);  
} 

void loop() {
  if(FreqCount.available()) {
    freq = FreqCount.read();
    lcd.clear();
    lcd.setCursor(1,0);
    lcd.print(" Frequency");
    lcd.setCursor(0, 1);
    lcd.print(freq);
    lcd.setCursor(10, 1);
    lcd.print("Hz");
    lcd.setCursor(0, 2);
    lcd.print("Impulse");
    lcd.setCursor(0,3);

    impulse = ((1/(float)freq)* 1000000);
    lcd.print(impulse);  
    lcd.print("  uS  ");
  } 
} 

该草图首先包含三个库:FreqCount.h 用于频率计数器,另外两个用于操作 LCD。要将 FreqCount.h 添加到你的 Arduino IDE 中,进入 草图 ▸ 包含库 ▸ 管理库... 并从库管理器中安装 FreqCount 库。setup() 部分准备 LCD 并启动频率计数器。loop() 部分获取频率,计算脉冲宽度并显示两者。

Arduino 实际上与信号的生成无关——这完全是在振荡器和随后的分频器中完成的。Arduino 的功能是查看信号并读取频率。

注意

尽管 Arduino 的第 5 引脚连接到 LTC1799 振荡器,但我在这个草图中并没有将其设置为模拟输入。显然,这在 FreqCount 库中已经处理好了。有关不同 Arduino 型号的详细信息,请参阅“频率输入引脚” www.pjrc.com/teensy/td_libs_FreqCount.html 。顺便说一下,使用这个库会使模拟引脚 3、9、10 和 11 无法用作模拟输出(PWM)

扩展板

对于这个项目,我开发了一个小型 PCB 保护板,用于固定各种组件。虽然这个保护板本可以设计成只使用单层板,但我选择使用了双层板。首先,这大大减少了布线时间;其次,由于我同时在生产另一个双层板,我可以同时曝光并蚀刻它们,几乎没有额外的工作量。(当你可以同时蚀刻多个板时,这是更高效的。)图 9-13 展示了保护板的上下铜箔图案。

image

图 9-13:方波生成器的 PCB 保护板的顶部(左)和底部(右)铜箔图案

在保护板上组装组件时,特别需要注意旁路电容。0.1 μF 电容从 LTC1799 振荡器的第 1 引脚到地的引线越短,振荡器工作得越好。我实际上将电容直接焊接到芯片安装板上。

图 9-13 展示了保护板上的组件布局。请注意,HCT4017(CD 4017)位于 Pro Mini 的下方;PCB 是这样设计的,以节省空间,并将高频信号的走线保持在最小长度。

像其他项目一样,只有在 Pro Mini 的插针与板子连接的地方才需要填充连接器,此外在第 1 号引脚处还需要一个连接器,以简化 Pro Mini 在保护板上的对接。LM7805 电压调节器不需要散热片。

构建

构建方波生成器相对简单,但需要注意的是,我在布线开关 SW1 的引脚时并没有特别小心,SW1 提供了振荡器的分频器,或者在布置和布线电位器时没有特别注意。缩短这些引线——也许还需要调整组件本身的位置——可能会在较高频率下改善波形的完整性。图 9-14 展示了我的方波生成器的内部结构;如果仔细观察,你可以看到我手写的标注,指示各部分的位置。

image

图 9-14:所有组件轻松装入斜面面板外壳。LCD 通过四个螺丝固定,保护板通过双面泡沫胶粘剂安装在 LCD 上方。开关、I/O 插孔和电位器都是手工焊接的

准备外壳

首先,在外壳的前面标记以下孔位:

• 两个用于切割 LCD 的空间

• 四个用于 LCD 的安装孔

• 四个香蕉插孔

• 四个用于开关

• 一个用于电位器

如果你使用的是我在 “零件清单” 中推荐的 Hammond 1595C 倾斜前外壳(见 第 260 页)或类似的外壳,可以按照图 9-15 中的模板操作。只需找到本书资源文件中的 PDF 绘图,打印出来,将其放在外壳前面,并小心地用中心冲孔标记孔的位置。我还会用细尖的 Sharpie 马克笔标记位置并在外壳上画线。多余的马克笔痕迹可以用异丙醇轻松清除。

图 9-16 展示了如何利用外壳的半径来确定显示屏的位置。

image

图 9-15:方波发生器的钻孔模板

image

图 9-16:使用外壳的半径来定位 LCD 的位置

我按照以下顺序钻孔:

  1. 小心地在 LCD 切口的四个角钻 1/2 英寸的孔。如果你正确标记了孔的中心,显示屏的边缘将与孔的外径相切。然后,你可以连接孔的边缘画线,作为切割显示屏的指导。

  2. 使用钥匙孔锯或弯锯切割显示屏。外壳由相对较软的 ABS 塑料制成,所以切割应该不成问题。

  3. 如有必要,用锉刀清理切口处的碎屑,并检查显示屏是否合适。

  4. 钻四个安装孔(在图 9-15 中标记为 A)以安装显示屏。

  5. 钻四个 5/16 英寸的孔以安装香蕉插座(标记为 B)。

  6. 钻四个 1/4 英寸的孔以安装开关(标记为 C)。建议在外壳的内部使用永久性标记笔标出开关位置,以简化接线过程。

  7. 钻一个 9/32 英寸的孔以安装电位器(标记为 D)。

  8. 找一个你喜欢的位置,将 3.5 毫米电源插孔距离外壳边缘 3/4 英寸,距离底部 1/2 英寸。然后在该位置钻一个 1/4 英寸的孔来安装 3.5 毫米插孔。

  9. 使用四个 4-40 螺丝将 LCD 安装在外壳上。某些 LCD 屏幕的一侧有一个凸起,用于背光。如果你的 LCD 有这个凸起,你需要将 LCD 抬离外壳表面,以适应右边缘的背光部分(当你将 LCD 放置在顶部连接端时)。我通常在螺丝背面放置 4-40 螺母,以腾出空间。如果单个螺母不够(4-40 螺母的厚度不同),可以加垫圈。然后,将显示屏固定在外壳上。如果你的显示屏没有凸起部分,只需将显示屏直接固定在外壳上。

  10. 将香蕉插头插座和开关安装到外壳中。有时,将电线焊接到开关和插座上比直接焊接到外壳上更容易,以减少意外接触焊接铁而造成的外壳损坏。

布线电子元件

在将 PCB 屏蔽板安装到外壳之前,先将元件焊接到屏蔽板上,并将 LCD、电位器、开关、电源插孔和香蕉插孔的所有电线焊接好。你可能会发现先焊接开关和插孔的电线会更方便。如果不确定的话,可以在电线预留一些额外的长度,但记住一句话:“如果电线太短,你总是可以接上;如果电线太长,你就不知道怎么处理了。”我建议使用公母排针连接 LCD,以便更方便地接线。

我直接使用双面泡沫胶带将屏蔽板固定在 LCD 的背面。然而,这可能导致在较高频率下波形出现失真。你可能更喜欢将模块安装得尽可能远离显示屏。外壳的前面除了根据需要放置标签外,不需要特别处理。

设计笔记与修改

在实现本章所述的方波生成器版本之前,我玩过几次方波生成器的不同版本。在这个过程中,我调整了一些方面,并考虑了其他修改。虽然这一部分的想法没有进入这个项目,但你可以尝试自己实现它们。

以其他单位显示频率

草图以 Hz 显示方波频率,因为我计划的大多数应用都在 100 Hz 到 10 kHz 之间。但如果你发现自己在高频率下频繁使用该设备,查看六个或七个整数可能会令人困惑。别担心:只需截断显示,轻松就能将草图更改为显示 kHz 甚至 MHz 的频率。

要截断显示,只需添加一个逗号和你希望显示的数字位数。例如,要从 Hz 更改为 kHz,只需在草图中更改以下行:

lcd.print(freq);

lcd.setCursor(10, 1);

lcd.print("Hz");

改为这些行:

lcd.print(freq/1000);

lcd.setCursor(10, 1);

lcd.print("kHz");

如果你想减少显示的数字位数,请更改这一行:

lcd.print(freq/1000);

改为:

lcd.print(freq/1000,3);

你可以将3改为你希望显示的数字位数。

读取外部输入频率

原理图和完成的项目包括一个开关,用于从生成脉冲切换到读取外部输入的频率。开关(SW3)将输入插孔直接连接到 Arduino 的输入端(第 5 引脚),这是振荡器通常连接的地方。我已成功地将其用于各种应用,特别是当我想在车间外部快速读取频率时。

由于没有电路保护处理器,所以请小心操作。该设备旨在使用标准 TTL 电平的输入—0 到 5V。Arduino 对信号较为敏感,甚至可以检测到较低电平的信号。然而,如果你计划将其与非常低电平的输入(即低于 0.5V)一起使用,那么你应该构建某种预分频器或前置放大电路。

如果你计划将方波发生器作为独立的频率计使用,你可能需要考虑使用前置放大器来提供放大功能,并防止处理器损坏。一个简单的前置放大器示例见于图 9-17,它使用了 74HC14 六反相施密特触发器的六分之一。

image

图 9-17:频率计输入的可选前置放大器/缓冲器

使用前置放大器有助于保护 Arduino 的输入,因为前置放大器的输出将被限制在供电电压内。

电池供电

尽管这个项目最初是为外部电源设计的,但它可以轻松转换为电池供电。LCD 背光开启时的总电流消耗略低于 100 毫安。锌锰电池的容量大约为 500 毫安时。因此,你可以预计电池使用时间大约为 5 小时。碱性电池通常会表现得更好。

为了适应电池供电,我简单地将电源开关替换为一个带有中立位置的开关。我将一个外部端子连接到基于交流电的电源插孔,另一个外部端子连接到电池的正极,中心端子连接到 PCB 屏蔽上的正电源轨。电池的负极连接到地。当前电路图中展示了这种配置。如果你使用我建议的外壳,电池应能方便地安装。你可以使用双面胶粘贴电池座。

第十一章:色度温度计

image

这个项目最初是为了提供一个快速的本地温度视觉指示。最简单的形式,它是一个通过依次点亮不同颜色的 LED 来显示温度的温度计。然而,在开发过程中,项目增加了更多的功能,包括一个 LCD 显示屏来补充基本的颜色显示。在实验过程中,我遇到了一个 IC,它提供了极为准确的测量而无需特殊校准,从而大大提高了设备的性能。

色度温度计包括 10 个不同颜色的 LED,当传感器检测到特定温度时,每个 LED 都会亮起。原始版本设计用于测量 68 到 78°F 的温度,每个 LED 表示 1°F 的温度变化。后来,我根据不同的应用对其进行了调整。完成的项目如图 10-1 所示,可以测量广泛的温度范围。它还包括一个防水探头,用于测量液体中的温度,这对于鱼缸、游泳池等非常有用,并且可以构建成各种物理配置。在草图中显示的版本,温度范围从 76 到 86°F,温度变化为 1°F 的增量。

image

图 10-1:完成的色度温度计

你还可以通过在特定温度下闪烁灯光来编程设置警报,或者通过增加一些硬件,你可以加一个可听警报。我相信你能想出更多的硬件或软件修改,使这个温度计成为一个非常实用的设备。

选择温度传感器

任何电子温度计的关键成分是温度传感器。市面上有许多种温度传感器可供选择。

热敏电阻随着温度的变化而改变电阻,其价格范围从便宜到非常昂贵,具体取决于它们的制造和测试方式。电阻温度探测器 (RTDs)使用纯金属线圈,如银、铂或铜,绕在玻璃核心周围。将 RTD 组合在一个电阻桥中,可以达到非常高的精度,但它们的价格相对较贵。热电偶仍然是行业标准的传感技术,特别是在高温下(即超过 500°C)。在较低温度下,由于准确性、精度、一致性和线性,热电偶正被 RTD 所取代。

半导体温度传感器——即专用的集成硅传感器电路——因其精度、可靠性、坚固性和便利性而持续受到欢迎。在准备这个项目时,我几乎看遍了所有的方案,并选择使用了半导体传感器,因为它提供了足够的准确性,同时连接简单,价格也适中。

对于任何温度计,精度分辨率都是问题。可以将精度视为测量温度的能力,其接近由 NIST(美国国家标准技术研究院)建立的某个标准值,带有一些偏差。对于这个简化的定义,分辨率可以称为重复性——即在相同环境下,能够稳定地读取相同的温度。

第七章中的自定义 pH 计使用了沸水和冰水溶液的温度,分别设定了 100°C 和 0°C 的边界,以校准温度计。我使用相同的方法检查了色差温度计,但我使用了这里描述的高精度 MCP9808 模块作为标准,因为它非常接近。

精度和分辨率最终是一个系统问题——并不一定是传感器的问题。这个项目讨论了两种具有基本相同精度和分辨率的不同传感器。最简单的传感器,LM35 模拟温度传感器,依赖于系统的其他部分来保证其精度和分辨率。第二种传感器,MCP9808 芯片,无论是否使用附带的分离板,都能提供精确的结果,因为它将其他可变组件集成到了芯片内部的子系统中。

LM35 和 MCP9808 都具有 0.25°C 的最大精度和 0.0625°C 的分辨率。为了实现这种精度,它们使用硅带隙温度传感器,该传感器利用了硅二极管的正向电压。然而,除了传感器外,MCP9808 还包括其自带的芯片内 ADC、电压参考和其他内部电路,以确保精度。

注意

如果你想深入了解带隙传感器技术,网上有大量相关信息,包括 Bob Widler 的背景资料,他通常被认为是发现这一现象的关键人物

在这个项目中,LM35 依赖于 Arduino 的 ADC 和电压参考,虽然其性能相当不错,但与 MCP9808 的单片系统不匹配,因此可能需要进行校准,正如在《LM35 系统示例》中所展示的,第 289 页中提到的。当我使用 MCP9808 构建一个版本时,我使用了 Adafruit 的芯片分离板,因为它极大简化了组装——无需为 MicroSMT 封装的小引脚而烦恼。

虽然 MCP9808 的价格高于 LM35D,但它的表现相当好。我在项目的 PCB 护盾板中包括了用于该芯片的引线,如果你选择使用《使用 SOIC 封装》中建议的某种技术来焊接它,第 20 页提供了详细说明。

所需工具

焊接铁和焊锡(可选)电钻和 1/4 英寸钻头(用于钻孔以连接远程温度传感器或为电源适配器打孔)

零件清单

首先,决定你想使用哪种温度传感器:LM35 还是 MCP9808。如果你只想使用 LM35,这里是制作基本色差温度计所需的配件:

一块 Arduino Nano 或其克隆版

一个 LM35 温度传感器

十个不同颜色的 LED(见“模块:尝试不同的 LED”在第 300 页)

十个 ZTX649 晶体管,十个 470 欧电阻

一个 7.5 至 9V 的墙壁适配器,或等效的(或 9V 电池)

一个塑料外壳(见“构建”在第 298 页),28 或 30 号的连接线

一块印刷电路板(使用提供的保护板模板,设计自己的保护板,或者使用任何你熟悉的原型板。)

在本章中,我还描述了几种色度温度计的变体。购物之前可以先快速浏览一下项目,如果你想制作其中一种变体,也需要购买以下物品:

如果你计划按照“设计决策:远程温度传感器”中描述的方式使用温度传感器,购买一个 3.5mm 立体声插孔。如果你的色度温度计需要数字显示屏,还需要购买一个 16×2 I²C LCD。

对于高精度色度温度计,将 LM35 替换为一个 MCP9808 Adafruit Breakout 板,或一个带 100nF 电容和两个 10 千欧电阻的 Microchip MCP9808 芯片。

对于面包板原型,请确保你有一块大型面包板(与本书中使用的大部分小型面包板不同)和至少 30 根跳线。

设计决策:远程温度传感器

如果你的应用需要走不同的方向,可以修改保护板以远程连接芯片。也就是说,你可以直接将长电线连接到芯片(只需要四根电线),并将芯片放置在与显示屏分开的地方。如果你远程连接芯片,只需在芯片附近的引脚 4 和 8 之间添加一个小电容(约 100nF),如图 10-2 所示。

image

图 10-2:MCP9808 与直接焊接的电线

然而,请记住,I²C 代表集成电路间通信,用于芯片间通信。因此,MCP9808 只能与 Arduino 保持有限的距离。虽然一些在线爱好者声称成功使用长达 100cm 的电缆,但我能够稳定使用的最长距离约为 50cm。另一方面,LM35 可以通过三根电线实现远程连接并且可防水,适用于更长的距离,而不需要微型工具和像钟表匠那样的灵活手指。(如果你只能容忍两根电线,可以参考 LM35 的数据表,它有解决方案。)

MCP9808 可能像我在第七章中的定制 pH 计中用 LM35 那样进行封装,尽管我没有尝试过。制作远程传感器时,尝试将连接点隔离开,并保持芯片的精密引脚不被折断,可能会成为使用 MCP9808 时的一个问题。

这是在制作最终色度温度计之前需要做出的设计决策,因此我建议你在组装设备之前,通读本章以便做出决定。

下载

LM35 版本的代码 LM35Thermo.ino

MCP9808 版本的代码 9808Thermo.ino

Adafruit_MCP9808 www.adafruit.com/product/1782(仅适用于 MCP9808 温度传感器)

电路板模式(用于扩展板) Thermo.pcb

Chromatic Thermometer(彩色温度计)的工作原理

在实际操作中,Chromatic Thermometer(彩色温度计)相当简单。首先,我们来看看使用 LM35 传感器的基本配置。

该传感器产生的电压为 10mV/°C。例如,在 28°C(约 82°F)时,芯片输出 0.280V。你可以用万用表轻松检查这个值。要制作一个可用的 Arduino 温度计,你所要做的就是将这个电压转换为 Arduino 能理解的值,然后让 Arduino 将其转换为你希望在 LED 或 LCD 上显示的内容。

第一步是将模拟电压转换为数字值,以便 Arduino 能处理。为此,将传感器的输出连接到 Nano 的一个模拟输入端口。(我通常使用 A0,但任何模拟输入都可以使用。只要不要使用 A4 或 A5,因为这两个端口用于本项目的 I²C 部分。)与 Nano 使用的 5V 电压相比,LM35 的输出电压相对较低,ADC 将 5V 电压分为 1,024 部分(范围 = 0 到 1,023)来确定输入电压的模拟值。如果直接使用 LM35 的输出,每变化 1 摄氏度,输出电压就会变化 0.010V,从而使 ADC 的结果在 1,024 总单位中变化 2.046 个单位。

这样工作正常,但参考电压非常低端时 ADC 的小增量容易受到随机误差的影响。由于 Nano 的 ADC 只输出整数,因此也会有显著的四舍五入误差。

为了减少误差的影响,你将把 ADC 的参考电压从 5V 更改为 1.1V,其中 1,024 个增量的每一个在 5V 时表示 0.004882V,而在 1.1V 时每个增量仅表示 0.00107V。这样,温度每变化 1 摄氏度,只会对应 1,024 单位中的 9.345 个增量。因此,LM35 在 28°C 时输出的 0.280V 将对应大约 261 个单位,而不是 52 个。

原理图

图 10-3 显示了该项目的原理图。

image

图 10-3:彩色温度计的原理图

请注意,在这个代码中,LM35 和 MCP9808 两个传感器都已经连接。这并不成问题,因为你可以通过修改上传到 Arduino 的代码,在软件中选择使用哪个传感器。你可以连接其中一个或两个传感器。该原理图还显示了带有 LCD 的彩色温度计,但如果你只想根据 LED 读取温度,这部分是可选的。

Arduino 处理器可能能够单独驱动 LED,但我选择为每个 LED 使用晶体管驱动器。这可以确保如果你选择使用更高输出的 LED,甚至白炽灯泡时,也不会有驱动问题。所使用的晶体管能够承受最高 1A 的电流。

一个第 11 个 LED-晶体管-电阻组(Q11)被连接到 Nano 的 D12 引脚,尽管最终的色温计仅使用 10 个 LED。我展示了这个额外的配对,甚至将其包含在了屏蔽 PCB 文件中,给你一个内置的自定义选项。你可以添加另一个温度数字、蜂鸣器报警或任何其他输出设备。

面包板

和本书中的其他项目一样,我建议先使用面包板来测试设计并运行草图,然后再进行最终的组装。因为该项目使用了 10 个 LED 和 10 个驱动晶体管,所以我使用了一个大尺寸面包板,以便能舒适地放置所有组件(见图 10-4)。

image

图 10-4:完成的色温计面包板

LED 位于面包板的中间,其中一个 LED 亮起。为了 LCD,我组装了一条线束。LM35 温度传感器(左)通过绳索连接,并被热缩管固定,这样它就防水了。

以下是我用来组装面包板的步骤:

  1. 将 Arduino Nano 放置在面包板的左上角。

  2. 将 Nano 的 VIN(引脚 30)连接到来自电池或其他电源的 9V 输入位置。

  3. 将 Nano 的 5V 引脚连接到红色正极轨道。

  4. 将 Nano 的 GND(引脚 4)连接到面包板上的蓝色负极轨道。

  5. 确定 10 个驱动晶体管(Q1 到 Q10)的放置位置,并将它们放置在面包板上。我将它们放置成晶体管的斜边朝右,当从板子的底部看时。

  6. 将所有晶体管的集电极连接到 9V 输入所在的位置(Nano 的 VIN)。请参见图 10-5 查看晶体管的引脚图。

    image

    图 10-5:ZTX649 晶体管的引脚图

  7. 将 Q1 的基极连接到 Nano 的 D2(引脚 5)。

  8. 将 Q2 的基极连接到 Nano 的 D3(引脚 6)。

  9. 将 Q3 的基极连接到 Nano 的 D4(引脚 7)。

  10. 将 Q4 的基极连接到 Nano 的 D5(引脚 8)。

  11. 将 Q5 的基极连接到 Nano 的 D6(引脚 9)。

  12. 将 Q6 的基极连接到 Nano 的 D7(引脚 10)。

  13. 将 Q7 的基极连接到 Nano 的 D8(引脚 11)。

  14. 将 Q8 的基极连接到 Nano 的 D9(引脚 12)。

  15. 将 Q9 的基极连接到 Nano 的 D10(引脚 13)。

  16. 将 Q10 的基极连接到 Nano 的 D11(引脚 14)。

  17. 将 Q1 到 Q10 的所有晶体管的发射极连接到每个有色 LED 的正极引脚。

  18. 将 LED 的负极引脚连接到面包板上的一个空位置。

  19. 将 470 欧姆电阻的一端连接到每个 LED 的负极引脚。

  20. 将 470 欧姆电阻的另一端连接到地(蓝色负极轨道)。

  21. 将 LM35 的引脚 1(4–20V)连接到红色正极轨。(请参见图 10-6 查看 LM35 的引脚图。)

    image

    图 10-6:LM35 温度传感器的引脚图

  22. 将 LM35 的引脚 3(GND)连接到蓝色负极轨。

  23. 将 LM35 的输出引脚(中间)连接到 Nano 的 A0(26)引脚。

    1. 将电源和接地分别连接到红色正极轨和蓝色负极轨。

现在,你已经完成了最基本的配置。要添加数字显示屏:

  1. 将 LCD 的 I²C 适配器的电源和接地引脚分别连接到红色正极轨和蓝色负极轨。

  2. 将 LCD 的 I²C 适配器的 SDA 引脚连接到 Nano 的 A4(22)引脚。

  3. 将 LCD 的 I²C 适配器的 SCL 引脚连接到 Nano 的 A5(21)引脚。

  4. 将适当的软件代码上传到 Nano。

如果你想使用高精度温度传感器:

  1. 从电路中移除 LM35(或者你也可以将其保留在电路中——它不会影响任何东西)。

  2. 将高精度传感器放置在一个位置,以避免引脚受到任何影响。

  3. 将 MCP9808 传感器的 I²C 连接的电源引脚分别连接到 Nano 的蓝色负极轨和 5V——引脚 27,或者红色正极轨。

  4. 将 MCP9808 传感器的 I²C 连接的 SDA 引脚连接到 Nano 的 A4(22)引脚。

  5. 将 MCP9808 传感器的 I²C 连接的 SCL 引脚连接到 Nano 的 A5(21)引脚。

  6. 使用高精度传感器版本的代码上传软件到 Nano。

现在你已经准备好开始了。

注意

这个面包板的正负电源轨不连续。前 15 个连接在一起,接下来的 20 个连接在一起,最后 15 个连接在一起——但它们之间没有连接。我使用跳线根据需要连接这些电源轨。

草图

这个草图有两个版本:一个是 LM35 版本的项目,另一个是 MCP9808 版本的项目。你可以根据想要构建的色谱温度计版本选择草图,但两个草图都包括三个基本部分。

在加载库和初步设置的样板代码部分之后,每个草图的第一部分涉及温度传感器本身。第二部分涉及设置温度和 LCD 显示(如果使用)。每个草图的最后部分详细说明了打开和关闭 LED 的条件,以指示温度。我已在代码中适当地添加了注释。

LM35 系统的草图

这是使用 LM35 传感器的色谱温度计草图,包括数字 LCD 显示。


    //Chromatic Thermometer sketch for the LM35, with an alarm
    //around 78 to 79 degrees Fahrenheit (26 degrees Celsius) 

    #include <Wire.h>              //Set up Comm wire library 
    #include <LiquidCrystal_I2C.h> //Set up LCD library with I2C 

    LiquidCrystal_I2C lcd(0x27, 16, 2); //16x2 display I2C address 0x27 

    //Establish the number of readings to average at 10
➊  const int numReadings = 10; 
    float readings[numReadings];        //The readings from the analog input 
    int index = 0;                      //The index of the current reading 
    float total = 0;                    //The running total
    float average = 0;                  //The average
    int tempPin = A0;
    float TempC; 
    float tempF; 

    void setup() {
      lcd.init();                       //Initialize LCD and turn on backlight
      lcd.backlight(); 

      //Initialize serial communication with computer:
      Serial.begin(9600); 

      //Initialize all the readings to 0:
      for(int thisReading = 0; thisReading < numReadings; thisReading++)
      readings[thisReading] = 0; 

      analogReference(INTERNAL);        //Set voltageReference = 1.1V 
    } 

    void loop() {
      total = total - readings[index];          //Subtract the last reading
      readings[index] = analogRead(tempPin);    //Read from the sensor
      total = total + readings[index];          //Add the reading to the total 

      //Advance to the next position in the array:
      index = index + 1; 

      if(index >= numReadings)     //If we're at the end of the array…
        index = 0;                    //…wrap around to the beginning 

      average = total / numReadings;  //Calculate the average temperature
      TempC = average / 9.81;         //Adjust/calibrate average 
                                      //based on empirical measurement

      tempF = (TempC * 9 / 5) + 32;   //Convert to Fahrenheit
     //Set up serial readout if desired
      Serial.println();
      Serial.print("TempC  ");
      Serial.println(TempC);
      Serial.print("TempF  ");
      Serial.println(tempF);
      Serial.print("Average  ");
      Serial.println(average);
      delay(10);                    //Delay in between reads for stability 

      //Set up for LCD
      lcd.setCursor(0, 0);
      lcd.print("Temp                  ");
      lcd.setCursor(7, 0);
      lcd.print(TempC, 1);
      lcd.print((char)223);         //Degree symbol see below
      lcd.print(" C");
      lcd.setCursor(0, 1);
      lcd.print("Temp  ");  
      lcd.setCursor(7, 1);
      lcd.print(tempF, 1);          //Truncate second decimal place
      lcd.print((char)223); 
    /*May need to use (char) 178 if LCD displays the greek alpha character. 
    Different LCDs display different special characters*/ 

      lcd.print(" F");
      delay(50); 

      //Beginning of conditional statements for display
      if((tempF > 85.00 ) && (tempF < 200)) {
        //85 degrees and 200 degrees are arbitrary.
        digitalWrite(2, HIGH);
      }
      else {
        digitalWrite(2, LOW);
      } 

      if((tempF > 84) && (tempF < 85)) {
        digitalWrite(3, HIGH);
      }
      else {
        digitalWrite(3, LOW);
      } 

      if((tempF > 83.00 ) && (tempF < 84)) {
        digitalWrite(4, HIGH);
      }
      else {
        digitalWrite(4, LOW);
      } 

     if((tempF > 82) && (tempF < 83)) {
        digitalWrite(5, HIGH);
      }
      else {
        digitalWrite(5, LOW);
      } 

      if((tempF > 81.00 ) && (tempF < 82)) {
        digitalWrite(6, HIGH);
      }
      else {
        digitalWrite(6, LOW);
      } 

      if((tempF > 80) && (tempF < 81)) {
        digitalWrite(7, HIGH);
      }
      else {
        digitalWrite(7, LOW);
      } 

      if((tempF > 79.00 ) && (tempF < 80)) {
        digitalWrite(8, HIGH);
      }
      else {
        digitalWrite(8, LOW);
      } 

      if((tempF > 78) && (tempF < 79)) {
        //Code for blinking LED as an alarm
        digitalWrite(9, HIGH);
        delay(50);
        digitalWrite(9, LOW);
        delay(50);
      }
      else {
        digitalWrite(9, LOW);
      } 

      if((tempF > 77.00 ) && (tempF < 78)) {
        digitalWrite(10, HIGH);
      }
      else {
        digitalWrite(10, LOW);
      }

      if(tempF < 76) {
        digitalWrite(11, HIGH);
      }
      else {
        digitalWrite(11, LOW);
      }
  }

在包括库之后,LM35 草图在➊处定义了要跟踪的样本数量。样本数量越高,读数越平滑,但稳定下来所需的时间也越长。使用常量而不是普通变量来表示样本数量,使得该值能够决定readings数组的大小。

setup() 代码初始化 LCD,打开串行通信以进行调试,将读取数组初始化为全零(因为草图尚未读取任何数据),并将 ADC 参考电压设置为 1.1V。loop() 代码将传感器数据存储在 readings 数组中,并通过平均这些读数来计算要显示的温度。如果你有 LCD,草图会在其上显示温度,然后检查各种温度范围,并通过 if 语句决定哪些 LED 需要打开。

这个草图和下一个草图之间的最大区别在于,LM35 版本设置系统以接受来自传感器的模拟电压,并将其引导到模拟输入。它还通过 analogReference(INTERNAL) 命令建立了一个 1.1V 的参考电压。

MCP9808 系统的草图

高精度 MCP9808 芯片版本(或 Adafruit 的开发板)的草图使用了大部分相同的代码;用于打开 LED 的条件语句是相同的。唯一不同的部分是 Arduino 如何从传感器获取温度信息。以下是完整的草图:


/*Sketch for MCP9808 version of Chromatic Thermometer

 This version of the Chromatic Thermometer uses the Adafruit MCP9808 breakout
 Board (or Microchip MCP9808 chip) and the Adafruit_MCP9808 library
 available from Adafruit ----> https://www.adafruit.com/product/1782

 The averaging may not be necessary. It tends to slow the
 response a little, but smoothes out the display.

 The result is truncated to a single decimal for both Celsius and Fahrenheit.
 This version includes the code to turn on and off 10 LEDs.
*/ 

#include <Wire.h>               //Set up wire/serial library 
#include "Adafruit_MCP9808.h" //Set up MCP9808 library 
#include <LiquidCrystal_I2C.h>  //Set up library for LCD 

LiquidCrystal_I2C lcd(0x27, 16, 2);   //16x2 display; define LCD 

// Create the MCP9808 temperature sensor object 
Adafruit_MCP9808 tempsensor = Adafruit_MCP9808(); 

const int numReadings = 10;     //Once again averaging 10 readings 
float readings[numReadings];    //The readings from the analog input
int index = 0;                  //The index of the current reading
float TempC = 0;
float tempF = 0;
float total = 0;                //The running total 
float average = 0;              //The average

 void setup() {
  Serial.begin(9600); 

  lcd.init();  //Initiate LCD and backlight
  lcd.backlight(); 

/*Make sure the sensor is found. You can also pass a different I2C address
from the default, as in tempsensor.begin(0x19).*/   
  if(!tempsensor.begin()) { 
    Serial.println("Couldn't find MCP9808!");
    while(1);
  }
} 
void loop() {
  //Read and print out the temperature; then convert to Fahrenheit
  float c = tempsensor.readTempC();
  total = total - readings[index];
  //Read from the sensor
  readings[index] = c;
  //Add the reading to the total
  total = total + readings[index];
  //Advance to the next position in the array
  index = index + 1;
  if(index >= numReadings)        //If we're at the end of the array… 
    index = 0;                        //…wrap around to the beginning:
  //Calculate the average
  average = total / numReadings; 

  TempC = average;
  tempF = (TempC * 9 / 5) + 32;
  delay(100); 

  //Set up LCD to print out temperatures
  lcd.setCursor(0, 0);
  lcd.print("Temp          ");
  lcd.setCursor(6, 0);
  lcd.print(TempC, 1);                //Truncate to one decimal place
  lcd.print((char)223);
  lcd.print(" C");
  lcd.setCursor(0, 1);
  lcd.print("Temp  ");  
  lcd.setCursor(6, 1);
  lcd.print(tempF, 1);               //Truncate to one decimal place
  lcd.print((char)223); 
/*May need to use (char) 178 if LCD displays the greek alpha character. Different LCDs display different special characters*/

  lcd.print(" F");
  delay(100); 

  //Beginning of conditional statements for display
  if((tempF > 85.00 ) && (tempF < 100)) {
  digitalWrite(2, HIGH);
  }
 else {
  digitalWrite(2, LOW);
  } 

  if((tempF > 84) && (tempF < 85)) {
  digitalWrite(3, HIGH);
  }
  else {
  digitalWrite(3, LOW);
  } 

  if((tempF > 83.00 ) && (tempF < 84)) {
  digitalWrite(4, HIGH);
  }
  else {
  digitalWrite(4, LOW);
  } 

  if((tempF > 82) && (tempF < 83)) {
  digitalWrite(5, HIGH);
  }
  else {
  digitalWrite(5, LOW);
  } 

  if((tempF > 81.00 ) && (tempF < 82)) {
  digitalWrite(6, HIGH);
  }
  else {
  digitalWrite(6, LOW);
  } 

  if((tempF > 80) && (tempF < 81)) {
  digitalWrite(7, HIGH);
  }
  else {
  digitalWrite(7, LOW);
  } 

  if((tempF > 79.00 ) && (tempF < 80)) {
  digitalWrite(8, HIGH);
  }
  else {
  digitalWrite(8, LOW);
  } 

  if((tempF > 78) && (tempF < 79)) {  //Code for blinking LED
  digitalWrite(9, HIGH);
  delay(50);
  digitalWrite(9, LOW);
  delay(50);
  }
  else {
  digitalWrite(9, LOW);
  }

 if((tempF > 77.00 ) && (tempF < 78)) {
  digitalWrite(10, HIGH);
  }
  else {
  digitalWrite(10, LOW);
  } 

  if(tempF < 76) {
  digitalWrite(11, HIGH);
  }
  else {
  digitalWrite(11, LOW);
  } 
}

MCP9808 草图版本的 setup() 代码检查确保你已连接 MCP9808 温度传感器。在 loop() 部分,它调用 Adafruit_MCP9808 库中的 readTempC() 函数来获取当前温度,而不是像 LM35 代码那样直接调用 analogRead()。与 LM35 代码不同,这个草图不需要设置外部电压参考:使用 MCP9808 的一个优点是该芯片自带内部参考电压。否则,除了几个变量名的不同外,其余的草图与 LM35 代码相同。

温度显示的工作原理

在这两个草图中,基本的温度显示由 10 个不同颜色的 LED 组成,LED 通过从 Nano 的 D2 到 D11 的输出端驱动的发射极跟随配置的晶体管来控制。

Nano 的输出由草图激活,每个输出对应一个条件语句,格式为:“如果温度在 X 度和 Y 度之间,开启 LED。如果不是,关闭 LED。”这些命令的 if 语句在 LM35 和高精度版本的 MCP9808 中是相同的。

当我第一次完成这个项目时,我将它用于一个盐水鱼缸,在那里我希望能够准确地远程查看温度。我设置了 LED 在温度达到不可接受的极限时闪烁,以引起我的注意,这样我就可以采取纠正措施。闪烁效果只需要在 LED 关闭和打开之间加入延迟。我修改了草图,使其在警告条件下如下所示:


  if((tempF > 78) && (tempF < 79)) {
    digitalWrite(9, HIGH);
    delay(50);
    digitalWrite(9, LOW);
    delay(50);
  }
    else {
      digitalWrite(9, LOW);
  }

这个示例仅当温度在 78°F 和 79°F 之间时才会闪烁显示,如完整草图所示。延迟的长度,再加上你可能添加的其他延迟,决定了闪烁的速率。

一般的读数系统和这个简单、安静的报警器一起工作得非常好。我可以设置报警,确保温度高于或低于阈值温度。

我还认为拥有一个数字读数可能很有价值,原因有两个:

  1. 我想要能够准确查看温度。

  2. 如果温度超出范围并且“闪烁”报警执行,我希望能够看到温度距离限制有多远。

添加数字显示屏相对简单,因为我使用了一个标准的 16×2 LCD 带有 I²C 接口,只需要四根线。这次我买了一个内置 I²C 适配器的 LCD。它比我希望的要大,但我很难找到一个更小的显示屏。如果你能找到一个更小的,尽管去买。

屏蔽

这个项目的 PCB 屏蔽板设计采用了两层铜而非单层。额外的层使得制造板子变得有些困难,但它在识别和连接跳线时节省了很多精力。我最初在内部蚀刻了板子,但最终是通过 Express PCB 制作了完成的板子。专业完成的板子上的电镀过孔使得组装更加容易。PCB 的层次结构在图 10-7 中展示。

请注意,LED 驱动晶体管位于 Nano 板下方,以节省表面面积。这样做的唯一缺点是 Nano 板稍微提高了一些。你可以在图 10-8 中看到这些晶体管,图中展示了带有 Nano 板的装配完毕的 PCB。

这个屏蔽板还包括了两个 I²C 设备的接口——每端一个。因为我认为这个板子可能会用到很多不同的项目中,所以我尽量让它尽可能灵活。I²C 连接使得连接高精度的 Adafruit breakout 板和数字显示屏变得非常容易。你可以直接接线,也可以将一个直角或直头的母头插座焊接到板子上,然后使用带有压接连接器外壳和电缆的方式(参见图 10-9)。

image

图 10-7:带有丝网印刷图像的 PCB 屏蔽板的顶层。你可以看到底部左侧的 MCP9808 图案

image

图 10-8:装配完毕的屏蔽板,旁边是一个 Arduino Nano。注意我为 Nano 使用了全长母头插座。还请注意右上角的第 11 个 LED 的孔和迹线

image

图 10-9:使用 MCP9808 芯片直接焊接到屏蔽板上的组装温度计(右下角)。一个 I²C 连接器位于 MCP9808 芯片的上方和右侧;另一个 I²C 连接器的连接点位于左下角

如果你选择将 MCP9808 芯片直接焊接到板上,屏蔽板上有为 MCP9808 芯片预留的焊盘(见图 10-9)。如果你使用的是 MCP9808 芯片而不是带有 I²C 接口的分离板,你将需要为 SDA 和 SCL 线路提供 10 千欧姆的上拉电阻。这些电阻没有包含在屏蔽板布局中,但可以很容易地添加到 I²C 端口连接中,因为这些连接本来是没有使用的。在图 10-9 中的实现中,10 千欧姆的电阻安装在 LCD 适配器上,因为会有一个 LCD 适配器插入到 I²C 端口,从而不需要额外的上拉电阻。

尽管为本项目提供的屏蔽板文件支持将 LED 直接安装到 PCB 板上,但在许多情况下,你可能希望将 PCB 板与 LED 分开。例如,我做了一个版本,将高强度的 10 毫米 LED 按一英寸的间距排列在一块装饰木板上,以创造更具戏剧性的效果。要实现这种效果,你需要将长电线焊接到 LED 引脚上,然后再将这些电线焊接到 PCB 板上。所有 LED 的阴极可以连接在一起,只有阳极需要单独连接到电路板上。

构建

如果你还没有将组件焊接到屏蔽板 PCB 或原型板上,现在就开始焊接,并记得按照正确的极性安装 LED。Chromatic Thermometer 的最终配置很大程度上取决于你的最终应用,因此我不会在构建此项目时提供过多的具体细节。

例如,如果你想使用远程温度传感器,你需要一个插孔或者其他适当的连接器。你可能还需要在外壳上切一个缝隙,以容纳传感器的电线,以及另一条用于长电源连接的线。如果你打算只使用 LED 而不使用 LCD 来构建 Chromatic Thermometer,你可能会以不同的方式将电子元件安装到外壳内。类似地,如果你构建的是高精度版本,你可能需要调整零件在外壳中的布局。图 10-10 中的 Chromatic Thermometer 使用了 LM35 传感器和 16×2 LCD。

我使用了在亚马逊上找到的一款小盒子(最初是用来放棒球卡的)将整个装置封装起来,并将传感器直接安装到三个孔位的屏蔽板上,以便将其适配到 PCB 板中。如果你不想让 Nano 板上的 LED 显示出来,可以将其拆除,或者简单地用一小块黑色电工胶带将其遮住。

无论你使用 3 毫米 LED 还是更重的高输出 5 毫米 LED,使用某种间隔器都有助于确保 LED 按照你喜欢的高度对齐。当我将读数 LED 安装到护盾上时,我放置了一块未使用的 PCB 材料,将所有 LED 保持在一个统一的高度(见图 10-11)。你也可以使用纸板,若想要不同的高度,只需使用更高或更矮的间隔器即可。

image

图 10-10:完成的色度温度计放置在亚克力外壳中,用于在旅行中监控冷却器中药物的温度。这个版本使用了 9V 电池,电池在外壳内部。我使用了带背光的显示器,但没有背光时电池寿命会更长。LED 的开关阈值被修改为适应低温使用

image

图 10-11:我使用了废弃的 PCB 材料条来保持 LED 的统一高度

如果你使用 5 毫米 LED,可能会发现它们难以通过标准 PCB 的孔洞,因为一些 5 毫米 LED 的引脚较宽。我使用钻头扩孔以适应较大的 LED;由于 PCB 的另一面没有连接,所以不需要镶嵌孔。

MOD:尝试不同的 LED

图 10-8 中所示的色度温度计使用了 3 毫米 LED。我在 eBay 上订购了 10 种不同颜色的 3 毫米 LED,但引脚有点短。随后,我订购了 200 颗 5 毫米 LED,包含 10 种不同的颜色。这些 LED 的引脚同样较短,但亮度更强,并且效果不错。我确实需要修整一些 LED 的边缘,去掉模具上留下的一些多余闪光,以便它们能适应 PCB 上 0.200 英寸(略大于 5 毫米)的间距。然而,我没能找到足够多不同颜色的高输出 5 毫米 LED。

对于一个实验版本,我使用了六种不同颜色的高输出 5 毫米 LED,在极端位置重复这些颜色,并返回草图,创造了闪烁模式以区分相似的颜色。这个版本的色度温度计效果很好,而且高输出的 LED 让它非常显眼。

为了吸引更多的注意力,你可以使用高输出的 10 毫米 LED。 但是,它们无法安装在此处所示的护盾 PCB 上,因为我只将 LED 间距设置为 0.200 英寸。这个间距适用于大多数 3 毫米和 5 毫米 LED,但不适用于 10 毫米 LED。有关尺寸比较,请参见图 10-12。

image

图 10-12:从左到右,10 毫米、5 毫米和 3 毫米 LED 显示在一个米制尺旁

要使用 10 毫米 LED,你必须将它们安装在其他地方,并用导线将它们连接到 PCB 上。可以参考第四章中的手表绕线器的灯条获取灵感。

使用色度温度计

如何将温度计放置在你想要监控的环境中,只有你的想象力可以限制。最初我在鱼缸上使用的版本没有 LCD 显示屏,所以我只是将几个金属线钩固定在裸板上,然后把它挂在水箱的边缘,LED 灯朝外。(我本可以把整个装置安装在一个小的丙烯酸盒子里,但我很难找到合适尺寸的盒子。)这种配置效果很好。

最终,我将那个色差温度计替换成了一个带有 LCD 显示屏的版本,并将其封装在一个丙烯酸盒子里。我正在考虑再次修改它,使用高强度的 LED 灯照射水箱,这应该能创造出一个有趣的效果!

posted @ 2025-11-25 17:04  绝不原创的飞龙  阅读(15)  评论(0)    收藏  举报