智能送药小车实战:STM32+树莓派双核架构与二维码识别方案详解

发布时间:2026/9/2 21:04:24
智能送药小车实战:STM32+树莓派双核架构与二维码识别方案详解 简介本资源为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题的实战精髓那年电赛的F题“智能送药小车”可以说是一个集大成的综合性项目它完美地融合了自动控制、机器视觉、嵌入式开发和机械设计等多个学科的知识点。题目要求小车在模拟的医院病房环境中自主识别房间号规划路径并准确地将药品送达指定病房最后还要能自动返回充电桩。这听起来像是一个简化版的物流机器人或者医院服务机器人原型其核心挑战在于如何在有限的比赛时间内搭建一个稳定、快速且鲁棒性强的软硬件系统。对于参赛队伍而言这不仅是对技术能力的检验更是对项目规划、团队协作和临场应变能力的全面考验。我结合自己多年的嵌入式开发和带队经验来深度拆解一下这个项目的核心脉络、技术选型的底层逻辑以及那些在官方文档里绝不会写的“踩坑”实录与调优技巧。无论你是即将参赛的学生还是对移动机器人感兴趣的爱好者相信这篇从一线实战中总结出的干货都能为你提供清晰的思路和可直接复现的参考方案。2. 核心系统设计与整体架构拆解面对这样一个复杂的系统最忌讳的就是一上来就埋头写代码、焊电路。一个清晰、模块化的顶层设计是成功的一半。我们的核心思路是将整个系统分解为感知、决策、执行三大模块并通过一个可靠的中心控制器进行调度和信息融合。2.1 硬件平台选型与核心控制器考量硬件是系统的骨架选型直接决定了性能上限和开发难度。对于电赛这类有严格时间和成本限制的比赛平衡性能、易用性和可靠性是关键。主控制器大脑这是最核心的决策。常见的选择有STM32系列、ESP32、树莓派Raspberry Pi或Jetson Nano等。STM32如F4或H7系列这是电赛的“传统强项”。优势在于实时性极佳对电机控制、传感器数据采集等底层时序要求严格的任务处理得心应手功耗和成本也控制得很好。缺点是处理复杂的图像识别或路径规划算法时能力有限通常需要搭配额外的视觉处理模块。树莓派/类似Linux开发板优势是强大的通用计算能力和丰富的生态库如OpenCV、ROS非常适合跑视觉算法和复杂的决策逻辑。缺点是实时性不如单片机对电机控制的PWM精度、中断响应可能不如STM32直接且系统相对复杂启动时间较长。双核架构推荐方案我们最终采用的是“STM32 树莓派/或高性能单片机如K210”的主从架构。STM32作为底层执行单元专责电机驱动、编码器计数、陀螺仪数据融合、超声波避障等实时性要求高的任务树莓派或K210作为上层决策单元负责摄像头图像处理、房间号识别、全局路径规划并通过串口或CAN总线向STM32发送运动指令如前进1米、左转90度。这种架构兼顾了实时性和算力是应对此类复杂赛题的稳健选择。注意如果选用Linux系统作为主控务必关注启动时间。比赛上电即开始计时一个优化不佳的Linux系统启动可能需要30秒以上这会白白浪费宝贵时间。可以通过定制裁剪内核、使用RAM磁盘、设置自动登录并启动应用程序等方式进行优化。运动执行单元双腿电机与驱动我们选择了带增量式编码器的直流减速电机搭配TB6612或DRV8833这类双H桥电机驱动芯片。编码器用于实现精确的里程计计算测距和速度闭环控制这是实现精准走直线、定角度转弯的基础。TB6612相比古老的L298N效率更高发热更小是更优的选择。车体结构结构强度至关重要很多队伍的小车在快速启停或转弯时因结构刚性不足导致整体抖动严重影响了传感器读数尤其是摄像头图像和运动精度。我们使用了铝合金型材搭配3D打印件来制作车架在保证轻量化的同时确保了坚固性。2.2 传感器套件配置与信息融合策略小车的“眼睛”和“耳朵”决定了其感知世界的能力。全局定位与房间识别核心这是F题最核心的难点之一。题目通常会在赛道旁放置代表房间号的数字或二维码标识。方案一OpenCV数字识别。使用树莓派搭配普通USB摄像头或CSI摄像头采集图像后利用OpenCV进行灰度化、二值化、轮廓查找然后进行数字模板匹配或使用轻量级机器学习模型如SVM、KNN进行识别。优点是灵活可适应不同字体缺点是对光照变化敏感算法调参需要经验。方案二二维码识别。在房间标识处放置二维码内容即为房间号。使用专门的二维码识别库如pyzbar、OpenCV的QRCodeDetector进行识别。这是当时我们选择的方案也是强烈推荐的稳定方案。二维码识别速度快、准确率极高几乎100%、抗光照干扰能力强。虽然看似“取巧”但在比赛追求稳定第一的准则下这是最可靠的选择。我们只需在车头安装一个向下倾斜的摄像头对准地面标识区域即可。自身姿态感知编码器用于里程计Odometry计算小车相对于起点的粗略位置x y和航向角。但存在累积误差长时间运行会漂移。陀螺仪IMU中的角速度计常用MPU6050或更高级的BMI088。用于测量转弯的角速度积分后得到角度变化与编码器数据融合互补滤波或卡尔曼滤波可以得到更准确的航向角是实现精准90度转弯的关键。环境感知与避障超声波传感器HC-SR04等用于检测前方障碍物如模拟的临时障碍、其他小车实现紧急制动或绕行。通常作为安全冗余在路径规划层之外提供一层快速反应保护。巡线传感器可选虽然F题主要是自主导航但有些赛题版本或自己训练时可能会在走廊中央铺设引导线。可以使用灰度传感器阵列或OpenCV巡线作为辅助定位手段纠正里程计的累积误差。信息融合STM32通过定时中断高速采集编码器和IMU的原始数据进行滤波和融合计算实时估算出小车的速度、位移和航向角并打包通过串口发送给上位机树莓派。树莓派结合视觉识别到的房间号信息和自身的里程计信息做出决策。3. 核心算法与软件实现细节硬件搭好了软件就是灵魂。下面重点拆解几个核心算法的实现思路和避坑点。3.1 运动控制让小车“走准”是第一步精准的基础运动是完成所有任务的前提。我们实现了几个基础动作原语精准走直线单纯开环控制电机PWM会因为电池电压波动、地面摩擦不均等原因跑偏。我们采用了双电机速度闭环PID控制。思路设定一个目标线速度如0.3m/s。STM32通过编码器反馈计算每个电机的实际转速与目标转速做差经过PID控制器运算动态调整PWM占空比。同时加入一个偏航角纠正环使用IMU融合得到的当前航向角与目标航向角例如保持0度做差其误差值经过一个比例系数P转化为两个电机速度的差值从而微调转向抵抗跑偏。PID调参心得先调速度环的P让电机能快速响应且不震荡再调I消除静差D项在电机控制中要谨慎使用容易引入噪声。偏航纠正环通常一个较大的P就够了反应要迅速但不过激。精准定点转弯90度/180度这是进出房间的关键。思路采用位置式PID控制转角。目标角度设为90度。控制器输入是IMU反馈的当前角度与目标角度的误差输出是电机的差速值一个正转一个反转。当误差小于一个阈值如0.5度时停止转弯。避坑点电机惯性会导致过冲。我们的策略是“分段刹车”当角度误差小于20度时就大幅降低PID的输出限幅或比例系数让小车“轻柔”地逼近目标角度有效抑制过冲和振荡。3.2 视觉识别稳定可靠的“眼睛”我们采用二维码识别方案其稳定性的关键在于图像预处理。# 树莓派上使用Python OpenCV pyzbar的简化示例 import cv2 from pyzbar import pyzbar def decode_qr_code(frame): # 1. 图像预处理提升识别率的关键 gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 自适应二值化应对光照不均 binary cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) # 2. 识别二维码 decoded_objects pyzbar.decode(binary) # 也可以直接解码gray图但binary更稳 for obj in decoded_objects: room_number obj.data.decode(utf-8) print(f识别到房间号: {room_number}) # 返回房间号及二维码在图像中的位置用于后续定位微调 return room_number, obj.rect return None, None # 主循环中 cap cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # 分辨率不必过高 cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) while True: ret, frame cap.read() if not ret: break room_num, qr_rect decode_qr_code(frame) if room_num: # 触发决策逻辑例如停车、发出提示音等 break实操技巧摄像头安装位置和角度需要反复调试。确保在小车正常行驶高度和距离下二维码能完整、清晰地出现在画面中央区域。可以增加补光灯LED条来消除环境光影响保证识别稳定性。3.3 路径规划与任务调度逻辑这是小车的“大脑”决策层。由于比赛环境通常是结构化的笔直走廊房间在两侧我们采用了**基于状态机的有限状态自动机FSM**来实现逻辑清晰且易于调试。我们定义了以下几个主要状态STATE_IDLE 空闲状态等待启动命令。STATE_NAV_TO_CORRIDOR 从起点导航到主走廊。STATE_CORRIDOR_CRUISING 在走廊中巡航同时用摄像头扫描右侧或左侧地面寻找目标房间号。STATE_QR_DETECTED 识别到二维码减速并准备转弯。STATE_TURN_INTO_ROOM 执行90度转弯进入房间。STATE_DELIVER_MEDICINE 进入房间后前进指定距离模拟送达触发卸货机构如舵机推动药盒。STATE_EXIT_ROOM 倒车出房间或转弯出房间。STATE_RETURN_HOME 所有药品送达后返回充电桩起点。状态之间的转换由事件触发例如“到达走廊入口点”触发进入巡航状态“识别到目标房间号”触发进入转弯状态“转弯完成”触发进入送货状态。关键实现在STATE_CORRIDOR_CRUISING状态下小车需要一边匀速前进一边处理视频流。这里采用多线程一个线程负责控制小车匀速运动向STM32发送固定速度指令另一个线程专责图像识别。当识别线程发现目标二维码时立即设置一个共享标志位主控线程检测到该标志位便触发状态转移发送减速和转弯指令。4. 系统集成、调试与性能优化实战将各个模块整合在一起并调通是项目中最耗时也最考验人的环节。4.1 通信协议设计与联调STM32与树莓派之间的通信必须可靠、高效。我们采用串口通信并自定义了一套简单的文本协议便于调试。协议格式[命令头],[参数1],[参数2],...\n例如树莓派发送运动指令$SPEED,0.25,0.0\n(线速度0.25m/s角速度0)STM32上传传感器数据$ODOM,1.2,0.5,45.3\n(x1.2m, y0.5m, 航向角45.3度)STM32上传二维码信息$QR,502\n(识别到502房间)联调技巧先独立后联合先在PC上用串口助手调试STM32确保它能正确解析指令并控制电机。再用Python脚本模拟树莓派向STM32发送指令验证通信链路。加入心跳包与超时重发在应用层设计心跳机制如每秒互发$ALIVE\n监测连接是否正常。对于关键指令如开始任务如果没有收到应答应进行重发。日志记录在树莓派上将关键状态、接收到的传感器数据和发出的指令实时写入文件。当小车行为异常时这些日志是 priceless 的排查依据。4.2 系统标定与参数整定这是提升精度的必要步骤。轮子周长与编码器精度标定让小车在光滑地面上直线行走一段精确距离如2米记录编码器总脉冲数。计算每个脉冲对应的实际距离轮子周长 / (编码器线数 * 减速比 * 4)中的“4”是因为对AB相进行了4倍频。这个参数是里程计准确的基础。陀螺仪零偏校准将小车静止放置数十秒采集陀螺仪Z轴垂直方向的输出计算平均值作为零偏值。在后续读数中减去这个零偏能显著提高角度积分精度。摄像头内参标定如果做视觉测距如果除了识别还想用摄像头粗略估计到房间门的距离可以用OpenCV的棋盘格法标定摄像头获取内参矩阵和畸变系数进行图像去畸变。但对于单纯的二维码识别这一步不是必须的。4.3 现场调试与抗干扰策略比赛现场环境复杂必须提前考虑。光照干扰这是视觉识别的头号杀手。解决方案除了软件上的自适应二值化硬件上一定要加装可调亮度的LED补光灯环并准备不同颜色的滤光片如在某些日光灯环境下加红色滤光片可能有效抑制特定频闪。电磁干扰电机、尤其是有刷电机在启停时会产生强烈的电磁噪声可能干扰单片机、串口通信甚至摄像头。务必做好电源隔离电机驱动部分与单片机、传感器部分使用不同的稳压模块供电或在总电源入口处加装大容量电解电容如1000uF缓冲。信号隔离如果条件允许STM32与电机驱动之间使用光耦隔离。至少确保PWM、编码器等信号线使用双绞线或屏蔽线。共地确保所有模块的“地”是干净且连接良好的单点接地。机械振动振动会导致摄像头图像模糊、螺丝松动、接线脱落。所有连接处电机与车架、电路板与支架使用防滑螺母或点胶固定。线缆用扎带或热熔胶固定。5. 常见故障排查与应急方案实录在紧张的比赛或调试中问题总会不期而至。这里记录几个我们踩过的“坑”及解决办法。故障现象可能原因排查步骤与解决方案小车启动后原地转圈或单轮不动1. 电机接线相序错误。2. 电机驱动芯片某一路损坏。3. PID参数中两个电机的目标速度符号设置相反。1. 交换不动电机的两根线看是否恢复。2. 用万用表测量驱动芯片输出端电压或直接给对应电机引脚输入固定PWM测试电机是否正常。3. 检查代码中左右轮的目标速度赋值。走直线严重跑偏1. 两个轮子实际直径或摩擦力差异大。2. 编码器计数方向不一致。3. 陀螺仪安装不水平或零偏未校准。4. 偏航角纠正环PID参数不当。1. 互换左右电机和驱动器如果跑偏方向反了是电机/轮子问题如果不变是电路或代码问题。2. 查看左右编码器计数前进时是否都增加。修改其中一个的方向逻辑。3. 重新校准IMU零偏。4. 适当增大偏航纠正环的比例系数P。二维码时灵时不灵1. 光照变化影响二值化效果。2. 摄像头对焦模糊。3. 图像处理帧率太低小车移动过快导致图像拖影。1. 启用自适应二值化并增加补光灯。2. 固定焦距摄像头或调整到合适距离。3. 降低图像处理分辨率如320x240优化代码提升识别帧率。确保小车巡航速度与处理速度匹配。串口通信突然中断1. 接线松动。2. 波特率设置错误。3. 电源波动导致单片机复位。4. 缓冲区溢出。1. 检查所有杜邦线连接重要连接最好焊接。2. 确认双方波特率、数据位、停止位、校验位完全一致。3. 加强电源滤波检查稳压模块输出是否稳定。4. 在STM32端增加串口接收中断超时管理定期清空缓冲区。转弯角度总是超过或不足1. IMU角度积分存在累积误差漂移。2. 电机惯性导致过冲。3. 转弯PID参数不匹配。1. 使用互补滤波或卡尔曼滤波融合编码器航向角估计抑制陀螺仪漂移。2. 如前所述采用“分段刹车”策略在接近目标角度时减小控制量。3. 在平整地面上反复测试精细调整转弯PID参数。最后的个人体会智能送药小车这样的项目其魅力不在于用了多么高深的理论而在于如何将书本上的知识控制理论、图像处理、嵌入式工程化集成到一个能稳定运行的物理系统中。它教会你的远不止代码和电路更是如何定义问题、分解模块、接口设计、调试排错和团队协作。我的建议是尽早搭建一个能跑起来的最小可行系统MVP——哪怕只能用手推着车走能识别出二维码并打印出来。然后在此基础上像搭积木一样一个个增加功能速度闭环、转弯、状态机每步都充分测试。永远为调试留出比开发更多的时间并且一定要在模拟真实比赛环境的场地上进行反复测试你会发现无数在桌面上发现不了的问题。记住稳定性和鲁棒性永远是竞技类项目的首要追求一个能稳定完成80%任务的方案远胜于一个性能卓越但十次里会失败三次的方案。本文还有配套的精品资源点击获取