简介针对2017年全国大学生电子设计大赛B题板球系统的完整开源工程涵盖嵌入式控制、传感器采集与图像处理等核心模块适合电子竞赛备赛者、嵌入式开发者及自动化控制方向学生深入学习也可作为相关课程设计与毕业设计的参考项目。资源共190个文件以C源文件与头文件为主体辅以Keil工程配置、备份调试文件及少量图片说明整体约5.96MB其中工程文件可直接打开查看图片示意了硬件组装与调试效果目录分类明确便于按需检索。目前已有1361人学习下载过该资源。工程代码包含PWM输出、超声波测距、编码器读取、激光检测等驱动模块以及定时器中断、SPI通信等底层配置可结合原理图直接进行二次开发。开放源码的方式保留了设计备份与构建记录方便对照生成文件理解编译流程对电赛控制系统类题目的方案搭建、外设初始化和代码组织都有直接参考价值。1. boardBallSystem 到底在做什么一场被名字低估的视觉闭环挑战2017年电赛B题的滚球控制系统圈内通常叫板球系统英文标题 boardBallSystem 暴露了它的真实工作量这不是“把球放在板子上别掉下来”而是让一个小球在一个二维倾斜平台上走出一条设定轨迹且轨迹由图像实时识别、由电机实时修正。很多人第一反应是“调个PID不就行了”实际动手才发现球根本不是“滚”上去的是“追”上去的——你永远在给一个滚动且无制动的对象做滞后补偿。这套系统的完整链路是摄像头识别小球坐标换算成平台目标倾角通过双轴电机驱动万向节或十字杆改变板面姿态让球朝指定方向加速或减速。非常典型的视觉伺服闭环。适合的人群很明确正在备战电赛、智能车或机器人竞赛的学生团队以及刚开始接触机器视觉与控制联合调试的嵌入式开发者。它的价值在于——这是少数能在实验室里把“图像处理延迟”和“控制响应带宽”同时逼到你面前的小系统调通它之后再看四轴、机械臂你会多一层直觉。2. 机械结构与传感器选型别让控制算法替机械结构背锅我见过太多队伍把时间全砸在PID调参上最后发现一个关键问题机械结构本身就是个大滞后环节。板球系统尤其如此因为你的执行器不是直接驱动小球而是先动板子板子再靠重力带动球。这个间接性的每一步都会消耗掉系统相位裕度。2.1 机械结构定版为什么大多数人死在自由度和回程差上主流的板球系统结构有两种一种是双轴万向节平台用一个球铰连接底座两个舵机或电机通过连杆推动平台倾斜另一种是十字滑轨或X/Y独立倾斜结构两个电机分别控制两轴的转动。电赛题目的要求通常允许两种存在但实际跑轨迹时差距很大。万向节方案的结构刚度好但两个轴的运动会互相耦合——你在X方向推板子时Y方向的重力分量也在变。工程上处理耦合的做法是“控制系统里解耦”但调参时你会明显感觉到两轴的沉降响应不一样。十字杆方案两个轴完全独立控制上清爽得多但结构件多、间隙多每个关节的虚位都会变成图像里球的随机漂移。我在做这套系统时选的是十字杆用了一个关键原则所有转动关节的间隙必须不大于0.5毫米否则你在图像里看到的球是在“微颤”PID无论如何都稳不住。还有一点经常被忽略板子表面的摩擦系数。板子的材质直接决定小球是否会出现“打滑”和“弹跳”。亚克力板太滑球在低速时会像溜冰一样不受控软木垫板摩擦力好但球的滚动阻力大需要更大的倾角来驱动。我最后用了亚克力板贴一层植绒布既保证了滚动通畅又让球的减速过程可控。摩擦不均比摩擦过大更致命——板面上如果有污渍或凹陷球每次经过相同位置时响应都不一样你会在图像数据里看到周期性“鬼飘”。2.2 传感器选型摄像头、角度传感器和电机怎么搭配视觉部分通常是用摄像头从上往下拍板面识别小球圆心。这里有个容易搞错的地方摄像头分辨率不是越高越好。200万像素已经足够因为你的控制帧率要求决定了图像处理必须跑得快。分辨率太高处理时间拉长整个环路的延迟变大球会更难控。我当时用的是一个普通的免驱USB摄像头640×480分辨率固定曝光模式能稳定输出30帧就够用。角度反馈方面舵机内置的电位器精度不够需要在关节处加装磁编码器或电位器做角度闭环否则电机前端的死区会让小球在一个小邻域内极限环振荡。电机选择建议用带减速箱的直流电机或者数字舵机。电赛限制电压所以电机的输出力矩和响应速度之间的平衡要提前算平台边长40厘米左右、球重约30克时舵机力矩建议在5千克·厘米以上。更关键的是舵机的刷新率——普通模拟舵机的刷新率只有50Hz也就是20毫秒才能响应一次角度指令这个延迟放在视觉闭环里很快就会察觉。数字舵机的刷新率可以到300Hz响应延迟大幅缩短是板球系统的更优选择。2.3 电气连接与供电一个隐形的翻车点电机启动瞬间的电流跌落是很多队伍调试时反复“重启”的幕后黑手。舵机在大力矩输出时电流可以到1A以上USB摄像头和控制板如果和电机共用同一路电源图像就会因为电压骤降出现横纹甚至黑帧。常见的做法是电源分两路一路给电机一路给控制板和摄像头两路电源的GND在单点连接。这个细节不花一分钱但能让你排查出很多“明明是控制有问题”的假象。3. 视觉识别与坐标换算把“看到球”变成“知道球在哪”板球系统的视觉不是做目标检测而是做目标定位。也就是说你不需要识别“这是什么”只需要稳定地输出“球心在哪里”。这决定了方案选型的天平深度学习不是首选传统图像处理的阈值分割加几何拟合才是最可靠、最快、且最容易被裁判认可的方案。3.1 用传统视觉识别小球阈值分割的工程边界常见做法是在板面四角贴黑色边框或固定标记先通过角点检测建立投影映射这样即使摄像头架得有倾斜也能把图像坐标转换到以板面为基准的世界坐标。我通常先用HSV颜色空间做二值化再用轮廓检测找圆形。HSV相比RGB对光照变化更鲁棒因为色相分量受亮度影响小。ball_color_low (0, 100, 100) ball_color_high (10, 255, 255) mask cv2.inRange(hsv_frame, ball_color_low, ball_color_high) mask cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel_5x5) contours, _ cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if contours: largest max(contours, keycv2.contourArea) (x, y), radius cv2.minEnclosingCircle(largest) ball_pos (int(x), int(y))这段代码的思路很直接先把图像从BGR转到HSV然后用颜色范围滤出小球候选区域。morphologyEx M打开操作是为了去除孤立噪点它可以消掉反光导致的细小白色区域。findContours拿到所有连通的白色块过滤掉面积太小的干扰最后用最小外接圆算出球心坐标。要注意的坑是HSV的低饱和度和低亮度阈值不能设得太死。当小球被板子阴影遮挡一角时红色或橙色的色相会略微偏移阈值范围需要保留10%的余量。白色球是最难做的因为任何反光都会让球和背景混淆这也是比赛时很多队伍最后改用红球的原因——不是说必须用红球但如果你在测试时发现白色球的识别帧率上不去尽早换球比换算法更省时间。3.2 坐标平滑与延迟滤波是双刃剑识别出来的球心坐标直接喂给PID会非常“吵”。摄像头本身的噪声加上滚动时的轻微振动会让球心位置每帧抖动2~3像素这在闭环里就会变成控制输出的高频抖动。常见的做法是加一个滑动窗口滤波或一阶低通滤波。ball_x_smooth ball_x_smooth * 0.6 ball_x_raw * 0.4 ball_y_smooth ball_y_smooth * 0.6 ball_y_raw * 0.4这行代码的系数选择是有讲究的。0.6/0.4意味着新位置占40%权重是一个折衷值。系数太小坐标很平滑但延迟变大系数太大噪声仍然明显。板球系统的视觉延迟本来就存在平滑滤波叠加的延迟如果超过100毫秒控制系统的相位裕度会被吃掉大半结果就是球一直在目标点附近来回震荡俗称“鬼畜”。我一般把这个低通系数放在0.5~0.7之间然后实测球从一个点走到另一个点的调节时间如果调节时间超过2秒就说明滤波太强了。还有一个优化方向是预测球的位置。在做直线轨迹跟踪时我们其实可以假定球的运动状态是近似匀速的用上一帧和当前帧的位置差推出下一帧的预估值。这个思路对圆形轨迹帮助不大但对走直线、折线帮助很明显因为它相当于给PID控制器提前“报信”。我自己的实现里只对直线轨迹做了位置预测预测系数同样是经验值增量不能超过当前帧位移的50%否则预测点会偏离真实值。3.3 坐标系映射摄像头必须正装还是斜装摄像头安装在板面上方70~80厘米左右视角略微倾斜是允许的只要板面四个角在图像里都可见。但正装的好处是坐标换算简单直接线性映射不需要做透视校正。很多队伍为了图省事直接把摄像头用胶枪固定在支架上结果板面稍微挪动一点整个映射就偏了。建议画一个定位标记在板面上每次开机先做一次角点检测自动计算出映射矩阵。这样即使比赛中途摄像头被碰歪也不需要重新手动标定。4. 控制系统方案与PID调参把位置环和速度环正确分层控制部分是整个板球系统最容易“看着简单、做着玄学”的地方。核心原因是你无法直接给球发指令只能通过改变板面倾角来改变球的加速度。这决定了系统的固有特性是二阶积分特性——倾角对应加速度速度是倾角的积分位置是速度的积分。对这种系统单环PID往往不够需要按串级结构来处理。4.1 控制模型为什么位置单环PID会疯狂超调先想清楚一个事如果你直接用位置误差作为PID的输入输出的是一整个倾角目标那么当球到达目标点时位置误差是零但球还有速度板面必须提前反向倾斜来刹车。P增益大了球在目标点附近来回冲P增益小了球在路上就走不动。这就是典型的二阶系统共振调参窗口非常窄。常见的解法是串级控制外环是位置闭环内环是速度闭环。位置外环输出的是目标速度速度内环再根据当前速度算出目标倾角。速度哪里来可以直接用图像差分算出来也就是两帧之间的位移除以时间间隔。如果你用的是MPU6050或编码器来测球的位置速度估算会更准确但对比赛而言图像差分已经足够。我用的是外环P加内环PI的结构。位置外环用纯P比例系数作用在位置误差上输出一个目标速度速度内环用PI把估算速度和目标速度的误差通过比例积分算出倾角指令。这个结构的好处是速度内环像一个“阻尼器”它天然抑制了位置的来回超调。关键是速度环的带宽要比位置环高3到5倍否则内环响应太慢外环看到的“速度”其实是滞后的。4.2 PID参数初始化与整定顺序抄作业也要知道为什么很多资料给出一套参数让你直接用但我建议先用以下方式自己走一遍。首先把位置环和速度环分开给小球一个初始速度然后让系统只运行速度环调整内环的P让小球速度能够稳定在目标值的80%左右再把I加上去消掉稳态误差。速度环调好后再启用位置外环这时候外环的P从小往大加观察球接近目标点时是否平稳减速。这里有一组比较靠谱的初始参数表适合30克小球、40厘米平台。实际使用时先照这个跑再按手感微调。调参的时候注意一个判断顺序先保证不振荡再追求快速性。振荡是必然存在的但如果振荡频率很高、幅度很小说明是内环刚度不够如果振荡是低频、幅度大说明是外环太激进跟内环无关。4.3 前馈与边界条件给PID装上“刹车灯”板球系统的边界条件很残酷球到达板边就跌落这意味着一部分目标轨迹会超出可跑区域。常见的做法是给位置控制加一个“虚拟边界”——当球离边界小于设定值比如板宽的15%时强制把该方向的目标速度限幅为反向。这个限幅值不能太硬否则球会在边界处弹开。另一个可选项是加速度前馈。如果目标是圆形轨迹球的向心加速度需要板面提供一个恒定倾角来维持。没有前馈时纯PID会在每个轨迹点不断修正误差表现为转角处冲出轨迹再拉回来。加了前馈后你直接把理论倾角叠加到PID输出上球会更贴轨迹。前馈量的计算是 v²/rv是目标线速度r是轨迹半径单位要统一成板面倾角对应的加速度。5. 避坑指南板球系统从裸板到能跑通的常见问题与排查这套系统踩坑的地方很集中下面这几条几乎覆盖了90%团队翻车的场景。每条都按“现象→原因→解决”的顺序写你可以在调试时对照排查。5.1 球在目标点附近持续振荡怎么调都稳不住现象是球到了目标点后不是停下来而是以小幅度高频往复运动像在抖。原因通常是视觉坐标平滑滤波的延迟太大叠加了控制输出本身的延迟形成了一个低阻尼的振荡环路。我见过有人把低通系数调到0.9这时候滤波器已经产生肉眼可见的滞后。解决方法是第一步把手放在球旁边观察图像里的十字光标是否比实际球晚半拍。如果滞后明显降低滤波系数到0.5重新测试。第二步检查控制周期如果整个控制循环在50毫秒以上说明主循环里图像处理占了大头需要优化处理逻辑把ROI缩小到球周围一个小区域而不是全图处理。5.2 球在板子的某一个特定区域突然失控现象是板面大部分区域工作正常唯独某个角落后球的响应异常而且每次到同一个位置都复现。这几乎可以锁定是硬件问题而不是控制问题。最常见的原因是板面不平或者是关节间隙在某个角度下突然吃掉了传动量。用一个水平尺或者手机上的水平仪把板面放在零倾角逐点按压四个角检查运动是否顺畅。如果某个角度卡顿拆开关节重新调整螺丝松紧度。如果是十字杆结构还要排查一个容易被忽略的点两轴在中位附近时连杆是否和球铰中心产生干涉。机械限位比控制限位可靠得多绝对不能指望程序里把倾角限制在某个范围就万事大吉。5.3 光线一变小球识别就开始跳动电赛赛场的光照通常和你实验室不一样尤其是头顶的LED灯和窗户自然光混在一起色温差别很大。现象是上午调好的阈值下午比赛就失灵。解决思路是不要在固定光线下调试而是引入一个自动曝光策略摄像头设置为固定曝光值而不是自动曝光。自动曝光会在画面亮度变化时主动调整这会让图像的颜色在HSV空间里漂移阈值形同虚设。固定曝光后即使画面偏暗HSV色相也基本稳定。再进阶一点的是做白平衡校正在板面角落贴一片标准白色色卡每次启动时自动计算白平衡增益。但比赛中往往不允许额外加装无关设备所以最简单的做法是用一块遮光布包裹整个支架营造一个光线稳定的暗环境。我的很多次比赛调试经验都证明用物理手段消除光线变化比算法鲁棒性更省心。5.4 球走圆弧时总在切点附近往外飘这是加速度前馈缺失的典型症状。球走直线没问题走圆弧就往外偏——因为球在弯道需要向心力而这个向心力只能靠板面倾角提供。纯PID只能在球已经偏出轨迹后才产生修正力所以看起来是“滞后地往外飘”。解决方法是给控制器加上前馈项按目标轨迹的理论加速度计算额外倾角。如果你的控制输出是以角度为单位那计算方式是倾角前馈等于 v²/(r×g)v是目标线速度r是圆弧半径g是重力加速度。前馈量可以先算出来后乘以0.8再在实际运行中微调。注意前馈只能补偿牵引力不能补偿轨迹的初始误差所以它不能替代PID只能作为叠加项。5.5 换上备用电机后参数全部失效现象是调试好的PID参数在换了一个电机或舵机后同样的板子跑起来变得很“肉”响应明显变慢。原因是不同电机的减速比、齿隙和响应时间不一样。伺服系统的响应带宽变了PID的增益自然也要跟着变。遇到这种情况不要纠结参数应该先重新测量系统开环响应——给一个阶跃倾角指令记录小球从静止到达最大速度的时间。这个时间称为系统延迟如果它比之前大了20%以上就需要把所有PID增益按比例缩小。6. 调好的系统如何验证用它压出控制系统的真实边界最后聊一个我常用的验证方法。大部分人调试板球系统的方法就是“让它跑一个圆看它圆不圆”。这个判断太模糊你没法定量地知道问题在哪。我习惯用定点往返测试来压边界Step 1 在板面上以坐标方式设定8个目标点程序控制小球依次从A点移动到B点再返回A点。 Step 2 记录每次到达目标点时的最大过冲量单位是毫米。用图像坐标的像素偏差乘以映射比例换算。 Step 3 重复10次求出平均过冲量和标准差。如果标准差大于平均值的50%说明系统里存在随机扰动优先检查机械间隙和滤波稳定性。这个测试的价值在于它可以把整个系统的性能压缩成一个数字往返时间、平均过冲、稳态抖动幅度。不同参数之间的对比就变得非常直观不再靠手感拍板。另一个验证技巧是加“斜坡激励”而不是阶跃激励。阶跃目标位置会让球的初速度为零系统在最平稳的状态下启动测试不出动态性能。斜坡激励是让目标点以恒定速度移动球需要持续跟踪——这会逼出系统的速度误差和相位滞后。你会发现同一个系统在低速斜坡下表现很好提高速度后开始拉出弧线这个“拉弧”的速度阈值就定义了系统的真正能力上限。做完这些测试你会对项目的上限和下限都有体感。我当年把系统调到能稳定跑一个直径25厘米的圆之后又花了两个晚上压边界才发现原来系统在反向切换时有一小段“死区”没有被PID覆盖。这个死区不是控制算法的问题而是舵机在中位附近的齿轮回程差——机械问题优化完后代码一行没改跑圆误差直接降了40%。所以我的习惯一直是先怀疑机械结构再怀疑视觉延迟最后才是PID参数。希望帮到你。本文还有配套的精品资源点击获取