Arduino 从入门到进阶完整指南

版本:V1.0.0  |  更新日期:2026/11/07 19:53

本文档整合了最全的微课与进阶教材大纲,围绕 Arduino UNO 主板、传感器扩展板与面包板,提供从软件安装、基础语法到复杂电机控制的无缝完整教程。

1. 软件平台与基础架构

1.1 官方与第三方下载源

为了确保软件的安全与纯净,请务必从官方或国内权威镜像站下载开发环境:

1.2 IDE 1.x 与 2.x 操作指南

Arduino IDE 是编写、编译并上传代码的专用软件。目前有两大主流版本:

1.3 库管理器与生态拓展

对于复杂的外设(如屏幕、传感器),需要引入第三方库。在 IDE 中点击左侧的“库管理器”图标,搜索名称并安装。在代码头部使用 #include 调用。官方社区提供了大量开源的驱动支持。

1.4 代码基础结构与运行原理

在开始接线和编写逻辑之前,必须了解 Arduino 程序的“空壳”结构。每一个 Arduino 程序都由 setup() 和 loop() 两个必须存在的核心函数构成。

C++ 空壳结构
void setup() {
    // 上电或复位后,只执行一次。用于初始化配置
}

void loop() {
    // setup执行完毕后,无限循环执行。用于编写主逻辑
}

运行原理详解:

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 以固定频率闪烁。

C++
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 求救信号。

C++ 流水灯
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);  // 熄灭当前引脚
    }
}
C++ SOS 求救
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,解决机械按键在按下瞬间产生的抖动问题。

C++
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:蜂鸣器发声与电子琴

作用: 使无源蜂鸣器输出指定频率的声音,并模拟警报或制作电子琴。

C++ 警报器
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毫秒
    }
}
C++ 电子琴
// 定义音符频率的常量
#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 亮度。

C++
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 亮度。

C++
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) 报警

作用: 检测人体运动,触发声光报警。

C++
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:热敏电阻温度计

作用: 读取热敏电阻的阻值变化,通过串口输出当前温度值。

C++
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 屏幕上打印文字和传感器数据。

C++
#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:超声波测距仪

作用: 测量前方障碍物距离并打印到串口。

C++
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 库。

C++
#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 库。

C++
#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度),并来回扫动。

C++
#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:步进电机精准定位

作用: 驱动步进电机按固定步数旋转,实现精确定位。

C++
#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:直流电机调速与正反转

作用: 控制直流电机的正反转与转速。

C++
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:综合智能小车避障逻辑

作用: 结合超声波传感器与直流电机,实现小车遇到障碍物自动后退转弯。

C++
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(),避免程序假死卡顿。

C++
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 被大量字符串耗尽导致不断重启。

C++
void setup() {
    Serial.begin(9600); // 初始化串口
}

void loop() {
    // 使用 F() 宏,将字符串强制存储在 Flash 闪存中,避免占用 SRAM
    Serial.println(F("String stored in Flash")); 
    delay(1000);
}

接线步骤

所需设备:无需额外接线,只需将 UNO 用 USB 连接至电脑,打开 IDE 的串口监视器(波特率 9600)即可看到输出。

7.3 供电危机与共地原则

致命警告: UNO 的 5V 引脚输出电流极其有限。驱动电机、继电器时,必须使用外部独立电源供电,并确保外部电源的负极与 UNO 的 GND 相连(共地),否则必烧板子。