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串口方式占用数字口0RX和1TX。这意味着在上传代码时需要暂时拔掉Pixy2与这两脚的连接否则会造成串口冲突上传失败。电源系统电池推荐使用2S锂聚合物电池7.4V容量在1000mAh左右既轻便又能提供足够电流。绝对不要使用9V方块电池其电流输出能力完全无法驱动两个舵机。锂电保护器LiPo Saver这是一个安全装置监测电池电压当电压过低时自动切断输出防止锂电池因过放而损坏。对于任何锂电项目这都应是标准配置。船型开关用于控制整个系统的电源通断方便调试。机械结构轮子与轮胎乐高轮毂和O型圈轮胎是一个巧妙且易得的组合提供了良好的抓地力和适配性。你也可以使用任何能与舵机输出轴匹配的小轮子。万向球轮Ball Caster作为机器人的前支撑点或后支撑点提供灵活的多方向转动确保小车在差速转向时顺畅无阻。这是两轮差分机器人底盘的标准配置。车体平台乐高积木、3D打印件、甚至一块切割好的亚克力板都可以。核心要求是坚固、平整并能稳妥固定所有电子元件。2.2 电路连接步骤与避坑指南连接顺序很重要遵循“先信号后电源先模块后整合”的原则可以避免很多问题。步骤一核心模块互联将电机驱动扩展板插到Arduino Uno上确保引脚完全对准。连接Pixy2到Arduino使用4根杜邦线母对母。Pixy2的引脚通常有丝印标注Pixy2GND→ ArduinoGNDPixy2VIN→ 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等或者有排针输出。根据原理图右轮舵机→ 电机驱动板的输出5Out 5左轮舵机→ 电机驱动板的输出6Out 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_Xerror为正小车应左转。速度映射连续舵机的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项目就像一把钥匙为你打开了嵌入式视觉机器人世界的大门。从硬件连接到软件调试从信号处理到控制逻辑你遇到的每一个问题和解法都是宝贵的实战经验。最重要的是享受这个过程看着自己亲手打造的机器人第一次“认出”你并向你驶来时那种成就感是无与伦比的。