Arduino 从入门到进阶完整指南
版本:V1.0.0 | 更新日期:2026/11/07 19:53
本文档整合了最全的微课与进阶教材大纲,围绕 Arduino UNO 主板、传感器扩展板与面包板,提供从软件安装、基础语法到复杂电机控制的无缝完整教程。
1. 软件平台与基础架构
1.1 官方与第三方下载源
为了确保软件的安全与纯净,请务必从官方或国内权威镜像站下载开发环境:
- Arduino 官网: https://www.arduino.cc/en/software (支持 Windows, macOS, Linux)
- 清华大学 TUNA 镜像站(国内极速): https://mirrors.tuna.tsinghua.edu.cn/arduino/
- 上海交通大学镜像站: https://mirror.sjtu.edu.cn/arduino/
1.2 IDE 1.x 与 2.x 操作指南
Arduino IDE 是编写、编译并上传代码的专用软件。目前有两大主流版本:
- IDE 1.x(经典版): 界面朴素,对老旧电脑兼容性极好。工具栏包含验证、上传按钮。底部控制台显示编译信息,右下角显示开发板与端口。
- IDE 2.x(推荐版): 界面现代,支持代码自动补全。左侧新增了边栏,集成了开发板管理器、库管理器、调试器。串口监视器作为底部选项卡显示。
- 上传流程(通用): 用 USB 连接电脑 → 在“工具”选择开发板型号(UNO)及端口 → 点击“上传”箭头按钮,等待提示 Done uploading。
1.3 库管理器与生态拓展
对于复杂的外设(如屏幕、传感器),需要引入第三方库。在 IDE 中点击左侧的“库管理器”图标,搜索名称并安装。在代码头部使用 #include 调用。官方社区提供了大量开源的驱动支持。
- 官方社区与文档: Arduino 语言参考 与 官方论坛 是排错和获取第三方库的最佳去处。
1.4 代码基础结构与运行原理
在开始接线和编写逻辑之前,必须了解 Arduino 程序的“空壳”结构。每一个 Arduino 程序都由 setup() 和 loop() 两个必须存在的核心函数构成。
void setup() {
// 上电或复位后,只执行一次。用于初始化配置
}
void loop() {
// setup执行完毕后,无限循环执行。用于编写主逻辑
}
运行原理详解:
- setup() 函数(初始化): 当开发板通电或按下复位键时,程序从上到下执行,只执行一次。我们通常把引脚模式设置(pinMode)、启动串口通信(Serial.begin)等准备工作写在这里。
- loop() 函数(主循环): 当 setup() 执行完毕后,CPU 会立刻进入 loop() 函数。一旦 loop() 里的代码执行到底部,它会自动跳回顶部无限循环执行,直到断电或复位。我们所有的传感器读取、逻辑判断、控制输出,都写在这个无限循环里。
2. 硬件基础与电路连接
2.1 UNO 核心板与传感器扩展板
本指南实验均基于 Arduino UNO R3 与 Sensor Shield 传感器扩展板 叠层使用。扩展板将 UNO 所有引脚引出为标准的 S (信号)、V (电源)、G (地) 三针接口,用公对母杜邦线即可将任意引脚引出到面包板,极大简化了接线过程。
2.2 面包板的内部玄机
面包板两侧的红蓝电源轨竖向连通,中间孔位横向连通(5 孔一组),中间凹槽隔断上下半区。接线时,将扩展板或 UNO 的 5V 与 GND 分别接入面包板两侧的红蓝电源轨,后续所有需要供电的元件都从这两条轨取电。
2.3 电阻与电子元件原理
驱动 LED 时,必须串联 220Ω 限流电阻,以防电流过大烧毁 LED 或微控制器引脚。光敏电阻等阻值变化的传感器,需配合 10kΩ 固定电阻 组成分压电路,才能将电阻变化转化为可读取的电压。
3. 基础数字 I/O 与输出进阶
3.1 案例1:点亮第一颗 LED
作用: 验证数字输出,让 LED 以固定频率闪烁。
void setup() {
pinMode(9, OUTPUT); // 将9号引脚设置为输出模式
}
void loop() {
digitalWrite(9, HIGH); // 9号引脚输出高电平(5V),点亮LED
delay(1000); // 程序暂停1000毫秒(1秒)
digitalWrite(9, LOW); // 9号引脚输出低电平(0V),熄灭LED
delay(1000); // 程序暂停1000毫秒(1秒)
}
接线步骤
所需设备:UNO + 扩展板(已插好)、面包板、LED 灯 1 个、220Ω 电阻 1 个、公对母杜邦线 2 根。
步骤:
1. 取一根杜邦线,母头插在扩展板 D9 的 S 针(信号),公头插在面包板任意一组(如第 1 行的 a 孔)。
2. 将 220Ω 电阻的一端插在第 1 行 b 孔,另一端插在第 1 行 d 孔(跨接在同组导通的孔内)。
3. 将 LED 长脚(正极)插在第 1 行 e 孔,短脚(负极)插在第 2 行 a 孔。
4. 再取一根杜邦线,母头插在扩展板 GND 的 G 针,公头插在面包板第 2 行 b 孔。
3.2 案例2:炫彩流水灯与 SOS 求救
作用: 通过数组控制多个 LED 依次点亮,并模拟摩斯密码 SOS 求救信号。
int ledPins[] = {2, 3, 4, 5, 6}; // 定义一个数组,存放5个LED的引脚号
void setup() {
for (int i = 0; i < 5; i++) { // 循环5次
pinMode(ledPins[i], OUTPUT); // 将数组中的5个引脚都设置为输出模式
}
}
void loop() {
for (int i = 0; i < 5; i++) { // 从左到右依次点亮
digitalWrite(ledPins[i], HIGH); // 点亮当前引脚
delay(100); // 延时100毫秒
digitalWrite(ledPins[i], LOW); // 熄灭当前引脚
}
for (int i = 4; i >= 0; i--) { // 从右到左依次点亮
digitalWrite(ledPins[i], HIGH); // 点亮当前引脚
delay(100); // 延时100毫秒
digitalWrite(ledPins[i], LOW); // 熄灭当前引脚
}
}
void setup() {
pinMode(9, OUTPUT); // 设置9号引脚为输出模式
}
void loop() {
// 字母 S:3次短闪
for (int i = 0; i < 3; i++) {
digitalWrite(9, HIGH); delay(200); digitalWrite(9, LOW); delay(200);
}
// 字母 O:3次长闪
for (int i = 0; i < 3; i++) {
digitalWrite(9, HIGH); delay(600); digitalWrite(9, LOW); delay(200);
}
// 字母 S:3次短闪
for (int i = 0; i < 3; i++) {
digitalWrite(9, HIGH); delay(200); digitalWrite(9, LOW); delay(200);
}
delay(2000); // 发完一轮SOS,等待2秒后重新开始
}
接线步骤
流水灯所需设备:LED 灯 5 个、220Ω 电阻 5 个、公对母杜邦线 6 根(5 根信号,1 根地线)。
流水灯接线:
1. 将 D2、D3、D4、D5、D6 的 S 针分别用杜邦线引到面包板第 1、3、5、7、9 行的 a 孔。
2. 每一行之间跨接 220Ω 电阻(如 1b 到 1d)。
3. 5 个 LED 的负极全部汇总到面包板的蓝色电源轨。
4. 从扩展板 GND 引一根线接到面包板蓝色电源轨,完成共地。
SOS 所需设备:LED 1 个、220Ω 电阻 1 个、杜邦线 2 根。
SOS 接线:同案例 1,接在 D9 即可。
3.3 案例3:按键控制与软件消抖
作用: 读取按键状态并控制 LED,解决机械按键在按下瞬间产生的抖动问题。
int buttonPin = 2; // 按键连接在2号引脚
int ledPin = 13; // LED连接在13号引脚
int lastReading = HIGH; // 记录上一次的读取状态
unsigned long lastDebounce = 0; // 记录上一次状态改变的时间
void setup() {
pinMode(ledPin, OUTPUT); // 设置LED为输出模式
pinMode(buttonPin, INPUT_PULLUP); // 设置按键为输入模式,并启用内部上拉电阻
}
void loop() {
int reading = digitalRead(buttonPin); // 读取当前按键状态
if (reading != lastReading) { // 如果状态发生了变化(按下或松开)
lastDebounce = millis(); // 记录当前时间
}
if ((millis() - lastDebounce) > 50) { // 如果距离上次变化已经过了50毫秒(消抖)
if (reading == LOW) { // 如果当前状态是低电平(按下)
digitalWrite(ledPin, HIGH); // 点亮LED
} else {
digitalWrite(ledPin, LOW); // 熄灭LED
}
}
lastReading = reading; // 更新上一次的读取状态
}
接线步骤
所需设备:四脚轻触按键 1 个、LED 灯 1 个、220Ω 电阻 1 个、公对母杜邦线 3 根。
步骤:
1. 将按键跨接在面包板中间凹槽上方(如第 5 行的 e 孔和 f 孔),因为按键同侧两脚内部是不连通的。
2. 杜邦线母头接扩展板 D2 的 S 针,公头接按键左上角引脚(第 5 行 e 孔)。
3. 杜邦线母头接扩展板 GND,公头接按键左下角引脚(第 5 行 a 孔)。
4. LED 接在 D13 或面包板上均可(参考案例 1)。代码中使用了 INPUT_PULLUP,因此无需外部电阻即可读取按键状态。
3.4 案例4:蜂鸣器发声与电子琴
作用: 使无源蜂鸣器输出指定频率的声音,并模拟警报或制作电子琴。
void setup() {
pinMode(8, OUTPUT); // 设置8号引脚为输出模式
}
void loop() {
// 频率从200Hz逐渐升高到800Hz
for (int freq = 200; freq <= 800; freq += 10) {
tone(8, freq); // 在8号引脚输出对应频率的声音
delay(5); // 延时5毫秒
}
// 频率从800Hz逐渐降低到200Hz
for (int freq = 800; freq >= 200; freq -= 10) {
tone(8, freq); // 在8号引脚输出对应频率的声音
delay(5); // 延时5毫秒
}
}
// 定义音符频率的常量
#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_E4 330
void setup() {
pinMode(2, INPUT_PULLUP); // 设置按键引脚为输入,启用内部上拉
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(8, OUTPUT); // 设置蜂鸣器引脚为输出
}
void loop() {
if (digitalRead(2) == LOW) tone(8, NOTE_C4); // 如果按键1按下,发出C4音
else if (digitalRead(3) == LOW) tone(8, NOTE_D4); // 如果按键2按下,发出D4音
else if (digitalRead(4) == LOW) tone(8, NOTE_E4); // 如果按键3按下,发出E4音
else noTone(8); // 如果都没按,停止发声
}
接线步骤
警报器所需设备:无源蜂鸣器 1 个、公对母杜邦线 2 根。
警报器接线:蜂鸣器正极(长脚)接扩展板 D8 的 S 针,负极接 GND。
电子琴所需设备:无源蜂鸣器 1 个、按键 3 个、杜邦线若干。
电子琴接线:
1. 蜂鸣器正极接 D8(S 针),负极接 GND。
2. 按键 1 两端分别接 D2 的 S 针和 GND。
3. 按键 2 两端分别接 D3 的 S 针和 GND。
4. 按键 3 两端分别接 D4 的 S 针和 GND。
4. 模拟信号与传感器生态
4.1 案例5:电位器 ADC 采集与调光
作用: 旋转电位器,手动控制 LED 亮度。
void setup() {
pinMode(9, OUTPUT); // 设置9号引脚为输出模式
}
void loop() {
int val = analogRead(A0); // 读取A0引脚的模拟值(0-1023)
int brightness = map(val, 0, 1023, 0, 255); // 将0-1023映射到0-255的PWM范围
analogWrite(9, brightness); // 输出PWM信号控制LED亮度
}
接线步骤
所需设备:旋转电位器(3 脚)1 个、LED 1 个、220Ω 电阻 1 个、杜邦线若干。
步骤:
1. 将电位器插在面包板上,引脚分别占据 a、b、c 三行。
2. 电位器左侧引脚连 5V(扩展板 V 针),右侧引脚连 GND。
3. 中间引脚(滑片)用杜邦线连到扩展板 A0 的 S 针。
4. LED 正极经 220Ω 电阻接 D9 的 S 针,负极接 GND。
4.2 案例6:光敏电阻智能夜灯
作用: 根据环境亮度自动调节 LED 亮度。
void setup() {
pinMode(9, OUTPUT); // 设置9号引脚为输出模式
}
void loop() {
int lightVal = analogRead(A0); // 读取A0引脚的模拟值(光线越暗,值越大)
int pwmVal = map(lightVal, 300, 1023, 0, 255); // 将环境光线映射到PWM输出范围
analogWrite(9, constrain(pwmVal, 0, 255)); // 限制PWM值在0-255之间,并输出控制LED
delay(50); // 短暂延时
}
接线步骤
所需设备:光敏电阻 1 个、10kΩ 固定电阻 1 个、LED 1 个、220Ω 电阻 1 个、杜邦线若干。
步骤:
1. 在面包板上搭建分压电路:将光敏电阻一端接 5V,另一端接 A0(S 针)。
2. 在 A0 所在的同一行,跨接 10kΩ 电阻到 GND。这样 A0 读取的电压会随光线变化。
3. LED 正极经 220Ω 电阻接 D9 的 S 针,负极接 GND。
4.3 案例7:热释电红外 (PIR) 报警
作用: 检测人体运动,触发声光报警。
void setup() {
pinMode(3, INPUT); // 设置3号引脚为输入模式(连接PIR传感器)
pinMode(13, OUTPUT); // 设置13号引脚为输出模式(连接LED)
pinMode(8, OUTPUT); // 设置8号引脚为输出模式(连接蜂鸣器)
Serial.begin(9600); // 初始化串口通信
}
void loop() {
int pirState = digitalRead(3); // 读取PIR传感器的状态
if (pirState == HIGH) { // 如果检测到人体运动(高电平)
digitalWrite(13, HIGH); // 点亮LED
tone(8, 1000); // 蜂鸣器发声
} else { // 如果没有检测到运动
digitalWrite(13, LOW); // 熄灭LED
noTone(8); // 关闭蜂鸣器
}
delay(200); // 延时200毫秒
}
接线步骤
所需设备:HC-SR501 PIR 模块 1 个、LED 1 个、无源蜂鸣器 1 个、杜邦线若干。
步骤:
1. PIR 模块有 3 根针(VCC、OUT、GND)。直接用母对母杜邦线或公对母线将 VCC 接扩展板 5V,GND 接 GND,OUT 接 D3 的 S 针。
2. LED 正极经 220Ω 电阻接 D13 的 S 针,负极接 GND。
3. 蜂鸣器正极接 D8 的 S 针,负极接 GND。
4.4 案例8:热敏电阻温度计
作用: 读取热敏电阻的阻值变化,通过串口输出当前温度值。
void setup() {
Serial.begin(9600); // 初始化串口通信,波特率9600
}
void loop() {
int raw = analogRead(A1); // 读取A1引脚的模拟值
float voltage = raw * 5.0 / 1023.0; // 将模拟值转换为电压值(0-5V)
// 根据分压公式计算热敏电阻阻值
float resistance = (10000.0 * voltage) / (5.0 - voltage);
// 使用Steinhart-Hart方程(B值法)计算温度
float temperature = 1.0 / (1.0 / 298.15 + log(resistance / 10000.0) / 3950.0) - 273.15;
Serial.println(temperature); // 将温度值打印到串口
delay(1000); // 延时1秒
}
接线步骤
所需设备:NTC 热敏电阻 1 个、10kΩ 固定电阻 1 个、杜邦线 3 根。
步骤:
1. 在面包板上搭建分压电路:热敏电阻一端接 5V,另一端连接 A1(S 针)。
2. 在 A1 的同组孔位,跨接 10kΩ 固定电阻到 GND。
5. 通信协议与显示系统
5.1 案例9:I2C OLED 屏幕显示
作用: 在 OLED 屏幕上打印文字和传感器数据。
#include // 引入I2C通信库
#include // 引入图形库
#include // 引入OLED驱动库
// 创建一个OLED对象,宽度128,高度64
Adafruit_SSD1306 display(128, 64, &Wire, -1);
void setup() {
// 初始化OLED屏幕,地址为0x3C
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay(); // 清空屏幕
display.setTextSize(1); // 设置文字大小
display.setTextColor(WHITE); // 设置文字颜色为白色
display.setCursor(0, 10); // 设置文字起始坐标
display.println("Hello Arduino"); // 打印文字
display.display(); // 将缓冲区内容刷新到屏幕
}
void loop() {
// 屏幕上显示静态内容,无需循环
}
接线步骤
所需设备:I2C 接口 0.96 寸 OLED 屏 1 个、母对母或公对母杜邦线 4 根。
步骤:
1. 扩展板 A4 是 SDA,A5 是 SCL。
2. 将 OLED 的 GND 接扩展板 GND,VCC 接 5V。
3. 将 OLED 的 SDA 接扩展板 A4 的 S 针。
4. 将 OLED 的 SCL 接扩展板 A5 的 S 针。
5.2 案例10:超声波测距仪
作用: 测量前方障碍物距离并打印到串口。
const int trigPin = 9; // 触发引脚连接9号
const int echoPin = 10; // 回响引脚连接10号
void setup() {
Serial.begin(9600); // 初始化串口
pinMode(trigPin, OUTPUT); // 设置触发引脚为输出
pinMode(echoPin, INPUT); // 设置回响引脚为输入
}
void loop() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10); // 发送10微秒的高电平脉冲触发超声波
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH); // 测量回响引脚高电平的持续时间
int distance = duration * 0.034 / 2; // 根据声速计算距离(单位:厘米)
Serial.print(distance); // 打印距离到串口
Serial.println(" cm");
delay(500); // 延时500毫秒
}
接线步骤
所需设备:HC-SR04 超声波模块 1 个、母对母或公对母杜邦线 4 根。
步骤:
1. VCC 接扩展板 5V,GND 接 GND。
2. Trig(触发)接扩展板 D9 的 S 针。
3. Echo(回响)接扩展板 D10 的 S 针。
5.3 案例11:DHT11 温湿度气象站
作用: 读取环境温度和湿度数据,需要安装 DHT 库。
#include "DHT.h" // 引入DHT传感器库
DHT dht(2, DHT11); // 创建DHT对象,数据引脚接2号,型号为DHT11
void setup() {
Serial.begin(9600); // 初始化串口
dht.begin(); // 启动DHT传感器
}
void loop() {
float t = dht.readTemperature(); // 读取温度
float h = dht.readHumidity(); // 读取湿度
Serial.print(t); Serial.print("C "); // 打印温度
Serial.print(h); Serial.println("%"); // 打印湿度
delay(2000); // DHT11读取间隔至少2秒
}
接线步骤
所需设备:DHT11 模块(3 针或 4 针)1 个、杜邦线 3 根。
步骤:
1. 模块 VCC 接扩展板 5V,GND 接 GND。
2. 模块 DATA(数据)引脚接扩展板 D2 的 S 针。
5.4 案例12:红外遥控与串口通信
作用: 接收红外遥控器发出的键值,需要安装 IRremote 库。
#include // 引入红外遥控库
const int RECV_PIN = 3; // 红外接收头连接3号引脚
IRrecv irrecv(RECV_PIN); // 创建红外接收对象
decode_results results; // 用于存储解码结果
void setup() {
Serial.begin(9600); // 初始化串口
irrecv.enableIRIn(); // 启动红外接收
}
void loop() {
if (irrecv.decode(&results)) { // 如果接收到红外信号并解码成功
Serial.println(results.value, HEX); // 将按键值以十六进制打印到串口
irrecv.resume(); // 准备接收下一个信号
}
}
接线步骤
所需设备:HX1838 红外接收头(通常 3 针)1 个、杜邦线 3 根。
步骤:
1. 接收头 VCC 接 5V,GND 接 GND。
2. 接收头 OUT(数据)接扩展板 D3 的 S 针。
6. 执行器与电机控制系统
6.1 案例13:舵机扫频与角度控制
作用: 通过代码控制舵机旋转到指定角度(0-180度),并来回扫动。
#include // 引入舵机控制库
Servo myservo; // 创建舵机对象
void setup() {
myservo.attach(9); // 将舵机信号线连接到9号引脚
}
void loop() {
// 从0度旋转到180度
for (int pos = 0; pos <= 180; pos += 5) {
myservo.write(pos); // 设置舵机角度
delay(15); // 等待舵机转动到位
}
// 从180度旋转回0度
for (int pos = 180; pos >= 0; pos -= 5) {
myservo.write(pos);
delay(15);
}
}
接线步骤
所需设备:SG90 舵机 1 个(带 3 根线:棕、红、橙/黄)。
步骤:
1. 舵机的棕色线(GND)接扩展板 GND。
2. 红色线(VCC)接扩展板 5V。
3. 橙色或黄色线(信号)接扩展板 D9 的 S 针。
注意:如果舵机抖动严重,说明 UNO 供电不足,需使用外部 5V 电源供电,并将外部电源负极与 UNO 的 GND 相连(共地)。
6.2 案例14:步进电机精准定位
作用: 驱动步进电机按固定步数旋转,实现精确定位。
#include // 引入步进电机库
const int stepsPerRev = 200; // 步进电机转一圈的步数
// 创建一个步进电机对象,控制引脚为8, 9, 10, 11
Stepper myStepper(stepsPerRev, 8, 9, 10, 11);
void setup() {
myStepper.setSpeed(60); // 设置电机转速为60 RPM
}
void loop() {
myStepper.step(stepsPerRev); // 正转一圈
delay(500); // 停顿500毫秒
myStepper.step(-stepsPerRev); // 反转一圈
delay(500);
}
接线步骤
所需设备:28BYJ-48 步进电机及 ULN2003 驱动板 1 套、母对母杜邦线 6 根。
步骤:
1. 步进电机的 5 针插头直接插在驱动板的白色插座上。
2. 驱动板上的 IN1、IN2、IN3、IN4 用杜邦线分别连接到扩展板的 D8、D9、D10、D11 的 S 针。
3. 驱动板的 VCC 接扩展板 5V(若电机不转,可尝试接外部电源),GND 接 GND。
6.3 案例15:直流电机调速与正反转
作用: 控制直流电机的正反转与转速。
const int ENA = 9; // 使能引脚(控制速度),接9号PWM引脚
const int IN1 = 8; // 方向控制引脚1
const int IN2 = 7; // 方向控制引脚2
void setup() {
pinMode(ENA, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
}
void loop() {
// 正转,速度中等 (150/255)
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
analogWrite(ENA, 150);
delay(2000); // 转动2秒
// 反转,速度全开 (255/255)
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
analogWrite(ENA, 255);
delay(2000); // 转动2秒
}
接线步骤
所需设备:L298N 电机驱动模块 1 个、直流电机 1 个、外部电池盒(供电)、杜邦线若干。
步骤:
1. 将外部电源(如 9V 电池)正极接 L298N 的 12V 输入,负极接 GND。
2. 极其重要:将 L298N 的 GND 与扩展板的 GND 连在一起(共地)。
3. L298N 的 ENA 接扩展板 D9 的 S 针(必须是 PWM 引脚)。
4. IN1 接扩展板 D8,IN2 接扩展板 D7。
5. 将直流电机的两根线分别接入 L298N 的 OUT1 和 OUT2 端子。
6.4 案例16:综合智能小车避障逻辑
作用: 结合超声波传感器与直流电机,实现小车遇到障碍物自动后退转弯。
const int trigPin = 12; // 超声波触发引脚
const int echoPin = 13; // 超声波回响引脚
const int motorLeft = 5; // 左电机速度控制(PWM)
const int motorRight = 6; // 右电机速度控制(PWM)
void setup() {
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(motorLeft, OUTPUT);
pinMode(motorRight, OUTPUT);
}
// 封装一个函数用于测量距离
int getDistance() {
digitalWrite(trigPin, LOW); delayMicroseconds(2);
digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH);
return duration * 0.034 / 2;
}
void loop() {
int dist = getDistance(); // 获取距离
if (dist < 20) { // 如果距离小于20厘米
// 停止
digitalWrite(motorLeft, LOW);
digitalWrite(motorRight, LOW);
delay(500);
// 后退转向
digitalWrite(motorLeft, HIGH);
digitalWrite(motorRight, LOW);
delay(500);
} else {
// 安全,全速前进
digitalWrite(motorLeft, HIGH);
digitalWrite(motorRight, HIGH);
}
}
接线步骤
所需设备:HC-SR04 超声波 1 个、L298N 驱动板 1 个、两个直流电机、小车底盘、外部电源、杜邦线若干。
步骤:
1. 超声波 Trig 接扩展板 D12,Echo 接 D13。
2. L298N 的 ENA 接 D5(控制左轮速度),IN1 接 D8,IN2 接 D7(控制左轮方向)。
3. L298N 的 ENB 接 D6(控制右轮速度),IN3 接 D4,IN4 接 D3(控制右轮方向)。
4. 电机接入 OUT1/OUT2(左)、OUT3/OUT4(右)。
5. 必须确保 L298N 使用外部电池供电,并将 L298N 的 GND 与 UNO 扩展板的 GND 相连。
7. 底层进阶与入坟避坑
7.1 millis() 非阻塞调度
作用: 在多任务系统中替代 delay(),避免程序假死卡顿。
unsigned long previousMillis = 0; // 记录上一次触发的时间
const long interval = 1000; // 设定时间间隔(1000毫秒)
void setup() {
pinMode(13, OUTPUT); // 设置13号引脚为输出
}
void loop() {
unsigned long currentMillis = millis(); // 获取当前系统运行时间
// 如果当前时间减去上次时间,大于设定的间隔
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis; // 更新上次触发时间
digitalWrite(13, !digitalRead(13)); // 翻转LED的状态
}
// 这里可以继续写其他任务,绝对不会被卡住
}
接线步骤
所需设备:无需外部元件,使用 UNO 板载 13 号引脚 LED 即可。若需外接,参考案例 1 接在 D13。
7.2 内存溢出与 F() 宏
作用: 防止 UNO 仅有的 2KB SRAM 被大量字符串耗尽导致不断重启。
void setup() {
Serial.begin(9600); // 初始化串口
}
void loop() {
// 使用 F() 宏,将字符串强制存储在 Flash 闪存中,避免占用 SRAM
Serial.println(F("String stored in Flash"));
delay(1000);
}
接线步骤
所需设备:无需额外接线,只需将 UNO 用 USB 连接至电脑,打开 IDE 的串口监视器(波特率 9600)即可看到输出。