今年早些时候,我看了一集《Tech Ingredients》节目,其中讲到激光云台如何自动追踪无人机并将其击落。我对它们的运动控制机制非常着迷,尤其是PI控制器(高频时钟Teensy微控制器)的使用,以及它们与定制硬件和机器视觉驱动的追踪器的集成。
不久之后,我开始研究底层电子元件以及如何基于它们的概念进行实验。最显而易见的驱动这些元件的微控制器是 Arduino,但一些建议建议购买套件而不是单个微控制器,而Elegoo Arduino Uno R3 入门套件似乎是最佳选择。
该套件包含 200 多个组件和一个详尽的指导教程,我已经完成了所有教程(除了最后一部分,需要使用额外的扩展板)。在本文中,我将带您回顾这段旅程中的亮点、沿途的惊喜发现以及对核心电子概念的探索。让我们开始吧!

发光二极管
你好,世界:点亮 LED
我一生中以不同的方式接触过电子技术,但令人惊讶的是,我还没有做过类似 Hello World 的练习,也就是点亮一个 LED。这个简单的练习本身就非常有趣,引出了一系列问题:
- 问:为什么需要电阻?答:高电流和高温会损坏电阻精密的异质结结构,最终导致电阻烧坏
- 问:如果极性接反了会怎么样?答:与普通二极管类似,电流不会流动,LED也不会亮。只要反向功率不高,LED就不会烧坏,之后只要极性正确,仍然可以使用。
- 问:如何解读它的数据表?答:它的数据表有几个有趣的方面,比如LED的波长曲线、工作电流和电压等等。

RGB LED [代码]
RGB LED 内部封装了红色、绿色和蓝色 LED,可以独立控制,从而可以使用 Arduino 的三个脉冲宽度调制 (PWM)输出实现广泛范围的色彩呈现。
PWM 是一种通过改变数字信号中脉冲的宽度来控制输送到电气设备的平均功率的技术,当该技术在 LED 等视觉输出中完成得足够快时,人眼就会感觉到平滑连续的振幅,而不是一连串的单个脉冲。
逐步改变 RGB LED 的颜色
通过 74HC595 控制 8 个 LED [ 代码]
我们可以连接一个 74HC595 IC 来扩展 Arduino 可能的输出数量,但代价是一些延迟。
将每个输入的所需值写入 74HC595 时,这些值只有在其锁存器激活后才会被外部化。一旦锁存器被触发,所有存储的输入将一次性外部化。这与视频中的双缓冲非常相似。无闪烁体验。
我们本质上控制的是一块非常有限的外部存储器。
通过 74HC595 控制 8 个 LED
使用电容器使 LED 亮度平滑衰减
电容器本质上是一种能量储存器(即电池),其充放电时间是恒定的。通过将一个电容器(或两个,如本视频中所示,使其电容相加)与LED并联,当电路通电时,LED会立即亮起,电容器也会同时充电。一旦主电源断开,电容器就会开始平稳地向LED放电,从而使LED的亮度平稳衰减。
使用电容器实现平滑的 LED 强度变化
展示
单段显示:数字倒计时 [ 代码]
我们可以在段级别控制这个单元七段显示器,在这个例子中,我们依次写入一组我们感知为数字的段集。
数字倒计时
单段显示:自定义模式 [ 代码]
我们还可以创建任意图案,按照我们想要的顺序和时间。以下是一些自定义图案的三个示例。
旋转模式
八字形图案
交替模式
四段显示:所有字符相同 [ 代码]
扩展上述内容,如果我们在四单元段显示器上写入与上述相同的模式,我们会看到这些模式在所有单元上复制。
所有人都是同一个角色
四段显示:不同字符 [ 代码]
为了让每个单元都呈现出它们特定的段模式,我们需要写入模式,然后选择应该写入该模式的单元,等待一小段时间,然后移动到下一个单元,在那里我们将做完全相同的事情,只是这次选择应该写入该模式的单元。
独特的人物
LED 矩阵:滚动 [ 代码]
此 LED 矩阵接受显式位图,其中每个像素要么启用,要么禁用。为了实现滚动效果,我们根据通过电位器接收到的值设置偏移量。
滚动位图
LCD 显示屏:显示一长串 [代码]
滚动效果是通过利用LiquidCrystal库中的功能实现的。这里我们使用了一串普通字符,但也可以使用自定义字符。
滚动浏览长字符串
声音
蜂鸣器
指南中写道:“我们应该注意不要使用 UNO R3 板的 analogWrite() 函数来生成有源蜂鸣器的脉冲,因为 analogWrite() 的脉冲输出是固定的(500Hz)。”我使用了analogWrite()
,结果如下:
改变蜂鸣器的音调
使蜂鸣器发出像 8 位引擎一样的声音 [代码]
通过调整蜂鸣器离散触发的频率,我们可以实现类似于上面用于控制 LED 强度的 PWM 的感知效果,只是这次指的是某种音调,在这种情况下,它与旧电脑/控制台游戏的音量非常相似。
使用蜂鸣器的“8位”引擎声音
感知声音 [代码]
我在对这个集成进行语音摆弄时烧毁了板载 LED(13),因为其中一根杜邦线在执行此操作时接触到了电路板的错误位置。
红色 LED 代表音频峰值,黄色 LED 代表音频低谷。
检测手指弹响和声音
空间传感器
倾斜球开关 [代码]
该组件由一个导电性极佳的球体构成,该球体可在组件的圆柱形内部自由移动。圆柱体的一面导电,另一面不导电。
倾斜组件以引起其状态变化
超声波传感器测量距离 [ 代码]
我想知道为什么需要外部模块来计算距离,所以我从头实现了一个算法,该算法考虑了声速和超声波脉冲被传感器接收所需的时间。我用真实的尺子验证了测量结果,结果确实很准确!无需任何外部代码模块。
使用从头构建的自定义算法进行距离测量
被动红外传感器(PIR)运动传感器[代码]
这是一种常用于检测人体等发热物体的运动的传感器,并触发副作用,例如门厅灯。其输出为简单的二进制高电平或低电平。
通过 PIR 传感器检测运动
MPU-6050:加速度计和陀螺仪绘图 [代码]
使用 Arduino 的串行绘图仪工具来可视化捆绑加速度计、陀螺仪和温度传感器的 MPU-6050 模块的输入。
加速度计和陀螺仪绘图
MPU-6050:中断信号[代码]
我查看了陀螺仪模块的数据表,发现只要检测到运动达到一定阈值,模块就可以发出中断信号。这对于低功耗系统非常有用,因为中断信号会指示相关的运动数据正在启动,主控制器应该处于完全活动状态。
本次实验的目的是让蓝色LED在陀螺仪受到干扰时闪烁,但这导致输出几乎无法预测,其根本原因很可能在于设置模块所需的命令组合不正确。这方面还需要进一步探索。
尝试在运动开始时获取中断信号
环境传感器
通过光敏电阻测量光强度 [代码]
光敏电阻是一种光敏电阻,当光线照射到其表面时,其电阻会减小,如果我们将电线连接到光敏电阻和另一个固定值电阻之间的 Arduino 模拟输入之一,我们就能检测到由光敏电阻的可变电阻引起的电压。
LCD 显示屏上显示光强度
温度测量[代码]
使用与上述完全相同的设置(除了脚本的轻微调整),通过用热敏电阻(另一个可变电阻,只是这次根据温度改变其电阻)替换光敏电阻,我们能够测量环境温度,我利用手的温度并通过向热敏电阻中吹气来冷却它来操纵它。
LCD 显示屏上显示温度
水位传感器 [代码]
我紧张地将水位传感器插入电脑旁边的茶杯中。
水位传感器随着进一步浸入水中而发生变化
执行器
BJT晶体管驱动直流电机:通过开/关按钮控制[ 代码]
Arduino 的设计初衷是驱动低输出电流的逻辑电路,因此当我们想要控制高功率电路时,我们希望 Arduino 微控制器控制的是“阀门”,而不是“管道”本身。这非常适合晶体管(或继电器,我们将在下文中介绍)的应用,晶体管就像一个“阀门”,要么让电流自由通过,要么完全阻断电流。
该套件包含两种型号的 NPN 双极结型晶体管 (BJT):PN2222 和 S8050。两者经常互换使用(如本视频所示),但 PN2222 的集电极-发射极电压额定值更高(60V vs 25V),但这在本例中无关紧要,因为我们没有超过 5V 的门槛。在这些晶体管中,基极相当于“阀门”,集电极和发射极相当于“管道”。
请注意,我没有使用反激二极管来保护电路免受直流电机关闭时产生的反电动势电压尖峰的影响,这在进行多次测试时并非明智之举。我当时并没有意识到这种影响,幸运的是,没有造成任何损害。
通过开/关按钮控制直流电机
BJT晶体管驱动LED和直流电机:通过电位器控制[ 代码]
与上述设置相同,只是这次我们驱动的是 LED 而不是直流电机。
通过电位器控制的 LED
通过电位器控制的直流电机
L293D使用电池供电驱动直流电机 [代码]
L293D 是一款精巧的 IC,其内部包含了驱动电感负载(如继电器、螺线管、直流和双极步进电机)所需的所有功能,以及双向驱动和过流和反冲保护(因此不需要反激二极管)。
请注意,当尝试以低功率驱动直流电机时,它很难开始旋转,但一旦增加功率或轻轻推动,它就会迅速开始自由旋转。
L293D利用电池供电驱动直流电机
L293D + 继电器驱动直流电机 [代码]
与晶体管相比,继电器更大,开关速度更慢,但可以处理更高的电流和电压,并提供良好的电气隔离。
有趣的是,在老款车型中,打开转向灯时听到的“滴答滴答”声实际上是继电器闭合和断开电路,点亮转向灯的声音。这些继电器与这里使用的继电器非常相似,在视频中也能听到类似的噪音,这是继电器闭合和断开驱动直流电机的电路时发出的。
L293D + 继电器驱动直流电机
用于延迟触发的电阻器和电容器 (RC) 电路
在设置电阻电容 (RC) 电路时,我们可以利用其可预测的充电曲线来延迟晶体管的激活,从而激活另一组元件。根据晶体管是 BJT(电流控制型)还是 MOSFET(电压控制型),它们会具有不同的电流或电压阈值,允许电流在集电极和发射极(BJT)之间或漏极和源极(MOSFET)之间流动。
在这种情况下,双极结型晶体管 (BJT) 的基极连接到 RC 电路,当其激活时,LED 和/或直流电机会被激活。请注意,直流电机要么没有足够的功率启动,要么在 RC 电路上放置较小电阻后几乎没有延迟。我认为这是由于电容容量较小的电容器以及 RC 电路上没有使用理想电阻造成的,但这需要进一步探索并更深入地理解这个问题。
通过 RC 电路 + BJT 晶体管延迟 LED 照明
通过 RC 电路 + 单 BJT 晶体管延迟 LED 照明和直流电机
通过 RC 电路 + 两个 BJT 晶体管延迟 LED 照明和直流电机
通过电位器控制的伺服电机[ 代码]
伺服电机用于需要精确控制运动的应用,这些应用需要精确控制电机的位置、速度和扭矩。本例中使用按钮在伺服电机位置与电位器定义的同步位置状态和伺服电机默认位置状态之间切换。
还要注意在操作分离的电位器输入线时产生的轻微电压噪声,以及它对试图与这些接收值同步的伺服器的影响。
通过电位器控制的伺服电机
步进电机:自动控制[ 代码]
步进电机是一种巧妙的工程设计,无需外部反馈即可实现精确运动。
在此设置中,电机完全由自动脚本控制,并且由于 9V 电池开始耗尽,因此通过电源适配器供电。
步进电机:自动控制
步进电机:旋转编码器控制,使用 ELEGOO 脚本 [ 代码]
在上述基础上,我们添加了一个旋转编码器,用于发送精确的步进电机移动指令。这种旋转编码器与鼠标滚轮、汽车收音机旋钮和洗衣机等电器中的编码器相同。
请注意,运动相当不稳定,无论我们如何移动旋转编码器,实际上都只能计算最近的运动。
步进电机:旋转编码器控制,使用 ELEGOO 脚本
步进电机:旋转编码器控制,精度更高 [ 代码]
为了解决上述问题,该脚本考虑了旋转编码器的所有运动,以确定步进电机每个周期自我校正的目标旋转角度。
请注意,在视频开头,当旋转编码器被操作时,两个LED会亮起,这样我们就能看到脚本捕获的信号。这些信号由可预测的格雷码序列组成,使我们能够高精度地感知编码器是向右旋转还是向左旋转。
一旦两个演示 LED 断开连接,我们就会通过 Arduino 输入收到信号,我们会利用上述概念进行解释,此外,我们还确保不仅为其中一个输入触发设备中断(如上面的脚本所示),而且为两个输入触发设备中断,以便我们可以捕捉所有动作。
步进电机:旋转编码器控制,精度更高
步进电机:红外遥控 [ 代码]
结合上面的红外传感器和遥控器,我们还可以使用此遥控机制来控制该步进电机。
步进电机:红外遥控
通信接口
Arduino 键盘的工作原理,无需额外的库
您可以作为 Arduino 输入提供的外围设备之一是 16 按钮键盘,它为微控制器项目提供了有用的人机界面组件。
该键盘模块包含在Elegoo UNO R3 入门套件中,还附带相应的教程和库,有助于方便其使用。
在本视频中,我们将从头编写一个使用该键盘模块的实现,而不使用额外的库,并且我们将介绍相应的概念和电路,包括上拉电阻的工作原理(可通过 INPUT_PULLUP 访问)
Arduino 键盘的工作原理
支持代码:
请注意,代码中有相当多的重复,但这明确地展示了整个机制是如何工作的,而没有通过抽象来遮挡
红外信号复制 [ 代码]
在探索常见的红外通信协议在日常电器中的使用方式时,我想知道是否可以通过红色 LED 源插入自定义光脉冲,该脉冲可以被红外接收器解释为有效信号,并以 25ms 的间隔开始脉冲,以符合红外接收器上的 38khz 信号调制预期(1 秒/38000 Hz ~= 25ms)。
事实证明,这对于普通的红色 LED 来说永远行不通,因为它的波长位于 640nm 峰值附近,而我们需要 900nm 到 1000nm 的波长才能让红外接收器接收该信号。

本次尝试中,我比较了红色LED的连续脉冲和标准红外遥控器产生的脉冲。一个有趣的后续尝试是尝试相同的设置,但使用红外LED发射器。
红外信号复制尝试
RFID 读卡器 [代码]
该视频展示了套件中包含的两张卡中的 MIFARE 内容转储,但该设置能够从其他来源(如信用卡或电子护照)读取最少的信息。
请注意,当连接到 Arduino 的 VIn 输出而不是 Arduino 的 3.3v 电源输出时,此模块参考电压效果最佳。
套件中包含的两张卡中读取的信息内容转储
操纵杆 [代码]
该操纵杆模块本质上与多个游戏控制器中使用的相同,并且使用 Arduino 其使用相当简单。
操纵杆模块演示
通信和存储
通过TX输出传输串行信息[代码]
这对很多人来说可能很明显,但只有在不同的 Arduino 脚本上使用Serial.print()
作为调试机制之后,我才意识到这个命令实际上不仅通过 USB(计算机)向主机发送结构化信息,而且还通过 Arduino 的 TX 输出发送结构化信息。
这个视频/脚本非常简单:它们使用非常低的波特率将很长的字符串和单个字节写入串行接口,以便连接到 TX 输出的右侧黄色 LED 上可以粗略地看到它们的各个位。在我们开始向串行接口发送命令之前,左侧绿色 LED 保持亮起状态,写入阶段完成后将禁用。
请注意,即使所有写入操作都已提交,仍有比特流经 TX 输出。这种情况会一直持续,直到 Arduino 的内部串行通信缓冲区完全刷新。
写入阶段,左侧 LED 保持亮起。黄色 LED 表示 TX 通信流中的单个位
写入单个位并通过 RX 输入反馈 [ 代码]
基于上述内容,如果我们通过仔细计时正常引脚输出的低电平和高电平来写入各个位,以符合UART 标准,从而形成 8 位数据包,然后通过电线将它们馈送到 Arduino 的 Rx 引脚,读取生成的串行通信接收缓冲区,最后将这些内容写入串行端口,我们就能看到这些内容记录到串行监视器中。
这是摆弄 Arduino 时最有趣的事情之一。
写入单个位并通过 RX 输入反馈
从主机发送信息到 Arduino [代码]
使用串行监视器,我们可以轻松地通过串行通信向 Arduino 发送信息包。在此脚本中,Arduino 从串行通信缓冲区读取数据,如果接收到的相应信息为 0 或 1,则启用或禁用 LED。
从主机向Arduino发送信息
使用内部 EEPROM 保存信息 [代码]
基于上述设置,我们集成了ATmega 的 EEPROM来保存信息。这意味着即使在断电后,信息仍然可用,如下面的视频所示。
使用内部 EEPROM 保存信息
从主机发送信息到 Arduino + 74CH95 来驱动 LED [ 代码]
我们可以连接一个 74HC595 IC 来扩展 Arduino 的输出数量,操作与上述相同,但是为了增加输出数量。该设置支持 7 种不同的 LED,但视频中只展示了 3 种,并且对于这个特定示例来说,使用 74CH95 IC 除了演示其用法之外,并没有什么实际好处。
使用 3 个 LED 和 74HC595 的串行读取副作用
时间
实时时钟(RTC)模块方波输出 [ 代码]
我对 RTC 模块的方波输出很好奇,并在 YouTube 上找到了一个视频,介绍如何向模块发送命令,强制方波引脚 (SQW) 输出 1Hz 方波,这意味着该波的周期每秒重复一次。
在视频中,该信号首先连接到 LED,使其每秒闪烁一次,然后输出指向 Arduino 的引脚 8,从而在串行输出上显示此循环的结果。
方波输出首先在 LED 上可见,然后在串行输出日志上可见
一体化
整合:计时器 [代码]
时间项目是 Elegoo 提供的教程中最精彩的作品,但有些组件不能直接工作,即中断库,因此我调整了提供的示例以使用内置的 Arduino 中断库,并更改了一些连接,从而使上述所有课程达到了完美的高潮。
定时器集成