核心概念:Arduino 与摄像头的角色
要明确 Arduino 在这个系统中的定位。Arduino 通常不直接处理视频流,因为它计算能力和内存有限,处理复杂的视频数据非常吃力。

典型的架构是 “分工协作”:
-
Arduino (飞行控制器/大脑):
- 负责读取陀螺仪、加速度计等传感器数据,通过 PID 算法稳定无人机姿态。
- 接收遥控器信号,控制电机的转速。
- 通过串口与摄像头通信,发送简单的指令(如:拍照、录像、设置参数)。
- 如果摄像头是智能摄像头(如 OpenMV),它会接收摄像头处理后的简单数据(如:物体的坐标、颜色信息),并据此做出决策(如:跟踪目标)。
-
摄像头 (眼睛/通讯员):
- 负责捕捉图像。
- 普通摄像头 (如 OV7670):只能输出原始的图像数据流,需要非常强大的外部处理器(如树莓派)来压缩成视频,再通过 WiFi 传输。这种方案不适合直接用 Arduino。
- 智能摄像头 (如 OpenMV):这是与 Arduino 配合的最佳选择,它自带一个微型处理器,可以在摄像头内部进行图像处理(如颜色识别、人脸追踪、巡线等),然后将处理结果(目标的 X, Y 坐标)通过串口发送给 Arduino,Arduino 根据这些数据执行相应动作。
- 数字视频摄像头 (如 ESP32-CAM):这类模块自带 WiFi 功能,可以直接将视频流通过 WiFi 发送到手机或电脑,Arduino 可以通过串口向它发送指令(如拍照、录像),但视频解码和显示需要另一台设备(手机/电脑/另一块 ESP32)来完成。
硬件选择与清单
根据你的项目目标,选择合适的摄像头和配套硬件。

入门级 - 图像传输 (FPV)
这个方案的目标是让无人机拥有第一人称视角,像大疆无人机一样。
- 核心思路:Arduino 负责飞行,另一块负责视频处理和传输的模块(如 ESP32-CAM 或树莓派 Zero)负责摄像头和 WiFi。
- 硬件清单:
- 飞行控制器:可以使用基于 Arduino 的开源飞控(如
Paparazzi或ArduPilot的旧版),但更常见的是使用成熟的飞控(如CC3D,Naze32),它们运行的是更专业的飞控固件。 - Arduino:可以作为辅助控制器,连接 ESP32-CAM。
- 摄像头模块:ESP32-CAM,这是首选,因为它集成了 ESP32 微处理器、摄像头接口和 WiFi,性价比极高。
- 图传发射/接收系统:如果要求低延迟,可以单独购买模拟图传(如 5.8G FPV TX/RX + 监视器),如果使用 WiFi,则可以省略这套设备,但延迟较高。
- 其他:无人机机架、电机、电调、电池、遥控器、接收机等。
- 飞行控制器:可以使用基于 Arduino 的开源飞控(如
进阶级 - 视觉智能追踪
这个方案的目标是让无人机能够自主识别并跟踪一个物体。
- 核心思路:OpenMV 在内部完成复杂的图像识别,然后将目标的简单坐标数据通过串口发送给 Arduino,Arduino 根据坐标差值来调整无人机的姿态,实现跟踪。
- 硬件清单:
- Arduino:任何带有串口的 Arduino 都可以,如
Arduino Uno,Arduino Nano或更强大的Arduino Mega。 - 摄像头:OpenMV Cam,这是该方案的完美选择,它基于 MicroPython,有丰富的库支持颜色识别、人脸追踪、AprilTag 等。
- IMU 传感器:Arduino 本身不是飞控,你需要一个 MPU6050 或 BNO055 这样的九轴姿态传感器,来获取无人机的姿态数据。
- 电机驱动:需要一个 电机驱动板 (如 L298N, VESC 或更专业的电调) 来接收 Arduino 的 PWM 信号并控制无刷电机。
- 其他:无人机机架、电机、电池、遥控器、接收机等。
- Arduino:任何带有串口的 Arduino 都可以,如
软件编程与实现
这里我们以方案二(视觉追踪)为例,因为它更能体现 Arduino 的核心控制作用。
步骤 1:OpenMV 端编程 (视觉识别)
- 安装 OpenMV IDE:从 OpenMV 官网 下载并安装。
- 编写 OpenMV 代码:编写一个脚本来识别特定颜色的物体,并计算其在图像中的中心坐标。
# OpenMV 示例代码:识别红色物体并发送其坐标
import sensor, image, time, pyb, math
# 初始化摄像头
sensor.reset()
sensor.set_pixformat(sensor.RGB565) # 颜色格式
sensor.set_framesize(sensor.QVGA) # 分辨率 (320x240)
sensor.skip_frames(time=2000) # 等待设置生效
sensor.set_auto_gain(False) # 关闭自动增益
sensor.set_auto_whitebal(False) # 关闭白平衡
clock = time.clock()
# 定义红色阈值 (LAB颜色空间,需要根据你的环境校准)
red_threshold = (30, 100, 15, 127, 15, 127)
uart = pyb.UART(3, 115200) # 使用串口3,波特率115200 (连接到Arduino的RX/TX)
while(True):
clock.tick()
img = sensor.snapshot()
# 查找色块
blobs = img.find_blobs([red_threshold], pixels_threshold=200, area_threshold=200)
if blobs:
# 找到最大的色块
largest_blob = max(blobs, key=lambda b: b.pixels())
img.draw_rectangle(largest_blob.rect(), color=(0,255,0))
img.draw_cross(largest_blob.cx(), largest_blob.cy(), color=(0,0,255))
# 计算中心坐标 (归一化到 -1 到 1)
# OpenMV默认坐标系:左上角为(0,0)
x_center = largest_blob.cx()
y_center = largest_blob.cy()
img_w = img.width()
img_h = img.height()
# 归一化坐标,使中心点为(0,0)
norm_x = (x_center - img_w / 2) / (img_w / 2)
norm_y = (y_center - img_h / 2) / (img_h / 2)
# 将坐标打包成字符串并通过串口发送
# 格式: "X:0.12Y:-0.45\n"
data_str = "X:%.2fY:%.2f\n" % (norm_x, norm_y)
uart.write(data_str)
print(data_str) # 在OpenMV IDE上打印
print("FPS %f" % clock.fps())
步骤 2:Arduino 端编程 (飞行控制)
- 安装库:在 Arduino IDE 中,你需要安装
MPU6050库(用于读取姿态)和Servo库(用于生成 PWM 信号控制电机)。 - 连接硬件:
- OpenMV 的
TX-> Arduino 的RX(D0) - OpenMV 的
GND-> Arduino 的GND - MPU6050 的
SDA-> Arduino 的A4 - MPU6050 的
SCL-> Arduino 的A5
- OpenMV 的
- 编写 Arduino 代码:
#include <Wire.h>
#include <MPU6050.h>
#include <Servo.h>
// --- 初始化 MPU6050 ---
MPU6050 mpu;
// --- 初始化电机 (假设使用4个电机) ---
Servo motor1, motor2, motor3, motor4;
// 定义电机连接的引脚
const int motorPins[] = {9, 10, 11, 6}; // 示例引脚
// --- PID 控制参数 (需要根据你的无人机调试) ---
float Kp = 1.0, Ki = 0.02, Kd = 0.5;
float errorIntegral = 0, lastError = 0;
// --- 目标位置 (由OpenMV发送) ---
float targetX = 0.0;
float targetY = 0.0;
void setup() {
Serial.begin(115200); // 与电脑通信,用于调试
// Serial1.begin(115200); // 如果有额外的串口,用于与OpenMV通信
// 初始化 MPU6050
Wire.begin();
mpu.initialize();
if (!mpu.testConnection()) {
Serial.println("MPU6050 connection failed!");
while (1);
}
// 初始化电机
for (int i = 0; i < 4; i++) {
motorPins[i].attach(motorPins[i]);
motorPins[i].writeMicroseconds(1000); // 初始化为最小油门
}
Serial.println("System Ready");
}
void loop() {
// 1. 从 OpenMV 读取数据
if (Serial.available() > 0) {
String data = Serial.readStringUntil('\n');
parseData(data);
}
// 2. 读取 MPU6050 数据 (这里简化,实际需要融合陀螺仪和加速度计)
// int16_t ax, ay, az;
// mpu.getAcceleration(&ax, &ay, &az);
// float currentX = ax / 16384.0; // 归一化
// float currentY = ay / 16384.0;
// 为了简化,我们假设当前姿态就是目标姿态
// 在实际项目中,你需要实现完整的姿态融合和PID控制
float currentX = 0;
float currentY = 0;
// 3. 计算误差
float errorX = targetX - currentX;
float errorY = targetY - currentY;
// 4. PID 计算 (这里只对X轴做示例)
errorIntegral += errorX;
float errorDerivative = errorX - lastError;
float pidOutput = Kp * errorX + Ki * errorIntegral + Kd * errorDerivative;
lastError = errorX;
// 5. 根据PID输出调整电机 (这是简化的差速控制)
int baseThrottle = 1100; // 基础油门
int motorSpeed1 = baseThrottle + pidOutput * 100; // 左前
int motorSpeed2 = baseThrottle - pidOutput * 100; // 右前
int motorSpeed3 = baseThrottle - pidOutput * 100; // 左后
int motorSpeed4 = baseThrottle + pidOutput * 100; // 右后
// 6. 限制电机速度范围 (如 1000-2000)
constrain(motorSpeed1, 1000, 2000);
constrain(motorSpeed2, 1000, 2000);
constrain(motorSpeed3, 1000, 2000);
constrain(motorSpeed4, 1000, 2000);
// 7. 设置电机速度
motor1.writeMicroseconds(motorSpeed1);
motor2.writeMicroseconds(motorSpeed2);
motor3.writeMicroseconds(motorSpeed3);
motor4.writeMicroseconds(motorSpeed4);
// 打印调试信息
Serial.print("Target: X="); Serial.print(targetX); Serial.print(" Y="); Serial.println(targetY);
Serial.print("Output: "); Serial.println(pidOutput);
delay(50); // 控制循环频率
}
void parseData(String data) {
int xIndex = data.indexOf("X:");
int yIndex = data.indexOf("Y:");
if (xIndex != -1 && yIndex != -1) {
targetX = data.substring(xIndex + 2, yIndex).toFloat();
targetY = data.substring(yIndex + 2).toFloat();
}
}
实际应用与项目灵感
- 视觉跟踪:如上所述,让无人机跟踪一个特定颜色的球、你的手或人脸。
- 巡线飞行:在地面画上黑线,摄像头识别线条,引导无人机沿着路线飞行。
- 颜色分类:在空中抓取不同颜色的物体,并投放到对应颜色的区域。
- 姿态识别:使用 OpenMV 识别特定手势(如“起飞”、“降落”),通过串口发送给无人机执行。
- 航拍与传输:使用 ESP32-CAM 实现 WiFi 图传,将实时画面传到手机 App,打造一个廉价的 FPV 无人机。
挑战与注意事项
- 稳定性:视觉数据会受到光照、背景干扰等因素影响,导致数据抖动,需要在代码中加入滤波算法(如卡尔曼滤波)来平滑数据。
- 延迟:串口通信、图像处理和 PID 计算都会引入延迟,延迟过高会导致无人机控制不稳定,产生振荡。
- PID 调试:PID 参数是项目成功的关键,需要花费大量时间进行耐心调试。
- 电源管理:摄像头和 Arduino 都会消耗电力,要确保电池能提供足够的电流,并且电压稳定。
- 安全第一:在调试时,务必做好保护措施(如安装桨叶保护罩),并在开阔、无人的地方进行测试。
希望这份详细的指南能帮助你开启 Arduino 无人机摄像头项目的旅程!祝你成功!

