简介:本资源为2021年全国大学生电子设计竞赛F题‘智能送药小车’的完整参赛方案实现包,面向嵌入式系统开发初学者、电赛备赛学生及智能控制方向实践者,聚焦多传感器融合、视觉识别与运动控制等典型工程问题。压缩包共298个文件,含59个C源码与头文件(核心控制逻辑)、57个PCB/SCH设计文件(Altium格式)、47个DLL动态库及MATLAB相关M脚本(用于PID参数优化与仿真)、9个可执行工具(如STM32烧录批处理)、7个Word设计文档与PDF说明,整体容量317.67MB。已有1881人学习下载,内容覆盖从OpenMV/K210图像识别、六轴姿态解算、光电编码器测距到串级PID与多群进化算法调参的全链路实现,配套硬件清单、电赛原题及字模资源,便于快速复现、调试与二次开发。
1. 项目概述:从“智能送药小车”看电赛F题的实战精髓
看到“21年电赛F题智能送药小车”这个标题,很多参加过电子设计竞赛的朋友,尤其是对控制、机器视觉和嵌入式系统感兴趣的同学,估计都会会心一笑。这不仅仅是一个比赛题目,更是一个经典的、综合性极强的工程实践项目缩影。它要求参赛者在有限的时间内,将机械结构、电路设计、运动控制、传感器融合、图像识别乃至无线通信等多个技术领域融会贯通,最终打造出一个能自主执行任务的智能体。我当年带队做类似项目时,最大的感触就是:它完美模拟了一个小型智能机器人从零到一的开发全流程,每一个环节的取舍都直接关系到最终的系统稳定性和任务完成度。今天,我就以这个F题为例,抛开那些官方文档里干巴巴的要求,从一个一线开发者的角度,深入拆解一下这个项目背后的核心逻辑、技术选型的门道,以及那些只有真正动手做过才能体会到的“坑”与“技巧”。
这个项目的核心目标非常明确:设计并制作一辆能够自主循迹、识别病房编号、精准到达指定位置并完成模拟药品(通常用一个小方块或小球代表)投放的小车。听起来像是机器人比赛的简化版,但它麻雀虽小,五脏俱全。题目通常会设定一个模拟医院走廊的环境,地面有引导线(黑色或白色),两侧有代表病房的编号标识(可能是数字卡片或二维码),小车需要从药房出发,根据指令将“药品”送到正确的“病房”。这背后考验的是几个硬核能力:首先是高鲁棒性的运动控制,小车不能跑偏、不能打滑、更不能在十字路口“迷路”;其次是快速准确的视觉识别,要在运动过程中或短暂停顿时迅速抓取并识别编号;最后是稳定可靠的系统集成,让单片机、电机驱动、摄像头、机械爪等各个模块协同工作,不掉链子。无论是对于电赛备赛,还是对于想入门移动机器人开发的朋友,把这个项目吃透,价值远超奖状本身。
2. 项目整体设计与核心思路拆解
2.1 需求分析与功能模块划分
接到题目,第一步不是急着画电路图或写代码,而是把任务书“嚼碎了”。智能送药小车的需求可以分解为几个核心子任务,每个子任务对应一个功能模块,模块之间通过清晰的接口和数据流进行耦合。
核心任务链:接收任务指令 -> 循迹移动至目标区域 -> 识别病房编号 -> 精确定位与停靠 -> 执行投药动作 -> 返回或等待新指令。这个链条环环相扣,任何一个环节的延迟或失误都会导致任务失败。
基于此,我们可以将系统划分为五大核心模块:
- 主控与决策模块:通常由一块高性能单片机(如STM32F4系列、K210甚至树莓派)担任大脑,负责调度所有任务、处理传感器数据、做出路径决策、以及管理状态机。
- 运动控制模块:包括电机(直流减速电机或步进电机)、电机驱动芯片(如TB6612、DRV8833)、编码器(用于测速和里程计)以及循迹传感器(多路灰度传感器或摄像头)。这是小车的“腿”,稳定与否直接决定基础。
- 环境感知模块:核心是视觉单元,用于识别病房编号。常用方案有OpenMV、K210、或者用STM32驱动OV系列摄像头再配合图像处理算法。此外,可能还需要超声波或红外传感器用于避障或辅助定位。
- 执行机构模块:即投药装置。常见的有舵机控制的推杆、电磁铁吸放、或简单的斜坡翻转机构。设计要点是可靠、快速、且不影响小车重心。
- 电源与通信模块:为所有模块提供稳定、干净的电源(常用12V锂电池降压),以及可能需要的无线通信(如蓝牙、Wi-Fi)用于接收远程指令或调试。
设计思路的关键在于实时性与可靠性的权衡。例如,视觉识别耗时较长,就不能让小车在高速运动时做复杂识别,而应采用“运动-停顿-识别”的策略。再比如,循迹控制环的频率(PID计算频率)要远高于视觉处理帧率,两者需要用中断或RTOS(实时操作系统)妥善管理,避免互相阻塞。
2.2 核心方案选型与权衡
方案选型是决定项目成败的第一步,也是最能体现工程思维的地方。这里没有绝对的最优解,只有最适合当前团队能力和时间约束的平衡点。
主控芯片选型:
- STM32F4系列(如F407、F429):这是电赛中的“万金油”。优势是资源丰富(主频高、RAM大、外设多),生态成熟,有丰富的HAL库和标准库,容易上手。适合对实时性要求高、需要复杂PID控制和多传感器数据融合的场景。缺点是图像处理能力较弱,若用其做图像识别,通常只能处理二值化后的简单形状,对数字识别挑战较大。
- Kendryte K210:近年来在AIoT和机器视觉赛题中异军突起。这是一款带硬件AI加速(KPU)的双核RISC-V芯片。最大优势是能本地、低功耗地运行轻量级神经网络模型,进行数字、物体识别速度快且准。非常适合本题目中的病房编号识别。但它的实时控制、多外设管理能力不如STM32熟练工来得直接。
- 双核架构(STM32 + K210/OpenMV):这是我个人最推荐的稳健方案。让STM32专心负责底层实时控制(电机PID、传感器读取、状态机),让K210或OpenMV专攻图像识别。两者通过串口(UART)通信,STM32作为主机发送识别指令并接收结果。这样既保证了控制系统的实时性和稳定性,又拥有了强大的视觉能力,是性能与可靠性的最佳结合。虽然增加了系统复杂度,但模块间解耦清晰,调试更方便。
循迹方案选型:
- 多路灰度传感器阵列:最经典、最可靠的方案。通常使用8-16个红外对管,一字排开,通过检测地面黑线与白底的反射值差异来获取小车相对于引导线的横向位置偏差。优点是响应速度快(微秒级)、算法简单(直接用于PID控制)、抗环境光干扰能力强(可通过调制解调技术)。缺点是信息量少,对于复杂的岔路口判断需要逻辑积累。
- 摄像头循迹:使用全局快门摄像头(如OV7725)拍摄前方路面,通过图像算法提取引导线中心。优点是前瞻距离远,可以提前预知弯道甚至岔路,理论上控制更平滑。缺点是对处理能力要求高,算法复杂(涉及图像采集、ROI设定、二值化、边缘检测、中心线拟合),且受环境光照影响大。在紧张的比赛环境中,稳定性是首要考虑,因此多数成熟队伍会选择灰度传感器方案作为主循迹手段,摄像头可能仅用于辅助路口识别或作为视觉方案的复用。
识别方案选型:
- 传统图像处理:使用OpenMV或STM32+OV摄像头,采集图像后,进行灰度化、二值化、轮廓查找、然后使用模板匹配或特征提取(如七段数码管特征)来识别数字。优点是方案直接,不依赖大量数据。缺点是受光照、角度、数字字体影响大,泛化能力弱,调试参数繁琐。
- 基于神经网络的目标检测/分类:使用K210训练一个轻量级模型(如MobileNet SSD或YOLO tiny的K210适配版本),直接识别并定位图像中的数字。这是当前的主流和优势方案。优点是识别率高、鲁棒性强、对字体和轻微形变不敏感。缺点是需要准备数据集、训练模型,有一定的学习门槛。但对于“送药小车”这种目标固定的场景,收集几十张不同光照、角度的数字图片训练一个小模型,效果远好于传统方法。
3. 核心模块详解与实操要点
3.1 运动控制:让小车“走得稳、停得准”
运动控制是整个系统的基石。再聪明的“大脑”,如果“腿脚”不稳,一切归零。
硬件搭建要点:
- 电机与驱动:建议使用带减速箱的N20或TT马达,搭配带编码器反馈的型号。驱动芯片TB6612是经典之选,它支持双路PWM控制,内置防短路保护,比古老的L298N效率高、发热小。接线时务必确保电机驱动板的电源(VM)来自电池,逻辑电源(VCC)来自单片机稳压后的5V或3.3V,共地。
- 编码器:增量式编码器是实现精准速度控制和里程计(粗略定位)的关键。STM32的定时器编码器接口模式可以轻松读取双相正交编码信号。注意,电机减速比、轮子直径、编码器线数这三个参数共同决定了“每脉冲对应的实际距离”,这个参数必须准确测量并校准,它是速度控制和里程估算的基础。
- 灰度传感器阵列:自己制作或购买成品模块。安装时,传感器距地面高度建议在1-2cm,通过可调电阻或软件ADC值校准,确保在黑线和白地上能产生明显、稳定的数值差异。阵列的宽度应略大于引导线宽度,以提供足够的偏差检测范围。
控制算法核心——PID: 循迹的本质是一个位置跟踪问题。灰度传感器阵列读回的数值,经过处理(例如,将传感器状态加权平均)可以计算出一个“偏差值”(error)。我们的目标就是通过控制左右轮的速度差,让这个偏差值始终趋于零。
- P(比例):与当前偏差成正比。P越大,纠正力度越大,但过大会引起小车在直线段左右振荡。
- I(积分):累积历史偏差,用于消除静态误差(例如,小车因两轮摩擦力轻微不同导致的恒定偏航)。但在循迹中,I项要非常小心,容易引起超调振荡。
- D(微分):与偏差变化率成正比,具有“预见性”,能抑制振荡,让小车过弯更平滑。
实操心得:对于循迹,通常一个PD控制器就足够了。先调P,让小车能跟着线走但有些抖动;再加入D,抖动会明显平滑。I项除非在长直线上发现存在无法消除的固定偏向,否则慎用。PID计算周期(中断频率)建议在1-5ms,太快没必要,太慢控制不跟手。调试时,一定要在真实赛道上进行,用蓝牙模块将实时偏差、PWM输出等数据发送到电脑上位机(如SerialPlot)可视化,这是调参的“眼睛”。
里程计与定位: 单纯循迹是“局部”的,要让小车知道“我到了哪个路口”、“离目标病房还有多远”,就需要粗略的全局定位。利用编码器累计的脉冲数,可以估算小车行驶的距离。结合对路口(十字、丁字)的识别(通过灰度传感器状态突变判断),可以构建一个简单的“状态-里程”地图。例如:“从起点直行50cm到达1号路口,左转,再直行30cm到达2号病房区”。虽然精度不高(受打滑影响),但对于题目要求的顺序任务,这种基于事件(路口)和里程的定位方法简单有效。
3.2 视觉识别:快速准确地“看清门牌号”
这是项目的技术高点,也是区分队伍水平的关键。
基于K210+MaixPy的开发流程:
- 数据收集:在比赛场地类似的光照条件下,用K210摄像头拍摄各个病房编号(0-9)。每个数字至少从不同角度、距离拍摄20-30张。图片背景要尽量干净,与比赛环境一致。
- 数据标注:使用Labelimg等工具,将图片中的数字用矩形框标注出来,并打上对应标签。生成VOC或COCO格式的标注文件。
- 模型训练:在PC上使用YOLO或SSD等框架的轻量级版本(如YOLOv2-tiny)进行训练。由于目标单一(数字),类别少,几百张图片训练几十个epoch就能得到不错的效果。然后将训练好的模型转换为K210支持的
.kmodel格式。 - 模型部署与推理:在MaixPy IDE中,加载kmodel,初始化摄像头。在程序循环中,捕获图像,送入模型进行推理。模型会返回识别到的数字类别、置信度以及其在图像中的坐标。
- 坐标转换与决策:得到数字在图像中的位置后,可以结合摄像头焦距、安装高度等(或简单地根据图像中心与数字中心的像素偏差),估算数字相对于小车的方位,用于辅助小车微调位置,使数字处于画面中心,从而代表小车正对病房。
注意事项:
- 光照是最大敌人:比赛现场灯光可能不均匀。解决方案:一是在数据收集中涵盖多种光强;二是在图像预处理中加入自动白平衡或直方图均衡化;三是考虑给摄像头加一个遮光罩。
- 模型别贪大:选择参数量小的模型,确保在K210上推理一帧的时间在100-200ms以内,否则会影响系统实时性。
- 通信协议要可靠:K210识别到数字后,通过串口将结果发送给STM32。协议要包含帧头、数据、校验和帧尾,防止数据错乱。STM32端要用中断接收,并做好数据包解析和超时处理。
传统图像处理方案(备用): 如果时间紧迫或对神经网络不熟悉,可以用OpenMV的find_template(模板匹配)或find_features(特征点匹配)。先给每个数字拍一张“标准模板”,然后小车在疑似病房前停下,摄像头拍摄当前画面,与所有模板进行匹配,取相似度最高的作为结果。这种方法在光照、角度变化时极易失效,只能作为保底方案。
3.3 机械与执行机构设计
“投药”动作要求稳定可靠,一次成功。常见的机构有:
- 舵机推杆式:一个舵机带动连杆,将放置在车厢前部的小方块向前推出。结构简单,但需要精确控制推出力度和行程,防止方块弹出或卡住。
- 翻转滑槽式:药仓底部是活动的翻板,由舵机控制。小车到达位置后,舵机转动,翻板打开,药品依靠重力滑入目标区域。这种方案更可靠,对控制要求低。
- 电磁铁吸附式:用电磁铁吸住金属药片,到达后断电释放。优点是动作迅速、安静。缺点是只能投递磁性药品,且电磁铁可能对单片机电路产生干扰,需做好屏蔽和续流二极管保护。
设计核心:无论哪种机构,都必须进行多次重复性测试。舵机的扭力要足够,安装要牢固,避免动作时引起整车晃动,影响定位精度。执行机构的动作最好由一个独立的定时器或延时函数控制,与主控制循环分离,避免阻塞其他任务。
4. 系统集成与软件架构实战
4.1 状态机设计:小车的大脑逻辑
送药小车的工作流程是典型的顺序+事件驱动,用有限状态机(FSM)来建模是最清晰的。下面是一个简化的状态机设计:
typedef enum { STATE_IDLE, // 空闲,等待指令 STATE_FOLLOW_LINE, // 循迹前进 STATE_CROSS_DETECT, // 路口检测与处理 STATE_NUM_SEARCH, // 进入病房区,寻找编号 STATE_NUM_RECOG, // 停止,进行编号识别 STATE_POS_ADJUST, // 位置微调,对准病房 STATE_DELIVER, // 执行投药动作 STATE_TASK_CHECK, // 任务检查(是否全部送完) STATE_RETURN // 返回起点 } CarState_t; CarState_t g_current_state = STATE_IDLE;主循环中,根据当前状态执行相应的函数,并根据事件(如传感器触发、识别结果、定时器到点)进行状态迁移。例如,在STATE_FOLLOW_LINE状态下,持续运行PID循迹;当灰度传感器检测到特定模式(如全部变黑或特定组合),产生EVENT_CROSS_FOUND事件,状态迁移到STATE_CROSS_DETECT,在此状态根据任务列表决定直行、左转还是右转,完成后回到STATE_FOLLOW_LINE。
使用RTOS的优势: 如果系统复杂(例如需要同时管理电机控制、图像采集、无线通信、状态机),可以考虑在STM32上移植FreeRTOS。可以将关键任务分解为不同优先级的线程:
- 高优先级线程:电机PID控制、编码器读取。
- 中优先级线程:状态机主逻辑、传感器数据融合。
- 低优先级线程:与K210的串口通信、调试信息发送。 使用RTOS可以避免长延时函数阻塞系统,让程序结构更清晰,但同时也增加了内存开销和调试复杂度。对于初次参赛,一个精心设计的前后台系统(超级循环+中断)同样可以胜任。
4.2 通信与调试系统构建
一个强大的调试系统是项目成功的“倍增器”。
- 无线调试:务必预留一个蓝牙模块(如HC-05)或Wi-Fi模块(ESP8266)的串口接口。用于:
- 实时数据监控:将PID的偏差、输出、编码器速度、当前状态等发送到PC上位机,绘制曲线。
- 参数在线调整:通过设计简单的串口指令,可以实时修改PID参数、速度设定值等,无需重新烧录程序。
- 远程指令发送:手动发送任务指令(如“去3号病房”)进行测试。
- 状态指示:利用LED或蜂鸣器表示不同状态(如寻线中、识别中、投药成功/失败),便于现场快速判断问题。
- 日志系统:在SD卡或串口输出带时间戳的关键事件日志,用于复盘分析异常情况。
5. 现场调试与常见问题排查实录
比赛现场环境多变,时间紧迫,系统性的调试和快速排错能力至关重要。
5.1 分模块独立测试
在集成前,必须确保每个模块单独工作正常。
- 电机驱动:编写测试程序,分别控制左右轮正反转,观察是否有力,有无异响。
- 灰度传感器:用ADC读取每个传感器的值,打印出来,在黑线和白地上移动,观察数值跳变是否清晰、稳定。
- 编码器:旋转轮子,在中断服务程序里打印计数值,检查是否正反转计数正确。
- 摄像头与识别:固定K210,对着数字卡片,在MaixPy IDE的终端里查看识别输出是否准确。
- 执行机构:单独给舵机或电磁铁发送信号,观察动作是否到位、有力。
5.2 集成联调问题速查表
| 问题现象 | 可能原因 | 排查思路与解决方案 |
|---|---|---|
| 小车循迹左右剧烈振荡 | PID参数P值过大,或D值过小。 | 降低P值,适当增加D值。通过上位机观察偏差曲线,目标是让曲线收敛快且平稳。 |
| 过弯时冲出跑道 | 弯道曲率大,前瞻不够或舵轮响应慢。 | 增加灰度传感器阵列的宽度以提高前瞻性;提高PD控制的计算频率;对于急弯,可以适当引入“提前转向”逻辑,当检测到弯道内侧传感器先变黑时提前增加转向量。 |
| 在路口误判或漏判 | 灰度传感器阈值设置不合理,或路口判断逻辑有漏洞。 | 重新校准传感器在路口全黑区域的阈值。路口判断不能只看单个传感器,要看一个特定组合模式(如中间几个变黑,两边还是白),并加入去抖动延时。 |
| 数字识别时对时错 | 光照影响,或模型泛化能力不足。 | 加强数据集的多样性(不同光照、角度)。在识别前增加图像预处理(如自动对比度调整)。考虑在识别到数字后,让小车轻微左右移动一下,多识别几次,采用“投票法”决定最终结果。 |
| 串口通信接收乱码或丢包 | 波特率不匹配,或未处理数据粘包、断包。 | 检查STM32与K210的波特率、停止位等是否完全一致。在通信协议中加入帧头(如0xAA, 0xBB)和校验和(如累加和)。STM32接收使用中断+环形缓冲区,在主循环中解析完整数据包。 |
| 执行机构动作后小车位置偏移 | 机构动作时的反作用力导致小车移动。 | 机械上优化结构,减少动作冲击。软件上,在执行动作前,让电机进入“刹车”或“锁死”模式(PWM输出特定占空比使电机堵转),增加小车惯性。 |
| 系统运行一段时间后复位 | 电源问题(压降),或程序跑飞。 | 用示波器监测单片机电源引脚,在大电流负载(如电机启动、舵机动作)时观察是否有大幅压降。确保电源功率充足,并在电机驱动电源端并联大容量电解电容(如470uF以上)缓冲。检查是否有数组越界、堆栈溢出等软件问题。 |
5.3 赛场实战技巧
- 电池管理:赛前充满电,准备备用电池。电机驱动电源与单片机逻辑电源尽量分开稳压,避免电机噪声耦合进控制系统。
- 环境适应性:提前到赛场测试。光线可能与实验室不同,立即重新校准灰度传感器阈值和摄像头曝光。地面摩擦系数也可能不同,微调PID参数。
- 代码版本管理:赛前将稳定可用的代码备份好。现场修改任何参数,都使用通过调试接口在线修改的方式,尽量不要改动核心代码并重新烧录,除非万不得已。
- 制定应急预案:如果主要识别方案失效,是否有降级方案?(比如用灰度传感器辅助定位病房大致区域,然后采用“扫描式”投药)。如果某个执行机构故障,是否有手动补救措施?
做“智能送药小车”这类项目,最大的收获不是最终的比赛名次,而是这个从需求分析、方案设计、硬件焊接、软件编程、调试排错到现场应对的完整工程实践过程。它强迫你将书本上的理论变成手中实实在在能跑起来的机器,每一个深夜调通的BUG,每一次参数调整后小车更稳的轨迹,都是无法替代的经验。技术方案会过时,但这种系统性的工程思维和解决问题的能力,会让你在以后面对任何复杂项目时,都能心中有谱,手中有术。最后,一个小建议:在机械结构上多花点心思,一个刚性足、重心低、布线整齐的车体,是所有高级算法稳定运行的前提,这往往是新手最容易忽视的“基本功”。
本文还有配套的精品资源,点击获取