简介:2022年广东省大学生电子设计竞赛三等奖作品——智能送餐机器人完整项目包,面向电子设计、机器人竞赛参赛者和嵌入式系统学习者。项目集合了系统设计方案、软件源码与调试环境配置,覆盖感知、控制、通信等模块,可帮助读者快速理解功能型服务机器人的实现思路,适用于备赛参考与二次开发。资源共128个文件,压缩包大小约26.15MB。主要文件类型包括Python及C++源码、Arduino程序、ROS launch/yaml配置、微信小程序前端(wxml/wxss/js/json)以及多张PNG/JPG设计示意图,既有核心控制代码,也有上位机交互界面与可视化资料,便于按模块对照学习。目前已有50人学习下载。这份资料能让参赛者直接获得一套可参考的赛题完整方案,从框架搭建到细节实现均有迹可循;对于准备智能机器人、嵌入式系统类竞赛的学生,是集文档、源码、交互界面于一体的实用参考,具有较高的借鉴与扩展价值。 这个项目是我在2022年广东省大学生电子设计竞赛里的参赛作品,定位就是智能送餐机器人。当时拿到题目,脑子里第一反应是:这不就是把小车加上机械臂再让它跑起来吗?真正动手之后才发现,把这句“跑起来”变成稳定跑完整个赛道,背后全是细节。团队四个人花了两周时间搭完硬件,又花了两周反复调软件,最后拿了个三等奖。回头看这个成绩,不算亮眼,但整个项目从方案选型到现场调试,踩过的坑和摸出来的经验,我觉得比奖项本身更值得记一笔。

这篇文章我会把当时整个项目是怎么拆解、怎么选型、怎么实现以及怎么踩坑的,完整复盘一遍。内容不会写成比赛说明书,而是偏实战记录,适合正在准备电子设计竞赛、智能车比赛,或者想自己做一台送餐机器人的朋友参考。哪怕你还没开始碰单片机,只要跟着思路走一遍,也能搞清楚一台“能送餐”的机器到底需要解决哪些问题。

1. 项目拆解:从题目到需求

1.1 先别急着选硬件,把得分点拆开

很多队伍拿到“智能送餐机器人”这种题目,第一件事就是打开网购平台找底盘、找机械臂,这其实是最容易走偏的一步。竞赛题目不是企业产品需求,它本质上是“在限定场地、限定时间内完成规定任务”的工程挑战,所以第一步永远是把题目里的得分点拆出来。

当时我们反复读题,总结出几个核心考核方向:第一,机器人能不能沿着规划路线稳定行走,这里涉及底盘运动控制和定位;第二,能不能识别送餐目标点,通常场地里会有模拟餐桌、餐盘或标签,涉及视觉或传感器检测;第三,能不能完成餐盘的抓取或放置动作,涉及机械结构和执行机构的可靠性;第四,整套系统在现场能不能快速恢复,因为在比赛现场经常会出现突发状况,你不可能像在实验室一样反复改代码。

把这些需求翻译成工程模块,就变成了移动底盘、传感器导航、视觉识别、机械执行和主控逻辑五大部分。分好模块以后,团队每个人负责一块,进度才推得动。我们当时就是没做这一步拆分,前三天全在讨论“要不要上ROS”,浪费了不少时间。后来把目标收敛为“先跑通一趟完整送餐”,事就简单了。

1.2 整体方案选型:别迷信高端平台

选型这件事,方向比性能重要。当时我们内部争论过两套方案。一套是树莓派加ROS,激光雷达建图导航,听着很唬人,Walkthrough看起来也完备。但问题是我们四个人里没有一个真正系统性学过ROS,光是环境配置、节点通信、TF变换这些就够吃一壶,更别说比赛现场要是调度出了问题,可能连日志都看不明白。

另一套是STM32做主控,OpenMV做视觉,传感器用灰度循迹加超声波避障,机械部分用舵机加滑台。这套方案的优势在于每个模块都相对独立,可以用最简单的逻辑把整条链路打通。我们最终选了这套,不是因为技术上有多高级,而是它把“工程不确定性”压缩到了最低。评委看的是你能不能稳定完成任务,不是看你用了多贵的板子。

具体分工是:STM32F103C8T6负责底盘运动、传感器采集、执行机构控制和状态机调度,OpenMV负责识别餐桌编号和二维码,两者通过串口通信。机器人身上没有用嵌入式Linux,也就少了掉电文件损坏、开机启动慢这些麻烦。事实证明,这个选择在现场救了我们很多次,有一次隔壁队树莓派启动花了将近半分钟,我们这边按下开关三秒就能开始跑。

2. 核心硬件与机械结构

2.1 车体与机械臂:越简单越可靠

送餐机器人的底盘,我们一开始想上麦克纳姆轮,毕竟全向移动看起来很灵活。但后来想了下,比赛场地大概率是平整的KT板或地砖,路线也都是规则直线和弯道,用麦克纳姆轮反而引入了额外的打滑和坐标系换算问题。普通双轮差速加两个万向支撑轮就够用了,控制逻辑简单,轮胎特性也稳定。最后底盘用的是两块铝合金板加四个铜柱搭的,前轮是万向轮,后轮是两个带编码器的直流减速电机,驱动轮径选65mm,电机减速比1:30,速度上限大概能到0.8m/s,但实际比赛时只跑了0.3m/s左右,这个速度下循迹和避障都比较稳。

机械臂是重头戏。当时看过很多队伍用六自由度机械臂,能夹杯子能倒水,看起来很帅,但问题也明显:自由度越多,运动学解算越复杂,任何一点舵机误差都会被放大,最后往往连一个简单的“放到指定位置”都做不到。我们最后选择的是“升降滑台+餐盘托架”的结构,用一根丝杆加步进电机控制升降,托架是一个L型亚克力板,餐盘直接放在托架上。这样做的思路是:比赛要求的动作是“把餐盘送到对应餐桌”,并不需要模拟人手去捏住杯子,托架比夹爪可靠得多,因为夹爪要考虑抓取位置、夹持力度、防滑,而托架只需要在到达目标后把餐盘放下。

这里有一个特别容易被忽略的细节:餐盘放在托架上以后,车身停止和起步的瞬间,餐盘会因为惯性滑动。我们一开始没有在托架表面做任何处理,结果放好的餐盘总是偏位。后来在托架上贴了一层防滑垫,又加了两个小的定位挡边,问题立刻解决。这个改动花了不到十块钱,但效果比调半天PID还明显。

2.2 电机驱动与电源分配:稳电是稳定性的地基

电源方案一开始我们走了弯路。最初图省事,直接用一块12V锂电池给电机和单片机供电,电机一转,单片机就复位,OLED屏幕跟着闪。后来检查发现,电机启动瞬间电流冲击能把电压拉低到7V左右,而单片机的稳压芯片根本扛不住这种波动。解决办法其实很基础:电机驱动单独从电池取电,主控和传感器通过降压模块供电,同时把各个模块的电源地线汇集到一个公共点,也就是共地。电机电源线也做了绞线处理,减少对信号的干扰。

驱动芯片选了TB6612FNG,没用L298N。TB6612的导通压降小,发热低,体积也小,最重要的是它的PWM频率响应比L298N好,配合STM32的定时器输出用起来很顺手。电机的速度控制信号频率放在10kHz,能听到轻微啸叫,但工作正常。编码器是霍尔式的,装在电机尾轴上,用于测速闭环。电源分配上,总体是12V电池进来看压,然后再分成两路,一路直接给TB6612,一路经DC-DC降到5V给主控、OpenMV和舵机,5V后面再经AMS1117降出3.3V给单片机外设。最初想着省一个降压模块,让舵机直接吃电池电压,结果舵机一抖动引发整机电压波动,后来老老实实加了独立稳压。

3. 软件与控制逻辑

3.1 主控流程:状态机比什么都好使

送餐流程看起来简单,但真要让机器人连续跑完“出发、循迹、识别、停靠、放盘、返回”这一整套动作,主控逻辑一旦写成“从上到下顺序执行”,中途任何一个传感器误判都会导致整个程序卡死。我们的做法是写一个状态机,每个环节对应一个状态,状态之间靠传感器事件触发切换。

状态机的大致划分是:IDLE、MOVE、DETECT、STOP、PLACE、BACK。在IDLE状态下等待启动指令,按一下按键进入MOVE,MOVE状态下循迹行驶,行驶中如果OpenMV发来“检测到目标餐桌”的消息,就切入DETECT,在DETECT里判断车头是否正对餐桌,确认后切入STOP并刹车,然后机械结构执行PLACE,最后BACK沿原路返回。这个逻辑的好处是,任何时刻系统只处于一个明确状态,调试时通过串口把当前状态打印出来,就能立刻知道机器人卡在哪一步。

状态机的实现代码并不复杂,但是要注意状态切换的“条件”必须带消抖和超时保护。比如识别信号不能只读一次,连续收到三次一致信号才确认切换,避免OpenMV一帧误判影响全流程。每个状态也可以加一个最大执行时间,超过时间强制回到IDLE并报警,这算是一种软件看门狗,现场演示时很管用。

3.2 PID巡线与避障:参数靠手感不如靠方法

路径循迹用的是五路灰度传感器,发射红外光并检测反射光线。场地上的引导线是黑色,背景是白色,传感器返回的模拟值经过阈值二值化以后,可以判断当前车体是偏左、偏右还是居中。一开始我只做了简单的“查表转向”,就是检测到最左侧传感器压线就往右打一点方向,反之亦然。这种开关量控制在直道上没问题,一进弯道就左右来回摆,车头像喝醉一样。

后来改成PID控制,误差定义为五个传感器加权偏移量,比如中间传感器权重0,左侧负值、右侧正值,把这个误差作为PID输入,输出作为左右轮的速度差。调参过程比较费时间,我和队友在实验室地胶上把速度分了三档,先调P,把P调到车过弯不冲出去;再加一点D抑制震荡;I加得很小,主要消除直道上的静态误差。实测下来,比例项在0.8左右,微分项在0.2左右,积分项只有0.02。参数范围没有普适性,但整定方法是一致的:先把I和D设成0,只加P直到系统开始震荡,然后把P乘以0.6作为初值,再加D让震荡收敛,最后加一点I修正稳态误差。

避障模块用的是超声波HC-SR04,安装高度大概8厘米,能探测到前方模拟的障碍物或动态走来的人。策略很简单:距离小于25厘米时减速,小于15厘米时停车并等待。送餐机器人不太需要做复杂的动态避障,毕竟场地就是在固定路线里,超声波的作用更多是安全保护,防止撞到评委或者观众。有一次现场测试,有人突然从赛道前走过,超声波检测到障碍后车直接刹停,等人走了才继续走,这个小细节在答辩时被评委问到了,他们觉得这个安全意识不错。

3.3 视觉识别:OpenMV当眼睛够用了

视觉部分是整个项目中我担心最多的地方。OpenMV是一款基于MicroPython的视觉开发板,用它做色块识别、二维码识别都比较方便,不至于像纯跑OpenCV那样写一大堆依赖。送餐场景里,每张模拟餐桌前贴一个二维码,二维码内容就是餐桌编号,比如“table1”“table2”。机器人巡线走到某个位置后,OpenMV开始扫描前方区域,一旦读到有效的二维码,就把编号和二维码中心相对画面的横坐标偏差发回STM32。

代码思路是:OpenMV在主循环里抓取画面,使用 find_apriltags() 或 find_qrcodes() 函数识别标签,识别到以后解析payload,同时计算标签中心坐标。如果标签中心在画面中心偏左,说明车头偏右,需要向左微调;反之亦然。这个调整通过串口发送一个简单的协议给主控,主控再控制左右轮差速,让车头逐渐对准标签方向。整个调整过程是一个开环微调,不需要做复杂的视觉伺服,因为我们的机械结构允许一定的对准误差,托架伸出去以后还有一点冗余空间。

这里要特别提醒:OpenMV对光照极其敏感。比赛现场灯光一般是演播室那种大功率射灯,角度一换,画面亮度变化非常明显,很容易导致标签识别断断续续。我们的解决办法是在OpenMV里固定曝光时间和白平衡,取消自动调节,同时给镜头加了一个可以转的偏振片。虽然颜色信息会有损失,但二维码是黑白块,对比度反而更稳定。现场实测下来,识别率从七成提到了九成五以上。

4. 竞赛调试与避坑实录

4.1 现场最容易翻车的几个地方

比赛现场和实验室最大的不同,是环境的不可控性。第一是地面条件,实验室里我们自己买的地胶平整度比较好,比赛场地是拼接的展板,板与板之间会有几毫米的缝隙,灰度传感器经过缝隙时读数会跳变。我们当时在灰度二值化阈值里加了一个“连续采样三次相同才更新状态”的保护,相当于软件滤波,才把跳变问题压下去。第二是灯光,前面提过视觉识别受光照影响,如果现场有几盏灯在机器人头顶正上方,OpenMV会出现镜头反光,停车区识别很容易失灵。最直接的办法是在Debug模式下让OpenMV把画面经过WiFi传到手机上看,现场快速调整曝光参数。第三是电池电压,刚充满的电池和跑了几圈之后的电池,舵机力量和电机速度都会有差别。这不是玄学,是实实在在的工程问题。我们准备了两块电池轮换,并且给系统做了低压提示,电压低于11V时OLED会闪烁,提醒换电池。

还有一个很反直觉的坑:每轮比赛前都有准备时间,机器人在待机状态时OpenMV和主控都在运行,但机械臂的舵机一直在通电保持位置。舵机比较大,堵转电流很高,会让电池电压掉得特别快。我们后来在PLACE状态之前才给机械臂舵机通电,待机时彻底断电,一个看似无关紧要的改动,让整套系统的续航时间多了将近三分之一。

4.2 调试工具和参数标定

如果让我给准备比赛的人一条建议,那就是“调试工具越早做越好”。我们前期太相信代码本身,总是用串口打印一堆原始数据去猜问题,效率很低。后来花一个晚上写了一个简单的串口调试上位机,通过USB转TTL连接主控,可以实时显示当前状态、传感器值、PID输出和目标车速,还能直接下发参数,不用反复编译烧录程序。参数标定速度至少快了三倍。所以我非常推荐准备一个可以离线调参的方案,哪怕是用蓝牙透传模块加手机APP,也好过每次改参数都重新烧录。

PID参数的整定,要有记录习惯。我们当时用坐标纸画了一条测试赛道,每一组参数跑一圈,记录超调量、摆动次数、过弯是否压线,然后把参数记录到表格里。这种方法很笨,但非常有效,尤其是到了比赛前一天,你会发现之前记录的某一组参数可能正是现场条件下最优的。还有灰度阈值标定,不要在代码里写死,要在程序启动时做一个校准流程:让机器人静止在黑白交界面,自动记录当前最大和最小值,然后将阈值设为两者中点。这个校准逻辑最多二十行代码,却能省去大量手工调试时间。

参数标定最容易忽略的是机械结构的一致性。比如两个驱动电机虽然型号相同,但实际转速可能存在5%左右的差异,这会导致直道跑不直。我们只在软件上做速度闭环不够,还要在开机时执行一次“直道校正”:让机器人空跑两米,测量偏移方向,然后把对应的PWM补偿系数写进flash。其实就是简单校准,没有那么高大上,但现场如果跑偏,至少不会让你束手无策。

4.3 复盘:三等奖到底输在哪里

最后说说成绩。我们拿了三等奖,往上差一步。复盘的时候,我们发现主要输在三个地方。一是稳定性的边界不够强,整个流程虽然跑通了,但现场跑了五次,只有三次是完全顺利的,有一次卡在灰度传感器缝附近,有一次机械臂没放正。评委打分时,顺利完成次数是一个很重要的指标,稳定性不足直接拉低了印象分。二是视觉识别没有冗余,OpenMV只认二维码,一旦现场有一个餐桌的二维码贴的位置偏高或偏低,超出画面上边缘,识别就直接失败。改进方案其实也很简单:在二维码下方加一个色块引导区,先用颜色粗定位,再用二维码精识别,这样鲁棒性会好很多。三是团队分工前期不清晰,硬件和软件没有并行推进,导致软硬件联调时间被压缩。

当然,这个项目也不是没有收获。最值钱的是整套系统的“问题定位方法论”。我们后来总结出一套排查顺序:先看电源,再看接线,然后看传感器状态,最后才怀疑算法问题。这个顺序在之后的智能车比赛里也帮我省了大量时间。另一个收获是明白了“完成比完美重要”,比赛不需要展示最前沿的技术,而是需要你在有限时间内交付一套可靠的东西。这个认知直到现在都很影响我做工程项目的思路。

最后再分享一个小经验:送餐机器人这类比赛项目,赛后一定要把所有代码、机械图纸、接线图、调参记录整理到一个压缩包里,按日期命名好。那段时间你想不通的bug,过半年再看可能一眼就能找出问题。这个zip文件里不只是代码,更是一份完整的工程日志,是这段经历最实在的沉淀。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐