Arduino开发环境搭建与LED控制实战:从零开始硬件编程
1. 项目概述与核心价值
如果你对硬件编程感兴趣,想亲手点亮一个LED,或者让一个小马达转起来,但又觉得那些复杂的电路图和底层寄存器操作让人望而却步,那么Arduino就是你最好的朋友。我接触嵌入式开发有十几年了,从早期的51单片机到现在的各种ARM Cortex-M系列,一路走来,发现Arduino这个平台最大的魅力就在于它把“让硬件动起来”这件事变得像搭积木一样直观。它用一套简洁的C/C++风格API,把底层硬件的复杂性封装起来,让你可以专注于逻辑和创意本身。今天,我们就以Adafruit Metro这块板子为例,从零开始,手把手带你完成开发环境的搭建,并实现第一个经典的“Hello World”——让LED闪烁起来。这个过程不仅是学习Arduino的起点,更是理解“程序如何控制物理世界”这一核心概念的绝佳窗口。无论你是电子爱好者、学生,还是软件工程师想拓展硬件技能,这篇指南都将为你铺平道路。
2. 开发环境搭建:跨平台实战详解
环境搭建是第一步,也是最容易让人打退堂鼓的一步,尤其是面对不同操作系统时。别担心,我会把在macOS和Linux上踩过的坑和验证过的最佳路径都告诉你。Windows用户也别急,思路是相通的,只是图形界面操作略有不同。
2.1 macOS环境部署:从下载到驱动验证
在Mac上搞开发,整体体验比较顺畅,但串口驱动是个需要特别注意的环节。
Arduino IDE安装与准备首先,访问Arduino官网下载适用于macOS的集成开发环境(IDE)。我建议直接下载“macOS 64 bits”的版本,它是一个.zip压缩包。下载完成后,直接双击解压,你会看到一个名为“Arduino.app”的应用程序。这里有个小技巧:不要直接从解压的文件夹里运行它,而是把它拖拽到你的“应用程序”(Applications)文件夹中。这样做有两个好处:一是符合Mac的应用管理习惯,二是在后续通过终端命令行调用arduino命令时,系统能正确找到它。
串口识别与驱动安装核心Arduino板子(包括Adafruit Metro)通过USB与电脑通信,这个通信通道在系统中被虚拟成一个串行端口(Serial Port)。要让电脑识别这个端口,就需要对应的驱动程序。Adafruit Metro Classic(基于ATmega328P芯片)通常使用FTDI或CP210x系列的USB转串口芯片,因此我们需要安装这两种驱动。
查找串口:连接你的Metro板到电脑USB口。打开“应用程序” -> “实用工具” -> “终端”。在终端中输入命令
ls /dev/cu.*。如果驱动已正确安装且板子被识别,你应该会看到类似/dev/cu.usbmodem14101或/dev/cu.wchusbserial1410的设备文件。这个文件名就是你的板子对应的串口。驱动安装:
- FTDI VCP驱动:前往FTDI官网下载最新的VCP(虚拟串口)驱动。选择与你的macOS版本(如macOS 14.x, ARM64)匹配的安装包。下载后是一个.dmg文件,打开并运行其中的安装程序即可。
- SiLabs CP210x驱动:前往Silicon Labs官网下载CP210x USB to UART Bridge的驱动。同样,选择对应你系统版本的安装包进行安装。
注意:在macOS Catalina (10.15) 及更高版本上,系统安全性设置可能会阻止来自“未经认证的开发者”的驱动安装。如果遇到提示,你需要进入“系统偏好设置” -> “安全性与隐私”,在“通用”标签页中点击“仍要允许”来授权安装。
驱动验证与端口选择安装完驱动后,最好重启一下电脑,以确保驱动完全加载。然后再次连接Metro板,打开Arduino IDE。在IDE的顶部菜单栏,依次点击“工具” -> “端口”。你应该能看到一个以/dev/cu.usbserial-或/dev/cu.wchusbserial-开头的选项,这就是你的Metro板。选中它。
如果在这里看不到任何端口,或者端口是灰色的,请按以下步骤排查:
- 检查USB线:确保你使用的是一根数据线,而不是只能充电的电源线。这是新手最常遇到的问题。
- 尝试不同的USB端口:有时前置USB口供电或识别不稳定,换到主板后置的USB口试试。
- 重新安装驱动:确保下载的驱动版本与你的操作系统完全匹配(特别是Apple Silicon Mac要选ARM64版本)。
- 查看系统信息:点击屏幕左上角苹果菜单 -> “关于本机” -> “系统报告” -> 左侧选择“硬件”下的“USB”。在这里你应该能看到“Adafruit Metro 328”或类似描述的设备。如果能看到设备但IDE里没有端口,通常是驱动问题。
2.2 Linux环境部署:终端操作与权限配置
Linux环境下安装Arduino IDE相对更“原生”,大部分工作通过终端完成,而且通常不需要额外安装驱动,因为内核已经集成了支持。
安装Arduino IDE在Linux上,我推荐直接使用官方提供的.tar.xz压缩包进行安装,这样能获得最新版本,也便于管理。前往Arduino官网下载对应你系统架构的包(64位选linux64,树莓派等ARM设备选ARM)。假设你下载到了~/Downloads目录。 打开终端,执行以下命令:
cd ~/Downloads tar -xvf arduino-*.tar.xz sudo mv arduino-* /opt/arduino-ide cd /opt/arduino-ide sudo ./install.shinstall.sh脚本会创建桌面快捷方式和菜单项。之后,你可以在应用菜单中找到Arduino IDE,或者直接在终端输入arduino-ide启动(如果PATH设置正确)。
串口权限配置(关键步骤)在Linux上,最大的坑不是驱动,而是用户权限。默认情况下,普通用户无法直接访问串口设备(如/dev/ttyUSB0或/dev/ttyACM0),这会导致IDE中端口列表为空或上传时提示权限错误。
连接你的Metro板,在终端输入ls /dev/ttyUSB*或ls /dev/ttyACM*来查看设备名。通常会是/dev/ttyUSB0。
为了解决权限问题,最一劳永逸的方法是将你的用户添加到dialout组(该组传统上用于拥有串口访问权限的用户):
sudo usermod -a -G dialout $USER执行此命令后,你必须注销当前用户并重新登录,或者重启电脑,这个组变更才会生效。
验证与冲突排查登录后,重新连接板子,在终端输入ls -l /dev/ttyUSB0。如果输出中显示组为dialout,并且你的用户名在所属组列表中,就说明配置成功了。
还有一个历史遗留问题需要留意:一些旧的Linux发行版可能会安装一个名为brltty的盲文设备支持包,它会占用串口导致冲突。检查并移除它:
# 对于Debian/Ubuntu系 sudo apt-get remove brltty # 对于其他发行版,使用对应的包管理器,如yum, dnf, pacman等移除后,重新插拔USB设备即可。
2.3 针对Adafruit Metro Express的特别配置
如果你使用的是Adafruit MetroExpress(基于ATSAMD21芯片),那么除了上述基础步骤,还需要在Arduino IDE中添加额外的板卡支持包,因为它的核心芯片不是传统的AVR。
- 打开Arduino IDE,进入“文件” -> “首选项”(Windows/Linux)或“Arduino IDE” -> “首选项”(macOS)。
- 在“附加开发板管理器网址”的输入框中,填入以下URL:
https://adafruit.github.io/arduino-board-index/package_adafruit_index.json如果你还需要其他板卡支持(如ESP8266),可以用英文逗号分隔多个URL。 - 点击“好”保存。
- 然后,进入“工具” -> “开发板” -> “开发板管理器”。等待索引更新。
- 在搜索框中输入“Arduino SAMD Boards”,找到由Arduino官方提供的包,点击安装。这是SAMD系列芯片的基础支持。
- 接着,搜索“Adafruit SAMD Boards”,找到由Adafruit提供的包并安装。这个包包含了Metro M0 Express等Adafruit特定板子的定义。
- 安装完成后,关闭并重新打开Arduino IDE。现在,你可以在“工具” -> “开发板”列表中选中“Adafruit Metro M0 Express”了。
3. 第一个项目:LED闪烁(Blink)深度解析
环境搭好了,现在让我们来点实际的——让一个LED闪烁。这不仅是Arduino的入门仪式,更是理解数字输出(Digital Output)概念的基石。
3.1 电路搭建:不只是连接,更是理解
你需要准备以下元件:
- Adafruit Metro 或 Metro Express 开发板 x1
- 面包板 x1
- 5mm 或 10mm LED(蓝色或其他颜色)x1
- 560Ω 电阻 x1(色环:绿-蓝-棕,也可以用470Ω或1kΩ的,亮度略有不同)
- 公对公杜邦线若干
电路连接原理与步骤:
- LED方向性:LED是二极管,电流只能单向通过。长脚是阳极(正极,Anode),短脚是阴极(负极,Cathode)。接反了不会亮,但通常也不会烧坏。
- 限流电阻的必要性:Metro的I/O引脚输出电压是5V(或3.3V,取决于板型和设置),而一个典型的LED工作电压约为2-3V,工作电流在20mA左右。如果不加电阻直接连接,过大的电流会瞬间损坏LED。电阻的作用就是“限流”。根据欧姆定律
R = (Vcc - Vled) / I,其中Vcc是引脚电压(5V),Vled是LED正向压降(约2V),I是我们想要限制的电流(例如20mA,即0.02A)。计算可得R = (5-2)/0.02 = 150Ω。我们使用560Ω是一个更保守、更安全的值,计算电流约为(5-2)/560 ≈ 5.4mA,LED能稳定点亮且寿命更长。 - 实际连接:
- 将LED的长脚(阳极)通过一根导线连接到Metro的数字引脚13(D13)。这个引脚很特殊,它通常直接连接在板载的另一个小LED上,所以当你控制D13时,板载LED也会同步闪烁,方便调试。
- 将LED的短脚(阴极)连接到560Ω电阻的一端。
- 将电阻的另一端连接到面包板的“地”(GND)电源轨。
- 最后,用一根红线将Metro的“5V”引脚连接到面包板的正极电源轨,用一根黑线将Metro的“GND”引脚连接到面包板的负极电源轨。这一步是为整个面包板提供电源参考地,虽然本例中只用了GND,但养成完整接电源轨的习惯对复杂电路很重要。
3.2 代码解读:从setup()到loop()
打开Arduino IDE,通过“文件” -> “示例” -> “01.Basics” -> “Blink”打开经典的闪烁示例代码。我们一行行来看:
// the setup function runs once when you press reset or power the board void setup() { // initialize digital pin LED_BUILTIN as an output. pinMode(LED_BUILTIN, OUTPUT); }void setup():这是一个特殊的函数,它只在板上电或复位后运行一次。用于进行初始化设置。pinMode(LED_BUILTIN, OUTPUT):这是最关键的一步。pinMode函数用于配置指定引脚的工作模式。LED_BUILTIN是一个Arduino预定义的常量,在大多数板子上(包括Metro)它等于数字引脚13。OUTPUT模式意味着我们将这个引脚设置为输出模式,即由微控制器主动控制这个引脚输出高电平(5V)或低电平(0V)。如果错误地设置为INPUT模式,你将无法可靠地控制LED。
// the loop function runs over and over again forever void loop() { digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second }void loop():这是另一个特殊函数,在setup()执行完毕后,它会无限循环执行。digitalWrite(LED_BUILTIN, HIGH):digitalWrite函数用于向一个已配置为OUTPUT的引脚写入数字值。HIGH代表高电平(约5V),这会在LED两端形成电压差,电流流过,LED点亮。delay(1000):delay函数让程序暂停执行。参数单位是毫秒(ms),1000毫秒就是1秒。在这1秒里,LED保持点亮状态。digitalWrite(LED_BUILTIN, LOW):写入LOW,即低电平(0V),引脚与GND同电位,LED两端没有电压差,电流停止,LED熄灭。- 又一个
delay(1000),保持熄灭状态1秒。 - 然后循环回到开头,周而复始,LED就实现了1秒亮、1秒灭的闪烁效果。
3.3 编译与上传:打通最后一步
- 选择开发板:在“工具” -> “开发板”中,选择“Arduino Uno”(对于Metro Classic)或“Adafruit Metro M0 Express”(对于Metro Express)。选择错误会导致编译失败。
- 选择端口:在“工具” -> “端口”中,选择你之前识别到的串口(如
/dev/cu.usbserial-XXXX或COMX)。 - 验证(编译):点击工具栏上的“对勾”图标,或按
Ctrl+R。IDE会检查代码语法并将其编译为机器码。如果下方控制台显示“编译完成”,说明代码无误。 - 上传:点击工具栏上的“右箭头”图标,或按
Ctrl+U。IDE会先将编译好的代码通过串口发送到板子上的引导加载程序(Bootloader),然后由Bootloader将代码写入微控制器的闪存(Flash)中。上传时,你会看到板子上的TX/RX指示灯快速闪烁。上传成功后,控制台会显示“上传完成”,你的LED应该立刻开始闪烁了。
4. 举一反三:深入操控与扩展实验
让一个LED闪起来只是开始。通过修改这个简单的项目,我们可以探索更多Arduino的核心功能。
4.1 更换控制引脚与理解引脚复用
原电路使用D13,但Metro的大多数数字引脚(D0-D13)都可以用来控制LED。你可以把连接到D13的线改插到D2-D12中的任意一个。但代码必须同步修改:
- 在
setup()中,将pinMode(LED_BUILTIN, OUTPUT)改为pinMode(2, OUTPUT)(假设你换到了D2)。 - 在
loop()中,将所有LED_BUILTIN替换为数字2。 - 重新上传代码。
为什么可以?这些数字引脚在芯片内部都是平等的通用输入输出(GPIO)引脚,都可以被配置为OUTPUT模式。D13的特殊性仅在于它通常硬件连接了一个板载LED。
4.2 模拟输出(PWM)与亮度控制
你是否注意到Blink示例中LED只有“全亮”和“全灭”两种状态?如果我们想调节亮度,就需要用到模拟输出。但严格来说,像ATmega328P这样的微控制器并没有真正的模拟电压输出引脚。它使用的是脉冲宽度调制(PWM)技术来模拟模拟输出。
PWM原理:PWM通过快速开关(数字输出)来模拟中间电压。例如,在一个周期内,50%的时间输出高电平(5V),50%的时间输出低电平(0V),那么用万用表测量到的平均电压就是2.5V。由于开关频率很高(通常490Hz或980Hz),人眼看到LED就是半亮状态,而不是在闪烁。
实操:实现呼吸灯效果
- 硬件改动:将LED的控制线从D13移到D9、D10或D11(在Arduino Uno/Metro上,这些是支持PWM输出的引脚,旁边通常标有“~”符号)。
- 代码改动:使用
analogWrite(pin, value)函数。value的取值范围是0到255。0对应0%占空比(常低,熄灭),255对应100%占空比(常高,最亮)。
上传这段代码,你会看到LED像呼吸一样柔和地明暗变化。这就是PWM的魅力。void setup() { pinMode(9, OUTPUT); // 假设LED接在D9 } void loop() { // 逐渐变亮 for (int brightness = 0; brightness <= 255; brightness++) { analogWrite(9, brightness); delay(10); // 短暂延迟,控制变化速度 } // 逐渐变暗 for (int brightness = 255; brightness >= 0; brightness--) { analogWrite(9, brightness); delay(10); } }
4.3 多LED控制与数组、循环的应用
控制一个LED不过瘾?让我们来操控8个LED,并学习两个重要的编程概念:数组和for循环。
硬件连接:将8个LED的正极(长脚)分别连接到数字引脚D2至D9。每个LED的负极(短脚)通过一个560Ω电阻连接到GND。这需要一些耐心来布线,确保不要接错。
软件思维升级:如果像控制一个LED那样写8遍digitalWrite,代码会非常冗长。我们可以使用数组来管理引脚编号,用循环来批量操作。
int ledPins[] = {2, 3, 4, 5, 6, 7, 8, 9}; // 定义一个数组,存放所有LED引脚号 void setup() { // 使用for循环,一次性初始化所有8个引脚为输出模式 for (int i = 0; i < 8; i++) { pinMode(ledPins[i], OUTPUT); } } void loop() { // 流水灯效果:依次点亮,再依次熄灭 for (int i = 0; i < 8; i++) { digitalWrite(ledPins[i], HIGH); // 点亮当前LED delay(100); // 等待 digitalWrite(ledPins[i], LOW); // 熄灭当前LED } }这段代码实现了经典的“流水灯”效果。ledPins[i]中的i是循环变量,从0到7变化,从而依次访问数组中的每一个引脚号。通过这种方式,无论你要控制8个还是80个LED,核心代码结构都保持不变,只需扩展数组和循环次数即可。这是嵌入式编程中管理多个同类设备的通用思路。
5. 驱动电机:引入晶体管与外部电源
LED电流很小(几mA到20mA),可以直接用MCU引脚驱动。但像玩具电机这种需要几百mA电流的设备,直接连接会烧毁MCU引脚。这时就需要晶体管作为电流开关。
5.1 为什么需要晶体管?
Arduino的单个I/O引脚最大输出电流约为20-40mA(具体看数据手册),而一个小型直流电机的启动电流可能高达100-200mA甚至更高。晶体管在这里扮演了一个“水龙头”的角色:我们用MCU引脚提供的微小电流(流入晶体管基极)去控制一个由外部电源供电的大电流(流过晶体管集电极-发射极)的通断。
5.2 电路设计与连接(以NPN型晶体管为例)
你需要新增的元件:
- NPN晶体管(如常见的2N2222) x1
- 直流玩具电机(工作电压与你的外部电源匹配,如5V) x1
- 续流二极管(如1N4007) x1(非常重要!)
- 外部电源(如4节AA电池盒) x1
连接步骤与原理:
- 电机与外部电源:将电机的一端连接到外部电源的正极(如电池盒的+端)。
- 晶体管作为开关:将电机的另一端连接到晶体管的集电极(C)。
- 续流二极管(保护):在电机两端反向并联一个二极管(阴极接电源正极侧,阳极接集电极侧)。电机是感性负载,在断电瞬间会产生很高的反向电动势(电压尖峰),这个二极管为其提供泄放回路,保护晶体管不被击穿。这是硬件设计中必须考虑的细节。
- 完成回路:将晶体管的发射极(E)连接到外部电源的负极(GND)。同时,将此外部电源的GND与Arduino的GND用导线连接起来,使它们有共同的参考地。
- MCU控制:将Arduino的一个数字引脚(如D9)通过一个限流电阻(如220Ω-1kΩ)连接到晶体管的基极(B)。这个电阻用于限制流入基极的电流,保护Arduino引脚。
- 控制逻辑:当Arduino的D9输出
HIGH(5V)时,晶体管导通,电流从外部电源正极 -> 电机 -> 晶体管C极 -> 晶体管E极 -> 外部电源负极,形成回路,电机转动。当D9输出LOW(0V)时,晶体管截止,电路断开,电机停止。
代码控制:控制代码和LED闪烁几乎一样,只是对象从LED变成了电机控制引脚。
int motorPin = 9; void setup() { pinMode(motorPin, OUTPUT); } void loop() { digitalWrite(motorPin, HIGH); // 电机转 delay(2000); digitalWrite(motorPin, LOW); // 电机停 delay(2000); }通过这个实验,你不仅学会了控制大电流设备,更重要的是理解了在嵌入式系统中隔离控制信号与功率部分的基本思想。对于更大的电机,你可能需要用到电机驱动模块(如L298N、TB6612FNG)或继电器,但它们背后的核心逻辑——用小电流/电压信号控制大电流/电压通路——是相通的。
6. 常见问题排查与实战心得
在多年的教学和项目开发中,我总结了新手最容易遇到的几个“坑”,以及一些能让你事半功倍的小技巧。
6.1 上传失败问题深度排查表
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 上传时提示“avrdude: ser_open(): can‘t open device ...” | 1. 端口选择错误。 2. 端口被其他程序占用。 3. 驱动未安装或安装不正确。 4. 使用了错误的USB线(充电线)。 | 1. 在IDE的“工具”->“端口”菜单中重新确认并选择正确的端口。 2. 关闭可能占用串口的软件(如串口助手、其他Arduino IDE窗口)。 3. 前往设备管理器(Windows)或系统报告(macOS)检查设备是否被识别,重新安装驱动。 4. 换一根确认可以传输数据的USB线。 |
| 上传时提示“avrdude: stk500_recv(): programmer is not responding” | 1. 开发板型号选择错误。 2. Bootloader损坏或芯片型号不匹配。 3. 上传时未正确复位板子(对于某些老款板子)。 | 1.最最常见的原因!仔细核对“工具”->“开发板”中选择的型号是否与你手中的板子完全一致(如Arduino Uno vs. Arduino Nano)。 2. 尝试用另一个已知正常的程序(如Blink)测试。对于Metro,确保选择了正确的处理器型号(如ATmega328P)。 3. 在上传开始瞬间(进度条刚出现时),手动按下板子上的复位按钮(RESET)。 |
| 编译时提示“error: ‘xxx’ was not declared in this scope” | 1. 变量或函数名拼写错误。 2. 未包含必要的库文件。 3. 库文件版本不兼容或损坏。 | 1. 仔细检查代码中的拼写,区分大小写。 2. 如果使用了第三方库(如 Servo.h),确保已通过“项目”->“加载库”->“管理库”正确安装。3. 尝试删除 文档/Arduino/libraries目录下对应的库文件夹,重新安装。 |
| 代码上传成功,但硬件无反应 | 1. 电路连接错误或接触不良。 2. 引脚定义与代码不符。 3. 元件损坏(如LED接反过久烧毁)。 4. 电源问题。 | 1.用万用表!这是硬件调试的终极武器。测量目标引脚在程序运行时是否在HIGH和LOW之间跳变。2. 再次核对代码中 pinMode和digitalWrite使用的引脚号与实际连接的物理引脚是否一致。3. 更换一个LED或电机试试。 4. 确保开发板供电充足(USB口供电能力不足时,外接电源是解决方案)。 |
6.2 硬件连接实战心得
- 面包板不是永久的:面包板内部的金属簧片会随着反复插拔而松动,导致接触不良。如果电路行为不稳定(时而正常时而不正常),第一个怀疑对象就是面包板和杜邦线。用力按紧元件,或者换一个孔位试试。
- 养成画图习惯:在连接复杂电路前,哪怕只是在纸上简单画一下连接关系,也能避免很多低级错误。推荐使用Fritzing这样的免费工具。
- 电源去耦:当电路中同时有数字部件(如MCU)和模拟部件(如传感器)或电机时,电机启停造成的电源波动可能会干扰MCU甚至导致复位。一个简单的改进方法是在MCU的电源引脚(VCC和GND)之间就近焊接一个10uF的电解电容和一个0.1uF的瓷片电容,前者应对低频波动,后者滤除高频噪声。
- 善用板载LED:数字引脚13(D13)连接的板载LED是绝佳的调试工具。即使你的外接电路出了问题,你仍然可以通过让板载LED闪烁不同的模式(例如,快闪3次代表传感器A错误,慢闪2次代表通信超时)来了解程序的运行状态。这在没有串口监视器可用的场景下非常有用。
6.3 软件与思维进阶建议
- 拥抱串口监视器:
Serial.begin(9600)和Serial.println(“Hello”)是你最好的朋友。任何变量值、程序状态、传感器读数都可以打印到串口监视器(IDE中点击右上角的放大镜图标)查看。这是调试复杂逻辑不可或缺的手段。 - 理解“阻塞”与“非阻塞”:
delay()函数虽然简单,但它会让整个程序停下来等待。在需要同时处理多个任务(如一边读取传感器一边控制LED闪烁频率)时,delay()会成为障碍。学习使用millis()函数来记录时间戳,是实现非阻塞多任务调度的关键一步。例如,用if (millis() - previousMillis >= interval)来判断是否该执行下一个动作,而不是用delay(interval)。 - 版本控制你的代码:即使是Arduino项目,也值得用Git管理。当你尝试了一个复杂的修改却把东西搞砸了,能轻松回退到上一个能工作的版本,会节省大量时间。
- 阅读错误信息:编译器给出的错误信息通常已经指明了问题的行数和性质。从最后一行往上看,理解它告诉你的信息,而不是盲目地从头开始检查。
从点亮第一个LED到驱动电机,你走过的这条路,正是无数嵌入式项目的基础。环境搭建教会你与硬件对话的基础规则,Blink程序揭示了软件控制硬件的本质,而扩展实验则展示了GPIO、PWM、晶体管开关这些基础元件如何组合成复杂功能。硬件项目的乐趣在于这种看得见摸得着的即时反馈。当你按下上传按钮,灯光如约闪烁,马达开始旋转时,那种“我创造了这个物理反应”的成就感,是纯软件编程难以替代的。接下来,不妨尝试结合一个按钮(数字输入)来控制LED,或者用电位器(模拟输入)来调节电机速度,你会发现,软硬件交织的世界,大门才刚刚打开。
