第一部分:核心概念 - 机器人程序的“大脑”和“神经”
一个典型的 Arduino 机器人程序,无论多复杂,都围绕着几个核心概念构建:

-
传感器输入:机器人的“感官”,它们收集关于外部世界的信息。
- 示例:超声波传感器(测距)、红外线传感器(巡线、避障)、红外接收器(遥控)、IMU(姿态传感器,如MPU6050)。
-
逻辑处理:机器人的“大脑”,这是 Arduino 的核心,它根据传感器输入,按照预设的规则做出决策。
- 示例:
if-else语句(如果前面有障碍物,就转弯)、switch-case(根据遥控器不同按键执行不同动作)、状态机(管理机器人复杂的行为模式)。
- 示例:
-
执行器输出:机器人的“肌肉和骨骼”,它们根据大脑的指令来行动。
- 示例:直流电机(驱动轮子)、舵机(控制机械臂、云台)、LED(指示灯)、蜂鸣器(发声)。
-
控制算法:连接“感官”和“肌肉”的“高级神经”,这是让机器人“智能”起来的关键。
(图片来源网络,侵删)- 示例:
- 开环控制:直接发送指令,不关心结果。
motor.setSpeed(200);电机就以固定速度转。 - 闭环控制:持续反馈,不断调整,这是机器人控制的核心。
- PID 控制器:用于精确控制,如保持机器人直线行走、平衡车、机械臂精确定位。
- 循线算法:如 P (比例) 控制器,根据传感器偏离中心线的程度来调整左右轮速。
- 开环控制:直接发送指令,不关心结果。
- 示例:
第二部分:基础示例 - 从“点亮”到“行走”
让我们从一个最简单的避障小车开始,这是机器人的“Hello, World!”。
项目:超声波避障小车
硬件需求:
- Arduino Uno (或任何 Arduino 板)
- L298N 电机驱动板
- 2 个直流电机 + 轮子
- 1 个超声波传感器 (HC-SR04)
- 轮子底盘、电池盒、螺丝等结构件
接线简图:
- 超声波传感器:
- VCC -> 5V
- GND -> GND
- Trig -> Pin 9
- Echo -> Pin 10
- L298N 电机驱动:
- IN1, IN2, IN3, IN4 -> Arduino 数字引脚 (5, 6, 7, 8)
- ENA, ENB -> Arduino PWM 引脚 (9, 10) (注意:如果超声波也用这两个引脚,需要更换)
- +12V, GND -> 电池电源
- +5V -> Arduino 5V (如果需要为 Arduino 供电)
核心代码
// 定义引脚
const int trigPin = 9;
const int echoPin = 10;
const int motorA1 = 5; // 左电机控制引脚1
const int motorA2 = 6; // 左电机控制引脚2 (PWM)
const int motorB1 = 7; // 右电机控制引脚1
const int motorB2 = 8; // 右电机控制引脚2 (PWM)
// 定义变量
long duration;
int distance;
void setup() {
// 初始化串口通信,用于调试
Serial.begin(9600);
// 设置引脚模式
pinMode(trigPin, OUTPUT); // 触发信号为输出
pinMode(echoPin, INPUT); // 回波信号为输入
// 电机控制引脚为输出
pinMode(motorA1, OUTPUT);
pinMode(motorA2, OUTPUT);
pinMode(motorB1, OUTPUT);
pinMode(motorB2, OUTPUT);
Serial.println("避障小车已启动!");
}
void loop() {
// 1. 读取距离
distance = getDistance();
Serial.print("Distance: ");
Serial.println(distance);
// 2. 逻辑判断与决策
if (distance > 20) {
// 距离大于20cm,前方无障碍,直行
moveForward();
} else {
// 距离小于等于20cm,前方有障碍,停止并后退,然后转向
stopMotors();
delay(500);
moveBackward();
delay(1000);
stopMotors();
delay(500);
turnRight(); // 或者 turnLeft();
delay(1000);
}
}
// --- 辅助函数 ---
// 获取超声波测量的距离
int getDistance() {
// 发送一个10us的高电平来触发Trig
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// 读取回波时间,单位为微秒
duration = pulseIn(echoPin, HIGH);
// 计算距离:声速 = 340m/s = 0.034cm/us
// 距离 = (时间 * 速度) / 2 (因为去和回)
distance = duration * 0.034 / 2;
return distance;
}
// --- 电机控制函数 ---
void moveForward() {
digitalWrite(motorA1, HIGH);
digitalWrite(motorA2, LOW);
digitalWrite(motorB1, HIGH);
digitalWrite(motorB2, LOW);
}
void moveBackward() {
digitalWrite(motorA1, LOW);
digitalWrite(motorA2, HIGH);
digitalWrite(motorB1, LOW);
digitalWrite(motorB2, HIGH);
}
void turnRight() {
digitalWrite(motorA1, HIGH);
digitalWrite(motorA2, LOW);
digitalWrite(motorB1, LOW);
digitalWrite(motorB2, HIGH);
}
void turnLeft() {
digitalWrite(motorA1, LOW);
digitalWrite(motorA2, HIGH);
digitalWrite(motorB1, HIGH);
digitalWrite(motorB2, LOW);
}
void stopMotors() {
digitalWrite(motorA1, LOW);
digitalWrite(motorA2, LOW);
digitalWrite(motorB1, LOW);
digitalWrite(motorB2, LOW);
}
第三部分:进阶技巧与项目思路
当你掌握了基础,就可以尝试更复杂、更智能的机器人了。

循迹小车
- 原理:使用 TCRT5000 红外对管传感器阵列检测地上的黑线,传感器在不同颜色表面会输出不同电平。
- 核心算法:P (比例) 控制。
- 假设有5个传感器,中间一个,两边各两个。
- 如果中间传感器检测到黑线,说明车在正上方,左右轮速度相同。
- 如果左边传感器检测到黑线,说明车偏右了,需要减速左轮或加速右轮来修正。
- 将传感器偏离中心线的“程度”转换为一个“误差值”,然后用这个误差值来调整左右轮的速度差。
- 代码结构:在
loop()中,先读取所有传感器的值,计算出位置误差,然后根据误差调用不同的电机控制函数。
自平衡车
- 原理:这是一个经典的倒立摆问题,必须使用闭环控制。
- 硬件:需要 IMU 传感器(如 MPU6050)来精确测量俯仰角度和角速度。
- 核心算法:PID 控制器。
- 目标:保持车身垂直(角度为0)。
- 测量:MPU6050 实时获取当前角度。
- 计算误差:
误差 = 目标角度 - 当前角度。 - PID 计算:
- P (Proportional):
P = Kp * 误差,误差越大,电机力量越大,但只有 P 会导致车在平衡位置附近震荡。 - I (Integral):
I = Ki * (误差的累加和),用来消除静差(比如因为地面不平导致的微小倾斜)。 - D (Derivative):
D = Kd * (误差的变化率),用来抑制震荡,让系统更稳定。
- P (Proportional):
- 输出:
总输出 = P + I + D,这个输出值被用来控制车轮的转速,不断调整以维持平衡。
- 代码结构:需要一个高效的
loop(),尽可能快地读取数据、计算PID、控制电机。
机械臂
- 原理:精确控制多个舵机到达指定角度。
- 硬件:MG996R 或 SG90 等舵机。
- 核心算法:运动学逆解。
- 正运动学:已知每个关节的角度,计算末端执行器(抓手)在空间中的位置。
- 逆运动学:已知末端执行器想要到达的位置,反推出每个关节需要转动的角度,这是机械臂编程的难点。
- 代码结构:
- 可以定义一个函数
moveArm(joint1_angle, joint2_angle, ...)来控制所有舵机。 - 对于简单应用,可以预先记录几个关键位置(如“抓取”、“抬起”、“放置”),然后通过按钮或串口命令切换。
- 可以定义一个函数
蓝牙/WiFi 远程遥控车
- 原理:通过蓝牙模块(如 HC-05)或 WiFi 模块(如 ESP8266)接收来自手机或电脑的指令。
- 核心代码:
Serial.available()和Serial.read()。- 在
loop()中不断检查串口是否有数据到来。 - 当收到数据(比如字符 'F' 代表前进),就调用相应的
moveForward()函数。
- 在
- 手机App:可以使用 MIT App Inventor 或蓝牙串口App 来创建一个简单的遥控界面。
第四部分:代码结构与最佳实践
当项目变复杂时,把所有代码都写在 loop() 里会变得一团糟,良好的代码结构至关重要。
推荐结构:
-
包含库:在文件开头引入需要的库。
#include <Servo.h> // 如果使用舵机 #include <NewPing.h> // 如果使用超声波传感器,这个库更方便 #include <MPU6050.h> // 如果使用IMU
-
定义常量和全局变量:集中管理所有引脚和配置。
// 引脚定义 const int ECHO_PIN = 10; const int TRIG_PIN = 9; // ... 其他引脚 // 全局变量 int robotSpeed = 150; // 全局速度变量
-
setup()函数:只做初始化工作。void setup() { Serial.begin(9600); pinMode(TRIG_PIN, OUTPUT); // ... 其他初始化 Serial.println("Robot Initialized."); } -
loop()函数:作为主调度器,保持简洁。void loop() { // 1. 读取所有传感器 readAllSensors(); // 2. 执行核心逻辑(决策) makeDecision(); // 3. 控制所有执行器 updateActuators(); // 4. (可选) 添加短暂延时,稳定循环 delay(50); } -
模块化函数:将不同功能写成独立的函数。
void readAllSensors() { ... }void makeDecision() { ... }(这个函数可以再调用更细分的决策函数)void updateActuators() { ... }void moveForward(int speed) { ... }(带参数的函数更灵活)void calculatePID() { ... }
-
使用状态机:对于行为复杂的机器人(如自动吸尘器),状态机是最佳选择。
- 定义几种状态:
enum State { STATE_IDLE, STATE_FORWARD, STATE_AVOID, STATE_CHARGING }; - 在
makeDecision()中根据条件和当前状态,决定下一个状态。 switch(currentState)来执行不同状态下的动作。
- 定义几种状态:
总结与学习路径
- 起点:从 “超声波避障小车” 开始,理解输入-处理-输出的基本流程。
- 进阶:尝试 “循迹小车”,学习比例控制,感受算法如何让机器人变“聪明”。
- 挑战:挑战 “自平衡车”,深入学习PID控制,这是机器人控制的精髓。
- 拓展:探索 “机械臂” 或 “远程遥控”,了解人机交互和更复杂的执行器控制。
- 融合:尝试做一个多功能机器人,比如既能循线又能避障,还能通过蓝牙遥控。
最重要的是 实践!不要害怕失败,调试是学习过程中最重要的一环,多使用 Serial.println() 来打印变量值,这是你调试的“眼睛”,祝你玩得开心!
标签: Arduino 机器人编程入门 Arduino 机器人代码教程 Arduino 机器人控制程序设计