Arduino-项目手册-全-

Arduino 项目手册(全)

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

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

Arduino 是一款小型、廉价的计算机,可以通过编程控制无数的创作,唯一的限制就是你的想象力。正如你很快会看到的,Arduino 可以用于制作各种项目,比如鬼魂探测器、摇杆控制的激光器、电子骰子、激光触发警报器、运动传感器警报器、密码键盘系统等等。这些项目都很容易制作,而且有一个共同点——它们都使用了 Arduino 的强大功能。

在 1980 年代初,我在一家本地书店发现了一本很棒的企鹅出版的平装书,书名大概是小玩意和小工具。书中的项目很简单,比如用手电筒灯泡制作一个工作中的灯塔,或者用旧钟表做一个旋转展示台。那本书里的创意激发了我的想象力,从那时起我就一直在进行创作。

我的好奇心促使我拆解各种电器产品进行实验,看看它们是如何工作的。我通常很难把它们重新组装起来,但也积累了许多可以进行实验的零部件。(顺便说一句,这是收集零件的一个好方法。)

我记得曾经将一串小型手电筒灯泡连接起来,为我的 Subbuteo 桌面足球游戏制作聚光灯,还创建了一个扬声器系统,在比赛的中场休息时播放音乐。我甚至设法从一款《星球大战》玩具中取出了几个 LED 灯,但因为当时不理解什么是电阻器,结果把它们烧坏了。我使用小马达、蜂鸣器和太阳能电池制作入侵警报器和超快速小车,也烧坏了几个马达!

大约在同一时期(1983 年),英国的 Sinclair Research 推出了 ZX Spectrum 48k 微型计算机,将家庭计算机引入了英国大众市场。(美国有它的 Commodore 64。)尽管 ZX Spectrum 本来是作为一台严肃的计算机推出的,但由于它包含了简单的编程语言 BASIC,它意外地更适合用于游戏。因此,软件公司如雨后春笋般在全国各地的卧室里涌现,人们争相为 ZX Spectrum 开发游戏。

这激发了我对编程的兴趣,但那时我无法将我的两个爱好结合起来。物理计算,软件和硬件与物理世界互动的领域,早在 80 年代就存在,但它局限于非常高端的计算和机器人技术,大多数家庭无法接触到。如今,30 多年过去了,随着 Arduino 的问世,我再次沉迷于电子技术,但这次我可以通过编程让我的项目栩栩如生。

Arduino 革命

简单来说,Arduino 是一台可以编程的小型计算机,用来连接和控制各种电子元件。Arduino 有多个引脚,可以设置为 输入,意味着它们可以接收来自开关、按钮和传感器等物品的数据,或者设置为 输出,意味着它们会发送数据来控制马达、灯光和蜂鸣器等设备。这种可编程开发板更常被称为 微控制器

Arduino 项目始于 2005 年的意大利伊夫雷亚,目的是创建一种比当时其他原型系统更便宜的设备,用来控制学生构建的互动设计项目。创始人 Massimo Banzi 和 David Cuartielles 将项目命名为 Arduino,灵感来自一个当地的酒吧(该名字来源于意大利男性名字,意为“强大的朋友”)。

Arduino 主板由两个主要元素组成:硬件或微控制器,它是主板的大脑,以及你用来将程序发送到大脑的软件。这个软件叫做 Arduino 集成开发环境(IDE),可以免费下载安装。

IDE 是一个简单的界面,适用于运行 Windows、OS X 或 Linux 的计算机。你使用 IDE 创建一个 草图(Arduino 程序),然后通过 PC 和 USB 电缆将其上传到 Arduino 主板。草图告诉硬件该做什么。在接下来的几章中,我会更详细地讲解硬件和软件。

Arduino 可以通过电池、USB 或外部电源供电。一旦 Arduino 被编程,它可以从计算机断开连接,并通过电源或电池独立运行。

关于本书

是什么促使我写这本书?互联网上充满了关于 Arduino 和潜在项目的教程、视频和文章,但许多内容缺乏详细的视觉效果或构建这些项目所需的代码。就像多年前激励我的 《小玩意与小工具》 一书一样,本书旨在帮助你构建简单的项目,激发你使用所学的技能和技巧创造自己的装置。

本书将重点介绍如何在面包板上创建你的项目。这是了解电路工作原理的最佳方法,因为连接并不是永久性的;如果你犯了错误,只需拔掉电线或元件并重新尝试。每个项目都有逐步的连接主组件的说明,并附有帮助你布线的照片。大多数项目都使用表格作为快速参考。

项目将提供电路图,以清晰地显示连接方式,如 图 1 所示。这些电路图是通过 Fritzing 程序(* www.fritzing.org/*)创建的,这是一个免费的开源程序,用于创建项目的可视化原理图。

图 1:

Fritzing 图示示例

image

每个项目都包含了编程 Arduino 所需的代码,因此你在开始之前不需要担心学习编程。早期的项目会简单地解释代码中的内容,帮助你理解编程过程,并让你在需要时能够自行修改代码。如果你不想手动输入所有的代码,可以从 www.nostarch.com/arduinohandbook/ 下载程序。

本书的项目从基础开始,逐步进展到更复杂的设计。也就是说,本书不会深入讲解电子理论或编程,但我会给你一个良好的起点。我写这本书是为了教你如何创造自己的小工具。通过提供必要的技术知识,我让你可以专注于创意设计部分。我们的理念是,学习电路的功能能够激发你的想象力,帮助你在实际应用中使用这些电路。

本书提供了实用的信息,你可以参考引脚连接,并在需要时在不同的项目中复用它们。你还可以将项目结合起来,制作更复杂和有趣的小工具。

许多 Arduino 书籍侧重于编程元素,这对某种学习方式来说是很好的,但我认为也有即插即用电子设备的学习空间。通过跟随这些项目中的步骤,你将边做边学。

本书结构

本书的内容按以下顺序从简单到复杂的项目进展,帮助你提升技能并了解各个元件:

第一部分:LED 你将从学习如何使用按钮和可变电阻控制简单的 LED 开始,然后将不同的组件组合起来,制作迪斯科闪光灯、植物监测器来告诉你何时给植物浇水,甚至是一个幽灵探测器。

第二部分:声音 在这一部分,你将了解压电蜂鸣器,这是一种非常实用的设备,既可以发出声音,也可以检测声音。你将使用 Arduino Melody 制作音乐,创建一个简单有趣的记忆游戏,并设置一个可以检测敲击音量的密码锁系统。

第三部分:伺服电机 这些项目都使用伺服电机,这是一种带有机械臂的小型电机,可以用于各种用途。你将构建一个摇杆控制的激光器,并解码遥控器,以便用遥控器上的按钮来控制伺服电机。

第四部分:LCD 显示器 LCD 屏幕在许多项目中都非常有用,可以显示信息和结果。在这一部分,你将学习如何设置 LCD 屏幕,建立一个天气站来报告天气情况,并设置两个游戏:占卜游戏和反应计时游戏。

第五部分:数字计数器 在这一部分,你将使用 LED 数字显示器,制作一个电子骰子和一个火箭发射倒计时系统,点燃引信。

第六部分:安全 这些更复杂的项目将向你展示如何通过安装触发线和入侵者追踪器、触发警报或哨兵导弹的运动传感器,以及使用键盘和卡片读取器的安全系统来保护你的空间,防止未经授权的人进入。

第七部分:进阶 在最后这一部分,你将把 Arduino 与一个灯光矩阵结合,创造出彩虹灯光秀。接着,你将通过构建属于你自己的 Arduino,为未来的项目打下基础。

这些项目不必按顺序构建,因此如果你看到自己喜欢的内容,并且有足够的信心去尝试,你可以直接跳到那个部分。不过,我还是建议你先尝试一些早期的项目,因为你会在其中找到对更复杂项目有用的信息。

我写下了这本我在刚开始使用 Arduino 时所寻找但找不到的书籍。我希望你在阅读和动手做这些项目时能像我写书一样享受其中的乐趣。

image

第一章:项目 0:入门

在开始使用 ARDUINO 构建项目之前,你需要了解并完成一些准备工作。让我们看看本书所需的硬件和软件,以及如何设置工作站。然后,你将通过一个简单的 LED 项目来测试 Arduino,并学习一些实用的技巧,如焊接和下载有用的代码库。

硬件

首先,让我们看看 Arduino Uno 板以及在几乎所有项目中都会使用的一些硬件。

Arduino Uno

市面上有许多种类的 Arduino 板,但本书将专门使用最流行的一款——Arduino Uno,如图 0-1 所示。Arduino Uno 是开源的(意味着它的设计可以自由复制),因此除了官方板(大约 25 美元),你还可以找到许多兼容的克隆板,价格大约 15 美元。

让我们来了解一下 Arduino Uno 的不同组成部分。

图 0-1:

Arduino Uno 板

image

Arduino 通过将信息发送给你连接到它的组件(如电机或 LED)来控制它们,这些信息称为输出(从 Arduino 发送出去的信息)。Arduino 从传感器读取的数据是输入(进入 Arduino 的信息)。Arduino 有 14 个数字输入/输出引脚(引脚 0–13),每个引脚可以设置为输入或输出,附录 B 中有完整的引脚参考表。

电源

当你将 Arduino Uno 板连接到计算机上传程序时,它会通过计算机的 USB 端口供电。如果 Arduino 没有连接到计算机,你可以通过连接一个 9 伏特的交流适配器或 9 伏特电池包(带有 2.1 毫米插孔,插孔的中心针连接到正极线)来独立运行,如图 0-2 所示。只需将插头插入 Arduino 的电源插座即可。

图 0-2:

一个 9 伏特电池包,你可以将其插入 Arduino 以提供电源

image

面包板

面包板是电子原型制作的构建基座。本书中的所有项目都使用面包板,而不是焊接。

“面包板”这个词来源于早期电子项目的制作方式,当时电子项目是通过将钉子钉入木板并将电线绕在钉子上来连接组件,而不使用焊接。今天的面包板,如图 0-3 所示,由塑料制成,表面有预钻孔(称为连接点),你可以将组件或电线插入这些孔中,夹子会将它们固定在位置。孔之间通过一条条导电材料连接,这些导电条位于板的下方。

图 0-3:

面包板连接

image

面包板有不同的尺寸。为了完成本书中的项目,你将需要四个面包板:两个全尺寸面包板,通常有 830 个孔;一个半尺寸面包板,拥有 420 个孔;以及一个迷你面包板,拥有 170 个孔。全尺寸面包板非常适合使用 LCD 屏幕或有很多元件的项目,而半尺寸和迷你面包板则更适合小型项目。我建议你购买与图 0-3 所示相似的面包板,带有红蓝线和孔之间的中心断开。

提示

传统上,使用红色线连接 5V 电源,黑色线连接地线(GND),这样你就能轻松区分哪根线是哪个。其余的线可以根据你自己的喜好选择颜色。

主板区域有 30 列连接点,它们是垂直连接的,如图 0-3 所示。板中间有一个断开,你通常需要用元件跨越它以完成电路。这个断开有助于将引脚单独连接,这样它们就不会意外地短接在一起,否则可能会导致项目失败,甚至损坏元件。

顶部和底部的蓝红线是电源轨,你可以用它们为插入主面包板区域的元件供电(见图 0-4)。电源轨将轨道中的所有孔水平连接;红线用于正电源,蓝线用于负电源(或地线,你常会看到它被这样称呼)。

图 0-4:

正负电源轨

图片

跳线

你将使用跳线来在面包板上进行连接。跳线是实心导线,每端都有一个塑料模具夹,方便插入和移除导线。(你可以使用自己有的导线,但确保使用实心导线,因为绞合导线不够强劲,无法有效地插入孔夹中。)

当你将跳线插入面包板的孔中时,它会通过一个小的弹簧夹固定在板下,这样就形成了电气连接,通常这一行包含五个孔。然后,你可以将元件放入相邻的孔中,以帮助创建电路,如图 0-5 所示。

图 0-5:

一个示例面包板电路

图片

编程 Arduino

为了让我们的项目按预期工作,我们需要编写程序来给 Arduino 下指令。我们通过一个叫做 Arduino 集成开发环境(IDE)的工具来实现。Arduino IDE 可以免费下载,支持 Windows、OS X 和 Linux 操作系统。它使你能够编写计算机程序(在 Arduino 世界中称为草图),然后通过 USB 线将其上传到 Arduino。Arduino 根据与外界的互动执行这些指令。

注意

由于 IDE 版本可能会很快发生变化,我不会带你一步步安装它们,但你应该会发现安装过程很简单。所有版本的 IDE 和有关如何为你的操作系统安装的详细信息都可以在线找到,网址是 www.arduino.cc/

IDE 界面

当你打开 Arduino IDE 时,它应该看起来非常类似于图 0-6。

IDE 界面分为顶部的工具栏,其中包含最常用功能的按钮;中间的代码或草图窗口,你将在其中编写或查看程序;以及底部的串行输出窗口。串行输出窗口显示你电脑和 Arduino 之间的通信信息,如果你的草图没有正确编译,还会列出任何错误。

图 0-6:

Arduino IDE

image

Arduino 草图

我会在每个相关项目中提供草图,并在那里进行讲解。所有草图都可以从 www.nostarch.com/arduinohandbook/ 下载。

像所有程序一样,草图是一组非常严格的指令,并且对错误非常敏感。为了确保你正确复制了草图,请按下屏幕顶部的绿色勾选按钮。这是“验证”按钮,它会检查是否有错误,并告诉你草图是否正确编译。如果遇到问题,你可以随时下载草图并将其复制粘贴到 IDE 中。

库文件

在 Arduino 世界中, 是一小段执行特定功能的代码。你无需在草图中反复输入相同的代码,而是可以添加一条命令,从库中借用代码。这种快捷方式节省时间,并使你能够轻松连接到传感器、显示器或模块等设备。

Arduino IDE 包含了许多内置库,例如 LiquidCrystal 库,它可以方便地与 LCD 显示器进行通信,还有更多的库可以在线获取。为了制作书中的项目,你需要导入以下库:RFID、Tone、Pitches、Keypad、Password、Ultrasonic、NewPing、IRRemote 和 DHT。你可以在www.nostarch.com/arduinohandbook/找到所有需要的库。

一旦你下载了库文件,你需要安装它们。要在 Arduino 版本 1.0.6 及更高版本中安装库,请按照以下步骤操作:

  1. 选择 Sketch image Include Library image Add .ZIP Library

  2. 浏览到你下载的 ZIP 文件并选择它。对于较旧版本的 Arduino,你需要解压库文件,并将整个文件夹及其内容放入 Linux 系统中的 sketchbook/libraries 文件夹,Windows 系统中的 My Documents\Arduino\Libraries 文件夹,或 OS X 系统中的 Documents/Arduino/libraries 文件夹。

要手动安装库,请转到包含库的 ZIP 文件并解压。例如,如果你正在安装一个名为 keypad 的库,它压缩在 keypad.zip 文件中,你需要解压 keypad.zip,它将展开为一个名为 keypad 的文件夹,文件夹中包含 keypad.cppkeypad.h 等文件。ZIP 文件解压后,将 keypad 文件夹拖到操作系统中的 libraries 文件夹:在 Linux 中是 sketchbook/libraries,在 Windows 中是 My Documents\Arduino\Libraries,在 OS X 中是 Documents/Arduino/libraries。然后重新启动 Arduino 应用程序。

库会列在草图的开始部分,并且很容易识别,因为它们以 #include 命令开头。库用尖括号 <> 包围,并以 .h 结尾,以下是调用 Servo 库的示例:

#include <Servo.h>

现在安装项目所需的库,以便以后节省一些时间。

测试你的 Arduino:闪烁 LED

现在你已经了解了硬件和软件,让我们开始经典的第一个 Arduino 项目:闪烁一个 发光二极管 (LED)。这不仅是确保你的 Arduino 正常工作的最简单方法,而且它还会让你接触到一个简单的草图。正如我之前提到的,草图只是运行在计算机上的一系列指令。Arduino 一次只能保存一个草图,因此一旦你将草图上传到 Arduino,每次打开 Arduino 时,那个草图都会运行,直到你上传新的草图。

在这个项目中,我们将使用 Arduino IDE 中自带的 闪烁 示例草图。这个程序每隔 1 秒打开 LED,然后再关闭 1 秒,循环重复。LED 在通过电流时会发光。LED 只能在一个方向上通电,因此较长的引线必须连接到正电源。LED 还需要一个限流电阻,否则它们可能会烧毁。Arduino 的 13 号引脚已经内置了一个电阻。

按照以下步骤设置测试:

  1. 将 LED 的长正极脚(也称为 +5V 或 阳极)插入 Arduino 的 13 号引脚,如图 0-7 所示。将短负极脚(也称为 阴极)连接到 13 号引脚旁边的 GND 引脚。

    图 0-7:

    闪烁项目设置

    image

  2. 使用 USB 电缆将 Arduino 连接到计算机。

  3. 在 IDE 中输入以下草图。

    ➊ // Blinking LED Project
    ➋ int led = 13;
    ➌ void setup() {
    ➍   pinMode(led, OUTPUT);
       }
    ➎ void loop() {
    ➏   digitalWrite(led, HIGH);
    ➐   delay(1000);
    ➑   digitalWrite(led, LOW);
    ➒   delay(1000);
    ➓ }
    
  4. 点击验证按钮(看起来像一个勾号),确认草图是否正常工作。

  5. 现在点击上传按钮,将草图发送到你的 Arduino。

理解草图

下面是草图中每行代码的作用:

➊ 这是一个注释。你程序中的任何以 // 开头的行都只供用户阅读,Arduino 会忽略它们,所以可以使用这种方式来输入注释并描述你的代码(称为 注释代码)。如果注释超过一行,第一行以 /* 开始,最后一行以 */ 结束。中间的所有内容都会被 Arduino 忽略。

➋ 这将引脚 13 命名为 led。草图中每次提到 led 都是指引脚 13。

➌ 这意味着紧随其后的 {} 中的代码将在程序开始时运行一次。开括号 { 开始了设置代码。

➍ 这告诉 Arduino 引脚 13 是一个输出引脚,表示我们要为 LED 提供电源。闭合大括号 } 结束了设置代码。

➎ 这创建了一个循环。大括号 {} 中的所有内容会在 Arduino 开机时运行一次,然后重复执行,直到断电为止。

➏ 这告诉 Arduino 将 led(引脚 13)设置为 HIGH,这会给该引脚提供电源。可以把它看作是打开该引脚。在这个草图中,这会点亮 LED。

➐ 这告诉 Arduino 等待 1 秒钟。Arduino 上的时间以毫秒为单位,因此 1 秒 = 1,000 毫秒。

➑ 这告诉 Arduino 将 led(引脚 13)设置为 LOW,这会切断电源并关闭该引脚。这会关闭 LED。

➒ 同样,Arduino 被告知再等 1 秒钟。

➓ 这个闭合的大括号结束了循环。所有在 setup 后面的代码都必须被大括号括起来。草图中常见的错误是缺少开括号或闭括号,这会导致草图无法正确编译。在这个大括号后,草图会返回到循环的起始位置 ➎。

运行此代码应该会让你的 LED 闪烁。现在你已经测试了你的 Arduino 并了解了草图的工作原理以及如何上传它,接下来我们将看看你需要哪些组件来完成本书中的所有项目。附录 A 提供了关于每个组件、它的外观和作用的更多细节。

项目组件清单

这是你完成本书中的项目所需的所有物品的完整列表。当然,最重要的部分是 Arduino 板本身——所有项目都使用 Arduino Uno R3 版本。如前所述,只有官方板才叫做 Arduino,但与软件兼容的克隆板可以从像 SlicMicro、Sainsmart 和 Adafruit 这样的公司购买,并且会被称为 Uno R3 或兼容 Arduino Uno R3。(你可以在arduino.cc/en/Main/Buy/找到官方供应商的列表。)

每个项目都会先列出所需的物品,因此,如果你只想完成其中的一些项目,可以翻到你感兴趣的项目并只获取那些组件。虽然你可以单独购买每一项物品,但我建议购买一个电子爱好者入门套件或 Arduino 套件。你可以在网上找到许多此类套件,附录 A 中列出了推荐的供应商。标有星号 (*) 的组件都可以在 Arduino Bare Bones Kit 中找到,这可以节省你一些时间和金钱。

1 个 Arduino Uno R3(或兼容的替代品)

1 个带 2.1 mm 插头的 9V 电池包

2 块全尺寸面包板

1 块半尺寸面包板

1 个迷你面包板

50 根公对公跳线

10 根母对母跳线

30 个 220 欧姆电阻

10 个 330 欧姆电阻

1 个 470 欧姆电阻

1 个 10k 欧姆电阻

1 个 1M 欧姆电阻

40 个 5 mm LED 灯:红色、绿色、黄色、蓝色(每种颜色 10 个)

1 个 50k 欧姆电位器

4 个瞬时触觉四针按钮

1 个 HL-69 湿度计土壤湿度传感器

1 个压电蜂鸣器

1 个 3.5 mm 手机插孔

2 个 Tower Pro SG90 9g 伺服电机

1 个光敏电阻(也称为光电阻,或 LDR)

1 个模拟五针、双轴操纵杆模块

1 个全景摇摆模块

1 个四针 HC-SR04 超声波测距传感器

1 个 4×4 薄膜键盘

1 个七段 LED 显示器

1 个四位七段式串行显示器

1 个 DHT11 湿度传感器

1 个 16x2 LCD 屏幕(与 Hitachi HD44780 兼容)

1 个倾斜球开关

1 个 8×8 RGB LED 矩阵

1 个 38 kHz 红外(IR)传感器

1 个 HC SR501 PIR(被动红外)传感器

1 个 Mifare RFID RC-522 读卡器、卡片和钥匙扣

4 个 74HC595 移位寄存器

1 支低功率激光指示笔

1 个 WLToys RC V959 导弹发射器

1 个 ATMEL ATmega328p 芯片*

1 个 16 MHz 晶体振荡器(HC-495)*

1 个 L7805cv 5V 稳压器*

2 个 100 μF 电解电容*

1 个 PP3 9V 电池夹*

2 个 22 pF 磁盘电容*

9V 电池*

设置工作空间

为了充分利用 Arduino,您应该创建一个既能让你的想象力自由发挥,又能保持组织有序的工作空间。如果可能的话,最好是一个专用空间,像图 0-8 中展示的那样;一些项目可能需要几个小时才能完成,因此你可能没有时间一次性完成它们,而且没有什么比不得不停下来整理一遍然后下次再重新拿出来更糟的了。

图 0-8:

一个示例工作空间

image

工作空间可以设在任何地方,但你需要的主要是一个桌子或足够大的平面,既能放下你的电脑或笔记本(方便使用 IDE 并上传程序),也能让你进行实际的构建工作。

你可能还需要一些空间来放置你的元件以及可能需要的工具,比如电烙铁、剥线钳、手工刀、手工钻等。将所有工具和材料一直放在外面可能不太实际,因此购买一些手工或工艺储物箱来存放零件是个不错的主意。我用一个大箱子来存放设备,如电烙铁或电线剪,另外的小箱子则用来存放元件。塑料渔具箱或工艺用的箱子非常适合存放元件(见图 0-9),而悬臂工具箱非常适合放置电烙铁和其他小设备(见图 0-10)。小型塑料盒子,通常设计用于存放珠宝或工艺用品,也是存放非常小的元件的好方法(见图 0-11)。

图 0-9:

渔具盒或工艺盒非常适合存放元件。

image

图 0-10:

悬臂工具箱非常适合存放电烙铁和其他小工具。

image

图 0-11:

塑料珠宝盒非常适合整理非常小的物品。

image

考虑购买一块账本大小的切割垫,作为一个定义明确的非导电工作空间(不会导电的空间),这样你就不必担心短路敏感的电子元件。

设备和工具指南

虽然这些设备对于本书中的项目并非必需,但以下是一些在设置工作空间时可能考虑购买的有用设备。

• 帮手—用于固定物品

image

• 大账本尺寸的非导电切割垫

image

• 钳嘴钳

image

• 电线剪

image

• 30 瓦电烙铁和焊锡(参见快速焊接指南第 18 页)

• 焊锡吸取器,用来吸取焊锡!

image

• 剥线钳—特别适用于制作跳线

image

• 用于 Arduino 的 USB A 对 B 电缆

image

• 数字万用表

image

• 螺丝刀

image

• 旋转工具及附件

image

• 热熔胶枪

image

快速焊接指南

一些你需要的元件可能在运输时没有附带头针(图 0-12),你需要将它们焊接到位。头针是你附加到元件上的一排引脚,以便使用跳线连接或插入面包板。它们通常以条状形式出售,可以轻松折断到所需的大小,通常被插入元件上为其设计的孔中。

图 0-12:

头针

image

例如,在第二十三章中使用的 RFID 模块没有附带引脚,因此我将演示如何将其焊接到位,作为快速焊接指南。如果你需要更深入的指导,可以参考这个有用的漫画焊接指南:* mightyohm.com/files/soldercomic/FullSolderComic_EN.pdf *。

首先,你需要一把焊接烙铁(图 0-13)。一把 30 瓦的通用焊接烙铁,带有细尖,应该能够满足你的需求。购买一个包含烙铁、支架和焊锡的套件是值得的。

图 0-13:

焊接烙铁和焊锡丝

image

焊接时,使用烙铁加热你要焊接的区域——例如,引脚和元件接触的地方——然后将焊锡丝涂到加热的区域;焊锡丝会迅速熔化,冷却后,它应能形成两个焊接物之间的干净连接。这里有一个示范。

  1. 插入焊接烙铁,并等待至少五分钟,让它达到工作温度。

  2. 根据你的组件,断开正确数量的头针。对于第二十三章中的 RFID 模块,我们需要一排八个引脚。按照图 0-14 所示插入它们到模块中。

    图 0-14:

    将头针插入模块。

    image

    注意

    你不应该将焊锡直接涂到烙铁上,只能涂到你正在焊接的接头上。

  3. 现在我们将焊接引脚到位。从最左边的引脚开始。将加热的烙铁尖端同时接触到引脚和模块。只需保持大约两秒钟。保持烙铁不动的同时,向该区域加焊锡;焊锡应会熔化并形成接头。

  4. 快速移除烙铁和焊锡——超过几秒钟可能会损坏你的元件。等待接头冷却。

一个好的焊接点应该像一个闪亮的锥形体(图 0-15)。只要稍加练习,你很快就能掌握焊接技巧。

图 0-15:

焊接点应该像这样。

image

安全第一

焊接烙铁非常非常热,使用时需要非常小心,并且不应由无人看管的儿童使用。这里有一些安全小贴士:

• 确保使用支架,切勿将热烙铁直接放在桌子上。

• 在通风良好的房间进行焊接。熔化焊锡释放的烟雾可能对健康有害。

• 将易燃物品远离工作区域。

• 将设备放在儿童接触不到的地方。

• 戴上护目镜。

• 在存放烙铁之前,务必让它完全冷却。

第一部分

image

LED

项目 1:按钮控制的 LED

在本项目中,你将向 LED 电路中添加一个按钮开关,用来控制 LED 何时亮起。

imageimage

所需部件

• Arduino 板

• 面包板

• 跳线

• LED

• 瞬时触觉四脚按钮开关

• 10k 欧姆电阻

• 220 欧姆电阻

本项目将带你了解开关的基础知识,开关将在本书中大量使用。几乎所有电气设备都使用开关来控制元件的开与关。开关的种类很多,你现在将使用的是一个按钮开关(图 1-1)。

图 1-1:

一个按钮开关

image

如何工作

按下按钮时,按钮完成电路连接,电路开启。一旦释放按钮,连接将恢复原状并断开电路,电路关闭。按钮开关也叫做瞬时开关或常开开关,常见于计算机键盘中。这与翻转开关不同,后者无论处于开还是关的位置,都会保持不变,直到你切换它,类似于灯光开关。

这种按钮开关有四个引脚,但你通常只会用其中两个进行连接。在本项目中,你将使用上面的连接,虽然下面的两个未使用的引脚也能完成相同的功能。如图 1-2 所示,这些引脚工作在电路中。引脚 A 和 C 总是连接的,B 和 D 也是如此。当按钮按下时,电路就完成了。

图 1-2:

一个按钮开关的不完整电路

image

构建

  1. 如图 1-3 所示,将按钮开关放置到面包板上。

    图 1-3:

    放置按钮开关

    image

  2. 将引脚 A 连接到一个 10k 欧姆电阻的一端,并将该电阻的另一端连接到 Arduino 的引脚 2。将电阻的另一端连接到 GND 轨道,并将 GND 轨道连接到 Arduino 的 GND。将按钮开关的引脚 B 连接到+5V 轨道,并将此轨道连接到 Arduino 的+5V。

    按钮开关 ARDUINO
    引脚 A 通过 10k 欧姆电阻连接至 GND 和引脚 2
    引脚 B +5V
  3. 将 LED 放置到面包板上,将较长的正极脚通过 220 欧姆电阻连接到 Arduino 的引脚 13,将较短的负极脚连接到 GND。

    LED ARDUINO
    正极 通过 220 欧姆电阻连接至引脚 13
    负极 GND
  4. 确认你的电路设置与图 1-4 中的电路图相符,然后上传位于第 27 页的“草图”代码。

    图 1-4:

    按钮控制的 LED 电路图

    image

草图

在这个草图中,你为按钮分配一个引脚并将其设置为 INPUT,为 LED 分配一个引脚并将其设置为 OUTPUT。代码告诉 Arduino 只要按钮被按下(完成电路),就打开 LED,并且在按钮未被按下时将 LED 关闭。当按钮被释放时,电路断开,LED 会再次关闭。

/* by DojoDave <http://www.0j0.org>
   modified 30 Aug 2011 by Tom Igoe
   This example code is in the public domain.
   http://www.arduino.cc/en/Tutorial/Button
*/

const int buttonPin = 2;      // Pin connected to pushbutton
const int ledPin = 13;        // Pin connected to LED
int buttonState = 0;          // Give pushbutton a value

void setup() {
  pinMode(ledPin, OUTPUT);    // Set LED pin as output
  pinMode(buttonPin, INPUT);  // Set pushbutton pin as input
}

void loop() {
  buttonState = digitalRead(buttonPin); // Read input from pin 2
  if (buttonState == HIGH) { // If pushbutton is pressed, set as HIGH
    digitalWrite(ledPin, HIGH); // Turn on LED
  }
  else {
    digitalWrite(ledPin, LOW);  // Otherwise, turn off LED
  }
}

项目 2:光调光器

在这个项目中,你将通过添加一个电位器来控制 LED 的亮度,从而创建一个调光开关。

imageimage

所需零件

• Arduino 板

• 面包板

• 跳线

• LED

• 50k 欧姆电位器

• 470 欧姆电阻

电位器是一个可变电阻器,带有一个旋钮,允许你在旋转时改变电位器的电阻。它通常用于音频设备中的音量控制等电子设备中。本项目使用的是一个 50k 欧姆的电位器。

工作原理

电位器操控一个连续的模拟信号,表示物理测量值。人类通过模拟感知世界;我们看到和听到的一切都是信息以连续的形式传输到我们的感官。这种连续流就是定义模拟数据的方式。另一方面,数字信息通过仅使用数字来估算模拟数据。为了逼近电位器的连续模拟数据,Arduino 必须将信号表示为一系列离散的数字——在此情况下为电压。电位器的中间引脚将信号发送到 Arduino 的模拟输入——任何 A0 到 A5 的引脚——以读取该值。

LED 实际上是被开关快速切换的,但这个切换速度非常快,以至于我们的眼睛可以补偿,从而看到一个持续点亮的 LED,在不同的光照水平下变化。这就是所谓的视觉保持效果

为了创造视觉保持效果,Arduino 使用一种叫做脉宽调制(PWM)的技术。Arduino 通过非常快速地开关电源来创建脉冲。电源开启或关闭的持续时间(称为脉冲宽度)在周期中决定了平均输出,通过变化这个脉冲宽度,模式可以模拟从完全开启(5 伏)到关闭(0 伏)之间的电压。如果 Arduino 的信号在一半时间内是开启的,另一半时间是关闭的,那么平均输出将是 2.5 伏,介于 0 伏和 5 伏之间。如果信号开启 80% 的时间,关闭 20% 的时间,那么平均电压就是 4 伏,依此类推。你可以通过旋转电位器来改变信号,从而改变脉冲宽度,增加或减少电阻。

使用这种技术,你可以改变发送到 LED 的电压,使其变得更暗或更亮,以匹配来自电位器的模拟信号。只有 Arduino 的 3、5、6、9、10 或 11 引脚可以使用 PWM。图 2-1 给出了 PWM 作为波形的示例。

图 2-1:

脉宽调制作为波形

image

搭建

  1. 将电位器插入面包板,并将中间的脚连接到 Arduino 的 A0 引脚。将一个外侧脚连接到面包板的 +5V 排,另一个外侧脚连接到面包板的 GND(实际上外侧电位器脚的连接顺序并不重要;这些说明仅反映本项目中的电路图),如图 2-2 所示。

    图 2-2:

    将电位器连接到 Arduino

    image

    电位器 ARDUINO
    左脚 +5V
    中心脚 A0
    右脚 GND
  2. 将 LED 插入面包板。将正极脚(较长的脚)通过 470 欧姆电阻连接到 Arduino 的引脚 9,将负极脚连接到 GND,如图 2-3 所示。

    LED ARDUINO
    正极 引脚 9
    负极脚 通过 470 欧姆电阻连接 GND

    图 2-3:

    调光电路图

    image

  3. 上传下方 “The Sketch” 中的代码。

  4. 转动电位器来控制 LED 的亮度。

这个项目有很多潜在的用途:你可以将多个 LED 集合在一起,制作一个可调节的手电筒、夜灯、展示柜灯光,或者任何需要调光灯的设备。

草图

这个草图的工作原理是将引脚 A0 设置为电位器,将引脚 9 设置为 OUTPUT 来为 LED 提供电源。然后你运行一个循环,不断读取电位器的数值,并将该数值作为电压传送给 LED。电压值在 0 至 5 伏之间,LED 的亮度会随之变化。

/* http://arduino.cc/en/Reference/AnalogWrite by Tom Igoe
   from http:itp.nyu.edu/physcomp/Labs/AnalogIn */

int potPin = A0; // Analog input pin connected to the potentiometer
int potValue = 0; // Value that will be read from the potentiometer
int led = 9; // Pin 9 (connected to the LED) is capable of PWM

// Runs once at beginning of the program
void setup() {
  pinMode(led, OUTPUT); // Set pin 9 to output
}

// Loops continuously
void loop() {
  potValue = analogRead(potPin); // Read potentiometer value
                                 // from A0 pin
  analogWrite(led, potValue/4);  // Send potentiometer value to LED
                                 // to control brightness with PWM
  delay(10);                     // Wait for 10 ms
}

项目 3:条形图

在这个项目中,你将结合之前在 LED 项目中学到的知识,制作一个可以通过电位器控制的 LED 条形图。

imageimage

所需零件

• Arduino 主板

• 面包板

• 跳线

• 9 个 LED

• 50k 欧姆电位器

• 9 个 220 欧姆电阻

工作原理

条形图是由一排 LED 组成的,类似于你在音频显示器上看到的那种。它由一排 LED 和一个模拟输入(如电位器或麦克风)构成。在这个项目中,你使用电位器的模拟信号来控制点亮的 LED。当你朝一个方向转动电位器时,LED 会按顺序依次点亮,如图 3-1(a)所示,直到全部点亮,如图 3-1(b)所示。当你朝另一个方向转动时,它们会按顺序熄灭,如图 3-1(c)所示。

图 3-1:

随着你转动电位器,LED 会按顺序点亮和熄灭。

image

构建过程

  1. 将 LED 插入面包板,将其较短的负极脚插入 GND 排,并通过跳线将此排连接到 Arduino 的 GND。

  2. 将每个 LED 插入 220 欧姆电阻,并将电阻的一条引脚连接到 LED 的正极脚。将电阻的另一条引脚依次连接到数字引脚 2–10,如图 3-2 所示。电阻必须跨接面包板中的断点,如图所示。

    LED Arduino
    正极脚 通过 220 欧姆电阻连接到 2–10 号引脚
    负极脚 GND

    图 3-2:

    条形图电路图

    image

    注意

    如项目 2 中所述,外部电位器引脚的连接方向其实并不重要,但我在这里给出了说明以配合图像。

  3. 将电位器放入面包板,并将中间引脚连接到 Arduino A0 引脚。将右侧外引脚连接到+5V,将左侧电位器引脚连接到 GND。

    电位器 Arduino
    左侧引脚 GND
    中间引脚 A0
    右侧引脚 +5V
  4. 上传下面的“草图”代码。

草图

草图首先读取电位器的输入。它将输入值映射到输出范围,在本例中为九个 LED。然后它在输出上设置一个for循环。如果系列中 LED 的输出编号低于映射的输入范围,则 LED 点亮;否则,LED 熄灭。明白了吗?很简单!如果你将电位器旋转到右侧,LED 将依次亮起。将电位器旋转到左侧,它们将依次熄灭。

/* By Tom Igoe. This example code is in the public domain.
   http://www.arduino.cc/en/Tutorial/BarGraph */

const int analogPin = A0; // Pin connected to the potentiometer
const int ledCount = 9;   // Number of LEDs
int ledPins[] = {2,3,4,5,6,7,8,9,10}; // Pins connected to the LEDs

void setup() {
  for (int thisLed = 0; thisLed < ledCount; thisLed++) {
    pinMode(ledPins[thisLed], OUTPUT); // Set the LED pins as output
  }
}

// Start a loop
void loop() {
  int sensorReading = analogRead(analogPin); // Analog input
  int ledLevel = map(sensorReading, 0, 1023, 0, ledCount);
  for (int thisLed = 0; thisLed < ledCount; thisLed++) {
    if (thisLed < ledLevel) { // Turn on LEDs in sequence
      digitalWrite(ledPins[thisLed], HIGH);
    }
    else { // Turn off LEDs in sequence
      digitalWrite(ledPins[thisLed], LOW);
    }
  }
}

项目 4:迪斯科频闪灯

在本项目中,你将应用在项目 3 中学到的技能,制作一个具有可调速度设置的频闪灯。

imageimage

所需零件

• Arduino 板

• 面包板

• 跳线

• 2 个蓝色 LED

• 2 个红色 LED

• 50k 欧姆电位器

• 4 个 220 欧姆电阻

工作原理

旋转电位器的旋钮可以改变闪烁灯光的速度,产生频闪效果。你可以使用红色和蓝色的 LED 来模拟闪烁的警灯效果(见图 4-1)。将相同颜色的 LED 连接到同一个 Arduino 引脚,这样它们就会一起点亮。如果你制作一个外壳来放置 LED,你就拥有了一个移动的频闪灯。你最多可以添加 10 个 LED,只需更新草图以包括你的输出引脚和新的 LED 数量。

图 4-1:

红色和蓝色的 LED 模拟警车的灯光。

image

搭建过程

  1. 将你的 LED 插入面包板,将较短的负极引脚连接到 GND 轨道,然后将该轨道连接到 Arduino GND。

    注意

    记得为面包板加电。

  2. 将电阻插入面包板,并将它们连接到 LED 的较长正极脚。使用跳线将两颗红色 LED 和两颗蓝色 LED 通过电阻连接在一起,如图 4-2 所示;这允许相同颜色的 LED 通过单个引脚控制。

    图 4-2:

    使用跳线连接 LED

    image

  3. 将红色 LED 连接到 Arduino 引脚 12,将蓝色 LED 连接到 Arduino 引脚 11。

    LEDs Arduino
    负极脚 GND
    正极脚(红色) 引脚 12
    正极脚(蓝色) 引脚 11
  4. 将电位器放置在面包板上,并将中间引脚连接到 Arduino 的 A0,引脚左侧连接到 GND,右侧连接到 +5V。

    电位器 Arduino
    左引脚 GND
    中间引脚 A0
    右引脚 +5V
  5. 确认您的设置与 图 4-3 中的设置一致,然后上传 第 43 页 中的 "程序草图" 代码。

    图 4-3:

    迪斯科频闪灯电路图

    image

程序草图

程序草图的工作原理是将电位器的模拟信号作为输入传递到 Arduino,将连接到 LED 的引脚作为输出。Arduino 读取来自电位器的模拟输入,并将该值作为 延迟值——即 LED 状态改变前的时间量(无论是开还是关)。这意味着 LED 会根据电位器的值开关,改变此值会改变闪烁的速度。程序草图通过 LED 间的切换来产生频闪效果。

const int analogInPin = A0; // Analog input pin connected to the
                            // potentiometer
int sensorValue = 0;        // Value read from the potentiometer
int timer = 0;              // Delay value

// Set digital pins 12 and 11 as outputs
void setup() {
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
}

// Start a loop to turn LEDs on and off with a delay in between
void loop() {
  sensorValue = analogRead(analogInPin); // Read value from the
                                         // potentiometer
  timer = map(sensorValue, 0, 1023, 10, 500); // Delay 10 to 500 ms
  digitalWrite(12, HIGH); // LED turns on
  delay(timer);           // Delay depending on potentiometer value
  digitalWrite(12, LOW);  // LED turns off
  delay(timer);
  digitalWrite(12, HIGH);
  delay(timer);
  digitalWrite(12, LOW);
  digitalWrite(11, HIGH);
  delay(timer);
  digitalWrite(11, LOW);
  delay(timer);
  digitalWrite(11, HIGH);
  delay(timer);
  digitalWrite(11, LOW);
}

项目 5:植物监测器

在这个项目中,我将介绍一种新型的模拟传感器,它能够检测湿度水平。你将建立一个光照和声音报警系统,用来告诉你何时给植物浇水。

imageimage

所需零件

• Arduino 板

• 跳线

• LED

• HL-69 湿度计土壤湿度传感器

• 蜂鸣器

工作原理

您将使用 HL-69 湿度传感器,它可以在网上购买到,价格仅为几美元,或从 附录 A 中列出的零售商处购买。传感器的探针通过土壤传递电流并测量电阻,从而检测周围土壤的湿度。潮湿的土壤导电性好,因此电阻较低,而干燥的土壤导电性差,电阻较高。

传感器由两部分组成,如 图 5-1 所示:实际的探针传感器 (a) 和控制器 (b)。传感器上的两个引脚需要连接到控制器上的两个单独的引脚(通常会提供连接线)。控制器的另一侧有四个引脚,其中三个连接到 Arduino。

图 5-1:

HL-69 湿度传感器的探针 (a) 和控制器 (b)

image

四个引脚从左到右分别是 AO(模拟输出)、DO(数字输出)、GND 和 VCC(见 图 5-2)。当控制器连接到计算机时,您可以通过 IDE 读取控制器的数值。这个项目不使用面包板,所以所有连接都直接连接到 Arduino 上。

图 5-2:

模块底部标有引脚位置

image

低读数表示检测到更多的湿气,高读数表示干燥。如果读数超过 900,说明植物非常缺水。如果植物太干,LED 灯将亮起,压电蜂鸣器会发出声音。压电蜂鸣器价格便宜,更多细节请参考项目 7。

构建过程

  1. 将传感器的两个引脚通过提供的连接线连接到控制器上的+和–引脚,如图 5-3 所示。

    图 5-3:

    连接传感器到控制器

    image

  2. 将控制器的三个引脚直接连接到 Arduino 上的+5V、GND 和 A0 引脚,如下表所示。DO 引脚未使用。

    传感器控制器 ARDUINO
    VCC +5V
    GND GND
    A0 A0
    DO 未使用
  3. 将 LED 直接连接到 Arduino,短的负极腿连接到 GND,长的正极腿连接到 Arduino 的 13 号引脚,如图 5-4 所示。

    图 5-4:

    将 LED 连接到 Arduino

    image

    LED ARDUINO
    正极 13 号引脚
    负极 GND
  4. 将压电蜂鸣器的黑色线连接到 GND,将红色线连接到 Arduino 的 11 号引脚。

    压电蜂鸣器 ARDUINO
    红色线 11 号引脚
    黑色线 GND
  5. 检查你的设置是否与图 5-5 中的一致,然后上传“代码”中的代码到第 51 页。

    图 5-5:

    植物监测器的电路图

    image

  6. 使用 USB 电缆将 Arduino 连接到计算机。打开 IDE 中的串口监视器,查看传感器的读数——这也将帮助你校准植物监测器。IDE 会显示传感器的读数。我的传感器干燥且未插入土壤时读数为 1000,所以我知道这是最高和最干燥的值。要校准此值,可以顺时针旋转控制器上的电位器来增加电阻,逆时针旋转则减少电阻(参见图 5-5)。

    当传感器插入湿润的土壤中时,读数会降至大约400。随着土壤逐渐干燥,传感器的读数会上升;当读数达到900时,LED 灯会亮起,蜂鸣器会响起。

    图 5-6:

    调节电位器以校准植物监测器。

    image

代码

代码首先定义了 Arduino 的 A0 引脚,用于读取湿度传感器的值。然后定义 Arduino 的 11 号引脚为蜂鸣器的输出引脚,13 号引脚为 LED 的输出引脚。使用Serial.Println()函数将传感器的读数发送到 IDE,以便在屏幕上查看。

修改以下行中的值

if(analogRead(0) > 900){

根据传感器干燥时的读数(这里是 900)。当土壤潮湿时,读数会低于 900,因此 LED 和蜂鸣器将保持关闭。当读数超过 900 时,表示土壤正在干燥,LED 和蜂鸣器会提醒你给植物浇水。

const int moistureAO = 0;
int AO = 0;       // Pin connected to A0 on the controller
int tmp = 0;      // Value of the analog pin
int buzzPin = 11; // Pin connected to the piezo buzzer
int LED = 13;     // Pin connected to the LED

void setup () {
  Serial.begin(9600); // Send Arduino reading to IDE
  Serial.println("Soil moisture sensor");
  pinMode(moistureAO, INPUT);
  pinMode(buzzPin, OUTPUT); // Set pin as output
  pinMode(LED, OUTPUT);     // Set pin as output
}

void loop () {
  tmp = analogRead( moistureAO );
  if ( tmp != AO ) {
    AO = tmp;
    Serial.print("A = "); // Show the resistance value of the sensor
                          // in the IDE
    Serial.println(AO);
  }
  delay (1000);
  if (analogRead(0) > 900) { // If the reading is higher than 900,
    digitalWrite(buzzPin, HIGH); // the buzzer will sound
    digitalWrite(LED, HIGH);     // and the LED will light
    delay(1000); // Wait for 1 second
    digitalWrite(buzzPin, LOW);
    digitalWrite(LED, HIGH);
  }
  else {
    digitalWrite(buzzPin, LOW); // If the reading is below 900,
                                // the buzzer and LED stay off
    digitalWrite(LED, LOW);
  }
}

项目 6:鬼魂探测器

谁不想做一个鬼魂探测器呢?这个项目非常简单,组装起来也不需要太长时间,所以你可以立刻开始探测鬼魂。

imageimage

所需零件

• Arduino 板

• 面包板

• 跳线

• 3 个红色 LED

• 1 个黄色 LED

• 6 个绿色 LED

• 10 个 220 欧姆电阻

• 20 厘米单芯线

• 1M 欧姆电阻

工作原理

好吧,可能我有点夸张地称这个项目为鬼魂探测器。这个项目实际上是检测电磁场,但许多人相信这就是判断是否有鬼魂或灵体的方法。

在这个项目中,你将设置一个鬼魂探测天线和 LED 条形图系统,用来检测附近是否有较强的电磁活动。裸线作为天线,在两米的半径范围内拾取电磁场。根据信号的强度,LED 会按顺序亮起:信号越强,亮起的 LED 越多。启动 Arduino 后,将探测器指向一个房间,查看是否有异常存在。需要注意的是,电视等电器设备会使探测器发生反应,因为它们发射的信号。

构建过程

  1. 将 LED 插入面包板,确保 LED 的引脚位于中心分隔线的两侧(有关面包板布局的更多信息,请参阅 Breadboards 章节,见第 4 页),如图 6-1 所示。我从一个黄色 LED 开始,然后使用六个绿色 LED 和三个红色 LED,按照从左到右的顺序排列。你可以使用任何颜色的 LED,并按你喜欢的顺序排列它们。

    图 6-1:

    放置 LED

    image

    电磁场

    电场是由电压差异产生的:电压越高,产生的电场越强。磁场是当电流流动时产生的:电流越大,磁场越强。电磁场(EMF)可以被看作是两者的结合体。

    image

    电磁场在环境中随处可见,但人眼无法直接看到。电场是由大气中局部积累的电荷产生的,并与雷暴相关联。地球持续发出磁场,鸟类和鱼类用它来导航,它还会使指南针指向北方。

  2. 将 220 欧姆电阻的一端连接到每个负极 LED 引脚,另一端插入面包板的 GND 排针(见图 6-2)。依次将每个正极 LED 引脚连接到数字引脚 2 至 11。

    LED 灯 Arduino
    正极引脚 引脚 2–11
    负极引脚 通过 220 欧姆电阻接地

    图 6-2:

    将 LED 灯连接到面包板

    image

  3. 取一段 20 厘米长的单股电线,用剥线钳从一端剥去约 1 厘米的绝缘层。将这端连接到 Arduino 的 A5 引脚。然后从另一端剥去约 7 厘米的绝缘层——这个裸露的线头就是你的天线,用来拾取电磁信号(见图 6-3)。

    图 6-3:

    剥线制作天线

    image

  4. 将 1M 欧姆电阻的一端直接连接到 Arduino 的 GND,另一端连接到 Arduino 的 A5 引脚;这将增加设备的灵敏度。

  5. 检查你的设置是否与图 6-4 相符,然后上传第 59 页的“代码”。

    图 6-4:

    幽灵探测器的电路图

    image

代码

裸线从大气中的电磁场拾取信号,并将 0 到 1023 之间的值发送到 Arduino。代码会评估模拟引脚的读取值,以确定有多少个 LED 灯按照顺序开关,以表示电磁信号的强度。例如,1023 是最高值,所有 LED 灯都会点亮;而 550 的读数则点亮五个 LED 灯。代码会不断循环读取模拟输入,LED 灯会不断移动以显示读数。如果你发现电磁场(EMF)读数每次都会让 LED 灯序列达到最大级别,可以通过降低senseLimit值来补偿。代码每次循环会取 25 次读数的平均值,并使用该平均值来减少可能导致 LED 灯过快点亮的大幅波动。

注意

完成幽灵探测器后,试着加入一些根据读数变化的声音效果,例如随着读数增加,声音的速度或音量也会增大。为项目制作外壳,打造你自己的手持传感器,带着它去探险。你还可以尝试使用不同类型和厚度的电线,或者去掉电阻来实现不同的灵敏度。

// Code by James Newbould used with kind permission
#define NUMREADINGS 25 // Raise number to increase data smoothing
int senseLimit = 1023; // Raise number to decrease sensitivity of
                       // the antenna (up to 1023 max)
int probePin = 5; // Set analog pin 5 as the antenna pin
int val = 0;      // Reading from probePin

// Pin connections to LED bar graph with resistors in series
int LED1 = 11;
int LED2 = 10;
int LED3 = 9;
int LED4 = 8;
int LED5 = 7;
int LED6 = 6;
int LED7 = 5;
int LED8 = 4;
int LED9 = 3;
int LED10 = 2;
int readings[NUMREADINGS]; // Readings from the analog input
int index = 0;             // Index of the current reading
int total = 0;             // Running total
int average = 0;           // Final average of the probe reading

void setup() {
  pinMode(2, OUTPUT); // Set LED bar graph pins as outputs
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
 Serial.pinMode(9600); // Initiate serial connection with IDE for
                        // debugging and so on
  for (int i = 0; i < NUMREADINGS; i++)
    readings[i] = 0; // Initialize all readings to 0
}

void loop() {
  val = analogRead(probePin); // Take a reading from probe
  if (val >= 1) {             // If the reading isn't zero, proceed
    val = constrain(val, 1, senseLimit); // If the reading is
                                         // higher than the current
                                         // senseLimit value, update
                                         // senseLimit value with
                                         // higher reading
    val = map(val, 1, senseLimit, 1, 1023); // Remap the constrained
                                            // value within a 1 to
                                            // 1023 range
    total -= readings[index]; // Subtract the last reading
    readings[index] = val;    // Read from the sensor
    total += readings[index]; // Add the reading to the total
    index = (index + 1);      // Advance to the next index
    if (index >= NUMREADINGS) // If we're at the end of the array
      index = 0;              // loop around to the beginning
    average = total / NUMREADINGS; // Calculate the average reading
    if (average > 50) { // If the average reading is higher than 50
      digitalWrite(LED1, HIGH); // turn on the first LED
    }
    else {                        // If it's not
      digitalWrite(LED1, LOW);    // turn off that LED
    }
    if (average > 150) {          // And so on
      digitalWrite(LED2, HIGH);
    }
    else {
      digitalWrite(LED2, LOW);
    }
    if (average > 250) {
      digitalWrite(LED3, HIGH);
    }
    else {
      digitalWrite(LED3, LOW);
    }
    if (average > 350) {
      digitalWrite(LED4, HIGH);
    }
    else {
      digitalWrite(LED4, LOW);
    }
    if (average > 450) {
      digitalWrite(LED5, HIGH);
    }
    else {
      digitalWrite(LED5, LOW);
    }
    if (average > 550) {
      digitalWrite(LED6, HIGH);
    }
    else {
      digitalWrite(LED6, LOW);
    }
    if (average > 650) {
      digitalWrite(LED7, HIGH);
    }
    else {
      digitalWrite(LED7, LOW);
    }
    if (average > 750) {
      digitalWrite(LED8, HIGH);
    }
    else {
      digitalWrite(LED8, LOW);
    }
    if (average > 850) {
      digitalWrite(LED9, HIGH);
    }
    else {
      digitalWrite(LED9, LOW);
    }
    if (average > 950) {
      digitalWrite(LED10, HIGH);
    }
    else {
      digitalWrite(LED10, LOW);
    }
    Serial.println(val);   // Use output to aid in calibrating
  }
}

第二部分

image

声音

项目 7:Arduino 旋律

到目前为止,所有项目都是视觉项目,现在是时候制作一些音乐了。在这个项目中,我们将使用压电蜂鸣器来播放一些旋律。

imageimage

所需组件

• Arduino 主板

• 压电蜂鸣器

工作原理

Arduino 旋律使用压电蜂鸣器产生类似于可辨认音符的频率。你可以使用 Arduino IDE 来指定音符的顺序、速率和时长,以播放特定的旋律。

压电元件是便宜的蜂鸣器,通常用于小型玩具。没有塑料外壳的压电元件看起来像一个金色的金属圆盘,带有连接的正极(通常为红色)和负极(通常为黑色)导线。压电元件只能发出“咔嗒”声,我们通过施加电压来产生这个声音。我们可以通过让压电元件在每秒钟以特定频率点击数百次来发出可辨认的音符,因此首先我们需要知道我们想要的不同音调的频率。表 7-1 显示了音符及其对应的频率。周期是以微秒为单位的时间长度,用于创建该频率。我们将这个数字除以二,得到timeHigh值,该值在代码中用于生成音符。

表 7-1:

音符及其对应的频率

音符 频率 周期 timeHigh
C 261 Hz 3,830 1915
D 294 Hz 3,400 1700
E 329 Hz 3,038 1519
F 349 Hz 2,864 1432
G 392 Hz 2,550 1275
A 440 Hz 2,272 1136
B 493 Hz 2,028 1014
C 523 Hz 1,912 956

该代码向压电元件发送适当频率的方波,生成相应的音调(有关波形的更多内容,请参见项目 2)。这些音调通过以下公式计算:

timeHigh = period / 2 = 1 / (2 * toneFrequency)

这个项目的设置非常简单,只需要两根连接到 Arduino 的导线。

构建

  1. 将压电元件的黑线直接连接到 Arduino 的 GND 引脚,红线连接到 Arduino 的引脚 9。

    压电元件 Arduino
    红线 引脚 9
    黑线 GND
  2. 检查你的设置是否与图 7-1 中的一致,然后上传接下来在“草图”中显示的代码。

    图 7-1

    Arduino 旋律的电路图

    image

草图

我们将从一段简单的旋律开始。在 ➊ 处,我们告诉 IDE 这段旋律由 15 个音符组成。然后,我们将旋律的音符按演奏顺序存储在字符数组中,音符播放的时长则存储在另一个整数数组中。如果你想改变旋律,你可以在 ➋ 处修改数组中的音符,在 ➌ 处修改每个音符的拍数。最后,在 ➍ 处我们设置旋律的演奏速度。将这些组合在一起,它会播放什么?

   // Melody (cleft) 2005 D. Cuartielles for K3

   int speakerPin = 9; // Pin connected to the piezo
➊ int length = 15; // Number of notes
➋ char notes[] = "ccggaagffeeddc "; // A space represents a rest
➌ int beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };
➍ int tempo = 300;
 void playTone(int tone, int duration) {
     for (long i = 0; i < duration * 1000L; i += tone * 2) {
       digitalWrite(speakerPin, HIGH);
       delayMicroseconds(tone);
       digitalWrite(speakerPin, LOW);
       delayMicroseconds(tone);
     }
   }

   // Set timeHigh value to specific notes
   void playNote(char note, int duration) {
     char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
     int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
     for (int i = 0; i < 8; i++) { // Play tone that corresponds
                                   // to note name
       if (names[i] == note) {
         playTone(tones[i], duration);
       }
     }
   }

   void setup() {
     pinMode(speakerPin, OUTPUT); // Set speakerPin as output
   }

   // Play the tune
   void loop() {
     for (int i = 0; i < length; i++) {
       if (notes[i] == ' ') {
         delay(beats[i] * tempo); // Rest
       }
       else {
         playNote(notes[i], beats[i] * tempo);
       }
       delay(tempo / 2); // Pause between notes
     }
   }

项目 8:记忆游戏

在本项目中,我们将使用四个 LED、四个按键开关、一个蜂鸣器以及一些电阻和跳线,制作一个名为“Touch Me”的 Atari 游戏记忆游戏版本。

imageimage

所需零件

• Arduino 板

• 面包板

• 跳线

• 蜂鸣器

• 4 个瞬时触觉四脚按键

• 4 个 LED

• 4 个 220 欧姆电阻

所需库

• 音调

工作原理

原始的 Atari 游戏有四个彩色面板,每个面板上都有一个 LED,以特定的模式亮起,玩家需要按这个模式重复(见图 8-1)。

图 8-1:

原始的Touch Me游戏

image

这个记忆游戏会播放一段简短的介绍音调并闪烁一个 LED。当你按下正确的对应按钮时,灯光会在一个更长的序列中再次闪烁。每当你正确地重复这个序列时,游戏会增加一个额外的步骤,使序列变得更具挑战性。当你犯错时,游戏会重置。

制作过程

  1. 将按键放置在面包板上,使其跨越中央断点,A 和 B 引脚在断点的一侧,C 和 D 引脚在另一侧,如图 8-2 所示。(参见项目 1 了解按键的更多信息。)

    图 8-2:

    一个按键有四个引脚。

    image

  2. 将每个按键的 B 引脚连接到面包板的 GND 轨道,再将轨道连接到 Arduino 的 GND。

  3. 将每个按键的 D 引脚按顺序连接到 Arduino 的数字引脚 2 至 5。

  4. 将 LED 插入面包板,短的负极脚连接到每个按键的 C 引脚,长的正极脚插入右侧的孔,如图 12-3 所示。

    按键 Arduino/LED
    引脚 B GND
    引脚 C LED 负极脚
    引脚 D Arduino 引脚 2–5
  5. 将一个 220 欧姆的电阻插入面包板,一端连接到每个 LED 的正极脚,电阻的另一端连接到 Arduino,如下所示。

    LED Arduino/按键
    正极脚 Arduino 引脚 8–11,通过 220 欧姆电阻
    负极脚 按键 C 引脚

    确保连接到针脚 11 的红色 LED 与连接到针脚 5 的按钮配对,连接到针脚 10 的黄色 LED 与连接到针脚 4 的按钮配对,连接到针脚 9 的绿色 LED 与连接到针脚 3 的按钮配对,连接到针脚 8 的蓝色 LED 与连接到针脚 2 的按钮配对。

  6. 将压电元件的黑色线直接连接到 Arduino 的 GND,红色线连接到 Arduino 的针脚 12。

    压电元件 Arduino
    红色线 针脚 12
    黑色线 GND
  7. 根据图 8-3 检查你的设置,然后上传第 73 页中“草图”中的代码。

    图 8-3:

    记忆游戏电路图

    image

草图

该草图生成一个随机序列,LED 会按此顺序点亮;在模式循环中生成的随机值y决定了哪个 LED 被点亮(例如,如果 y 是 2,则连接到针脚 2 的 LED 将点亮)。你需要跟随并重复这个模式才能进入下一关。

在每一关中,前面的灯光会重复,并且会随机添加一个新的灯光。每个灯光都与压电元件的不同音调相关联,所以每次你都会听到不同的旋律。当你输入的顺序错误时,草图将重新开始,并生成一个不同的随机序列。为了使草图能够正确编译,你需要安装 Tone 库(可从* nostarch.com.com/arduinohandbook/ *下载)。详细信息请参见第 7 页的“库”部分。

// Used with kind permission from Abdullah Alhazmy www.Alhazmy13.net

#include <Tone.h>
Tone speakerpin;
int starttune[] = {NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_C4,
                   NOTE_F4, NOTE_C4, NOTE_F4, NOTE_G4, NOTE_F4,
                   NOTE_E4, NOTE_F4, NOTE_G4};
int duration2[] = {100, 200, 100, 200, 100, 400, 100, 100, 100, 100,
                   200, 100, 500};
int note[] = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_C5, NOTE_G4, NOTE_C5};
int duration[] = {100, 100, 100, 300, 100, 300};
boolean button[] = {2, 3, 4, 5}; // Pins connected to
                                 // pushbutton inputs
boolean ledpin[] = {8, 9, 10, 11}; // Pins connected to LEDs
int turn = 0;         // Turn counter
int buttonstate = 0;  // Check pushbutton state
int randomArray[100]; // Array that can store up to 100 inputs
int inputArray[100];

void setup() {
  Serial.begin(9600);
  speakerpin.begin(12); // Pin connected to piezo buzzer
  for (int x = 0; x < 4; x++) {
    pinMode(ledpin[x], OUTPUT); // Set LED pins as output
  }
  for (int x = 0; x < 4; x++) {
    pinMode(button[x], INPUT); // Set pushbutton pins as inputs
    digitalWrite(button[x], HIGH); // Enable internal pullup;
                                   // pushbuttons start in high
                                   // position; logic reversed
  }
  // Generate "more randomness" with randomArray for the output
  // function so pattern is different each time
  randomSeed(analogRead(0));
  for (int thisNote = 0; thisNote < 13; thisNote ++) {
    speakerpin.play(starttune[thisNote]); // Play the next note
    if (thisNote == 0 || thisNote == 2 || thisNote == 4 ||
        thisNote == 6) { // Hold the note
      digitalWrite(ledpin[0], HIGH);
    }
    if (thisNote == 1 || thisNote == 3 || thisNote == 5 ||
        thisNote == 7 || thisNote == 9 || thisNote == 11) {
      digitalWrite(ledpin[1], HIGH);
    }
    if (thisNote == 8 || thisNote == 12) {
      digitalWrite(ledpin[2], HIGH);
    }
    if (thisNote == 10) {
      digitalWrite(ledpin[3], HIGH);
    }
    delay(duration2[thisNote]);
    speakerpin.stop(); // Stop for the next note
    digitalWrite(ledpin[0], LOW);
    digitalWrite(ledpin[1], LOW);
    digitalWrite(ledpin[2], LOW);
    digitalWrite(ledpin[3], LOW);
    delay(25);
  }
  delay(1000);
}

void loop() {
  // Generate the array to be matched by the player
  for (int y = 0; y <= 99; y++) {
    digitalWrite(ledpin[0], HIGH);
    digitalWrite(ledpin[1], HIGH);
    digitalWrite(ledpin[2], HIGH);
    digitalWrite(ledpin[3], HIGH);
    // Play the next note
    for (int thisNote = 0; thisNote < 6; thisNote ++) {
      speakerpin.play(note[thisNote]); // Hold the note
      delay(duration[thisNote]);       // Stop for the next note
      speakerpin.stop();
      delay(25);
    }
    digitalWrite(ledpin[0], LOW);
    digitalWrite(ledpin[1], LOW);
    digitalWrite(ledpin[2], LOW);
    digitalWrite(ledpin[3], LOW);
    delay(1000);
    // Limited by the turn variable
    for (int y = turn; y <= turn; y++) {
      Serial.println("");
      Serial.print("Turn: ");
      Serial.print(y);
      Serial.println("");
      randomArray[y] = random(1, 5); // Assign a random number (1-4)
      // Light LEDs in random order
      for (int x = 0; x <= turn; x++) {
        Serial.print(randomArray[x]);
        for (int y = 0; y < 4; y++) {
          if (randomArray[x] == 1 && ledpin[y] == 8) {
            digitalWrite(ledpin[y], HIGH);
            speakerpin.play(NOTE_G3, 100);
            delay(400);
            digitalWrite(ledpin[y], LOW);
            delay(100);
          }
          if (randomArray[x] == 2 && ledpin[y] == 9) {
            digitalWrite(ledpin[y], HIGH);
            speakerpin.play(NOTE_A3, 100);
            delay(400);
            digitalWrite(ledpin[y], LOW);
            delay(100);
          }
          if (randomArray[x] == 3 && ledpin[y] == 10) {
            digitalWrite(ledpin[y], HIGH);
            speakerpin.play(NOTE_B3, 100);
            delay(400);
            digitalWrite(ledpin[y], LOW);
            delay(100);
          }
          if (randomArray[x] == 4 && ledpin[y] == 11) {
            digitalWrite(ledpin[y], HIGH);
            speakerpin.play(NOTE_C4, 100);
            delay(400);
            digitalWrite(ledpin[y], LOW);
            delay(100);
          }
        }
      }
    }
    input();
  }
}

// Check whether input matches the pattern
void input() {
  for (int x = 0; x <= turn;) {
    for (int y = 0; y < 4; y++) {
      buttonstate = digitalRead(button[y]); // Check for button push
      if (buttonstate == LOW && button[y] == 2) {
        digitalWrite(ledpin[0], HIGH);
        speakerpin.play(NOTE_G3, 100);
        delay(200);
        digitalWrite(ledpin[0], LOW);
        inputArray[x] = 1;
        delay(250);
        Serial.print(" ");
        Serial.print(1);
        // Check if value of user input matches the generated array
        if (inputArray[x] != randomArray[x]) {
          fail(); // If not, fail function is called
        }
        x++;
      }
      if (buttonstate == LOW && button[y] == 3) {
        digitalWrite(ledpin[1], HIGH);
        speakerpin.play(NOTE_A3, 100);
        delay(200);
        digitalWrite(ledpin[1], LOW);
        inputArray[x] = 2;
        delay(250);
        Serial.print(" ");
        Serial.print(2);
        if (inputArray[x] != randomArray[x]) {
          fail();
        }
        x++;
      }
      if (buttonstate == LOW && button[y] == 4) {
        digitalWrite(ledpin[2], HIGH);
        speakerpin.play(NOTE_B3, 100);
        delay(200);
        digitalWrite(ledpin[2], LOW);
        inputArray[x] = 3;
        delay(250);
        Serial.print(" ");
        Serial.print(3);
        if (inputArray[x] != randomArray[x]) {
          fail();
        }
        x++;
      }
      if (buttonstate == LOW && button[y] == 5) {
        digitalWrite(ledpin[3], HIGH);
        speakerpin.play(NOTE_C4, 100);
        delay(200);
        digitalWrite(ledpin[3], LOW);
        inputArray[x] = 4;
        delay(250);
        Serial.print(" ");
        Serial.print(4);
        if (inputArray[x] != randomArray[x]) {
          fail();
        }
        x++;
      }
    }
  }
  delay(500);
  turn++; // Increment turn count
}

// Function used if player fails to match the sequence
void fail() {
  for (int y = 0; y <= 2; y++) { // Flash lights to indicate failure
    digitalWrite(ledpin[0], HIGH);
    digitalWrite(ledpin[1], HIGH);
    digitalWrite(ledpin[2], HIGH);
    digitalWrite(ledpin[3], HIGH);
    speakerpin.play(NOTE_G3, 300);
    delay(200);
    digitalWrite(ledpin[0], LOW);
    digitalWrite(ledpin[1], LOW);
    digitalWrite(ledpin[2], LOW);
    digitalWrite(ledpin[3], LOW);
    speakerpin.play(NOTE_C3, 300);
    delay(200);
  }
  delay(500);
  turn = -1; // Reset turn value to start the game again
}

项目 9:秘密敲击锁

数百年来,秘密组织一直使用秘密敲击来防止未经授权的进入。让我们将这个系统带入现代,创造属于我们的电子门卫。

imageimage

所需零件

• Arduino 板

• 面包板

• 跳线

• Tower Pro SG90 9g 伺服电机

• 压电蜂鸣器

• 3 个 LED

• 1M 欧姆电阻

• 3 个 220 欧姆电阻

所需库

• 伺服电机

工作原理

在这个项目中,你将制作一个电路,当你输入正确的秘密敲击时,伺服臂将移动以解锁一个盒子或门。到目前为止,我们只使用压电蜂鸣器发出声音,但我们也可以将它用作传感器来检测声音——在这种情况下,是敲击声。当压电元件被敲击时,它像铃铛一样响起,但它不会产生声音,而是输出电压,电压的数值取决于敲击的力度。我们将以数字形式测量这个电压,如果敲击的电压在某个范围内,Arduino 会将其识别为正确的。如果检测到三次正确电压的敲击,你就破解了密码,伺服臂将移动解锁盒子或门。

下面是我们将在草图中稍后使用的两行代码,用于设置电压的范围;如果电压在 10 到 100 之间,敲击将被识别为有效。

const int quietKnock = 10;
const int loudKnock = 100;

如果敲击太轻或太重,敲击将无法被识别。你需要进行三次“正确”的敲击才能触发伺服臂的移动。当正确的敲击顺序和力度被识别时,伺服臂将摆动 90 度,从而“解锁”设置好的设备。LED 灯(如图 9-1 所示)作为锁状态的指示灯:红色 LED 表示敲击不正确且伺服臂没有移动(即箱子或门仍然被锁住);黄色 LED 闪烁时表示敲击被识别且正确的代码被检测到;绿色 LED 亮起且伺服电机在三次正确敲击后开始运动。

图 9-1:

LED 设置

image

为了获得最佳效果,将压电元件从外壳中取出并将其直接固定在盒子的内部或门的外部,以便它更敏感地响应敲击的震动。

搭建过程

  1. 在面包板上插入一个 1M 欧姆电阻,并将压电元件的红色线连接到一端,黑色线连接到另一端。将黑色线连接到 GND 轨,红色线连接到 Arduino 的 A0 引脚。

    压电元件 ARDUINO
    红色线 通过 1M 欧姆电阻连接到 A0
    黑色线 通过 1M 欧姆电阻连接到 GND
  2. 将伺服电机的黄色信号线直接连接到 Arduino 的 9 号引脚,棕色线连接到 GND,红色线连接到+5V。

    伺服电机 ARDUINO
    黄色线 9 号引脚
    红色线 +5V
    棕色线 GND
  3. 将 LED 插入面包板,短的负极引脚连接到 GND,正极引脚通过 220 欧姆电阻与引脚连接,具体连接如下:黄色连接到 Arduino 的 3 号引脚,绿色连接到 4 号引脚,红色连接到 5 号引脚。

    LED 灯 ARDUINO
    正极引脚 通过 220 欧姆电阻连接到 3–5 号引脚
    负极引脚 GND
  4. 将 Arduino 的 2 号引脚连接到正电源轨。在我们的设置中,这个电源始终处于开启状态,但你也可以在 Arduino 2 号引脚和电源轨之间添加一个开关,以便在项目不使用时节省电量。

  5. 将面包板的电源轨连接到 Arduino 的 GND 和+5V。

  6. 确保你的设置与图 9-2 中的电路图一致,然后上传第 82 页中“草图”的代码。

    图 9-2:

    秘密敲击锁的电路图

    image

草图

我们首先调用 Servo 库,并将 Arduino 引脚 9 设置为控制舵机。LED 灯连接到 Arduino 引脚 3、4 和 5,根据敲击的有效性,这些灯会亮起。压电传感器在本项目中充当传感器,而不是蜂鸣器,并连接到 Arduino 引脚 A0。当有人敲击时,敲击会被压电传感器感知,并根据敲击的力度,发送一个电压值到 Arduino 的 A0 模拟引脚——敲击越强,电压值越高。一个值低于 10 的敲击被认为太轻,一个值高于 100 的敲击则太响,因此这两者都不会被认为是有效敲击。如果敲击无效,则红色 LED 灯亮起;如果敲击有效,则黄色 LED 灯亮起。任何值在 10 到 100 之间的敲击都会被接受为有效敲击并计数,如果接收到三个有效敲击,舵机就会移动,并且绿色 LED 灯会亮起。

如前所述,这两行代码设置了测量电压的参数:

const int quietKnock = 10;
const int loudKnock = 100;

如果你想特别保密,你可以将这个范围设得更紧一些,这样代码就更难破解。下面是草图:

/* Created 18 September 2012 by Scott Fitzgerald
   Thanks to Federico Vanzati for improvements
   http://arduino.cc/starterKit
   This example code is part of the public domain.
*/

#include <Servo.h>
Servo servo9; // Pin connected to servo mpo

const int piezo = A0;    // Pin connected to piezo
const int switchPin = 2; // Pin connected to servo
const int yellowLed = 3; // Pin connected to yellow LED
const int greenLed = 4;  // Pin connected to green LED
const int redLed = 5;    // Pin connected to red LED

int knockVal;   // Value for the knock strength
int switchVal;

const int quietKnock = 10; // Set min value that will be accepted
const int loudKnock = 100; // Set max value that will be accepted
boolean locked = false;    // A true or false variable
int numberOfKnocks = 0;    // Value for number of knocks

void setup() {
  servo9.attach(9);
  pinMode(yellowLed, OUTPUT);   // Set LED pins as outputs
  pinMode(greenLed, OUTPUT);
  pinMode(redLed, OUTPUT);
  pinMode(switchPin, INPUT);    // Set servo pin as input
  Serial.begin(9600);
  digitalWrite(greenLed, HIGH); // Green LED is lit when the
                                // sequence is correct
  servo9.write(0);
  Serial.println("The box is unlocked!");
}

void loop() {
  if (locked == false) {
    switchVal = digitalRead(switchPin);
    if (switchVal == HIGH) {
      locked = true;
      digitalWrite(greenLed, LOW);
      digitalWrite(redLed, HIGH);
      servo9.write(90);
      Serial.println("The box is locked!");
      delay(1000);
    }
  }
  if (locked == true) {
    knockVal = analogRead(piezo); // Knock value is read by analog pin
    if (numberOfKnocks < 3 && knockVal > 0) {
      if (checkForKnock(knockVal) == true) { // Check for correct
                                             // number of knocks
        numberOfKnocks++;
      }
      Serial.print(3 - numberOfKnocks);
      Serial.println(" more knocks to go");
    }
    if (numberOfKnocks >= 3) { // If 3 valid knocks are detected,
                               // the servo moves
      locked = false;
      servo9.write(0);
      delay(20);
      digitalWrite(greenLed, HIGH);
      digitalWrite(redLed, LOW);
      Serial.println("The box is unlocked!");
    }
  }
}

boolean checkForKnock(int value) { // Checks knock value
  if (value > quietKnock && value < loudKnock) { // Value needs to be
                                                 // between these
    digitalWrite(yellowLed, HIGH);
    delay(50);
    digitalWrite(yellowLed, LOW);
    Serial.print("Valid knock of value ");
    Serial.println(value);
    return true;
  }
  else { // If value is false then send this to the IDE serial
    Serial.print("Bad knock value ");
    Serial.println(value);
    return false;
  }
}

第三部分

image

舵机

项目 10:操纵杆控制激光

在本项目中,我们通过将两个舵机连接到操纵杆,并使用这个设置作为激光指示器的平移和俯仰控制器,来创建一个操纵杆控制的激光。

imageimage

所需零件

• Arduino

• 面包板

• 跳线

• 2 个 Tower Pro SG90 9g 舵机

• 模拟五针、双轴操纵杆模块

• 平移和俯仰支架模块

所需库

• 舵机

工作原理

舵机是小型电动机,可以精确地将其臂旋转到 0 到 180 度之间的位置。在本项目中,我们将舵机安装在一个倾斜和旋转支架中。倾斜和旋转支架是一个值得投资的模块,因为它使得将激光器安装到舵机上变得更加容易。在这里,我们控制的是激光器,但你也可以轻松地用一个网络摄像头或其他小型设备替代激光器。我们使用两个舵机:一个用于左右移动,另一个用于上下移动。正如你可能记得的,舵机有三根线,如图 10-1 所示:正电源线(红色)、负电源线或地线(黑色或棕色)和信号线(通常为黄色、橙色或白色)。

图 10-1:

舵机有三根线。

image

在我们开始构建之前,你需要了解一下操纵杆是如何工作的。图 10-2 中显示的操纵杆基本上由两个电位器和一个按钮组成,这些元件可以让我们在二维空间中测量摇杆的运动。

图 10-2:

这个操纵杆有两个电位器和一个按钮,用于测量运动。

image

电位器是可变电阻器,作为传感器根据设备围绕其轴的旋转来提供一个变化的电压。所以,当你移动操纵杆时,它的电阻值—也就是输出值—会发生变化。电位器的输出是模拟信号,因此在 Arduino 的模拟引脚读取时,它的值只能在 0 到 1,023 之间。这一数值会发送一个脉冲给 Arduino,Arduino 再控制舵机移动的距离。(有关电位器的更多内容,请参见项目 2)。

一个操纵杆通常有五根引脚:VRx(x 轴信号),VRy(y 轴信号),SW(一个我们在本项目中不会使用的按钮),以及 GND 和+5V 用于电源。

当操纵杆的 x 轴向左或向右移动时,相应的舵机会朝那个方向移动;当操纵杆的 y 轴向上或向下移动时,另一个舵机会向上或向下移动。

构建

  1. 将两个舵机的红色线连接到+5V 轨道,将它们的棕色线连接到面包板的 GND。

  2. 将其中一个舵机的黄色信号线直接连接到 Arduino 的 9 号引脚,另一个舵机的信号线直接连接到 Arduino 的 10 号引脚,如图 10-4 所示的电路图所示。

    舵机 Arduino
    红色线 +5V
    棕色线 GND
    黄色线 1 引脚 9
    黄色线 2 引脚 10
  3. 将操纵杆模块的 GND 连接到 Arduino 的 GND 轨道,将 +5V 连接到 Arduino 的 +5V 轨道。将 VRx 引脚直接连接到 Arduino A0,将 VRy 引脚直接连接到 Arduino A1。再次强调,SW 开关连接在此项目中没有使用。

    操纵杆 Arduino
    +5V +5V
    GND GND
    VRx A0
    VRy A1
    SW 未使用
  4. 将面包板的轨道连接到 Arduino GND 和 +5V,然后检查你的设置是否与 图 10-3 一致。

    图 10-3:

    该电路图展示了操纵杆控制激光器的电路。注意,这个电路图中的操纵杆品牌与项目中使用的不同,但连接方式相同,因此项目中的说明是有效的。

    image

激光器安装

对于这个项目,我将舵机安装到云台模块中;你应该能在 eBay 上通过搜索“Arduino 云台舵机套件”找到这个模块或类似的模块,价格相对合理。你可能需要自己组装,但按照附带的说明很容易完成。

将激光二极管安装在模块的顶部;我建议使用热熔胶枪进行永久固定,但如果需要临时固定,可以使用胶带。现在你可以通过操控操纵杆来控制激光器。舵机会夹入云台模块,如 图 10-5 所示。

图 10-4:

将舵机夹入云台模块

image

移动操纵杆向左和向右将控制 x 轴舵机,移动操纵杆向上和向下将控制 y 轴舵机。完整的组装如图 10-6 所示。

图 10-5:

完整的组装

image

草图

草图首先调用 Servo 库,然后将两个舵机定义为 tiltpan。操纵杆的 x 轴连接到 Arduino 引脚 A0,y 轴连接到 Arduino A1,这些是我们的 输入。然后将 x 轴和 y 轴设置为用于运动的变量。tilt 舵机连接到 Arduino 引脚 9,pan 舵机连接到 Arduino 引脚 10,这些是我们的 输出。Arduino 然后读取来自操纵杆的 输入,并将该电压转换为 输出,根据选择的方向来移动舵机。

// Used with kind permission from http://learn.explorelabs.com/
// Creative Commons 4.0 Share Alike (CC by SA 4.0) license

#include <Servo.h>
Servo tilt, pan;  // Create servo object
int joyX = A0;    // Analog pin connected to x-axis servo
int joyY = A1;    // Analog pin connected to y-axis servo
int x, y;         // Variables to read values

void setup() {
  tilt.attach(9); // Attach tilt servo on pin 9 to the servo object
  pan.attach(10); // Attach pan servo on pin 10 to the servo object
}

void loop() {
  x = joyX; // Read value of x-axis (between 0 and 1023)
  y = joyY; // Read value of y-axis (between 0 and 1023)
  x = map(analogRead(joyX), 0, 1023, 900, 2100); // Scale it to use
                                                 // with servo between
                                                 // 900 to 2100
                                                 // microseconds
  y = map(analogRead(joyY), 0, 1023, 900, 2100);
  tilt.write(x); // Set servo position according to scaled value
  pan.write(y);
  delay(15);     // Wait for servos to get to new position
}

项目 11:遥控舵机

在这个项目中,我们将使用 Arduino 检查和解码遥控器的信号,然后使用这些代码来控制舵机。

imageimage

所需部件

• Arduino 板

• 面包板

• 跳线

• 38 kHz 红外接收器

• 遥控器

• 2 个 Tower Pro SG90 9g 舵机

• 云台模块

所需库

• 舵机

• IRremote

工作原理

首先,我们将使用红外接收器解码遥控器。红外接收器有三个针脚:OUT、GND 和 VCC(如 图 11-1 所示,从左到右)。检查你购买的接收器的数据表,确保它与这个针脚布局匹配。在极少数情况下,你可能会发现接收器的针脚布局不同,但你仍然可以使用针脚图来接线。

图 11-1:

红外接收器——从左到右,针脚依次为 OUT、GND 和 VCC

image

你还需要一个遥控器。你可以使用任何类型的遥控器,包括电视遥控器,但最好使用一个你不再需要的旧遥控器。当你按下遥控器上的按钮时,它会发送一个数字值,该值会被接收器接收。每个按钮的值都是不同的。我们将使用 Arduino 解码每个按钮的值,然后在草图中将它们分配给 Arduino 引脚来控制输出——在这种情况下是伺服电机。

通过根据解码的值个性化草图,你可以将特定的按钮与特定的指令连接,并使用遥控器控制伺服电机。如果你已经按照 项目 10 构建了倾斜和旋转机架模型,你可以在此复用它。否则,翻到 项目 10,查看设置说明。

我们将为倾斜和旋转机架中的伺服电机的方向移动分配一个按钮,因此总共四个按钮将控制所有的运动:左右控制 x 轴伺服电机,上下控制 y 轴伺服电机。短按按钮将使伺服电机以小增量移动,而长按将使伺服电机持续移动,直到达到最大或最小值。

硬件设置

  1. www.nostarch.com/arduinohandbook/下载 IRremote 库,并将其添加到你的库文件夹中,具体操作请参见 “Libraries” 和 第 7 页。

  2. 将红外接收器插入面包板。将接收器的 OUT 针脚连接到 Arduino 的引脚 11,GND 连接到 Arduino 的 GND,VCC 连接到 Arduino 的 +5V。同样,对于某些版本的 38 kHz 接收器,针脚顺序可能与这里显示的不同,因此请检查与你的组件相对应的数据表。

    IR RECEIVER ARDUINO
    OUT 引脚 11
    GND GND
    VCC +5V
  3. 现在上传并运行以下代码。

    /* Copyright 2009 Ken Shirriff
       Used with kind permission
       http://arcfn.com
    */
    
    #include <IRremote.h> // Use library
    int receiver = 11;    // Pin connected to receiver
    
    IRrecv irrecv(receiver);
    decode_results results;
    void setup() {
      Serial.begin(9600);  // Show keypresses in IDE
      irrecv.enableIRIn(); // Start up receiver
    }
    
    void loop() {
      if (irrecv.decode(&results)) { // If there's an input, decode value
        Serial.println(results.value, HEX); // Display button value
                                            // on Serial Monitor in
                                            // hexadecimal format
        irrecv.resume(); // Receive next value
      }
    }
    

    草图首先调用 IRremote 库,该库从红外接收器读取数据并将相应的数据发送到 Arduino。红外接收器被分配到 Arduino 的引脚 11,草图开始与 Arduino IDE 通信,这样当按下按钮时,输入值会实时显示在串口监视器中。草图将持续运行,查找按钮按压,并将相应的值显示给 IDE。

  4. 打开 IDE 中的串口监视器。

  5. 将遥控器对准接收器,并尝试按下不同的按钮。它们将在串口监视器中以十六进制(HEX)格式解码为字母和数字,如图 11-2 所示。尝试快速而短促的按压以获得最佳效果。如果按住按钮时间过长,串口监视器将显示F,直到你松开按钮为止。

    图 11-2:

    当遥控器上的按钮被按下时,该按钮的 HEX 代码将在 Arduino IDE 的串口监视器中显示。

    image

    记下显示的数字及其对应的按钮。你以后需要这些数字。

现在我们已经解码了遥控器按钮的信号,可以用它们来控制两个舵机。

搭建

  1. 使用你在第 96 页第 2 步的面包板设置,接收器已连接,连接舵机到 Arduino。将每个舵机的棕色线连接到 GND,红色线连接到+5V。然后,将第一个舵机的黄色控制线连接到 Arduino 的引脚 10,将第二个舵机的黄色控制线连接到 Arduino 的引脚 9。

    舵机 Arduino
    红色线 +5V
    棕色线 GND
    黄色线(舵机 1) 引脚 10
    黄色线(舵机 2) 引脚 9
  2. 记得给面包板连接电源。

  3. 检查你的设置是否与图 11-3 中的电路图相符,然后上传在草图第 99 页的代码。

    图 11-3:

    遥控器舵机的电路图

    image

草图

确保在完成草图时使用在“设置”第 3 步中解码的值,而不是这里提供的值。更改草图中的值以匹配你自己的代码时,保持 0x 前缀,并在其后添加你的 HEX 代码。例如,对于我解码的第一个按钮,HEX 代码是 FFA05F,草图中的显示如下:

unsigned long Value1 = 0xFFA05F;

在这个项目中,我们控制的是舵机,但你可以稍微修改代码来远程控制任何需要设置为HIGH的设备,例如 LED 或压电蜂鸣器。

草图调用了 IRremote 库来读取接收器,调用了 Servo 库来驱动舵机。前两个按钮被分配给 x 轴舵机,控制角度最大可调为 70 度(向左转)或 160 度(向右转)。第三和第四个按钮被分配给 y 轴舵机,控制上下倾斜运动。

如果你想将此项目适配为其他输出,只需稍作修改代码:

servo.write

到:

digitalWrite(pin, HIGH)

按如下方式输入草图:

/* IR Library Copyright Ken Shirriff
   Used with kind permission
   http://arcfn.com
 */

#include <Servo.h>    // Include the Servo library
#include <IRremote.h> // Include the IRremote library

unsigned long Value1 = 0xFFA05F; // Change this to your value
unsigned long Value2 = 0xFF50AF; // Change this to your value
unsigned long Value3 = 0xFF807F; // Change this to your value
unsigned long Value4 = 0xFF609F; // Change this to your value

int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
Servo servo1;
Servo servo2;

void setup() {         // Set up routine
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the IR receiver
  servo1.attach(10);   // Pin connected to servo 1
  servo2.attach(9);    // Pin connected to servo 2
}

void loop() { // Loop routine runs forever
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
  if (results.value == Value1) { // If remote code matches value 1,
                                 // then move the servo
    servo1.write(160);
  }
  else if (results.value == Value2) { // If remote code matches
                                      // value 2, then move the
                                      // servo, and so on
    servo1.write(70);
  }
  else if (results.value == Value3) {
    servo2.write(70);
  }
  else if (results.value == Value4) {
    servo2.write(160);
  }
}

第四部分

image

LCD 屏幕

项目 12:LCD 屏幕编程器

不仅 LCD 屏幕显示你自己的信息很令人满足,而且它也非常有用。

imageimage

所需零件

• Arduino 主板

• 面包板

• 跳线

• 16×2 LCD 屏幕(兼容 Hitachi HD44780)

• 50k 欧姆电位计

所需库

• LiquidCrystal

工作原理

LCD(液晶显示)屏幕由两层偏振材料组成,中间夹着液晶溶液。电流通过溶液会形成图像或字符,在这个项目中就是字符。为了使 LCD 屏幕能够与 Arduino 一起工作,你需要一个与 Hitachi HD44780 驱动程序兼容的 LCD 屏幕——市场上有很多这样的屏幕,通常可以通过其 16 针接口来识别。

我们将使用 LiquidCrystal 库将字符发送到 LCD 屏幕。LiquidCrystal 库将字符映射并使用 print.lcd 命令将信息从草图复制到屏幕上。

在开始之前,你需要准备好你的 LCD 屏幕。

准备 LCD 屏幕

LCD 屏幕可能需要一些组装。你的屏幕应该有 16 个孔(如图 12-1 所示),并附带一排独立的插头引脚。

图 12-1:

LCD 屏幕的顶部有 16 个引脚。

image

拿起这排引脚并断开 16 个引脚的一排。将引脚的短侧插入 16 个 LCD 孔中。你需要将这些引脚焊接到位:首先焊接最右和最左的引脚来固定插头,等它们稳定后再焊接每个引脚。每个引脚的焊接时间不宜过长,只需几秒钟(如果你从未焊接过,可以查看快速焊接指南,见第 18 页)。

构建过程

  1. 将 LCD 屏幕放入面包板中,将插头引脚插入面包板孔中。也将电位计放入面包板中,并使用面包板和跳线连接 LCD 屏幕、Arduino 和电位计,如下表所示以及图 12-2 中所示。LCD 模块有三个 GND 引脚连接,因此可以使用面包板上的 GND 排来完成这些连接。

    图 12-2:

    LCD 屏幕与 Arduino 之间的连接。LCD 屏幕的引脚 15 和 16 是背光的电源和地线。

    image

    LCD 屏幕 Arduino
    1 VSS GND
    2 VDD +5V
    3 VO 对比度 电位计中心引脚
    4 RS 引脚 7
    5 R/W GND
    6 使能 引脚 8
    7 D0 未使用
    8 D1 未使用
    9 D2 未使用
    10 D3 未使用
    11 D4 引脚 9
    12 D5 引脚 10
    13 D6 引脚 11
    14 D7 引脚 12
    15 A BcL+ +5V
    16 K BcL– GND
  2. 50k 欧姆电位器的中心引脚连接到 LCD 的引脚 3(VO)。该电位器控制屏幕的对比度。旋转它直到你能清晰地看到屏幕上的字符。现在,将其中一个外侧引脚连接到 GND,另一个连接到+5V。

  3. 背光 LCD 屏幕(见图 12-3)会内置电阻,但如果你使用的是非背光 LCD 屏幕,应该在 LCD 的引脚 15 和+5V 之间插入一个 220 欧姆电阻。(屏幕包装上会注明是否有背光。)

    图 12-3:

    一个背光 LCD 屏幕

    image

  4. 你的设置应该像图 12-4 所示。对照图 12-5 中的电路图检查你的工作,然后上传代码,参见“草图”在第 107 页。

    图 12-4:

    完整的设置

    image

    图 12-5:

    LCD 屏幕编程的电路图

    image

草图

这个草图包含在你的 IDE 示例中。通过 IDE 加载它,方法是依次点击文件 image 示例 image LiquidCrystal,然后点击滚动。该草图使用内置在 Arduino IDE 中的 LiquidCrystal 库,将信息从 Arduino 发送到 LCD 屏幕。你可以通过将“Arduino Sketch”替换为其他文本来更改消息。

要使用这个电路设置与 Arduino IDE 中的示例草图,我们还需要在草图中更改 LCD 引脚(12, 11, 5, 4, 3, 2)到 7, 8, 9, 10, 11, 12,因为这些是我们分配的引脚。我在这里重新创建了草图,正如你在 IDE 中看到的一样,但已经做了这些更改。

   /*
   Library originally added 18 Apr 2008 by David A. Mellis
     library modified 5 Jul 2009 by Limor Fried (http://www.ladyada.net)
     example added 9 Jul 2009 by Tom Igoe
     modified 22 Nov 2010 by Tom Igoe
     This example code is in the public domain.
     http://www.arduino.cc/en/Tutorial/LiquidCrystal

   LiquidCrystal Library - scrollDisplayLeft() and scrollDisplayRight()

   Demonstrates the use of a 16x2 LCD display. The LiquidCrystal
   library works with all LCD displays that are compatible with the
   Hitachi HD44780 driver. There are many of them out there, and you
   can usually tell them by the 16-pin interface.

   This sketch prints "Arduino Sketch" to the LCD and uses the
   scrollDisplayLeft() and scrollDisplayRight() methods to scroll
   the text.
   */

   // Include the library code
   #include <LiquidCrystal.h>

   // Initialize the library with the numbers of the interface pins
➊ LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

   void setup() {
     // Set up the LCD's number of columns and rows
     lcd.begin(16, 2);
     // Print a message to the LCD
➋   lcd.print("Arduino Sketch");
     delay(1000);
   }

   void loop() {
     // Scroll 13 positions (string length) to the left
     // to move it offscreen left
     for (int positionCounter = 0; positionCounter < 13;
   positionCounter++) {
       // Scroll one position left
       lcd.scrollDisplayLeft();
       // Wait a bit
       delay(150);
     }
     // Scroll 29 positions (string length + display length) to the right
     // to move it offscreen right
     for (int positionCounter = 0; positionCounter < 29;
   positionCounter++) {
       // Scroll one position right
       lcd.scrollDisplayRight();
       // Wait a bit
       delay(150);
     }
     // Scroll 16 positions (display length + string length) to the left
     // to move it back to center
     for (int positionCounter = 0; positionCounter < 16;
   positionCounter++) {
       // Scroll one position left
       lcd.scrollDisplayLeft();
       // Wait a bit
       delay(150);
     }
     // Delay at the end of the full loop
     delay(1000);
   }

项目 13:天气站

在这个项目中,你将建立一个天气站来测量温度和湿度,并将数值显示在 LCD 屏幕上。

imageimage

所需部件

• Arduino 开发板

• 面包板

• 跳线

• 50k 欧姆电位器

• 16x2 LCD 屏幕(兼容 Hitachi HD44780)

• DHT11 湿度传感器

所需库

• LiquidCrystal

• DHT

工作原理

本项目使用的湿度传感器是相对便宜的 DHT11,如图 13-1 所示,它可以测量湿度和温度。它使用电容式湿度传感器和电阻式温度传感器来读取环境数据。它将这些数据作为电压发送给 Arduino,Arduino 将其转换为可读的数值并显示在屏幕上。为了获得最佳效果,建议将传感器安装在外墙上,并确保周围有足够的开放空间。你应将 LCD 屏幕安装在室内,或者将其小心密封在一个清晰的防水袋或外壳中,以保护它免受外部环境的影响。

图 13-1:

DHT11 既测量温度也测量湿度。

image

DHT11 传感器有四个脚或者三个脚。图 13-1 中显示的传感器有四个脚,但你可以使用任意版本的 DHT11 进行本项目,因为你不会使用第 3 脚。在书本开头查看零售商,了解在哪里购买 DHT11。

项目构建

  1. 首先,按照“准备 LCD 屏幕”中的焊接说明准备 LCD 屏幕(见第 104 页)。将 DHT11 传感器插入面包板。当传感器正面朝向你时,DHT11 的引脚从左到右依次编号为 1 至 4(或 3)。将引脚 1 连接到+5V 电源轨,将引脚 2 直接连接到 Arduino 的引脚 8,将引脚 4(或 3)连接到 GND。

    DHT11 ARDUINO
    引脚 1 +5V
    引脚 2 引脚 8
    引脚 3 未使用
    引脚 4 GND
  2. 将 LCD 屏幕插入面包板,并按照下表以及图 13-2 所示连接引脚到 Arduino。GND 和+5V 电源轨将有多个连接。

    LCD 屏幕 ARDUINO
    1 VSS GND
    2 VDD +5V
    3 VO 对比度 电位器中心脚
    4 RS 引脚 12
    5 R/W GND
    6 使能 引脚 11
    7 D0 未使用
    8 D1 未使用
    9 D2 未使用
    10 D3 未使用
    11 D4 引脚 5
    12 D5 引脚 4
    13 D6 引脚 3
    14 D7 引脚 2
    15 A BcL + +5V
    16 K BcL – GND

    图 13-2:

    将 LCD 屏幕插入面包板

    image

  3. 如图 13-3 所示,将电位器插入面包板,并将中心脚连接到 LCD 的引脚 3。将一个外脚连接到+5V 电源轨,另一个外脚连接到 GND 电源轨。

    图 13-3:

    将电位器插入面包板

    image

  4. 记得将面包板的电源轨连接到 Arduino 的 GND 和+5V。确认你的布线与图 13-4 中的电路图相符,并上传第 116 页中的“草图”代码。

    图 13-4:

    天气站电路图

    image

草图

此草图使用 LiquidCrystal 库,该库附带 Arduino IDE,还使用 DHT 库,您需要从nostarch.com/arduinohandbook/下载并安装(见第 7 页的“库文件”)。DHT 库控制传感器的功能,LCD 库则将读数显示在屏幕上。

/* Example testing sketch for various DHT humidity/temperature
sensors. Written by ladyada, public domain. */

#include <LiquidCrystal.h>
#include "DHT.h" // Call the DHT library
#define DHTPIN 8 // Pin connected to DHT
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#define DHTTYPE DHT11  // Define the type of DHT module
DHT dht(DHTPIN, DHTTYPE); // Command to the DHT.h library

void setup() {
  dht.begin(); // Start the sensor
  lcd.begin(16, 2); // LCD screen is 16 characters by 2 lines
}

void loop() {
  float h = dht.readHumidity(); // Value for humidity
  float t = dht.readTemperature(); // Value for temperature
  t = t * 9 / 5 + 32; // Change reading from Celsius to Fahrenheit
  if (isnan(t) || isnan(h)) { // Check that DHT sensor is working
    lcd.setCursor(0, 0);
    lcd.print("Failed to read from DHT");  // If DHT is not working,
                                           // display this
  } else { // Otherwise show the readings on the screen
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Humidity: ");
    lcd.print(h);
    lcd.print("%");
    lcd.setCursor(0, 1);
    lcd.print("Temp: ");
    lcd.print(t);
    lcd.print("f");
  }
}

项目 14:占卜师

在这个项目中,我们将制作一个经典的占卜装置的电子版:魔法 8 球。

imageimage

所需零件

• Arduino 开发板

• 面包板

• 跳线

• 16x2 LCD 屏幕(适用于日立 HD44780 兼容型)

• 倾斜球开关

• 50k 欧姆电位器

• 1k 欧姆电阻

所需库文件

• LiquidCrystal

工作原理

魔术 8 球是一种上世纪 50 年代创造的玩具,由一个空心球和浮动在酒精中的 20 面骰子组成。当你问球一个问题并摇动它时,骰子的一面会浮出并在球的窗口中显示你的答案。

在这个项目中,你将使用一个倾斜球开关,如 图 14-1 所示。倾斜球开关由一个金属球和金属外壳组成,当开关处于竖直位置时,金属球会接触并完成连接。如果你倾斜开关,金属球会移动,连接断开。有很多种倾斜开关可供选择,它们都能完成同样的工作。在这个项目中,你将提一个问题并摇动开关。当开关再次恢复竖直位置时,它会连接到 Arduino,Arduino 随后会从八个预设答案中随机选择一个,并在 LCD 屏幕上显示出来。

图 14-1:

倾斜球开关插入面包板

image

可变电阻控制 LCD 屏幕的对比度。

构建

  1. 按照 “准备 LCD 屏幕” 中的焊接说明准备 LCD 屏幕,该说明在 第 104 页。

  2. 将 LCD 屏幕放置在面包板上,将引脚插入面包板的孔中。同时将可变电阻也放置在面包板上,并使用面包板和跳线连接你的 LCD 屏幕、Arduino 和可变电阻。

    LCD 屏幕 ARDUINO
    1 VSS GND
    2 VDD +5V
    3 VO 对比度 可变电阻的中间引脚
    4 RS 引脚 12
    5 R/W GND
    6 Enable 引脚 11
    7 D0 未使用
    8 D1 未使用
    9 D2 未使用
    10 D3 未使用
    11 D4 引脚 5
    12 D5 引脚 4
    13 D6 引脚 3
    14 D7 引脚 2
    15 A BcL + +5V
    16 K BcL – GND
  3. 记得使用面包板导轨将多个连接连接到 Arduino 的 GND 引脚,如 图 14-2 所示。

    图 14-2:

    LCD 屏幕已连接到 Arduino。

    image

  4. 你应该已经将 10k 欧姆可变电阻的中间引脚连接到 LCD 的引脚 3 (VO)。现在,将其中一个外部引脚连接到 GND,另一个连接到 +5V。这将控制 LCD 屏幕的对比度。

  5. 将倾斜开关插入你的面包板,并通过一个 1k 欧姆电阻将一侧连接到 Arduino 的引脚 6,另一侧连接到 GND。

    倾斜球开关 ARDUINO
    引脚 1 通过 1k 欧姆电阻连接到引脚 6
    引脚 2 GND
  6. 将你的面包板导轨连接到 Arduino 的 +5V 和 GND 以供电。

  7. 确认你的设置与 图 14-3 相匹配,并上传 “草图” 中的代码,该代码在 第 122 页。

    图 14-3:

    占卜器的电路图

    image

草图

这个项目的代码相当简单。当你打开 Arduino 时,LCD 屏幕显示消息Ask a Question。摇动倾斜开关激活草图,Arduino 从八个可用的答案(案例 0-7)中随机选择一个答案。

这是代码中实现此功能的那一行:

reply = random(8);

要加入你自己的响应,改变值8为可能的响应数量,然后以与其他响应相同的格式添加你的响应(或案例):

case 8:

lcd.print("你敢打赌");

break;

这是完整的代码:

/* Created 13 September 2012 by Scott Fitzgerald
   http://arduino.cc/starterKit
   This example code is part of the public domain
*/

#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // Pins attached to LCD screen

const int switchPin = 6; // Pin attached to tilt switch
int switchState = 0;
int prevSwitchState = 0;
int reply;

void setup() {
  lcd.begin(16, 2);
  pinMode(switchPin, INPUT);   // Set tilt switch pin as an input
  lcd.print("FORTUNE TELLER"); // Print this on line 1
  lcd.setCursor(0, 1);
  lcd.print("Ask a Question"); // Print this on line 2
}

void loop() {
  switchState = digitalRead(switchPin); // Read tilt switch pin
  if (switchState != prevSwitchState) {
    if (switchState == LOW) { // If circuit is broken, give answer
      reply = random(8); // Reply is 1 of 8 random cases as below
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("The answer is: "); // Print this to the screen
      lcd.setCursor(0, 1);

      switch (reply) { // Reply will be one of the following cases
        case 0:
          lcd.print("Yes");
          break;

        case 1:
          lcd.print("Probably");
          break;

        case 2:
          lcd.print("Definitely");
          break;

        case 3:
          lcd.print("Don't be silly");
          break;

        case 4:
          lcd.print("Of course");
          break;

        case 5:
          lcd.print("Ask again");
          break;

        case 6:
          lcd.print("Doubtful");
          break;

        case 7:
          lcd.print("No");
          break;
      }
    }
  }
   prevSwitchState = switchState; // Reset the switch
}

项目 15:反应计时游戏

在这个项目中,让我们将 LCD 屏幕与 RGB LED 和压电蜂鸣器结合起来,制作一个反应计时游戏。

imageimage

所需零件

• Arduino 主板

• 面包板

• 跳线

• 16x2 LCD 屏幕(兼容 Hitachi HD44780)

• RGB LED 模块

• 压电蜂鸣器

• 瞬时触觉四脚按钮

• 50k 欧姆电位器

• 220 欧姆电阻

所需库

• LiquidCrystal

工作原理

你通过按住按钮来开始游戏。RGB LED 亮起并逐渐变换为一些随机颜色。你的目标是尽可能快地做出反应,当 LED 变红时松开按钮。LCD 屏幕显示你的反应时间,单位是毫秒,从 LED 变红到松开按钮的时间(见图 15-1)。

图 15-1:

当你松开按钮时,你的反应时间将显示在 LED 屏幕上。

image

压电蜂鸣器通过发出随机声音来分散你的注意力。如果你太快松开按钮,LCD 屏幕会显示一个消息,告诉你重新开始。

正如其名称所示,RGB LED 实际上是三个 LED 的组合:红色、绿色和蓝色(见图 15-2)。

图 15-2:

RGB LED 可以是红色、绿色或蓝色。

image

RGB 是一种加法色彩模型,这意味着通过组合两种或更多颜色的光,我们可以创造出其他颜色。红色、绿色和蓝色是通常用作其他颜色基础的加法原色,如图 15-3 所示。

图 15-3:

RGB 色彩模型是加法的。

image

让我们更详细地看看 RGB LED。图 15-4 展示了一个清晰的共阴极 LED。注意,LED 有四根脚,而不是通常的两根:一根分别用于红色、绿色和蓝色,最后一根是阴极或阳极。在这种情况下,最长的引脚是阴极,它连接到地(GND)。

图 15-4:

一个 RGB LED 有四根脚,而不是通常的两根。

image

本项目中使用的 RGB LED 是一个带内建电阻的模块,这样可以节省面包板上的空间。

搭建过程

  1. 按照《准备 LCD 屏幕》中的焊接说明,准备 LCD 屏幕,见第 104 页。

  2. 将 LCD 屏幕放置在面包板上,将其头针插入面包板孔中。同时,将电位器放入面包板,并使用面包板和跳线将 LCD 屏幕、Arduino 和电位器连接起来。

    LCD 屏幕 ARDUINO
    1 VSS GND
    2 VDD +5V
    3 VO 对比度 电位器中间引脚
    4 RS 引脚 11
    5 R/W GND
    6 启用 引脚 12
    7 D0 未使用
    8 D1 未使用
    9 D2 未使用
    10 D3 未使用
    11 D4 引脚 5
    12 D5 引脚 4
    13 D6 引脚 3
    14 D7 引脚 2
    15 A BcL + +5V
    16 K BcL – GND
  3. 你应该已经将 50 千欧电位器的中间引脚连接到 LCD 引脚 3(VO)。现在将一个外侧引脚连接到 GND,另一个连接到+5V。这个操作控制你的 LCD 屏幕的对比度。

  4. 将按钮插入面包板,使其跨过中间的断开部分。我们将按图 15-5 标记引脚。

    图 15-5:

    按钮横跨中心断开。

    image

    将引脚 A 通过 220 欧姆电阻连接到地,C 引脚连接到 Arduino 引脚 9,D 引脚连接到+5V(更多关于按钮如何工作的内容请参见项目 1)。

    按钮 ARDUINO
    引脚 A 通过 220 欧姆电阻接地
    引脚 C 引脚 9
    引脚 D +5V
  5. 插入 RGB 模块,将红色引脚连接到 Arduino 引脚 8,绿色连接到引脚 6,蓝色连接到引脚 7,+连接到+5V。

    RGB LED ARDUINO
    红色 引脚 8
    绿色 引脚 6
    蓝色 引脚 7
    + +5V
  6. 将蜂鸣器的红线直接连接到 Arduino 引脚 13,黑线连接到 GND。

    蜂鸣器 ARDUINO
    红线 引脚 13
    黑线 GND
  7. 检查你的构建是否符合图 15-7,然后上传《草图》中的代码到第 130 页,开始游戏吧!

    图 15-6:

    反应计时器游戏的电路图。你可能会发现,先添加所有的 GND 和+5V 线再接数据线会更容易。

    image

草图

当你按下并保持按钮时,LED 会闪烁随机颜色,最终变为红色。每种颜色显示的持续时间是随机的,灯光间的暂停时间也是随机的。这意味着你无法学习颜色的顺序,也无法预测 LED 何时变为红色。

你可以通过在草图中的以下代码行中增加间隔时间,使游戏变得更具挑战性:

PSE = random(500, 1200);

完整的草图如下:

// Created by Steven De Lannoy and reproduced with kind permission
// http://www.wingbike.nl
// Used an RGB LED with a common anode (3 cathodes: R, G, B)
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int LEDR = 8;   // Pin connected to red LED
int LEDB = 7;   // Pin connected to blue LED
int LEDGr = 6;  // Pin connected to green LED
int Button = 9; // Pin connected to pushbutton
int COLOR;      // Variable color
int Beep;
int PSE;        // Variable pause
int TME;        // Time
int RTME = 0;   // Reaction time

void setup() {
  lcd.begin(16, 2);
  pinMode(LEDR, OUTPUT);   // Set LED pins as output
  pinMode(LEDB, OUTPUT);
  pinMode(LEDGr, OUTPUT);
  pinMode(Button, INPUT);  // Set pushbutton as input
  digitalWrite(LEDR, LOW); // Switch on all LED colors
  digitalWrite(LEDB, LOW);
  digitalWrite(LEDGr, LOW);
}

void loop() {
  lcd.clear(); // Clear screen
  lcd.print("Hold Button to"); // Display message on LCD screen
  lcd.setCursor(0, 1); // Move to second line
  lcd.print("start.");
  while (digitalRead(Button) == LOW) { // Test does not start until
                                       // button is pushed (and held)
    tone(13, 1200, 30);
    delay(1400);
    noTone(13);
  }
 lcd.clear();
  digitalWrite(LEDR, HIGH); // Switch off start light
  digitalWrite(LEDB, HIGH);
  digitalWrite(LEDGr, HIGH);
  randomSeed(analogRead(0)); // Random noise from pin 0
  COLOR = random(1, 4); // Generate random color
  PSE = random(500, 1200); // Set random pause duration between lights
  // Repeat this loop while color is green or blue AND pushbutton
  // is held
  while (COLOR != 1 && digitalRead(Button) == HIGH) {
    digitalWrite(LEDGr, HIGH);
    digitalWrite(LEDB, HIGH);
    delay(PSE);
    randomSeed(analogRead(0));
    Beep = random(1, 4); // Select random beep from buzzer
                         // (buzzer beeps 1 in 3 times)
    PSE = random(750, 1200); // Select random pause duration between
                             // lights (to increase surprise effect)
    if (Beep == 1) {
      tone(13, 1600, 350);
      delay(750);
      noTone(13);
    }
    if (COLOR == 2) {
      digitalWrite(LEDGr, LOW);
    }
    if (COLOR == 3) {
      digitalWrite(LEDB, LOW);
    }
    delay(PSE);
    randomSeed(analogRead(0));
    COLOR = random(1, 4); // Select random color
  }
  // Execute this loop if color is red
  if (COLOR == 1 && digitalRead(Button) == HIGH) {
    digitalWrite(LEDGr, HIGH);
    digitalWrite(LEDB, HIGH);
    delay(PSE);
    TME = millis(); // Record time since program has started
    digitalWrite(LEDR, LOW);
    while (digitalRead(Button) == HIGH) { // Runs until button is
                                          // released, recording the
                                          // reaction time
      delay(1);
    }
    lcd.display();
    RTME = millis() - TME; // Reaction time in ms
    lcd.print("Reaction Time:"); // Display on LCD screen
    lcd.setCursor(0, 1);
    lcd.print(RTME);
  }

  // Execute if color is NOT red but the pushbutton is released
  if (COLOR != 1) {
    lcd.print("Released too");
    lcd.setCursor(0, 1); // Move to second line
    lcd.print("soon!!!");
    tone(13, 3000, 1500);
    delay(500);
    noTone(13);
  }
  // Test does not restart until the button is pushed once
  while (digitalRead(Button) == LOW) {
    delay(10);
  }
  digitalWrite(LEDR, LOW); // Reset all lights to begin again
  digitalWrite(LEDB, LOW);
  digitalWrite(LEDGr, LOW);
  lcd.clear();
  lcd.print("Hold Button to");
  lcd.setCursor(0, 1);
  lcd.print("start.");
  int Time = 0;
  delay(1000);
}

第五部分

image

数字计数器

项目 16:电子骰子

桌面游戏已经够危险了,别再争论掉落或丢失的骰子的数字了。完美的解决方案:电子骰子。

imageimage

所需部件

• Arduino 板

• 面包板

• 跳线

• 8 个 220 欧姆电阻

• 七段 LED 显示器

• 74HC595 移位寄存器

• 瞬时触觉四脚按钮

工作原理

在这个项目中,我们将使用七段 LED 显示器创建一个骰子。当按钮被按下时,会向 Arduino 发送一个脉冲,LED 会“摇动”并显示一个 1 到 6 之间的随机数字。

该项目使用 74HC595 移位寄存器,这是一种小型集成电路(IC)和顺序逻辑计数器,允许 Arduino 通过“移位”和存储数据来比通常的引脚更多地进行连接。移位寄存器有 16 个引脚;在一端,您会看到一个点或半圆标记,表示引脚 1 在左侧。然后,按逆时针方向对引脚编号。图 16-1 显示了引脚排列,表 16-1 描述了每个引脚的功能。

图 16-1:

74HC595 移位寄存器的引脚排列

image

表 16-1:

74HC595 移位寄存器引脚

移位寄存器引脚 连接 引脚功能
引脚 1–7,15 Q0–Q7 输出引脚
引脚 8 GND 地线,VSS
引脚 9 Q7 串行输出
引脚 10 MR 主复位,低有效
引脚 11 SH_CP 移位寄存器时钟引脚(时钟引脚)
引脚 12 ST_CP 存储寄存器时钟引脚(锁存引脚)
引脚 13 OE 输出使能,低有效
引脚 14 DS 串行数据输入(数据引脚)
引脚 16 VCC 正电源

连接到 Arduino 引脚 2 的线与我们的按钮相连,按下时会产生一个脉冲。为了使用骰子,按下按钮使骰子上的数字摇动并显示一个随机数字。

构建过程

  1. 将七段 LED 插入面包板,确保它跨越中心断开区域;否则,相对的引脚将连接并短路。将引脚 3 连接到 GND 电源轨,并将 220 欧姆电阻连接到其余引脚,除了引脚 8,它未使用。电阻是必要的,以防止段式 LED 被烧毁。有关此设置,请参见 图 16-2。

    图 16-2:

    连接七段 LED

    image

  2. 将 74HC595 移位寄存器插入面包板时,IC 的半圆标记应在左侧。左下角的引脚应该是引脚 1。您的 IC 需要跨越中间的断开区域,如 图 16-3 所示。

    图 16-3:

    74HC595 移位寄存器应跨越面包板的中心断开区域。

    image

  3. 小心连接七段 LED 显示器和 74HC595 移位寄存器之间的连接,如下表所示。

    七段数码管显示 移位寄存器 Arduino
    引脚 1 (E)* 引脚 4
    引脚 2 (D)* 引脚 3
    引脚 3 GND
    引脚 4 (C)* 引脚 2
    引脚 5 (DP)* 引脚 7
    引脚 6 (B)* 引脚 1
    引脚 7 (A)* 引脚 15
    引脚 8 不使用
    引脚 9 (F)* 引脚 5
    引脚 10 (G)* 引脚 6
    • 这些引脚需要一个 220 欧姆的电阻,在七段 LED 显示器和 74HC595 移位寄存器之间连接。
  4. 现在,将剩余的移位寄存器引脚按下表所示连接到 Arduino。

    移位寄存器 Arduino
    引脚 9 不使用
    引脚 10 +5V
    引脚 11 引脚 12
    引脚 12 引脚 8
    引脚 13 GND
    引脚 14 引脚 11
    引脚 16 +5V
    脉冲 引脚 2
  5. 将按钮插入面包板,使引脚跨越中间断点,如图 16-4 所示。一侧连接到 Arduino 的引脚 2,另一侧连接到 GND。

    图 16-4:

    按钮也应跨越面包板的中心断点。

    image

  6. 确认你的设置与图 16-5 中的电路图一致,并上传代码“草图”到第 140 页。

    图 16-5:

    电子骰子的电路图

    image

草图

草图首先设置引脚以控制驱动七段 LED 的 74HC595 芯片。当七段 LED 显示器通电时,点亮一个小点。当按下按钮时,LED 会以短暂的旋转动画点亮,表示骰子正在摇动。片刻后,1 到 6 之间的随机数将显示出来。再次按下按钮即可生成下一次骰子的结果。

// Code by Warrick A. Smith and reproduced with kind permission
// http://startingelectronics.com

const int latchPin = 8;   // Pins connected to shift register
const int clockPin = 12;
const int dataPin = 11;
const int buttonPin = 2;  // Pin connected to switch wire
// 1 to 6 and DP (decimal point) on 7-segment display
unsigned char lookup_7seg[] = {0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x80};
// Shaking die pattern on 7-segment display
unsigned char shake_dice[] = {0x63, 0x5C};
// Rolling die on 7-segment display
unsigned char roll_dice[] = {0x1C, 0x58, 0x54, 0x4C};
// Vary duration of time before die number is received
int rand_seed;
int rand_num = 0;                // Generate random number
unsigned char shake_toggle = 0;  // For shaking dice animation
int index = 0;                   // For rolling dice animation
int shake_speed;                 // Accelerates dice shake speed

void setup() {
  pinMode(latchPin, OUTPUT);     // Output pins for controlling the
                                 // shift register
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(buttonPin, INPUT);     // Read switch wire state
  digitalWrite(latchPin, LOW);   // Display DP on 7-segment display
                                 // at startup
  shiftOut(dataPin, clockPin, MSBFIRST, lookup_7seg[6]);
  digitalWrite(latchPin, HIGH);
  randomSeed(analogRead(0));     // Generate random seed
}

void loop() {
  if (digitalRead(buttonPin)) {
    shake_speed = 150; // Reset die shaking speed
    delay(30);
    // Generate number for random speed and show shaking animation
    while (digitalRead(buttonPin)) {
      rand_seed++;      // Generate random number
      // Animate shaking die
      if (shake_toggle) {
        AnimateDice(0, shake_dice);
        shake_toggle = 0;
      }
      else {
        AnimateDice(1, shake_dice);
        shake_toggle = 1;
      }
      delay(80 + shake_speed);  // Accelerate animation speed
      if (shake_speed > 0) {
        shake_speed -= 10;
      }
    }
    // Animate rolling die
    for (int rolls = 0; rolls < (rand_seed % 10 + 14); rolls++) {
      AnimateDice(index, roll_dice);
      delay((1 + rolls) * 20);
      index++;
      if (index > 3) {
        index = 0;
      }
    }
    rand_num = random(0, 6);  // Generate number thrown on die
    DiceNumber(rand_num);
  }
}

// Display the die number on 7-segment display
void DiceNumber(unsigned char num) {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, lookup_7seg[num]);
  digitalWrite(latchPin, HIGH);
}

// Display one frame of the shaking or rolling dice
void AnimateDice(int seg, unsigned char *table) {
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, MSBFIRST, table[seg]);
  digitalWrite(latchPin, HIGH);
}

项目 17:火箭发射器

在这个项目中,我们将创建一个可编程倒计时计时器,当倒计时达到 0 时,点燃引线发射火箭。

imageimage

所需材料

• Arduino 板

• 面包板

• 跳线

• 四位数七段串行显示器

• 蜂鸣器

• 2 个短按式触觉四脚按钮

• 50k 欧姆电位器

• 3 个 LED(红色、绿色、黄色)

• 3 个 220 欧姆电阻

所需库

• SoftwareSerial

我们将使用一个四位数的七段串行显示器,它内置集成电路用于控制 LED,只需要三根线即可连接到 Arduino。在选择显示器时,请确保它具有 RX 输入,这样你只需要一根线就能控制它。

工作原理

你可以使用像这样的定时器来触发任何需要电力的设备,比如伺服电机、LED 或报警器。你将使用电位计来选择倒计时的持续时间(从 5 秒到 60 秒不等)。LED 屏幕将显示数字,让你可以看到倒计时设置的时间。我们将包括两个按钮:Arm 按钮和 Launch 按钮。一旦你选择了倒计时的时间,按下 Arm 按钮来准备定时器。红色 LED 灯显示定时器已准备好。(Arm 按钮是一个安全功能,防止你不小心启动发射器。)当火箭准备好后,按下 Launch 按钮开始倒计时。绿色 LED 灯表示它已准备好,倒计时开始。

当定时器倒计时时,蜂鸣器每秒发出一声。倒计时到五秒时,蜂鸣器的鸣叫逐渐加速,直到发射。当定时器到达 0 时,电源通过引脚 7 传输到你连接的任何输出设备——在这个例子中,它点亮了黄色 LED。你可以将这个定时器连接到蜂鸣器、伺服电机来解锁门,甚至是连接到火箭引信。稍后我将向你展示如何制作一个简单的引信点燃器。

构建过程

  1. 将七段串行显示器的 RX 引脚连接到 Arduino 引脚 3,将 VCC 连接到 +5V,并通过面包板将 GND 连接到 Arduino 的 GND,如图 17-1 所示。你可能需要剥掉一些电线以便连接。

    七段串行显示器 ARDUINO
    RX 引脚 3
    VCC +5V
    GND GND

    图 17-1:

    将七段显示器连接到 Arduino

    image

  2. 将电位计插入面包板,将左侧针脚连接到 +5V,中间针脚连接到 Arduino 引脚 A0,右侧针脚连接到 GND,如图 17-2 所示。

    电位计 ARDUINO
    左侧针脚 +5V
    中间针脚 A0
    右针脚 GND

    图 17-2:

    将电位计放入面包板

    image

  3. 将蜂鸣器的红线连接到 Arduino 引脚 4,将黑线连接到 GND,如图 17-3 所示。

    蜂鸣器 ARDUINO
    红线 引脚 4
    黑线 GND

    图 17-3:

    连接蜂鸣器

    image

  4. 将两个按钮插入面包板,其中 A 和 B 引脚在中心断开的同一侧,C 和 D 引脚在另一侧,按照图 17-4 中的配置。

    图 17-4:

    按钮的针脚连接

    image

  5. 接下来,我们将连接按钮,如图 17-5 所示。要创建 Arm 按钮,将第一个按钮的 C 引脚连接到 GND,D 引脚连接到 Arduino 引脚 5。要创建 Launch 按钮,将另一个按钮的 C 引脚连接到 GND,D 引脚连接到 Arduino 引脚 6。

    按钮 ARDUINO
    臂针 C GND
    臂针 D 引脚 5
    发射针 C GND
    发射针 D 引脚 6

    图 17-5:

    连接按钮和 LED

    image

  6. 将红色 LED 插入面包板,较短的负极脚连接到臂按钮的 B 引脚。将另一只脚连接到 220 欧姆电阻,电阻的另一端连接到+5V。然后将绿色 LED 插入面包板,负极脚连接到发射按钮的 B 引脚,正极脚通过 220 欧姆电阻连接到+5V。

    电阻器 Arduino
    负极脚 GND
    正极脚 通过 220 欧姆电阻连接到+5V
  7. 连接点火器。我们暂时使用黄色 LED 作为点火指示器。将其插入面包板,负极脚连接到 GND,正极脚通过 220 欧姆电阻连接到 Arduino 的第 7 号引脚。(参见“制作工作保险丝”第 149 页,了解如何制作自己的点火器。)

    点火器 Arduino
    负极脚 GND
    正极脚 通过 220 欧姆电阻连接到引脚 7

    当倒计时到达 0 时,引脚 7 被设置为HIGH,触发点火器。我们没有真正点燃保险丝,而是点亮黄色 LED 来表示点火。

  8. 确认您的设置与图 17-6 中的电路图匹配,并上传“草图”中的代码(见第 151 页)。

    图 17-6:

    火箭发射器的电路图

    image

制作工作保险丝

如果不使用 LED 来指示点火,您可以使用简单的圣诞树灯制作一个工作保险丝。制作保险丝时,请确保佩戴护眼设备。这些说明仅供娱乐用途,应仅由成年人执行。

警告

在您的国家或州,可能会对发射爱好火箭或烟花有限制,因此请事先检查。确保项目使用符合法律规定是您的责任。

  1. 使用爱好钻头,在圣诞灯的玻璃外壳顶部施加轻微压力,将其切割掉(见图 17-7)。

    图 17-7:

    用爱好钻头切割尖端

    image

  2. 在玻璃外壳的尖端附近切割,顶部应能轻松弹开(见图 17-8)。

    图 17-8:

    弹出尖端

    image

  3. 现在切下木质火柴的火头(确保不要点燃它!),然后小心地将火柴头插入开口的灯泡内,注意不要损坏灯丝(见图 17-9)。

    图 17-9:

    将火柴头插入灯泡的下半部分

    image

  4. 最后,将灯泡的电线连接到点火电线。当电源送入灯泡时,灯丝会加热并点燃火柴头(见图 17-10),产生足够的能量点燃保险丝。

    图 17-10:

    点燃引信后

    image

程序代码

程序首先定义了每个组件及其与 Arduino 的连接。SoftwareSerial 库控制四位七段串行 LED 显示器,而来自电位器的模拟输入则将显示的时间从 5 秒到 60 秒进行调整。按下 Arm 按钮时,它充当数字开关和安全功能,允许按下 Launch 按钮。如果在倒计时期间按下 Arm 按钮,倒计时会中止,显示器会重置。

程序中的tone命令按倒计时的节奏脉冲驱动压电蜂鸣器发出“哔”声。当倒计时到达 0 时,引信针脚(在此情况下连接到 LED)被设置为HIGH,并点亮 LED。

// Ardunaut Arduining.com, reproduced with kind permission

#define FuseTIME      1500   // Duration of fuse current in ms
#include <SoftwareSerial.h>  // Call the SoftwareSerial library

#define Fuse     7     // Pin connected to fuse (your LED or igniter)
#define GoButt   6     // Pin connected to Launch button
#define ArmButt  5     // Pin connected to Arm button
#define BuzzPin  4     // Pin connected to piezo buzzer
#define TXdata   3     // Pin connected to RX of display
#define RXdata   2     // Not used
#define SetPot   0     // Analog pin connected to potentiometer

SoftwareSerial mySerialPort(RXdata, TXdata);

void setup() {
  pinMode(TXdata, OUTPUT);
  pinMode(RXdata, INPUT);
  pinMode(Fuse, OUTPUT);
  pinMode(ArmButt, INPUT);       // Set Arm button pin to input
  pinMode(GoButt, INPUT);        // Set Launch button pin to input
  digitalWrite(Fuse, LOW);       // Open igniter circuit
  digitalWrite(ArmButt, HIGH);   // Turn on resistor
  digitalWrite(GoButt, HIGH);    // Turn on resistor
  mySerialPort.begin(9600);
  delay(10);                     // Wait for serial display startup
  mySerialPort.print("v");       // Reset the serial display
  mySerialPort.print("z");       // Brightness
  mySerialPort.write(0x40);      // 3/4 intensity
  mySerialPort.print("w");       // Decimal point control
  mySerialPort.write(0x10);      // Turn on colon in serial display
}

int DownCntr;   // Countdown (1/10 seconds)
int Go = 0;     // Stopped

void loop() {
  if (!digitalRead(GoButt) || !digitalRead(ArmButt)) {
    Go = 0;   // Abort the countdown
    tone(BuzzPin, 440, 1500);
    delay(1500);
  }

  if (Go == 0) {
    WaitARM();
    WaitGO();
  }
  ShowTimer();
  if (DownCntr > 50) {
    if (DownCntr % 10 == 0)tone(BuzzPin, 1000, 50); // One beep/sec
  }
  else if (DownCntr % 2 == 0)tone(BuzzPin, 1000, 50); // Beep faster

  if (DownCntr == 0) {
    tone(BuzzPin, 440, FuseTIME);  // Launch tone
    digitalWrite(Fuse, HIGH);      // Close the fuse circuit
    delay(FuseTIME);
    digitalWrite(Fuse, LOW);       // Open the fuse circuit
    Go = 0;
  }
  while (millis() % 100);          // Wait 50 ms
  delay(50);
  DownCntr--;
}

void WaitGO() {
  ShowTimer();
  while (digitalRead(GoButt));
  Go = 1;
  delay(20);
  while (!digitalRead(GoButt)); // Debounce Launch button
}

void ReadTimer() {
  DownCntr = map(analogRead(SetPot), 0, 1023, 5, 60);
  DownCntr *= 10;
}

void ShowTimer() {
  String seconds = String (DownCntr, DEC);
  while (seconds.length() < 3)seconds = "0" + seconds; // Format to
                                                       // 3 numbers
  mySerialPort.print(seconds); // Write to serial display
  mySerialPort.print(" ");     // Last digit off
}

void WaitARM() {
  while (digitalRead(ArmButt) == 1) {
    ReadTimer();
    delay(50);
    ReadTimer();
    ShowTimer();
    delay(150);
  }

  Go = 0;
  ShowTimer();
  tone(BuzzPin, 2000, 150);
  delay(200);
  tone(BuzzPin, 2000, 150);
  delay(200);
  tone(BuzzPin, 2000, 150);

  delay(20);
  while (!digitalRead(ArmButt)); // Debounce Arm button
}

第六部分

image

安全性

项目 18:入侵者传感器

在这个项目中,我们将使用超声波传感器来检测入侵者。

imageimage

所需部件

• Arduino 开发板

• 面包板

• 跳线

• 四引脚 HC-SR04 超声波传感器

• 伺服电机

• 红色 LED

• 绿色 LED

• 2 个 220 欧姆电阻

我们将入侵者传感器与伺服电机和一些 LED 灯连接,这样当有人接近一定距离时,绿色 LED 会熄灭,红色 LED 会亮起,伺服电机也会移动(见图 18-1)。

图 18-1:

这些 LED 灯会提醒你有入侵者。

image

工作原理

这个项目非常灵活,可以以多种方式使用和改造。由于超声波传感器能够测量距离,你可以用它来定义一个区域,并在越过这个范围时触发警报。例如,它的工作原理类似于雷达:它发出一个超声波信号,或称为ping。当这个信号遇到物体时,会像回声一样反弹回来,ping 和回声之间的时间可以用来计算距离。Arduino 可以根据这个计算触发某些事件。

在这个项目中,当传感器检测到有入侵者接近预设范围时,红色 LED 会亮起,伺服电机臂将开始移动。你可以根据需要修改这个项目,使其在检测到入侵者时触发不同的事件,比如按下安全系统按钮或锁门。为了实现更友好的场景,你可以将距离设得非常近,这样当你在传感器前挥动手时,伺服电机会按下按钮释放糖果等奖励。

注意

要使用这些图中展示的相同超声波传感器,请参见“零售商列表”中的第 240 页,或在线搜索 HC-SR04 超声波模块。

构建

  1. 将超声波传感器插入面包板中。我们在这个项目中使用的传感器有四个引脚,如图 18-2 所示。将传感器的 GND 连接到 Arduino 的 GND 轨道,VCC 连接到 Arduino 的+5V 轨道,Trig 连接到 Arduino 的 12 号引脚,Echo 连接到 Arduino 的 13 号引脚。

    超声波传感器 Arduino
    GND GND
    VCC +5V
    Trig 12 号引脚
    Echo 13 号引脚

    图 18-2:

    HC-SR04 超声波传感器

    image

  2. 将伺服电机的棕色(接地)线连接到 Arduino 的 GND 轨道,红色(电源)线连接到 Arduino 的+5V 轨道,黄色信号(控制)线连接到 Arduino 的 9 号引脚。

    伺服电机 Arduino
    红色线 +5V
    棕色线 GND
    黄色线 9 号引脚
  3. 将红色和绿色 LED 插入面包板,短的负极引脚接入 Arduino 的 GND 轨道。为每个正极引脚加上 220 欧姆的电阻,并将红色 LED 连接到 Arduino 的 2 号引脚,绿色 LED 连接到 3 号引脚,通过电阻连接。

    LED 灯 Arduino
    负极引脚 GND
    正极(红色) 通过 220 欧姆电阻连接到引脚 2
    正极(绿色) 通过 220 欧姆电阻连接到引脚 3
  4. 将面包板上的电源轨连接到 Arduino 的 +5V 和 GND。最终配置如 图 18-3 所示。

    图 18-3:

    完整的入侵传感器项目

    image

  5. 检查你的设置是否与 图 18-4 一致,然后上传 “草图” 中的代码,代码位于 第 161 页。

    图 18-4:

    入侵传感器的电路图

    image

草图

当物体进入触发距离时,红色 LED 会亮起,伺服电机会转动 45 度。你可以在草图的以下行中改变传感器的探测距离:

if (distance <= 15)

在这个示例中,如果在 15 厘米内探测到物体,下一段代码将被执行。

传感器上的 Trig 引脚连接到 Arduino 引脚 12,发出超声波信号或 Ping。当信号到达物体时,会反弹回模块,这个回波会发送到 Arduino 引脚 13。两个信号之间的时间差给我们提供了距离读数。如果距离超过我们设定的最小值,绿色 LED 会保持亮起;如果不超过,红色 LED 会亮起,伺服电机会移动。

/* NewPing Library created by Tim Eckel teckel@leethost.com.
   Copyright 2012 License: GNU GPL v3
   http://www.gnu.org/licenses/gpl-3.0.html
*/

#include <NewPing.h> // Call NewPing library
#include <Servo.h>   // Call Servo library
#define trigPin 12   // Trig pin connected to Arduino 12
#define echoPin 13   // Echo pin connected to Arduino 13
#define MAX_DISTANCE 500
NewPing sonar(trigPin, echoPin, MAX_DISTANCE); // Library setting
int greenLed = 3, redLed = 2; // Set green LED to pin 3, red to pin 2
int pos = 20;
Servo myservo;

void setup() {
  Serial.begin (115200);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(greenLed, OUTPUT);
  pinMode(redLed, OUTPUT);
  myservo.attach(9); // Servo attached to pin 9
}

void loop() {
  int duration, distance, pos = 0, i;
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH); // Trig pin sends a ping
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH); // Echo receives the ping
  distance = (duration / 2) / 29.1;
  Serial.print(distance);
  Serial.println(" cm");
  // If sensor detects object within 15 cm
  if (distance <= 15) {
    digitalWrite(greenLed, LOW); // Turn off green LED
    digitalWrite(redLed, HIGH);  // Turn on red LED
    myservo.write(180);          // Move servo arm 180 degrees
    delay(450);
    digitalWrite(redLed, LOW);   // Light the red LED
    myservo.write(90);
    delay(450);
    digitalWrite(redLed, HIGH);
    myservo.write(0);
    delay(450);
    digitalWrite(redLed, LOW);
    myservo.write(90);
  }
  // Otherwise
  else {
    digitalWrite(redLed, LOW);    // Turn off red LED
    digitalWrite(greenLed, HIGH); // Turn on green LED
    myservo.write(90);
  }
  delay(450);
}

项目 19:激光触发报警器

在这个项目中,你将制作一个简单的激光触发报警器。

imageimage

所需组件

• Arduino 主板

• 面包板

• 跳线

• 光敏电阻

• 压电蜂鸣器

• 绿色 LED

• 10k 欧姆电阻

• 激光笔

你可能见过这样的电影场景:一个珍贵的物品被激光束网格保护着。这些激光束看起来很酷,似乎很高科技,但它们背后的原理其实非常简单。

工作原理

当激光笔照射到光敏电阻上时,绿色 LED 会亮起,表示电路准备就绪。当激光束被打破时,LED 熄灭,蜂鸣器发出声音。

正如我们在 项目 13 和 18 中所知,光敏电阻根据照射到其传感器上的光线强度产生可变电阻。当光敏电阻没有检测到激光光线时,它会降低电阻并触发 Arduino 向控制蜂鸣器的引脚发送电压。

在白天或甚至在黑暗中可见的激光束非常强大,可能非常危险。在这个项目中,我们将使用一支低功率的激光笔代替(见 图 19-1)。

图 19-1:

激光笔仍然可能是危险的,绝对不应该将其对准任何人的眼睛!

image

构建过程

  1. 将光敏电阻插入面包板。将一端连接到 +5V 电源轨,另一端连接到 10k 欧姆电阻,电阻的另一端连接到 Arduino 的 A0 和 GND 引脚。

    光敏电阻 Arduino
    引脚 1 +5V
    引脚 2 A0 通过 10kΩ 电阻和 GND
  2. 将蜂鸣器的红色(正极)线直接连接到 Arduino 的 11 引脚,黑色(GND)线连接到面包板的 GND。

    蜂鸣器 Arduino
    黑线 GND
    红线 引脚 11
  3. 将绿 LED 的长腿插入 Arduino 的 13 引脚,短腿插入 GND。

  4. 将电源轨连接到面包板。

  5. 在上传代码之前,你需要检查光敏电阻在环境光下的值。按照说明设置光敏电阻后,运行以下小程序。

    void setup() {
      pinMode(4, OUTPUT);
      Serial.begin(9600);
    }
    
    void loop() {
      digitalWrite(4, HIGH);
      Serial.println(analogRead(0));
    }
    
  6. 打开 Arduino IDE 中的串行监视器。它将显示从光敏电阻读取的值——在图 19-2 中,它为 964——在正常光照条件下。记录下这个数字,它会根据你的光照条件有所不同。

    图 19-2:

    从光敏电阻读取数值

    image

    现在将激光照射到电阻的光敏元件上,并记录下这个数值;我的读数是 620。这可能看起来有些反直觉,因为你会预期更多的光照会提供更高的数值,但这个数值实际上是在转换电阻——更多的光,电阻更小。你的数值可能与这里展示的不同,所以务必记录下你得到的两个读数。

  7. 检查你的设置是否与图 19-3 相匹配,然后上传第 168 页中“草图”中的代码。

    图 19-3:

    激光触发报警器的电路图

    image

草图

草图首先将 Arduino 引脚 11 设置为蜂鸣器的 输出,将引脚 13 设置为 LED 的 输出。光敏电阻连接到 Arduino 的 A0 引脚。如果 A0 的模拟读取值超过 850(意味着光线较少且激光束被打破),蜂鸣器将被设置为 ,并开启,LED 将关闭。记得根据你的校准调整此行中的电阻值:

if (analogRead(0) > 850) {

如前所述,当激光照射到电阻时,读数约为 620,因此在代码中,我设置蜂鸣器只有在数值超过 850 时才会发出声音。这个数值介于激光值和非激光值之间,因此当数值达到 850 时,我们就知道激光束已经被打破。

int buzzPin = 11; // Pin connected to the piezo
int LED = 13;     // Pin connected to the LED

void setup() {
  pinMode(buzzPin, OUTPUT); // Set pin as output
  pinMode(LED, OUTPUT);     // Set pin as output
}

void loop() {
  if (analogRead(0) > 850) { // Set this value depending on the
                             // values of your photoresistor
    digitalWrite(buzzPin, HIGH); // If value is above 850,
                                 // turn the piezo ON
    digitalWrite(LED, LOW);      // If value is above 850,
                                 // turn the LED OFF
    delay(1000); // Wait for 1 second
    digitalWrite(buzzPin, LOW);
    digitalWrite(LED, LOW);
  } else {
    digitalWrite(buzzPin, LOW); // If value is 850 or below
                                // (light shining on photoresistor),
                                // the piezo is off
    digitalWrite(LED, HIGH);    // If value is 850 or below
                                // (light shining on photoresistor),
                                // the LED is on
  }
}

项目 20:自动瞄准枪

自动瞄准枪是一种无人武器,能够通过超声波检测自主感知并对敌方目标进行射击。在本项目中,我们将制作这种枪的微型版本。

imageimage

所需组件

• Arduino 板

• 小型面包板

• 跳线

• 公对公跳线

• 四针 HC-SR04 超声波传感器

• WLToys RC V959 导弹发射器

• Tower Pro SG90 9g 伺服电机

所需库

• 伺服电机

• NewPing

工作原理

我们将玩具导弹发射器和超声波传感器安装到舵机臂上(见图 20-1),这样舵机可以将枪和传感器在 180 度范围内来回扫动,使超声波传感器具有更广泛的探测范围。当检测到敌人时,Arduino 会触发警戒枪并发射导弹。有关超声波传感器的更多信息,请参见第 18 项项目。

图 20-1:

将玩具枪和超声波传感器安装到舵机臂上,使它们具有更广泛的探测和运动范围。

image

本项目的关键组件是 WLToys RC V959 导弹发射器,也被称为 Walkera 部件 RC V959-19 导弹发射器,设计用于遥控直升机(见图 20-2)。

图 20-2:

Walkera 部件 RC V959-19 导弹发射器

image

这个酷炫的部件非常便宜(大约 6 到 10 美元),并且在网上非常容易购买。这个发射器内部有一个小型舵机,通过旋转来发射导弹。控制这个舵机的电线是白色(GND)和黄色(+5V)。你还会看到黑色和红色电线,它们是用于单次发射的,但我们将只使用黄色和白色线,以实现持续的加特林枪效果。

构建过程

  1. 首先我们准备好玩具导弹发射器。小心地将四根线从小塑料插座中拔出,它们应该会很容易地出来。你可以使用公对公跳线,按下塑料夹来帮助拔出。

  2. 电线的核心是绞合的,非常脆弱,因此需要剥掉黄色和白色电线的末端,并将它们焊接到可以插入 Arduino 的独立实心线中,如图 20-3 所示。修剪黑色和红色电线,或者将它们用胶带固定在一旁。

    图 20-3:

    剥皮并焊接导弹发射器电线

    image

  3. 将舵机电机的臂部粘贴到导弹发射器的底座上,如图 20-4 所示。

    图 20-4:

    粘贴舵机电机的臂部

    image

  4. 将超声波传感器粘贴到发射器的顶部,如图 20-5 所示。你可以使用热熔胶枪来确保连接牢固,或者如果之后可能需要修改,可以暂时用胶带粘贴。

    图 20-5:

    安装超声波传感器

    image

  5. 使用跳线将超声波传感器连接到 Arduino:将 Trig 直接连接到 Arduino 引脚 13,将 Echo 直接连接到 Arduino 引脚 12。我们将使用迷你面包板来辅助多个电源连接到 Arduino +5V 和 GND。

    超声波传感器 Arduino
    VCC +5V
    Trig 引脚 13
    Echo 引脚 12
    GND GND
  6. 将舵机的棕色线连接到 Arduino GND,红色线通过迷你面包板连接到 +5V,黄色/白色线直接连接到 Arduino 引脚 9。

    舵机 Arduino
    棕色线 GND
    红色线 +5V
    黄色线 引脚 9
  7. 将发射器的白色电线连接到迷你面包板的 GND 轨道,黄色电线直接连接到 Arduino 的 3 号引脚。

    发射器 ARDUINO
    白色电线 GND
    黄色电线 3 号引脚
  8. 你的岗哨枪应当如图 20-6 所示。将导弹插入发射器。

    图 20-6:

    你的岗哨枪已经准备好发射了!

    image

  9. 确认你的完成设置与图 20-7 一致。在第 176 页上传"草图"中的代码。

    图 20-7:

    岗哨枪的电路图

    image

草图

草图首先调用了 NewPing 和 Servo 库,以访问控制伺服电机和超声波传感器所需的功能。(确保从nostarch.com/arduinohandbook/下载并将 NewPing 库保存在你的 Arduino 文件夹中。)伺服电机会先向一个方向旋转,再向另一个方向旋转,移动超声波传感器 180 度。传感器发出超声波信号或ping,当这个 ping 信号遇到物体时,它会反射回来,并给出一个时间值。Arduino 将这个时间值转换为传感器与物体之间的距离。当距离小于 15 厘米时,伺服电机会停止,并向发射器发送电力,向物体发射子弹。你可以在➊处更改这个触发距离(单位为厘米)。

   #include <NewPing.h> // Call NewPing library
   #include <Servo.h>   // Call Servo library
   #define trigPin 12   // Pin connected to ultrasonic sensor Trig
   #define echoPin 13   // Pin connected the ultrasonic sensor Echo
   #define MAX_DISTANCE 500

   NewPing sonar(trigPin, echoPin, MAX_DISTANCE);

   int blaster = 3; // Pin connected to the blaster

   int angle = 0; // Set servo position in degrees

   Servo servo;

   void setup() {
     Serial.begin (115200);
     pinMode(trigPin, OUTPUT);
     pinMode(echoPin, INPUT);
     pinMode(blaster, OUTPUT);
     servo.attach(9); // Pin connected to servo
   }

   void loop() {
     int duration, distance, pos = 0, i;
     digitalWrite(trigPin, LOW);
     delayMicroseconds(2);
     digitalWrite(trigPin, HIGH); // trigPin sends a ping
     delayMicroseconds(10);
     digitalWrite(trigPin, LOW);
     duration = pulseIn(echoPin, HIGH); // echoPin receives the ping
     distance = (duration / 2) / 29.1;
     Serial.print(distance);
     Serial.println(" cm");
➊   if (distance <= 15) { // If distance is fewer than 15 cm
       digitalWrite(blaster, HIGH); // Blaster will fire
       servo.write(90);
     }
     else {
       digitalWrite(blaster, LOW); // Otherwise, blaster won't activate
       for (angle = 0; angle < 180; angle++) { // Sweep the servo
         servo.write(angle);
         delay(15);
       }
       for (angle = 180; angle > 0; angle--) {
         servo.write(angle);
       }
       delay(450);
     }
   }

项目 21:运动传感器报警

在本项目中,我们将使用一个被动红外(PIR)传感器来构建一个运动传感报警。

imageimage

所需零件

• Arduino 板

• 面包板

• HC SR501 PIR 传感器

• LED

• 压电蜂鸣器

你可以使用这个报警器触发各种输出,例如灯光、电机,甚至当你靠近前门时播放“欢迎回家”的信息。

工作原理

本项目基于 HC SR501 PIR 传感器,它在网上可以以几美元的价格轻松购买。我们将设置它,当有人走过 PIR 传感器前时,LED 会亮起,压电蜂鸣器会发出声音(见图 21-1),但你也可以根据需要将其改编为其他输出方式。

图 21-1:

任何压电蜂鸣器都可以用于这个项目,但记得大多数蜂鸣器有极性,因此红色电线必须连接到+5V,黑色电线连接到 GND。

image

其他类似的 PIR 传感器也能与此代码一起使用,但重要的是要检查传感器的数据表中的引脚布局,因为这可能会有所不同。所有传感器应有+5V、GND 和输出引脚。在此型号上,引脚没有明确标记,但如果你简单地取下外层镜头(它是卡在位置上的,可以很容易地解开),你可以看到下面的引脚,如图 21-2 所示。

图 21-2:

移除镜头的 PIR 传感器

image

传感器上的两个橙色电位器表示有两个可调节的设置。当传感器直立时,如图 21-3 所示,左侧电位器控制当检测到物体时输出信号为 HIGH 的持续时间,设置范围是 5 到 200 秒。当我们将 LED 连接到输出时,LED 将根据设置的时间亮起 5 到 200 秒。右侧电位器调整检测范围,从 0 到 7 米。

图 21-3:

PIR 传感器的电位器。左侧控制输出为 HIGH 的持续时间(5-200 秒),右侧控制检测范围(0-7 米)。

image

传感器通过检测红外辐射来工作,这些辐射来自产生热量的物体。传感器内部的晶体材料检测到红外辐射,当它检测到设定的阈值时,会触发传感器的输出信号。Arduino 读取此输出为电压,因此我们可以将其用作简单的开关来开启某个设备——在本项目中是一个 LED。

我们正在设置传感器,以便当传感器被触发时发出警报,但你可以通过其他方式自定义项目。例如,你可以通过连接一个舵机并设置它在朋友经过时释放一个橡皮筋来吓唬他们。

构建过程

  1. 将 PIR 传感器的 +5V 和 GND 电线连接到面包板上的 +5V 和 GND 导轨,并将这些导轨连接到 Arduino。将 PIR 传感器的输出电线连接到 Arduino 引脚 2。(请参见图 21-4。)

    PIR 传感器 ARDUINO
    +5V +5V
    GND GND
    输出 引脚 2

    图 21-4:

    PIR 传感器连接到电线

    image

  2. 将 LED 插入面包板,并将长的正极腿连接到 Arduino 引脚 13,短的负极腿连接到 GND。此项目中不需要为 LED 添加电阻。

    LED ARDUINO
    正极腿 引脚 13
    负极 GND
  3. 通过将红色电线连接到 Arduino 引脚 10,黑色电线连接到 GND,连接蜂鸣器。

    蜂鸣器 ARDUINO
    红色电线 引脚 10
    黑色电线 GND
  4. 确保你的设置与图 21-5 中的电路图一致,然后上传 “草图” 中的代码,页面可以参考第 183 页。

    图 21-5:

    运动传感器报警的电路图

    image

草图

草图通过将 Arduino 引脚 13 设置为 LED 输出、引脚 2 设置为 PIR 传感器输入、引脚 10 设置为蜂鸣器输出来工作。当 PIR 传感器被触发时,将发送一个 HIGH 信号到 Arduino,进而点亮 LED 并通过蜂鸣器发出声音。

int ledPin = 13;           // Pin connected to LED
int inputPin = 2;          // Pin connected to PIR sensor
int pirState = LOW;        // Start PIR state LOW with no motion
int val = 0;               // Variable for reading the pin status
int pinSpeaker = 10;       // Pin connected to piezo

void setup() {
  pinMode(ledPin, OUTPUT);  // Set LED as output
  pinMode(inputPin, INPUT); // Set sensor as input
  pinMode(pinSpeaker, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  val = digitalRead(inputPin);   // Read PIR input value
  if (val == HIGH) {             // Check if input is HIGH
    digitalWrite(ledPin, HIGH);  // If it is, turn ON LED
    playTone(300, 160);
    delay(150);
    if (pirState == LOW) {
      // Print to the Serial Monitor if motion detected
      Serial.println("Motion detected!");

      pirState = HIGH;
    }
  } else {
      digitalWrite(ledPin, LOW); // If input is not HIGH,
                                 // turn OFF LED
      playTone(0, 0);
      delay(300);
      if (pirState == HIGH) {
      Serial.println("Motion ended!");
      pirState = LOW;
    }
  }
}

void playTone(long duration, int freq) { // Duration in ms,
                                         // frequency in Hz
    duration *= 1000;
    int period = (1.0 / freq) * 1000000;
    long elapsed_time = 0;
    while (elapsed_time < duration) {
      digitalWrite(pinSpeaker, HIGH);
      delayMicroseconds(period / 2);
      digitalWrite(pinSpeaker, LOW);
      delayMicroseconds(period / 2);
      elapsed_time += (period);
    }
}

项目 22:键盘输入系统

现在是通过构建键盘输入系统将键盘引入你的 Arduino 的时候了。

imageimage

所需零件

• Arduino 板

• 面包板

• 跳线

• Tower Pro SG90 9g 伺服电机

• 绿色 LED

• 红色 LED

• 4×4 膜式键盘

• 2 个 220 欧姆电阻

所需库

• 键盘

• 伺服电机

• 密码

该项目使用一个 4×4 膜式键盘,底部有一条八根线的带状线,连接到一个伺服电机,用于转动解锁。

工作原理

键盘本质上是一系列按钮,根据按下的按钮输出数字或字符。将键盘面朝上时,线缆从左到右编号为 1–8。前四根线对应行,后四根线对应列。

您需要从 nostarch.com/arduinohandbook/ 下载键盘库,并将其保存到您的 IDE 的 Arduino 库文件夹中。

我们将把这个键盘连接到伺服电机和一些 LED,创建一个像 项目 9 中的秘密敲击锁系统。使用此锁时,输入您的代码并按下星号(*)确认。如果代码与草图中定义的密码匹配,绿色 LED 将闪烁,伺服电机将移动 90 度。如果代码不正确,红色 LED 将闪烁。使用井号(#)键在输入代码之间重置。您可以将此伺服电机替换为更强大的伺服电机,用于解锁门上的较重死锁,或使用安装在外部的键盘和 LED 来解锁和锁定盒子内部。

测试键盘

首先,我们将使用以下代码测试键盘:

#include <Keypad.h>

const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {2,3,4,5};
byte colPins[COLS] = {6,7,8,9};

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins,
                       ROWS, COLS);

void setup() {
  Serial.begin(9600);
}

void loop() {
  char key = keypad.getKey();
  if (key != NO_KEY){
    Serial.println(key);
  }
}

上传此代码,然后在您的 IDE 中打开串口监视器(图 22-1)。

图 22-1:

测试键盘

image

将键盘面朝上时,从左到右按顺序将线缆连接到 Arduino 数字引脚 9–2。当您上传完代码后,按几个键。每次按下键时,相应的字符应该出现在 Arduino IDE 的串口控制台中的单独一行上。

构建过程

  1. 按照下图 图 22-2 中所示,直接将键盘引脚连接到 Arduino 引脚。

    键盘 ARDUINO
    引脚 1 引脚 9
    引脚 2 引脚 8
    引脚 3 引脚 7
    引脚 4 引脚 6
    引脚 5 引脚 5
    引脚 6 引脚 4
    引脚 7 引脚 3
    引脚 8 引脚 2

    图 22-2:

    键盘引脚 1-8

    image

  2. 将绿色 LED 和红色 LED 插入面包板,较短的负极腿连接到 Arduino GND 导轨。将 220 欧姆电阻连接到每个较长的正极腿。将连接到绿色 LED 的电阻连接到 Arduino 引脚 11,将连接到红色 LED 的电阻连接到 Arduino 引脚 12。

    LED 灯 ARDUINO
    正极腿 通过 220 欧姆电阻连接到引脚 11 和 12
    负极腿 GND
  3. 现在连接伺服电机(见 图 22-3)。将棕色线连接到 GND 排,红色线连接到 +5V 排,黄色/白色线直接连接到 Arduino 的 13 号引脚。

    伺服电机 Arduino
    棕色线 GND
    红色线 +5V
    黄色线 引脚 13

    图 22-3:

    连接伺服电机

    image

  4. 确保你的设置与 图 22-4 中的设置一致,并上传 “草图” 中的代码,位于 第 192 页。

    图 22-4:

    键盘输入系统的电路图

    image

草图

首先,草图调用了 Keypad、Servo 和 Password 库。Servo 库已经包含在 IDE 中,但你需要下载 Keypad 和 Password 库(nostarch.com/arduinohandbook/)。然后,我们设置了八个引脚,用于从键盘获取输入,并将 Arduino 的引脚 11 和 12 设置为控制 LED,13 号引脚控制伺服电机。Arduino 等待你通过键盘输入代码,并在按下 * 确认输入后,草图会检查输入是否与代码中的密码匹配。如果输入不匹配密码,红色 LED 将被设置为 HIGH 并亮起;如果输入 匹配 密码,绿色 LED 将被设置为 HIGH 并亮起,伺服电机将开始转动。按下 # 将重置草图,准备接受另一个输入。

要更改密码,请修改以下行中的引号内的数字。

Password password = Password("2468");

草图中的默认密码是 2468。

/* Keypad Library for Arduino
   Authors: Mark Stanley, Alexander Brevig
   http://playground.arduino.cc/Main/KeypadTutorial
*/

#include <Password.h>
#include <Keypad.h>
#include <Servo.h>

Servo myservo;
Password password = Password("2468"); // Set password

const byte ROWS = 4; // Set four rows
const byte COLS = 4; // Set four columns

char keys[ROWS][COLS] = { // Define the keymap
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = { 9,8,7,6 };  // Pins connected to keypad
                                   // ROW0, ROW1, ROW2 and ROW3
byte colPins[COLS] = { 5,4,3,2, }; // Pins connected to keypad
                                   // COL0, COL1 and COL2
// Create the keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins,
                       ROWS, COLS);
void setup() {
  Serial.begin(9600);
  delay(200);
  pinMode(11, OUTPUT); // Set green LED as output
  pinMode(12, OUTPUT); // Set red LED as output
  myservo.attach(13);  // Pin connected to servo
  keypad.addEventListener(keypadEvent); // Add an event listener to
                                        // detect keypresses
}

void loop() {
  keypad.getKey();
  myservo.write(0);
}

void keypadEvent(KeypadEvent eKey) {
  switch (keypad.getState()) {
    case PRESSED:
    Serial.print("Pressed: ");
    Serial.println(eKey);
    switch (eKey) {
      case '*': checkPassword(); break;
      case '#': password.reset(); break;
      default: password.append(eKey);
    }
  }
}

void checkPassword() {
  if (password.evaluate() ){
    Serial.println("Success"); // If the password is correct...
    myservo.write(90);         // Move servo arm 90 degrees
    digitalWrite(11, HIGH);    // Turn on green LED
    delay(500);                // Wait 5 seconds
    digitalWrite(11, LOW);     // Turn off green LED
  } else {
    Serial.println("Wrong");   // If the password is incorrect...
    myservo.write(0);
    digitalWrite(12, HIGH);    // Turn on red LED
    delay(500);                // Wait 5 seconds
    digitalWrite(12, LOW);     // Turn off red LED

  }
}

项目 23:无线 ID 卡门禁系统

在这个项目中,我们将使用射频识别(RFID)读取器来构建一个无线 ID 卡门禁系统。

imageimage

所需组件

• Arduino 主板

• 面包板

• 跳线

• Mifare RFID-RC522 模块

• Tower Pro SG90 9g 伺服电机

• 声音蜂鸣器

• 红色 LED

• 绿色 LED

• 2 个 220 欧姆电阻

所需库

• RFID

• SPI

• 电线

• 伺服电机

• 引脚

工作原理

RFID 读取器使用无线技术在没有接触的情况下识别卡片、标签或钥匙扣。当卡片靠近读取器时,读取器会响应。首先,我们需要读取器读取我们 RFID 卡的唯一编号,然后添加一个伺服电机,根据 RFID 读取器是否识别该卡来控制伺服电机的动作。我们可以将这个 ID 系统用于门锁或盒子锁之类的场景,就像在 项目 9 中的秘密敲门代码锁一样。

你可能在购买的物品上看到过类似图 23-1 的贴纸。这些贴纸使用 RFID 技术,让商店能够跟踪物品以防盗。如果你在未支付的情况下通过 RFID 区域,贴纸会触发警报。RFID 读卡器和卡片也常用于身份验证,允许进入受限制区域,如绝密实验室或封闭小区。

图 23-1:

一张 RFID 贴纸

image

RFID 有两种类型:被动和主动。每个 RFID 系统使用无线频率在读卡器和标签或卡片之间交换信号。这个信号包含了标签或卡片的唯一代码,如果 RFID 读卡器识别到这个代码,它会做出相应的反应——例如,允许物品通过商店的探测器或解锁门锁。

在被动系统中,当两个设备靠得很近时,读卡器的无线信号为标签或卡片中的电路提供足够的电力,使它们能够交换数据。主动系统则有供电的读卡器和供电的标签,能够从更远的距离准确读取标签。主动系统价格昂贵,通常用于更复杂的应用,因此我们将使用被动 RFID 系统:Mifare RFID-RC522 读卡器,该读卡器附带一张空白卡和一个钥匙扣,如图 23-2 所示。该读卡器工作在 13.56 MHz 的频率下,这意味着它只能在距离卡片或钥匙扣几英寸以内时识别它们,因为这些设备都是由读卡器提供电力的。定位读卡器时,记住这一点非常重要。

图 23-2:

配有卡片和钥匙扣的 RFID 读卡器

image

我们将创建一个 RFID 控制的舵机。当你将卡片放在 RFID 读卡器前时,它会读取卡片。如果模块识别到卡片并且卡片有访问权限,绿色 LED 灯会亮起,播放一段音调,舵机会旋转 180 度。如果模块未能识别卡片,红色 LED 灯会亮起,播放另一段音调,舵机不会转动。

表 23-1 描述了 RFID 读卡器的各种功能。

表 23-1:

RFID 读卡器引脚功能

RFID 详细信息 备注
3.3V 3.3 伏特 模块仅能使用此电压。
RST 重置 会将模块清除到初始状态。
GND 连接到 Arduino 的 GND 引脚。
IRQ 中断请求 在本项目中未使用。
MISO 主设备输入从设备输出 有时被称为“数据输入”。
MOSI 主设备输出从设备输入 有时被称为“数据输出”。
SCK 串行时钟 从主设备输出。这会产生一个脉冲,通常由主设备设置,用于同步数据。
SDA/SS 串行数据/从设备选择 模块将使用 SDA 或 SS,尽管它们是相同的。这是 Arduino 和模块之间共享数据并进行通信的方式。
引脚 16 VCC 正电源。

构建过程

  1. 你可能需要先通过焊接插头引脚来设置模块。取下一个八个插头引脚的条形物。将每个插头引脚焊接到每个焊点上。确保焊接时保持焊枪只停留几秒钟,以免损坏电路。有关焊接的入门指南,请参阅“快速焊接指南”,该指南位于第 18 页。

  2. 将你的 RFID 模块放入面包板中,如图 23-3 所示,然后将 RFID 引脚连接到下表所示的 Arduino 引脚。记得将 RFID 板连接到 Arduino 的 3.3V 电源(不是+5V),否则会损坏模块。

    图 23-3:

    将 RFID 模块放入面包板

    image

    RFID ARDUINO
    3.3V 3.3V
    RST 引脚 5
    GND GND
    IRQ 未使用
    MISO 引脚 12
    MOSI 引脚 11
    SCK 引脚 13
    SDA 引脚 10
  3. 现在我们需要检查 RFID 模块是否正常工作。从www.nostarch.com/arduinohandbook/下载 RFID 库,并将其保存到你的libraries目录(有关下载库的详细信息,请参见“库”,位于第 7 页)。上传以下 RFID 读卡器测试代码。确保将 PC 的 USB 线连接到 Arduino。

    // RFID Library Created by Miguel Balboa (circuitito.com)
    #include <SPI.h>
    #include <RFID.h>
    #define SS_PIN 10
    #define RST_PIN 9
    RFID rfid(SS_PIN, RST_PIN);
    
    // Setup variables
    int serNum0;
    int serNum1;
    int serNum2;
    int serNum3;
    int serNum4;
    
    void setup() {
      Serial.begin(9600);
      SPI.begin();
      rfid.init();
    }
    
    void loop() { // This loop looks for a card(s) to read
      if (rfid.isCard()) {
        if (rfid.readCardSerial()) {
          if (rfid.serNum[0] != serNum0
              && rfid.serNum[1] != serNum1
              && rfid.serNum[2] != serNum2
              && rfid.serNum[3] != serNum3
              && rfid.serNum[4] != serNum4
             ) {
            // When a card is found, the following code will run
            Serial.println(" ");
            Serial.println("Card found");
            serNum0 = rfid.serNum[0];
            serNum1 = rfid.serNum[1];
            serNum2 = rfid.serNum[2];
            serNum3 = rfid.serNum[3];
            serNum4 = rfid.serNum[4];
    
            // Print the card ID to the Serial Monitor of the IDE
            Serial.println("Cardnumber:");
            Serial.print("Dec: ");
            Serial.print(rfid.serNum[0], DEC);
            Serial.print(", ");
            Serial.print(rfid.serNum[1], DEC);
            Serial.print(", ");
            Serial.print(rfid.serNum[2], DEC);
            Serial.print(", ");
            Serial.print(rfid.serNum[3], DEC);
            Serial.print(", ");
            Serial.print(rfid.serNum[4], DEC);
            Serial.println(" ");
            Serial.print("Hex: ");
            Serial.print(rfid.serNum[0], HEX);
            Serial.print(", ");
            Serial.print(rfid.serNum[1], HEX);
            Serial.print(", ");
            Serial.print(rfid.serNum[2], HEX);
            Serial.print(", ");
            Serial.print(rfid.serNum[3], HEX);
            Serial.print(", ");
            Serial.print(rfid.serNum[4], HEX);
            Serial.println(" ");
    
          } else {
            // If the ID matches, write a dot to the Serial Monitor
            Serial.print(".");
          }
        }
      }
      rfid.halt();
    }
    
  4. 打开你的 Arduino IDE 中的串口监视器。

  5. 将你的卡片或钥匙扣放在 RFID 模块前面。唯一的编号应出现在串口监视器中,如图 23-4 所示。记下这个编号,因为你稍后会用到它。在这个例子中,我的卡号是 4D 55 AD D3 66。

    图 23-4:

    屏幕上以十六进制表示的 RFID 编号

    image

  6. 将两个 LED 插入面包板,较短的负极线连接到 GND 轨道。将红色 LED 的较长正极线通过 220 欧姆电阻连接到 Arduino 引脚 3。将绿色 LED 的正极引脚通过另一个 220 欧姆电阻连接到引脚 2。

    LEDS ARDUINO
    负极引脚 GND
    正极(红色) 引脚 3 通过 220 欧姆电阻
    正极引脚(绿色) 引脚 2 通过 220 欧姆电阻
  7. 通过将红线连接到+5V,棕色(或黑色)线连接到 GND,黄色线连接到 Arduino 引脚 9,来连接伺服电机到 Arduino。

    SERVO ARDUINO
    红线 +5V
    黑线 GND
    黄色电线 引脚 9
  8. 通过将红线连接到 Arduino 的引脚 8,将黑线连接到 GND,来连接蜂鸣器到 Arduino。你的电路现在应该像图 23-5 那样。

    PIEZO ARDUINO
    红线 引脚 8
    黑线 GND

    图 23-5:

    完成的 RFID 项目

    image

  9. 打开 Arduino IDE 中的项目代码,并修改以下一行,使其与第 5 步中使用 RFID 读取器找到的卡片或钥匙扣的十六进制号码匹配。保持0x不变,但将其余部分填入你的号码。

    byte card[5] = {0x4D,0x55,0xAD,0xD3,0x66};
    
  10. 确认你的设置与图 23-6 中的电路图匹配,然后将第 203 页中的“草图”代码上传到你的 Arduino。

    图 23-6:

    无线 ID 卡门禁系统的电路图

    图片

草图

草图首先调用 SPI、RFID、Servo、Pitches 和 Wire 库,以控制 Arduino、RFID 模块和舵机之间的通信。定义了两种旋律,一种是卡片读取正确时的旋律,另一种是读取错误时的旋律。绿色 LED 连接到 Arduino 的引脚 2,红色 LED 连接到引脚 3,压电蜂鸣器连接到引脚 8,舵机连接到引脚 9。

以下这一行是你添加卡片十六进制值的地方:

byte card[5] = {0x4D,0x55,0xAD,0xD3,0x66};

将卡片放在读卡器前。如果卡片上的十六进制代码与草图中的代码匹配,绿色 LED 灯会亮起,播放一段旋律,舵机会移动。读卡器会拒绝所有其他卡片,除非你将它们的号码添加到➊处的代码中。如果卡片被拒绝,红色 LED 灯亮起并播放另一段旋律,但舵机不会移动。

   #include <SPI.h>
   #include <RFID.h>
   #include <Servo.h>
   #include "pitches.h"
   #include <Wire.h>

   RFID rfid(10, 5); // Define the RFID

   // Replace this with the code from your card in hex form
➊ byte card[5] = {0x4D,0x55,0xAD,0xD3,0x66};
   // List any other codes for cards with access here

   byte serNum[5];
   byte data[5];

   // Define the melodies for successful access and denied access
   int access_melody[] = {NOTE_G4, 0, NOTE_A4, 0, NOTE_B4, 0, NOTE_A4,
   0, NOTE_B4, 0, NOTE_C5, 0};
   int access_noteDurations[] = {8, 8, 8, 8, 8, 4, 8, 8, 8, 8, 8, 4};
   int fail_melody[] = {NOTE_G2, 0, NOTE_F2, 0, NOTE_D2, 0};
   int fail_noteDurations[] = {8, 8, 8, 8, 8, 4};

   int LED_access = 2;   // Pin connected to green LED
   int LED_intruder = 3; // Pin connected to red LED
   int speaker_pin = 8;  // Pin connected to piezo buzzer
   int servoPin = 9;     // Pin connected to servo

   Servo doorLock; // Define the servomotor

   void setup() {
     doorLock.attach(servoPin); // Set servo as a pin
     Serial.begin(9600); // Start serial communication
     SPI.begin(); // Start serial communication between the RFID and PC
     rfid.init(); // Initialize the RFID
     Serial.println("Arduino card reader");
     delay(1000);
     pinMode(LED_access, OUTPUT);
     pinMode(LED_intruder, OUTPUT);
     pinMode(speaker_pin, OUTPUT);
     pinMode(servoPin, OUTPUT);
   }

   void loop() { // Create a variable for each user
     boolean card_card = true; // Define your card
     if (rfid.isCard()) {
       if (rfid.readCardSerial()) {
         delay(1000);
         data[0] = rfid.serNum[0];
         data[1] = rfid.serNum[1];
         data[2] = rfid.serNum[2];
         data[3] = rfid.serNum[3];
         data[4] = rfid.serNum[4];
       }
       Serial.print("Card found - code:");
       for (int i = 0; i < 5; i++) {
         // If it is not your card, the card is considered false
         if (data[i] != card[i]) card_card = false;
       }
       Serial.println();
       if (card_card) { // A card with access permission is found
         Serial.println("Hello!"); // Print to Serial Monitor
         for (int i = 0; i < 12; i++) { // Play welcome music
           int access_noteDuration = 1000 / access_noteDurations[i];
           tone(speaker_pin, access_melody[i], access_noteDuration);
           int access_pauseBetweenNotes = access_noteDuration * 1.30;
           delay(access_pauseBetweenNotes);
           noTone(speaker_pin);
         }
       }
       else { // If the card is not recognized
         // Print message to Serial Monitor
         Serial.println("Card not recognized! Contact administrator!");
         digitalWrite(LED_intruder, HIGH); // Turn on red LED
         for (int i = 0; i < 6; i++) { // Play intruder melody
           int fail_noteDuration = 1000 / fail_noteDurations[i];
           tone(speaker_pin, fail_melody[i], fail_noteDuration);
           int fail_pauseBetweenNotes = fail_noteDuration * 1.30;
           delay(fail_pauseBetweenNotes);
           noTone(speaker_pin);
         }
         delay(1000);
         digitalWrite(LED_intruder, LOW); // Turn off red LED
       }
    if (card_card) { // Add other users with access here
         Serial.println("Access granted.......Welcome!");
         digitalWrite(LED_access, HIGH); // Turn on green LED
         doorLock.write(180); // Turn servo 180 degrees
         delay(5000); // Wait for 5 seconds
         doorLock.write(0); // Turn servo back to 0 degrees
         digitalWrite(LED_access, LOW); // Turn off green LED
       }
       Serial.println();
       delay(500);
       rfid.halt();
     }
   }

第七部分

image

高级

项目 24:彩虹灯光秀

在这个项目中,我们将使用 8×8 RGB LED 矩阵创建彩虹灯光秀。我们还将使用移位寄存器扩展 Arduino 并控制矩阵。

imageimage

所需零件

• Arduino 板

• 2 块全尺寸面包板

• 跳线

• 8×8 RGB LED 矩阵

• 4 个 74HC595 移位寄存器

• 16 个 220 欧姆电阻

• 8 个 330 欧姆电阻

工作原理

一个 RGB LED 矩阵(图 24-1)是一个由 64 个红、绿、蓝 LED 组成的网格。你可以通过分别控制每个 LED 并将颜色混合在一起,创造出彩虹的颜色。

图 24-1:

一个 RGB LED 矩阵

image

该 LED 矩阵共有 32 个引脚(图 24-2);8 个引脚控制每个 LED 的公共阳极正极,另外 8 个引脚分别控制红、绿、蓝的亮度。在我们这里使用的矩阵中,17 到 20 和 29 到 32 为阳极引脚,9 到 16 控制红色,21 到 28 控制绿色,1 到 8 控制蓝色,但你的矩阵可能有不同的连接方式。引脚编号 1 将在图 24-2 的左下角标出——引脚编号按顺时针方向排列。

图 24-2:

RGB LED 矩阵的引脚

image

你的矩阵应该带有一份数据表,告诉你哪些引脚控制红、绿、蓝 LED。如果数据表中的引脚编号与表 24-1 中列出的不同,请按照数据表的说明连接移位寄存器和 Arduino。每个颜色的引脚都需要一个电阻,以防止过载和烧坏,但它们的电阻值略有不同——蓝色和绿色使用 220 欧姆电阻,红色使用 330 欧姆电阻。

表 24-1:

RGB LED 矩阵的引脚配置

矩阵引脚功能 矩阵引脚编号
公共阳极 (+) 17, 18, 19, 20, 29, 30, 31, 32
红 LED 9, 10, 11, 12, 13, 14, 15, 16
绿 LED 21, 22, 23, 24, 25, 26, 27, 28
蓝 LED 1, 2, 3, 4, 5, 6, 7, 8

布局看起来可能很复杂,但那只是因为我们使用了这么多不同的电线。只需记住,一步一步地完成项目。

由于连接非常多,我们将在 Arduino 板上用尽引脚,因此我们将使用移位寄存器扩展板。移位寄存器是一种数字存储电路,广泛应用于计算器、计算机和数据处理系统中。本项目使用 74HC595 移位寄存器,每次控制 8 个输出,只占用 Arduino 上的 3 个引脚。我们将多个寄存器连接在一起,以同时控制更多引脚,一个控制公共阳极,另外的每个控制 LED 的不同颜色。

移位寄存器的引脚布局见图 24-3,功能描述见表 24-2。在构建项目时,我们将参考移位寄存器的引脚编号和功能,帮助识别。

图 24-3:

移位寄存器引脚布局

image

表 24-2:

移位寄存器引脚

移位寄存器 连接 引脚功能
引脚 1–7, 15 Q0–Q7 输出引脚
引脚 8 GND 地,VSS
引脚 9 SO 串行输出
引脚 10 MR 主复位,低电平有效
引脚 11 SH_CP 移位寄存器时钟引脚(时钟引脚)
引脚 12 ST_CP 存储寄存器时钟引脚(锁存引脚)
引脚 13 OE 输出使能,低电平有效
引脚 14 DS 串行数据输入(数据引脚)
引脚 16 VCC 正电源

构建过程

  1. 将 8×8 RGB LED 矩阵插入两块全尺寸面包板。

  2. 插入一个 330 欧姆电阻到每个红色 LED 引脚,插入一个 220 欧姆电阻到每个绿色或蓝色 LED 引脚。

  3. 将第一个移位寄存器插入其中一块面包板,靠近 LED 矩阵的共阳引脚。按照图 24-4 所示,使寄存器跨越中央断裂处。将 LED 矩阵的共阳引脚连接到移位寄存器 1,如下所示。这些引脚不需要电阻。

    共阳引脚 移位寄存器 1 引脚
    LED 矩阵 移位寄存器
    --- ---
    32 15: Q0
    31 1: Q1
    30 2: Q2
    29 3: Q3
    20 4: Q4
    19 5: Q5
    18 6: Q6
    17 7: Q7

    图 24-4:

    移位寄存器应跨越面包板的断裂处。

    image

  4. 现在插入其余的三个移位寄存器到面包板中。移位寄存器 2 控制绿色 LED,移位寄存器 3 控制蓝色 LED,移位寄存器 4 控制红色 LED。按照以下表格连接每个移位寄存器的电线。所有颜色的 LED 引脚都需要电阻。

    绿色 LED 引脚 移位寄存器 2 引脚
    LED 矩阵 移位寄存器
    --- ---
    28 15: Q0
    27 1: Q1
    26 2: Q2
    25 3: Q3
    24 4: Q4
    23 5: Q5
    22 6: Q6
    21 7: Q7
    蓝色 LED 引脚 移位寄存器 3 引脚
    --- ---
    LED 矩阵 移位寄存器
    --- ---
    1 15: Q0
    2 1: Q1
    3 2: Q2
    4 3: Q3
    5 4: Q4
    6 5: Q5
    7 6:Q6
    8 7:Q7
    红色 LED 引脚 移位寄存器 4 引脚
    --- ---
    LED 矩阵 移位寄存器
    --- ---
    9 15:Q0
    10 1:Q1
    11 2:Q2
    12 3:Q3
    13 4:Q4
    14 5:Q5
    15 6:Q6
    16 7:Q7
  5. Arduino 通过三个 PWM 引脚控制 LED,每个引脚分别用于时钟、数据和锁存。每个引脚的连接如下。

    移位寄存器 Arduino 功能
    引脚 9(移位寄存器 2) 引脚 11 数据
    引脚 12(所有移位寄存器) 引脚 10 锁存
    引脚 11(所有移位寄存器) 引脚 13 时钟
  6. 检查你的设置是否与图 24-5 中的电路图一致,然后上传下面的代码“草图”。

    图 24-5:

    彩虹制造器的电路图

    image

草图

草图首先定义了控制移位寄存器的三个 Arduino 引脚。锁存引脚定义为 Arduino 引脚 10,时钟引脚为 13,数据引脚为 11。我们定义了一些变量,范围从 0 到 255,用来控制 LED 颜色的亮度。草图随后逐个打开每个 LED,并将三种颜色组合在一起,创建彩虹的颜色。例如,当绿色亮起、蓝色熄灭、红色亮起时,显示的是黄色。草图最终通过循环随机颜色结束。

/* Example 18.1 - experimenting with RGB LED matrix
   CC by-sa 3.0
   http://tronixstuff.wordpress.com/tutorials
*/

int latchpin = 10; // Connect to pin 12 on all shift registers
int clockpin = 13; // Connect to pin 11 on all shift registers
int datapin = 11;  // Connect to pin 14 on shift register 2
int zz = 500; // Delay variable
int va[] = {
  1, 2, 4, 8, 16, 32, 64, 128, 255
};
int va2[] = {
  1, 3, 7, 15, 31, 63, 127, 255
};

void setup() {
  pinMode(latchpin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(datapin, OUTPUT);
  digitalWrite(latchpin, LOW);
  shiftOut(datapin, clockpin, MSBFIRST, 0);
  shiftOut(datapin, clockpin, MSBFIRST, 0);
  shiftOut(datapin, clockpin, MSBFIRST, 0);
  shiftOut(datapin, clockpin, MSBFIRST, 0);
  digitalWrite(latchpin, HIGH);
  randomSeed(analogRead(0));
}

void allRed() { // Turn on all red LEDs
  digitalWrite(latchpin, LOW);
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Turn cathodes to full
  shiftOut(datapin, clockpin, MSBFIRST, 0); // Turn green to 0
  shiftOut(datapin, clockpin, MSBFIRST, 0); // Turn blue to 0
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Turn red to full
  digitalWrite(latchpin, HIGH);
}

void allBlue() { // Turn on all blue LEDs
  digitalWrite(latchpin, LOW);
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Turn cathodes to full
  shiftOut(datapin, clockpin, MSBFIRST, 0); // Turn green to 0
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Turn blue to full
  shiftOut(datapin, clockpin, MSBFIRST, 0); // Turn red to 0
  digitalWrite(latchpin, HIGH);
}

void allGreen() { // Turn on all green LEDs
  digitalWrite(latchpin, LOW);
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Cathodes
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Green
  shiftOut(datapin, clockpin, MSBFIRST, 0); // Blue
  shiftOut(datapin, clockpin, MSBFIRST, 0); // Red
  digitalWrite(latchpin, HIGH);
}

void allOn() { // Turn on all LEDs
  digitalWrite(latchpin, LOW);
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Cathodes
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Green
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Blue
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Red
  digitalWrite(latchpin, HIGH);
}

void allYellow() { // Turn on green and red LEDs (yellow)
  digitalWrite(latchpin, LOW);
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Cathodes
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Green
  shiftOut(datapin, clockpin, MSBFIRST, 0); // Blue
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Red
  digitalWrite(latchpin, HIGH);
}

void allAqua() { // Turn on green and blue LEDs (aqua)
  digitalWrite(latchpin, LOW);
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Cathodes
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Green
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Blue
  shiftOut(datapin, clockpin, MSBFIRST, 0); // Red
  digitalWrite(latchpin, HIGH);
}

void allPurple() { // Turn on blue and red LEDs (purple)
  digitalWrite(latchpin, LOW);
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Cathodes
  shiftOut(datapin, clockpin, MSBFIRST, 0); // Green
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Blue
  shiftOut(datapin, clockpin, MSBFIRST, 255); // Red
  digitalWrite(latchpin, HIGH);
}

void clearMatrix() { // Turn off all LEDs
  digitalWrite(latchpin, LOW);
  shiftOut(datapin, clockpin, MSBFIRST, 0); // Cathodes
  shiftOut(datapin, clockpin, MSBFIRST, 0); // Green
  shiftOut(datapin, clockpin, MSBFIRST, 0); // Blue
  shiftOut(datapin, clockpin, MSBFIRST, 0); // Red
  digitalWrite(latchpin, HIGH);
}

void lostinspace() { // Random flashes of the LEDs
  for (int z = 0; z < 100; z++) {
    digitalWrite(latchpin, LOW);
    shiftOut(datapin, clockpin, MSBFIRST, va[random(8)]); // Cathodes
    shiftOut(datapin, clockpin, MSBFIRST, va[random(8)]); // Green
    shiftOut(datapin, clockpin, MSBFIRST, va[random(8)]); // Blue
    shiftOut(datapin, clockpin, MSBFIRST, va[random(8)]); // Red
    digitalWrite(latchpin, HIGH);
    delay(100);
  }
}

void displayLEDs(int rr, int gg, int bb, int cc, int dd) {
// Insert the base-10 values into the shiftOut functions
// and hold the display for dd milliseconds
  digitalWrite(latchpin, LOW);
  shiftOut(datapin, clockpin, MSBFIRST, cc); // Cathodes
  shiftOut(datapin, clockpin, MSBFIRST, gg); // Green
  shiftOut(datapin, clockpin, MSBFIRST, bb); // Blue
  shiftOut(datapin, clockpin, MSBFIRST, rr); // Red
  digitalWrite(latchpin, HIGH);
  delay(dd);
}

void loop() { // Light up the whole display in solid colors
  allOn();
  delay(zz);

  delay(zz);
  allRed();
  delay(zz);

  delay(zz);
  allGreen();
  delay(zz);

  delay(zz);
  allBlue();
  delay(zz);

  delay(zz);
  allPurple();
  delay(zz);

  delay(zz);
  allYellow();
  delay(zz);

  delay(zz);
  allAqua();
  delay(1000);
  // Light some individual LEDs using random values
  lostinspace(); // Scroll some horizontal and vertical lines
  for (int z = 0; z < 5; z++) {
    for (int q = 1; q < 129; q *= 2) {
      displayLEDs(255, 0, 0, q, 200);
    }
  }
  clearMatrix();
  delay(1000);

  for (int z = 0; z < 5; z++) {
    for (int q = 1; q < 129; q *= 2) {
      displayLEDs(0, 255, 0, q, 200);
      displayLEDs(q, 0, 0, 255, 200);
    }
  }
  clearMatrix();
  delay(1000);

  for (int z = 0; z < 5; z++) {
    for (int q = 1; q < 9; q++) {
      displayLEDs(0, 0, 255, va2[q], 200);
    }
  }
  clearMatrix();
  delay(1000);
}

项目 25:构建你自己的 Arduino!

这个项目将教你如何使用最少的单独组件构建你自己的 Arduino。

imageimage

所需组件

• ATMEL ATmega328p 芯片

• 面包板

• 绿色 LED

• 红色 LED

• 3 个 220 欧姆电阻

• 16 MHz 晶振(HC-495)

• L7805cv 5V 稳压器

• 2 个 100 μF 电解电容

• PP3 9V 电池夹

• 瞬时触觉四脚按钮

• 2 个 22 pF 磁盘电容

• 跳线

• 9V 电池

这是一个有趣且廉价的小板,其功能与 Arduino 相同,因此可以作为永久项目的一部分,代替更贵的 Arduino 板。

工作原理

我们的项目板与 Arduino 板的工作方式完全相同。它的核心是 ATMEL ATmega328p 芯片(见图 25-1),我们将在其上连接其他组件。ATmega 芯片是 Arduino 的大脑,负责执行上传的草图中的指令。

图 25-1:

ATMEL ATmega328p 芯片

image

L7805cv 5V 稳压器调节电压,并将 9V 电池的电流限制为 5V,这是 ATmega 芯片的工作电压,从而保护芯片和其他组件。16 MHz 的晶体振荡器(参见图 25-2)使 Arduino 能够计算时间,电容器则作为滤波器平滑电压。

图 25-2:

16 MHz 的晶体振荡器

image

表 25-1 详细列出了 ATmega328p 芯片的引脚及其对应的 Arduino 引脚。例如,我们在“测试你的 Arduino:使 LED 闪烁”中使用的 Arduino 上的 13 号引脚,在实际芯片上对应的是 19 号引脚。芯片顶部可以通过小半圆形凹陷来识别(参见图 25-3)。引脚 1 位于这个凹陷下面,从这里开始引脚按逆时针方向编号 1 到 28。

表 25-1:

ATmega 芯片的引脚及其对应的 Arduino 引脚

ATMEGA 引脚 ARDUINO 功能 ATMEGA 引脚 ARDUINO 功能
1 复位 15 引脚 9
2 引脚 0 16 引脚 10
3 引脚 1 17 引脚 11
4 引脚 2 18 引脚 12
5 引脚 3 19 引脚 13
6 引脚 4 20 BCC
7 VCC 21 AREF
8 GND 22 GND
9 晶体 23 A0
10 晶体 24 A1
11 引脚 5 25 A2
12 引脚 6 26 A3
13 引脚 7 27 A4
14 引脚 8 28 A5

图 25-3:

芯片顶部标有半圆形的凹陷。

image

准备芯片

确保购买的 ATmega 芯片已安装 Arduino 引导加载程序,因为它还会预加载闪烁 LED 的草图,这是你这个项目所需要的。

我们自制的 Arduino 没有 USB 连接器,无法将芯片直接连接到电脑,因此,如果你想用这个 Arduino 面包板配合不同的草图(或者如果你的芯片没有预装引导加载程序),你需要使用现有的 Arduino 板作为主机,并按以下步骤将草图上传到 ATmega 芯片:

  1. 小心地从现有的 Arduino 板上取下 ATmega 芯片(参见图 25-4),并将其替换为你的 ATmega 芯片。

    图 25-4:

    从 Arduino 中取出 ATmega 芯片

    image

  2. 使用 USB 线将 Arduino 连接到你的电脑。

  3. 打开你电脑上的 Arduino IDE。

  4. 将草图上传到芯片。

  5. 一旦草图上传完成,断开 Arduino 与电脑的连接,小心地从电路板上取下这个芯片,并替换回原来的 Arduino ATmega 芯片。

新的 ATmega 芯片应该加载上所需的草图。通常你会希望将自己的 Arduino 构建成一个长期项目的一部分,因此不太需要频繁加载新的草图;你只需要在项目开始时加载一个草图,并从此一直使用这个草图。

现在你可以开始准备自己的电路板了。

构建 Arduino 电路

我通常在章节末尾展示电路图,但在这个实例中,先看电路图有助于参考布局并识别正在使用的组件(图 25-5)。

图 25-5:

完整电路图

image

  1. 将 ATmega 芯片插入面包板,使其引脚跨越面包板中心的间隔。你需要在两端留出一些空间以放置其他组件,因此大致按照图 25-6 所示放置。记住,ATmega328p 的第 1 引脚位于芯片上方小半圆形凹陷的正下方。从这里开始,引脚按逆时针方向编号为 1 到 28。用这个信息来正确定位芯片。半圆形应位于电路的左侧。

    图 25-6:

    放置 ATmega 芯片,使其跨越中心间隔

    image

  2. 将 ATmega 的第 7、20 和 21 引脚连接到面包板上最接近的正电源轨,将第 8 和 23 引脚连接到负电源轨。使用跳线将电路板两侧的正电源轨和 GND 电源轨连接,如图 25-7 所示。

    图 25-7:

    连接到电源轨

    image

  3. 将晶体振荡器的一只引脚连接到 ATmega 芯片的第 9 引脚,另一只引脚连接到第 10 引脚。将其中一个 22 pF 磁盘电容器的引脚连接到第 9 引脚和 GND,将另一个磁盘电容器的引脚连接到第 10 引脚和 GND,如图 25-8 所示。

    图 25-8:

    插入晶体振荡器和 22pF 磁盘电容器

    image

  4. 将复位按钮插入面包板,位置在 ATmega 芯片的左侧,使其引脚跨越面包板的中心间隔。使用跳线将复位按钮的右下引脚连接到 ATmega 的第 1 引脚,左下引脚连接到 GND,如图 25-9 所示。将一只 220 欧姆电阻连接到右下引脚,并将电阻的另一端连接到 GND 电源轨。这个按钮将作为我们的复位按钮。

    图 25-9:

    插入复位按钮

    image

  5. 将 L7805cv 5V 稳压器插入面包板的左上角,组件上的打印数字朝向你,按图 25-10 所示放置——引脚从左到右编号为 1 到 3。将一只 100 μF 电解电容器插入面包板的上方电源轨,一只引脚连接到正电源轨,另一只引脚连接到负电源轨。将第二只 100 μF 电解电容器连接到 5V 稳压器的第 1 和第 2 引脚。然后将稳压器的第 2 引脚连接到负电源轨,第 3 引脚连接到正电源轨。

    图 25-10:

    连接电解电容器和 L7805cv 5V 稳压器

    image

  6. 将红色 LED 插入面包板,将长的正极引脚通过一个 220 欧姆电阻连接到正电源轨,将短的负极引脚连接到 GND。然后插入绿色 LED,将短的引脚连接到 ATmega 的 21 号引脚,长的引脚通过一个 220 欧姆电阻连接到正电源轨,如图 25-11 所示。将电池的正电源接到 5V 调节器的 1 号引脚,GND 接到调节器的 2 号引脚。

    图 25-11:

    插入 LED 并连接电池

    image

你的电路板现在已经完成,应该像图 25-12 所示那样。红色 LED 在面包板的电源轨接通时亮起,表示 Arduino 已开机并在正常工作,而绿色 LED 则响应加载到 ATmega 芯片上的“闪烁 LED”示例程序而亮起。

图 25-12:

完成的电路

image

使用表 25-1 中的参考,你可以像使用 Arduino Uno 一样使用这个电路板,通过将组件连接到 ATmega 芯片的引脚,而不是 Arduino 的引脚。如果你想将本书中的某个项目做成永久性的,可以考虑自己构建一个 Arduino 来为其供电!记得首先通过真实的 Arduino 板将程序加载到 ATmega 芯片上。

附录 A:组件

本附录提供了关于本书中项目所用组件的更多信息。每个组件都附有一张照片和一些详细信息,供快速参考和识别,同时我还提供了一个方便的零售商列表,帮助你购买这些零件。你还将获得一个快速的电阻器值读取课程。

组件指南

这里是你将使用的组件指南,附带了一些你可能觉得有用的细节。这些组件按书中的顺序列出。许多物品可以通过在 eBay 或 Amazon 等网站上的简单搜索找到,但第 240 页也提供了专业零售商的列表。

Arduino Uno R3

Arduino Uno R3 是本书的主要组件,也是所有项目的大脑。

image • 数量:1 个• 连接:14 个• 项目:除项目 25 外的所有项目

9V 电池组

9V 电池组通过插头连接到 Arduino,为你的项目提供电力。你需要连接电池,并将插头插入 Arduino 的端口,详细信息请参阅第 3 页的“电源”。请注意,Arduino 也可以通过 USB 电缆供电。

image • 数量:1 个• 连接:1 个• 项目:所有项目可选

面包板

面包板是一种原型电路板,用于连接组件并创建你的项目。有关更多信息,请参阅第 4 页的“面包板”。

image • 数量:2 块全尺寸电路板,1 块半尺寸电路板,1 块迷你电路板 • 连接:全尺寸电路板 940 个连接,半尺寸电路板 420 个连接,迷你电路板 170 个连接 • 项目:除项目 7 外的所有项目

LED

当小电流通过 LED 时,它会发光。它看起来像一个小电灯泡,带有两条引脚。较长的引脚是正极连接。LED 通常需要一个电阻器,否则它们可能会烧坏。LED 是有极性的,这意味着电流只能在一个方向流动。

image • 数量:40 个(红色、蓝色、黄色、绿色各 10 个)• 连接:2 个• 项目:1–6,8,9,17,18,19,21,22,23,25

电阻器

电阻器限制电流通过电路的量,以防止组件过载。它们看起来像带有彩色带和两端导线的圆柱体。电阻值由颜色编码表示——有关更多细节,请参阅第 241 页的“解码电阻值”。请仔细检查,因为选择错误的电阻值很容易。电阻器有两种、四种和五种带标记的版本,因此要注意,例如,四带 220 欧姆电阻器与同值的五带电阻器外观可能略有不同。

image • 数量:30 220 欧姆,10 330 欧姆,1 10k 欧姆,1 1m 欧姆电阻 • 接口:2 • 项目:1–4, 6, 8, 9, 16, 17, 18, 19, 22, 23, 24, 25

按键

按键是一个简单的开关,按下时会使电路连接。这个开关在按下时连接电路,但松开时会弹回并切断连接。它也被称为瞬时开关。按键的大小各异,但大多数都有四个引脚。

image • 数量:4 • 接口:4 • 项目:2, 8, 15, 16, 17, 25

电位器

电位器是一种电阻器,你可以通过调节它的值来控制流经它的电压。它有一个可以旋转的旋钮和底部的三个引脚。中间的引脚是控制引脚,电源接在两侧(连接方向无所谓)。它常用于控制输出设备,如收音机的音量。

image • 数量:1 50k 欧姆电位器 • 接口:3 • 项目:2, 3, 4, 12, 13, 14, 15, 17

HL-69 土壤传感器

土壤传感器用于测量土壤的湿度。它有两个叉状触点和顶部的两个引脚。本书中使用的传感器是 HL-69 土壤湿度计。它配有一个驱动模块,你需要将它连接到 Arduino,而不是直接连接到传感器。

image • 数量:1 • 接口:2 • 项目:5

蜂鸣器

蜂鸣器是一种非常基础的扬声器。电流脉冲使其非常快速地发出点击声,一连串的脉冲则会发出音调。它通常看起来像一个带有两根线的小黑盒子。取出外壳后,它看起来像一个小金色圆盘。它非常便宜,常用于廉价玩具中生成噪音(例如警报器)。它还可以作为噪音传感器使用,如在项目 9 中所示。

image • 数量:1 • 接口:2 • 项目:5, 7, 8, 9, 15, 17, 18, 19, 21, 23

伺服电机

伺服电机是一种具有可以定位的臂的电机,你可以通过向伺服电机发送编码信号将其定位到特定角度。它是一个小盒子,带有三根线和一个输出轴,输出轴可以连接附件(称为喇叭)。红色线是电源或+5V,黑色/棕色线是地线或 GND,橙色/白色线是信号线,连接到 Arduino 的模拟引脚。本书中使用的 Tower Pro 9g 伺服电机可以旋转 180 度,但其他伺服电机是连续旋转的,可以转动完整的 360 度。

image • 数量:2 • 接口:3 • 项目:9, 10, 11, 18, 20, 22, 23

摇杆

一个摇杆记录模拟输入,之后可以读取该输入并转换为数字输出。它基本上是两个电位器提供两个轴的信号:左右和上下。它有很多应用,如游戏或控制伺服电机。

image • 数量:1 • 接口:5 • 项目:10

红外 LED 接收器

红外(IR)LED 接收器从例如遥控器接收红外信号。它是一个小型外壳中的 LED,具有三个引脚:OUT、GND 和 +5V(正电源)。它是极性组件,因此需要正确连接。请查阅接收器的数据手册,以防连接方式不同。

image • 数量:1 • 连接:3 • 项目:11

LCD 屏幕

LCD 屏幕是一种用于输出字符的显示屏。屏幕有各种尺寸。此处展示的是 HD44780(16 字符 × 2 行),具有 16 个连接。LCD 屏幕由两片偏振材料和其间的液晶溶液组成;电流通过液晶时会产生图像。

image • 数量:1 • 连接:16 • 项目:12, 13, 14, 15

DHT11 湿度传感器

DHT11 传感器用于测量湿度和温度。它是一个小型的蓝色或白色塑料盒子,带有四个引脚,虽然有时它被安装在只有三个引脚的模块板上。本书使用的是 DHT11 传感器,我们只使用其中的三个引脚:+5V、DATA 和 GND。

image • 数量:1 • 连接:4(但我们只使用 3 个) • 项目:13

倾斜球开关

倾斜球开关是一个内部含有金属球的外壳,当开关处于竖直位置时,金属球会接通电路。倾斜开关时,连接会断开。

image • 数量:1 • 连接:2 • 项目:14

RGB LED

RGB LED 模块是三种颜色合一——红色、绿色和蓝色。通过组合这些颜色,你可以创造任何彩虹色。它是一个透明的 LED,具有四个引脚,有时会安装在带有内置电阻的模块板上,如图所示。你需要使用电阻来限制电流,否则 LED 会烧坏。最长的引脚要么是共阴极,要么是共阳极。

image • 数量:1 • 连接:4 • 项目:15

七段 LED 显示器

七段 LED 显示器使用 LED 段显示数字或字符。它们通常用于显示计数器、时钟或定时器的数字。你可以购买单数字到八数字的显示器,而四位数显示器常用于数字时钟。

image • 数量:1 • 连接:10–12 • 项目:16, 17

四位数七段串行显示器

这是一个四位数的七段 LED 显示器,内置了额外的电路,因此可以通过很少的连接来控制。这个串行模块是 SparkFun 版本,有不同的颜色可供选择。它有 10 个连接,但在 Arduino 上只需要使用 3 个(VCC、GND 和 RX)。

image • 数量:1 • 连接:10(但我们只使用 3 个) • 项目:17

超声波传感器

超声波传感器发出一个信号(通常称为ping),该信号会反射到物体上并返回到传感器。通过计算信号返回的时间来确定距离。书中使用的超声波传感器是 HC-SR04 超声波传感器,它是一个带有两个圆形传感器和四个引脚的模块板。

image • 数量:1 • 连接:4 • 项目:18, 20

光敏电阻

光敏电阻,也称为光依赖电阻或二极管,根据照射在其上的光线强度产生可变的电阻值,并用于检测光线水平。它有不同的样式,但通常是一个小巧、透明的椭圆形,带有波浪状线条和两根引脚。在使用它进行编程之前,你需要对其进行校准,以确定光照强度。

image • 数量:1 • 连接:2 • 项目:19

RC V959 导弹发射器

WLToys RC V959 导弹发射器是为无线电控制直升机设计的,它是一个迷你加特林枪,能够快速连续发射六个塑料火箭。它有四根线,但我们只使用黄色和白色线来实现连续发射。

image • 数量:1 • 连接:4(但我们只使用 2 个) • 项目:20

PIR 传感器

PIR(被动红外)传感器可以检测其范围内的运动。书中使用的是 HC SR501,这是最常见的 PIR 传感器。模块的前面有一个高尔夫球型透镜,并有三个连接:+5V、OUTPUT 和 GND。橙色的立方体是可调电阻,用于改变距离范围和输出时序。

image • 数量:1 • 连接:3 • 项目:21

键盘

4×4 键盘基本上是一系列开关。这里示例的键盘有 16 个串联的按钮,也有 12 按钮版本。八个连接中,四个控制行,四个控制列。Arduino 将复制按下按钮的数字。

image • 数量:1 • 连接:8 • 项目:22

RFID 读卡器

RFID(射频识别)模块读取 RFID 卡和钥匙扣,根据卡的访问级别允许或拒绝操作。它是一个带有八个引脚和内置天线的小板。书中使用的模块是 Mifare RFID-RC522 模块,通常配有一张卡和钥匙扣。

image • 数量:1 • 连接:8 • 项目:23

RGB 矩阵

8×8 RGB 矩阵是由 64 个 LED 组成的阵列,能够通过红色、绿色和蓝色的变化创造出彩虹的颜色。矩阵上有 32 个引脚:8 个控制每个 LED 的公共阳极,8 个控制红色,8 个控制绿色,8 个控制蓝色。每个控制颜色的引脚都需要电阻。

image • 数量:1 • 连接:32 • 项目:24

移位寄存器

移位寄存器是一种小型集成电路和顺序逻辑计数器,它允许 Arduino 通过“移位”并存储数据来增加更多连接。它是一个小型黑色芯片,具有 16 根引脚。在一端,你会看到一个点或半圆—引脚 1 在这个标记的左侧。项目 16 中的电子骰子使用了 74HC595 移位寄存器。

image • 数量: 1• 连接数: 16• 项目: 16, 24

ATmega328p 芯片

ATMEL ATmega328p 芯片是 Arduino 的大脑;它执行上传的草图中的指令。它是一个小型黑色芯片,具有 32 根引脚。在一端,你会看到一个点或半圆—引脚 1 在这个标记的左侧。

image • 数量: 1• 连接数: 32• 项目: 25

16 MHz 晶体振荡器

16 MHz 晶体振荡器使 Arduino 能够计算时间。它是一个小型金属外壳,具有两根引脚,并且每根引脚上都需要一个电容器来帮助平滑电压。晶体的频率通常印刷在正面。

image • 数量: 1• 连接数: 2• 项目: 25

5V 稳压器

L7805cv 5V 稳压器将 7 至 11 伏的电压降至稳定的 5 伏。

image • 数量: 1• 连接数: 3• 项目: 25

电容器

电容器可以储存少量电能以备后用,并且可以用来平滑电压输出和流动。它们看起来像小型圆柱体,带有两根引脚,数值通常印刷在侧面。电容器有极性,需要正确插入。长引脚为正极,短引脚为负极;这通常在圆柱体上标明。市面上有多种类型;这里展示的是一种铝制的 100μF 电解电容。

image • 数量: 2• 连接数: 2• 项目: 25

片式电容

22pf 片式电容是另一种能够储存少量电能以备后用的电容器。它看起来像一个小圆盘,带有两根引脚,数值通常印刷在正面。市面上有多种类型;这里展示的是一种陶瓷版本。

image • 数量: 2• 连接数: 2• 项目: 25

电池夹

PP3 9V 电池夹是一个简单的 9V 电池连接器。它是一个小型黑色夹子,带有两根线:黑色为地线,红色为正极。

image • 数量: 1• 连接数: 2• 项目: 25

零售商列表

大多数电子元件可以在像 eBay 或 Amazon 这样的通用网站上找到,但如果你遇到找不到的元件,这里列出的零售商可能能够帮助你。

美国零售商

Adafruit www.adafruit.com/

DigiKey www.digikey.com/

Jameco Electronics www.jameco.com/

Little Bird Electronics www.littlebirdelectronics.com/

MCM www.mcmelectronics.com/

Newark element14 www.newark.com/

RadioShack www.radioshack.com/

RS Components www.rs-components.com/

Seeed Studio www.seeedstudio.com/depot/

SparkFun www.sparkfun.com/

欧洲零售商

Electronic Sweet Pea’s www.sweetpeas.se/

Element 14 www.element14.com/

Farnell www.farnell.com/

Jameco Electronics www.jameco.com/

英国零售商

4tronix www.4tronix.co.uk/store/

Cool Components www.coolcomponents.co.uk/

CPC cpc.farnell.com

Hobby Components www.hobbycomponents.com/

Mallinson Electrical www.mallinson-electrical.com/shop/

Maplin www.maplin.co.uk/

Oomlout oomlout.co.uk/

The Pi Hut thepihut.com/

Proto-pic proto-pic.co.uk/

Rapid Electronics www.rapidonline.com/

RS uk.rs-online.com/web/

Spiratronics spiratronics.com/

解码电阻值

在本书的大多数项目中,我们使用了电阻器,这是一种限制电流通过电路的电气元件(以欧姆为单位)。它们用于保护像 LED 这样的元件,防止过载和烧毁。电阻器的值通过其外壳上的彩色带标识。电阻器可以有四、五或六个彩色带。

确定电阻器的值非常重要,这样你就可以确保在项目中使用了正确的电阻器。让我们尝试确定图 A-1 中显示的四环电阻器的值。

图 A-1:

四环电阻

image

查看电阻器时,将带有银色或金色带的那一侧朝右,注意从左到右的颜色顺序。如果电阻器没有银色或金色带,请确保带有三个彩色带的一侧在左边。

使用表 A-1 来确定电阻器的值。

表 A-1:

计算电阻值

颜色 第一带 第二带 第三带 倍数 容差
0 0 0
1 1 1 10Ω +/-1%
2 2 2 100Ω +/-2%
3 3 3 1KΩ
4 4 4 10KΩ
绿 5 5 5 100KΩ +/-0.5%
6 6 6 1MΩ +/-0.25%
7 7 7 10MΩ +/-0.10%
8 8 8 +/-0.05%
9 9 9
0.1Ω +/-5%
0.01Ω +/-10%

注意

表示公差的带通常是银色或金色的,尽管它也可以是任何列有百分比的颜色。如果你的电阻器的公差带不是银色或金色的,那么在数值带和公差带之间应该有一个小间隙,以便你能区分它们。

对应于第一和第二条带的数值给出数字值,第三条带告诉你需要在该数字后添加多少个零,第四条带则告诉你公差—即实际值与目标值的差异范围。对于图 A-1 中的电阻器:

• 第一条带是棕色的(1)= 1。

• 第二条带是黑色的(0)= 0。

• 第三条带是红色的(2)= 00(2 是零的个数)。

• 第四条带是金色的,因此公差(精度)为+/- 5%。

所以这个电阻器是 1,000 欧姆或 1 千欧,公差为 5%,意味着实际值可能比 1 千欧大或小 5%。我们也可以对五条或六条带的电阻器进行相同的计算。

如果你不确定电阻器的数值,快速在线查找电阻器本体上的色带将帮助你;只需确保按正确的顺序列出颜色,从左到右读取,公差带在右侧。

附录 B: Arduino 引脚参考

不深入细节,本附录为您提供了 Arduino UNO 引脚的参考,它们的技术名称和功能。引脚的详细解释将在使用这些引脚的项目中给出,因此当您构建了一些项目后,这里的信息会更加清晰。

ARDUINO 引脚 功能和标签 附加功能
0 RX—用于接收 TTL 串行数据
1 TX—用于传输 TTL 串行数据
2 外部中断
3 外部中断 脉宽调制
4 XCK/TO—外部时钟输入/输出(定时器/计数器 0)
5 T1(定时器/计数器 1) 脉宽调制
6 AIN0—模拟比较器正输入 脉宽调制
7 AIN1—模拟比较器负输入
8 ICP1—输入捕获
9 OC1A—定时器寄存器 脉宽调制
10 SS—从设备选择(串行数据),用于 SPI 通信 脉宽调制
11 MOSI—主设备到从设备的数据输入,用于 SPI 通信 脉宽调制
12 MISO—主设备到从设备的数据输出,用于 SPI 通信
13 SCK—串行时钟(从主设备输出),用于 SPI 通信
AREF 模拟输入的参考电压
A0 模拟输入可以提供 1,024 个不同的值。
A1 模拟输入可以提供 1,024 个不同的值。
A2 模拟输入可以提供 1,024 个不同的值。
A3 模拟输入可以提供 1,024 个不同的值。
A4 模拟输入可以提供 1,024 个不同的值。 SDA(串行数据线)引脚支持使用 Wire 库进行 TWI(两线接口),适用于 I2C 组件。
A5 模拟输入可以提供 1,024 个不同的值。 SCL(串行时钟线)引脚支持使用 Wire 库进行 TWI(两线接口),适用于 I2C 组件。
RESET 可用于重置微控制器
3.3V 3.3 伏特输出,用于低电压组件。这是唯一的 3.3V 电源。数字和模拟引脚在 5V 下工作。
5V 标准+5V 输出
GND 地/负电源
Vin 9V 电源可以输入到这里,或者通过电源插孔访问。

串行: 0 (RX) 和 1 (TX) 这些引脚用于接收(RX)和传输(TX)晶体管-晶体管逻辑(TTL)串行数据。在项目 17 中,我们在火箭发射器中使用了 TX 引脚。

外部中断: 2 和 3 这些引脚可以配置为在低电平、上升沿下降沿(分别是信号从低到高或从高到低)或值变化时触发中断。中断是一种信号,告诉 Arduino 在引脚检测到外部事件时停止当前操作并执行其他功能,例如按下按钮。

PWM: 3, 5, 6, 9, 10 和 11 这些引脚可以通过analogWrite()函数用于脉宽调制。更多信息请参见项目 2。

SPI: 10(SS),11(MOSI),12(MISO),13(SCK) 这些引脚支持使用 SPI 库进行的 SPI 通信,并且在本书中多次使用。我们在 项目 16 中使用 SPI 通信来控制电子骰子,使得 Arduino 可以与用于控制七段 LED 的移位寄存器进行数据交换。

LED: 13 数字引脚 13 上连接了一个内建 LED。当引脚为 HIGH 时,LED 打开;当引脚为 LOW 时,LED 关闭。引脚 13 上的内建 LED 用于显示板载 ATmega328p 引导加载程序的运行状态,通常在 Arduino 启动时亮起。

AREF 这是模拟输入的参考电压;它与 analogReference() 一起使用。我们可以输入从 0 到 5V 的电压,因此,如果您的传感器需要低于 5V 的电压,可以使用此引脚来提高分辨率,从而获得更准确的读数。

模拟输入: A0–A5 Uno 有六个模拟输入,每个输入提供 1,024 个不同的值。

TWI: A4 和 A5 这些引脚支持使用 Wire 库进行的 TWI(双线接口) 通信。此功能用于控制和与 I2C 设备进行通信,例如使用仅两根线的串行 LCD 屏幕。

RESET 将此引脚设置为 LOW 可以重置微控制器。这通常用于添加一个复位按钮。

如果这些信息现在对您来说没有太大意义,不必担心。您可能会在未来的 Arduino 项目中发现它们很有用,您可以在完成书中的项目时随时参考它们。

Arduino 项目手册 使用 Helvetica Neue、Montserrat、True North 和 TheSansMono Condensed 字体。此书由位于伊利诺伊州东皮奥里亚的 Versa Printing 打印和装订。纸张为 60# Evergreen Skyland。

本书采用平装装订方式,页面使用冷凝、柔性胶水装订,书块的第一页和最后一页与封面相连。封面并未实际胶粘在书脊上,当书本打开时,页面平展,书脊不会破裂。

image

posted @ 2025-11-25 17:04  绝不原创的飞龙  阅读(32)  评论(0)    收藏  举报