1. 项目概述与核心思路
几年前,当我第一次尝试让机器人“看见”并跟随一个物体时,我被复杂的摄像头标定、图像处理和实时计算问题搞得焦头烂额。直到我遇到了Pixy2这款视觉传感器,它把复杂的计算机视觉算法打包进了一个火柴盒大小的模块里,让在资源有限的Arduino上实现物体跟踪变得触手可及。今天要分享的这个“Pixy2Bot”项目,就是一个典型的“化繁为简”的实践:用最少的硬件(Arduino Uno、电机驱动板、两个连续旋转舵机和一个Pixy2),搭建一个能稳定跟随彩色物体的轮式机器人。它没有复杂的云台机构,核心逻辑就是“看到目标就前进,目标偏左就左转,目标偏右就右转”,简单直接,却完美诠释了感知-决策-执行这一机器人核心闭环。
这个项目非常适合对机器人、嵌入式系统和计算机视觉感兴趣的初学者。你不需要深厚的数学背景或OpenCV经验,Pixy2已经帮你处理好了最难的图像识别部分。你需要做的,是理解如何将传感器的“看见”转化为电机的“行动”,并解决其中遇到的硬件连接、供电和代码调试等实际问题。通过完成它,你不仅能收获一个会跟着你跑的酷炫小机器人,更能透彻理解嵌入式系统中传感器数据流、电机控制逻辑和简单PID(比例-积分-微分)思想的应用。下面,我将从设计思路开始,一步步拆解这个项目的每一个细节。
1.1 为什么选择Pixy2与连续旋转舵机?
在开始动手之前,搞清楚为什么选用这些核心部件至关重要。这决定了整个系统的可行性和稳定性。
Pixy2的核心优势在于“专用”与“高效”。传统的做法是在Arduino上连接一个普通摄像头模块,然后试图在单片机上运行图像处理算法,这对Uno的2KB RAM和16MHz主频来说是几乎不可能完成的任务。Pixy2内部集成了专用的图像处理芯片,它能在本地实时识别预设颜色的色块,并直接输出目标物体的坐标、宽度、高度等结构化数据,通过简单的串口或I2C发送给Arduino。这意味着Arduino只需要处理几条简单的数据包,就能知道“目标在哪”,计算负担极小。Pixy2默认使用基于HSV颜色空间的过滤算法,通过配套的PixyMon软件可以轻松“训练”它识别任何一种颜色,抗光线变化能力也比简单的RGB阈值法强得多。
连续旋转舵机(Continuous Rotation Servo)则是轮式机器人的理想动力单元。它与我们常见的角度舵机(0-180度旋转)内部结构相似,但移除了机械限位,并且修改了控制信号的含义:一个特定的脉冲信号(通常是1.5ms)代表停止,比它短代表全速反转,比它长代表全速正转。这样一来,它本质上就变成了一个带有内置驱动电路、可正反转、且速度可控的直流电机。对于这个小车来说,使用两个连续舵机分别驱动左右轮,构成差速转向系统,是最简洁的方案。我们无需额外的电机驱动芯片(舵机内部已有H桥),控制代码也极其简单,只需使用Arduino的Servo库生成不同脉宽的PWM信号即可。
整个系统的逻辑链条非常清晰:Pixy2持续扫描前方,一旦发现我们训练过的色块,就会计算出该色块中心点的X坐标(假设画面宽度为0~315像素)。Arduino读取这个X坐标,与画面中心点(例如157像素)进行比较。如果目标在中心左侧,则让左轮反转、右轮正转,实现左转;反之则右转;如果目标非常接近中心,则让两个轮子都正转,直行前进。这就是一个最基础的比例(P)控制器:误差(目标位置与中心的偏差)决定了转向的幅度和方向。
2. 硬件清单与连接详解
一份清晰准确的物料清单和连接图是成功的一半。这里我会在原清单基础上,补充一些关键的选择理由和替代方案,并详细解释每一个连接步骤背后的电气原理。
2.1 硬件清单深度解析
主控与驱动:
- Arduino Uno:项目基石。其丰富的数字I/O口和稳定的5V/3.3V输出,足以应对本项目。兼容板(如Elegoo Uno R3)同样可用,但务必确保其引脚定义与官方一致。
- Arduino电机驱动扩展板(Motor Shield):这是关键。它并非用来驱动舵机(舵机直接接数字口),而是为了解决电源问题。舵机,尤其是两个同时工作,启动瞬间电流很大,很容易导致Arduino板载的5V稳压器过载重启。电机驱动板通常带有独立的电源输入接口和稳压电路,可以将电池电源(如7.4V LiPo)直接接入,并由该板为Arduino和舵机提供稳定、充足的电力。原清单中提到的连接电池到电机驱动板正是此意。如果没有电机驱动板,你必须使用一个独立的外接5V/2A以上的稳压模块为舵机供电,并将此模块的地(GND)与Arduino的GND相连。
动力与视觉:
- 连续旋转舵机 x2:推荐FS90R、SG90连续旋转版等常见型号。务必在购买时确认是“连续旋转”(Continuous Rotation)而非“标准180度”。收到后最好先用一段测试代码校准其中位点(停止点),因为每颗舵机可能有微小差异。
- Pixy2:核心传感器。注意它有多个版本,选择基础版即可。它可以通过多种方式与Arduino通信,本项目使用最简单的UART(串口)方式,占用数字口0(RX)和1(TX)。这意味着在上传代码时,需要暂时拔掉Pixy2与这两脚的连接,否则会造成串口冲突,上传失败。
- 电源系统:
- 电池:推荐使用2S锂聚合物电池(7.4V),容量在1000mAh左右,既轻便又能提供足够电流。绝对不要使用9V方块电池,其电流输出能力完全无法驱动两个舵机。
- 锂电保护器(LiPo Saver):这是一个安全装置,监测电池电压,当电压过低时自动切断输出,防止锂电池因过放而损坏。对于任何锂电项目,这都应是标准配置。
- 船型开关:用于控制整个系统的电源通断,方便调试。
机械结构:
- 轮子与轮胎:乐高轮毂和O型圈轮胎是一个巧妙且易得的组合,提供了良好的抓地力和适配性。你也可以使用任何能与舵机输出轴匹配的小轮子。
- 万向球轮(Ball Caster):作为机器人的前支撑点或后支撑点,提供灵活的多方向转动,确保小车在差速转向时顺畅无阻。这是两轮差分机器人底盘的标准配置。
- 车体平台:乐高积木、3D打印件、甚至一块切割好的亚克力板都可以。核心要求是坚固、平整,并能稳妥固定所有电子元件。
2.2 电路连接步骤与避坑指南
连接顺序很重要,遵循“先信号后电源,先模块后整合”的原则,可以避免很多问题。
步骤一:核心模块互联
- 将电机驱动扩展板插到Arduino Uno上,确保引脚完全对准。
- 连接Pixy2到Arduino:使用4根杜邦线(母对母)。Pixy2的引脚通常有丝印标注:
- Pixy2GND→ ArduinoGND
- Pixy2VIN→ Arduino5V(注意:是5V,不是VIN。Pixy2工作电压为5V)
- Pixy2SOP1→ ArduinoDigital Pin 0 (RX)
- Pixy2SOP2→ ArduinoDigital Pin 1 (TX)
注意:这个连接占用了Arduino的硬件串口。因此,在通过USB线给Arduino上传程序之前,必须暂时拔掉Pixy2连接在Pin 0和Pin 1上的线,否则代码上传会失败。上传完成后,再重新接回。
步骤二:动力系统连��
- 将两个连续旋转舵机分别连接到电机驱动板。通常驱动板上有两组标准的3针舵机接口(标有SERVO 1, SERVO 2等),或者有排针输出。根据原理图:
- 右轮舵机→ 电机驱动板的输出5(Out 5)
- 左轮舵机→ 电机驱动板的输出6(Out 6)每个接口的三根线分别是:信号(S)、电源正极(V+)、地(GND)。舵机的三根线颜色通常为:橙色(信号)、红色(电源)、棕色(地)。
- 关键检查:正如原项目提醒的,不同厂家电机驱动板上的3针插座顺序可能不同!最常见的顺序是
[S, V+, GND],但也可能是[GND, V+, S]。务必用万用表确认:将万用表打到通断档,测量插座引脚与电机驱动板上明确标注的“GND”焊盘之间的连通性,先找到地线引脚。剩下的两个,通常靠外侧的是V+(连接驱动板电源输入),中间的是信号(S)。如果顺序不匹配,你需要用杜邦线跳接,确保舵机插头的信号线对准插座的信号引脚。
步骤三:电源系统集成
- 将船型开关串联到电池的正极输出线上。这样你可以通过开关控制整个系统的供电。
- 将锂电保护器的输入端接到开关后的电池正极,地线接电池负极。保护器的输出端就是受保护的电池电源。
- 将保护器的输出正负极,连接到电机驱动板的电源输入端子(通常标有“PWR IN”或“VIN / GND”)。注意正负极不要接反!
- 至此,当打开船型开关,电力流经保护器进入电机驱动板,驱动板再为Arduino和其上的舵机接口供电。整个系统的电力脉络就打通了。
步骤四:机械组装将乐高轮子牢固安装到舵机的输出轴上。把万向球轮安装在小车底盘前部或后部的中心位置。最后,用扎带或螺丝将Arduino(连同驱动板)、电池、Pixy2等所有部件稳妥地固定在底盘上,确保重心较低且分布均匀,避免行驶中翻车。
3. Pixy2配置与颜色训练
硬件连接好后,下一步是让Pixy2“认识”你想要它跟随的物体。这需要通过其官方配置工具PixyMon来完成。
3.1 初始设置与固件检查
- 从Pixy2官网下载并安装PixyMon软件。
- 使用随Pixy2附带的USB线,将其直接连接到电脑。此时Pixy2由USB供电,并作为一个独立的USB设备与PixyMon通信。
- 打开PixyMon软件。如果一切正常,你会在主窗口看到Pixy2摄像头实时捕捉到的画面。首次连接时,软件可能会提示更新固件,建议按照提示完成更新,以获得最新功能和稳定性修复。
- 在PixyMon中,切换到“Configure”标签页。这里我们需要关注两个重要设置:
- 接口(Interface):确保设置为“UART (Asynchronous Serial)”。这告诉Pixy2将通过串口与Arduino通信。
- 数据输出(Data out):选择“Detected objects only”或“Arduino”模式。这个模式只输出识别到的色块数据,数据量最小,最适合本项目。不要选择“Rich data”模式,那会输出大量调试信息,拖慢通信速度。
- 设置完成后,点击“Save”按钮,将配置保存到Pixy2的闪存中。这样即使断电,下次启动它也会保持UART通信模式。
3.2 训练颜色签名
这是最关键的一步,决定了机器人能跟随什么。
- 在PixyMon主窗口,将你想要跟随的物体(比如一个亮红色的水杯、一个绿色的网球)放在Pixy2前方,确保光线充足且均匀。
- 点击窗口下方的“Action”按钮,选择“Set signature 1...”(设置1号签名)。你也可以选择其他签名编号,最多7个。
- 此时会出现一个十字准星。拖动十字准星,在画面中你的目标物体上框选一个区域。这个区域应尽可能纯净地包含目标颜色,避免包含背景杂色。
- 框选后,Pixy2会分析该区域的颜色特征,并生成一个“颜色签名”。你会看到画面中所有符合该颜色的区域被高亮显示(默认是粉红色轮廓)。
- 微调技巧:如果识别区域过多(包含了背景中相似颜色)或过少(物体部分区域没识别到),你可以返回“Configure”页,调整该签名对应的颜色阈值(Color Codes)。稍微提高阈值可以过滤掉相似但不完全一样的颜色,让识别更精确。这是一个反复试验的过程,需要在你的实际环境光线下进行。
- 你可以重复步骤2-5,训练多个签名(比如签名1是红色,签名2是蓝色),这样你的机器人就可以切换跟随不同颜色的物体。
完成训练后,断开Pixy2与电脑的USB连接,将其重新按前述方式连接到Arduino。现在,Pixy2已经准备就绪,会持续通过串口向Arduino发送它识别到的色块的位置信息。
4. Arduino代码解析与调试
有了能“看见”的Pixy2和能“行动”的舵机,我们需要编写“大脑”的决策逻辑。原项目提供了代码文件,但其中可能包含一些需要根据实际情况修改的编译问题。我们来彻底拆解这份代码。
4.1 代码框架与核心逻辑
一个典型的Pixy2跟随代码包含以下几个部分:
#include <Pixy2.h> // 引入Pixy2库 #include <Servo.h> // 引入舵机库 // 定义引脚和常量 #define LEFT_SERVO_PIN 6 // 左舵机信号线接的数字引脚 #define RIGHT_SERVO_PIN 5 // 右舵机信号线接的数字引脚 #define CENTER_X 157 // Pixy2画面中心的X坐标(对于320x200分辨率) // 创建对象 Pixy2 pixy; Servo leftServo; Servo rightServo; // 全局变量 int leftSpeed = 90; // 舵机停止值(需校准,通常接近90) int rightSpeed = 90; int speedOffset = 20; // 转向时的速度增量 void setup() { Serial.begin(115200); // 初始化串口,用于调试输出 pixy.init(); // 初始化Pixy2,默认使用硬件串口 leftServo.attach(LEFT_SERVO_PIN); rightServo.attach(RIGHT_SERVO_PIN); stopRobot(); // 启动时先停止 } void loop() { static int lastX = 0; // 记录上一次目标位置,用于滤波 pixy.ccc.getBlocks(); // 获取识别到的色块数据 if (pixy.ccc.numBlocks) { // 如果识别到至少一个色块 int targetX = pixy.ccc.blocks[0].m_x; // 取第一个色块的中心X坐标 // 简单的低通滤波,防止因识别抖动导致小车剧烈晃动 targetX = (targetX * 0.3) + (lastX * 0.7); lastX = targetX; // 计算目标与中心的偏差 int error = CENTER_X - targetX; // 根据偏差大小和方向,设置左右轮速度(比例控制) if (abs(error) < 20) { // 偏差很小,直行 leftSpeed = 90 - 30; // 假设校准后,小于90为前进 rightSpeed = 90 + 30; // 假设校准后,大于90为前进(取决于舵机安装方向) } else if (error > 0) { // 目标在中心左侧,需要左转 leftSpeed = 90 + speedOffset; // 左轮减速或反转 rightSpeed = 90 + speedOffset + 30; // 右轮加速正转 } else { // 目标在中心右侧,需要右转 leftSpeed = 90 - speedOffset - 30; // 左轮加速正转 rightSpeed = 90 - speedOffset; // 右轮减速或反转 } // 将速度值写入舵机 leftServo.write(leftSpeed); rightServo.write(rightSpeed); } else { // 没有识别到任何目标,停止运动 stopRobot(); lastX = 0; // 重置滤波值 } delay(30); // 控制循环频率,约30Hz } void stopRobot() { leftServo.write(90); // 写入停止值 rightServo.write(90); }核心逻辑解读:
pixy.ccc.getBlocks()获取最新一帧中所有识别到的色块,存储在pixy.ccc.blocks数组里���- 我们通常只跟踪最大的或第一个色块 (
blocks[0])。 error = CENTER_X - targetX是关键计算。如果目标在画面左边(targetX < CENTER_X),error为正,小车应左转。- 速度映射:连续舵机的
write函数输入值对应不同的脉冲宽度。通常,90是停止点,0-89是反向全速到停止,91-180是停止到正向全速。但这个中点值90需要校准,因为每个舵机有差异。 - 引入
speedOffset和条件判断,实现了一个简单的“死区”和比例控制。在死区内直行,超出死区则根据偏差比例调整左右轮速差。
4.2 编译问题解决与库文件修改
原项目提示了编译时可能遇到的问题,这非常常见,主要是因为Pixy2库的版本或Arduino IDE设置问题。
问题一:Pixy2UART.h文件中的Serial1错误。在较新的Pixy2库中,用于UART通信的类可能默认使用了Serial1(这是Arduino Mega、Leonardo等板子才有的第二个硬件串口)。但Uno只有一个硬件串口,就是Serial。
- 解决方法:找到你的Arduino库文件夹下的
Pixy2库。路径通常是文档/Arduino/libraries/Pixy2。打开src文件夹里的Pixy2UART.h文件。搜索Serial1,将其全部替换为Serial。保存文件。
问题二:Pixy2CCC.h文件中的变量未声明错误。这可能是因为库中某些全局变量的声明方式与你的编译器设置不兼容。
- 解决方法:打开
Pixy2库src文件夹里的Pixy2CCC.h文件。在文件顶部附近,找到类似extern Block g_blocks[];的语句。如果这行被注释掉了或者没有,你可能需要手动添加变量声明。更稳妥的方法是,确保你下载的Pixy2库版本与Arduino IDE版本兼容。从Pixy2官网或Arduino库管理器安装最新版库,通常能避免此问题。
问题三:舵机校准。在将舵机安装到车上之前,强烈建议先进行校准。
- 写一个简单的测试程序,让舵机运行到
90。#include <Servo.h> Servo myServo; void setup() { myServo.attach(9); } // 临时接到引脚9 void loop() { myServo.write(90); delay(10000); } // 上电后观察10秒 - 观察舵机是否完全静止。如果它缓慢旋转,说明90不是它的停止点。你需要微调这个值。可能是88,也可能是92。记下这个准确的停止值,在正式代码中替换掉所有的
90。
4.3 参数调试与性能优化
代码烧录后,小车可能不会表现得尽如人意。这时就需要现场调试:
- 转向过于灵敏或迟钝:调整
speedOffset和直行速度值。增大speedOffset会让转向更猛;减小则更柔和。调整直行速度(代码中的30)可以改变小车前进的快慢。 - 在目标附近来回振荡:这是典型的“过冲”现象。可以尝试:
- 增大死区:将
if (abs(error) < 20)中的20调大,比如到30。这样小车在接近目标时更早进入直行状态。 - 加入微分(D)控制:记录上一次的误差,本次控制量不仅与当前误差成比例,还与误差的变化率成比例。这能有效抑制振荡。这需要更复杂的代码,但网上有很多Arduino PID库可以参考。
- 降低循环频率:适当增加
delay(30)的值,让系统反应慢一点,有时反而更稳定。
- 增大死区:将
- 丢失目标后原地打转:在
else(未识别到目标)分支中,除了停止,还可以让小车缓慢原地旋转(一个轮正转,一个轮反转)进行搜索,直到重新发现目标。
5. 系统集成测试与故障排查
当所有部分准备就绪,进入激动人心的总装测试阶段。遵循系统化的测试流程,可以高效定位问题。
5.1 分模块测试流程
不要一次性组装完就上电,应分步验证:
- 供电测试:只连接电池、开关、保护器和电机驱动板。用万用表测量驱动板输出给Arduino的5V引脚电压是否稳定正常。打开/关闭开关,确认电源控制有效。
- Arduino与Pixy2通信测试:连接Arduino和Pixy2(注意上传代码时要断开RX/TX)。上传一个简单的串口测试程序,读取Pixy2数据并打印到串口监视器。你应该能看到当有色块出现在镜头前时,串口输出类似
Detected: sig:1 x:120 y:80的数据。这证明视觉感知链路是通的。 - 舵机单独测试:将舵机单独接上电源和信号线(可先用一个独立的5V电源),用测试代码控制其正转、反转、停止,确认每个舵机响应正确,且左右轮安装方向符合预期(即:相同的
write值应使小车直行,一个大于停止值、一个小于停止值应使小车转向)。 - 集成静态测试:将所有部件连接好,但抬起小车,让轮子悬空。上电,用手在Pixy2前移动色块,观察两个轮子的转动方向是否符合逻辑(色块左移,小车应左转,即右轮正转、左轮反转或减速)。
- 地面动态测试:将小车放在空旷平整的地面进行实测。从简单的开始,比如让小车跟随你手中的色块缓慢移动。
5.2 常见问题与解决方案速查表
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 上电后无任何反应 | 1. 开关未打开或损坏。 2. 电池没电或保护器触发。 3. 电源线连接松动或反接。 | 1. 检查开关通断。 2. 用万用表测量电池输出电压,检查保护器状态灯。 3. 重新检查所有电源连接,特别是电机驱动板的电源输入端子。 |
| Pixy2指示灯不亮 | 1. Pixy2供电错误(接了VIN而非5V)。 2. Arduino未给Pixy2供电。 | 1. 确认Pixy2的VIN引脚接的是Arduino的5V。 2. 测量Arduino 5V引脚是否有输出。 |
| 串口监视器无Pixy2数据 | 1. Pixy2未设置为UART模式。 2. RX/TX线接反。 3. 代码中串口波特率不匹配。 4. 上传代码时未断开Pixy2。 | 1. 用PixyMon检查并保存UART设置。 2. 交换Pixy2的SOP1/SOP2与Arduino的0/1引脚连接。 3. 确保代码 Serial.begin()的波特率与PixyMon中设置的波特率一致(默认115200)。4. 牢记上传代码前拔掉RX/TX线。 |
| 舵机不转或抽搐 | 1. 供电不足(最主要原因)。 2. 信号线接触不良。 3. 舵机中位点未校准。 4. 电机驱动板舵机接口顺序错误。 | 1.重点检查:使用独立大电流5V电源测试舵机。确保电池电量充足(7.4V LiPo)。 2. 重新插拔舵机信号线。 3. 运行舵机校准程序,找到准确的停止值。 4. 用万用表确认电机驱动板上舵机接口的引脚顺序。 |
| 小车行为与预期相反 | 1. 左右舵机安装方向反了。 2. 代码中左右轮速度映射逻辑写反。 3. Pixy2画面坐标系理解错误。 | 1. 交换左右舵机的信号线。 2. 检查代码中 error的计算公式(CENTER_X - targetX),如果反了,就改为targetX - CENTER_X。3. 确认 targetX是色块中心的X坐标,且画面最左是0,最右是最大值。 |
| 跟随不稳定,剧烈抖动 | 1. 机械结构松动。 2. 代码中没有滤波,对噪声敏感。 3. 比例控制参数( speedOffset)过大。4. 环境光线变化影响Pixy2识别。 | 1. 紧固所有机械连接。 2. 在代码中加入对 targetX的简单滤波(如示例中的加权平均)。3. 减小 speedOffset,增大死区阈值。4. 在光线稳定的环境下测试,或重新训练颜色签名。 |
| 代码编译错误 | 1. 缺少必要的库(Pixy2, Servo)。 2. 库文件存在上述的 Serial1等问题。 | 1. 通过Arduino IDE的库管理器安装官方Pixy2库和标准Servo库。2. 按4.2节所述修改库源文件。 |
5.3 进阶优化与扩展思路
当你的基础版机器人能稳定工作后,可以考虑以下方向进行升级:
- 增���云台跟踪:加入两个180度舵机构成Pan-Tilt云台,让Pixy2可以左右上下转动,这样小车不仅能跟随,还能持续将目标锁定在画面中央,实现更灵活的跟踪。
- 多目标与策略选择:修改代码,让机器人可以识别多个颜色签名,并制定策略(例如,优先跟随最大的目标,或者跟随特定颜色的目标)。
- 加入超声波避障:在车头加装HC-SR04超声波模块,在跟踪的同时检测前方障碍物,实现“跟随+避障”的复合功能。
- 无线遥控与模式切换:增加一个蓝牙模块(如HC-05)或2.4G射频模块,通过手机或遥控器切换机器人的工作模式(手动遥控/自动跟随)。
- 更高级的控制算法:将简单的比例(P)控制升级为完整的PID控制,让小车运动更加平滑精准。还可以尝试在跟踪中加入对目标大小(距离)的判断,实现“靠近”或“保持距离”的行为。
这个Pixy2Bot项目就像一把钥匙,为你打开了嵌入式视觉机器人世界的大门。从硬件连接到软件调试,从信号处理到控制逻辑,你遇到的每一个问题和解法,都是宝贵的实战经验。最重要的是享受这个过程,看着自己亲手打造的机器人第一次“认出”你并向你驶来时,那种成就感是无与伦比的。