1. 项目概述:从零到一的送药小车实战复盘
最近刚带着团队完成了一个送药小车的集训项目,从最初的方案构思到最后的场地调试,整个过程可以说是既烧脑又充满成就感。这个项目听起来简单——不就是一个小车把药从A点送到B点吗?但真正上手后你会发现,它融合了机械结构、电子控制、嵌入式编程、传感器应用甚至简单的路径规划算法,是一个典型的综合性创客或机器人入门项目。无论是用于高校的工程训练、科创比赛,还是作为个人学习嵌入式系统和自动化的练手项目,都非常有价值。它解决的问题很具体:在模拟的医院病房、养老院或隔离区域,实现无接触式的定点药品配送,减少人员接触和交叉感染风险,同时也能锻炼解决实际工程问题的能力。
接下来,我会把我们这次集训中趟过的路、踩过的坑以及最终验证可行的方案,进行一次彻底的梳理和复盘。内容会涵盖从整体设计思路、核心硬件选型、软件框架搭建,到具体的循迹、避障、抓取机构实现,以及调试过程中那些让人头疼的常见问题和解决技巧。目标是让你看完后,能自己动手复现一个基础功能完善的送药小车,或者至少能对其中涉及的技术点有一个清晰、落地的认识。
2. 整体设计与核心思路拆解
2.1 需求分析与功能定义
送药小车不是一个天马行空的概念,它的设计必须围绕核心需求展开。我们首先明确了几个关键功能点:
- 自主移动:这是基础。小车需要能在地面上稳定行走,并具备基本的循迹或导航能力,以沿着预设路径(如地面上的黑线)或通过坐标定位到达目标点。
- 精准送达:小车需要知道何时到达“发药点”和“送药点”,并准确停下。这通常通过识别地面标记(如十字线、AprilTag码)或到达指定坐标来实现。
- 药品载运与交接:小车需要一个机构来携带药品(模拟药盒),并在目的地完成“交付”。这个交付可以是简单的倾倒、推出,也可以是更复杂的机械臂抓取放置。
- 环境感知与避障:在实际环境中,路径上可能出现临时障碍(如行人、掉落的物品),小车需要能检测并安全绕行,避免碰撞。
- 状态指示与交互:最好能有简单的灯光或声音提示当前状态(如运行中、已到达、故障),方便观察。
基于这些功能,我们确定了以“巡线+信标识别”为主、辅以超声波避障的方案。选择巡线是因为它在室内结构化环境中简单可靠,成本极低;信标(如RFID卡或视觉标签)用于精确标定发药点和病房点。这个方案在复杂度和可靠性之间取得了很好的平衡。
2.2 硬件平台选型与考量
硬件是小车的骨架,选型直接决定了项目的上限和调试难度。我们对比了几种常见平台:
主控板:
- Arduino Uno/Mega:经典入门选择,生态丰富,库函数多,对于新手极其友好。但处理复杂传感器融合或高级算法时性能稍显不足。对于基础巡线避障送药,Uno足够。
- STM32系列:性能强大,外设丰富,更贴近工业应用,适合希望深入学习嵌入式实时系统的同学。但开发环境搭建和调试门槛比Arduino稍高。
- 树莓派(Raspberry Pi):如果项目涉及复杂的图像识别(如直接通过摄像头识别门牌号)、Wi-Fi通信或上层决策算法,树莓派是更好的选择。它可以运行完整的Linux系统,但实时性控制不如单片机直接,通常需要与Arduino或STM32结合使用(树莓派做决策,单片机做实时控制)。
我们的选择:为了聚焦于移动机器人控制的核心逻辑,并确保实时性和稳定性,我们选择了**STM32F103C8T6(蓝色药丸板)**作为主控。它性能足够,价格便宜,并且可以通过PlatformIO或STM32CubeIDE进行开发,既能享受现代开发工具的便利,又能深入底层。
电机与驱动:
- 电机类型:普通直流减速电机即可满足移动需求。需要注意电机的转速和扭矩参数。转速太高小车会“飘”,不易控制;扭矩太小可能爬不了坡或带不动负载。
- 驱动模块:必须使用电机驱动模块(如L298N、TB6612FNG)来连接主控板和电机。主控板的IO口驱动能力太弱,无法直接驱动电机。TB6612FNG比L298N效率更高,发热更小,体积也更小巧,是我们推荐的选择。
传感器套件:
- 循迹模块:通常使用红外对管式传感器(TCRT5000)。它发射红外光并接收反射光,根据地面颜色(黑/白)反射率不同输出数字信号。一般需要3-5个并排安装,用于检测小车是否偏离黑线。
- 避障模块:超声波传感器(HC-SR04)最常用,通过测量声波往返时间计算距离。用于检测前方障碍物。
- 定位/识别模块:用于精确站点识别。RFID读卡器(MFRC522)是一个低成本可靠方案,在发药点和每个病房门口地面贴一个RFID卡,小车读到特定卡号即停车。另一种方案是使用OpenMV或ESP32-CAM等摄像头模块识别AprilTag或ArUco码,视觉方案更灵活但复杂度更高。
- 电源:务必重视!电机启动瞬间电流很大,会导致电压骤降,可能引起主控板复位。建议使用独立的18650锂电池组(两节串联,7.4V)为电机驱动供电,并通过一个降压模块(如LM2596)稳定输出5V为控制板和传感器供电。电池容量建议在2000mAh以上。
3. 机械结构与电路搭建实操
3.1 车体组装与机构设计
车体是基础,稳定第一。你可以购买现成的智能小车底盘套件,这能节省大量时间。如果自制,需要注意:
- 重心:电池、主控板等重物应尽量放在车体底部和中心位置,降低重心,防止急停或转弯时翻车。
- 轮距与轴距:合理的轮距(左右轮距离)和轴距(前后轮距离)影响转弯灵活性和直线稳定性。通常四轮小车采用后轮差分驱动(两个主动轮独立控制),前轮使用万向轮。
- 药品载运机构:我们设计了一个简单的“升降推杆”式机构。用一个舵机控制一个可以翻转或平移的托盘。当小车到达送药点时,舵机旋转一定角度,将托盘上的药盒“推”出去。舵机直接由主控板PWM信号控制,选择扭矩足够(如9g舵机以上)的型号即可。固定舵机和托盘时,要确保动作顺畅,不卡顿。
3.2 电路连接与布线规范
电路连接是故障高发区,务必仔细。
- 电源分区:如前所述,电机电源与控制电源最好分开。TB6612FNG的VM(电机电源)接7.4V电池,VCC(逻辑电源)接控制板的5V。控制板的5V再由电池通过降压模块提供。
- 共地:所有模块(主控板、驱动板、传感器)的GND必须连接在一起,形成共同的参考零电位,这是电路正常工作的基础。
- 信号线连接:
- TB6612FNG的AIN1/AIN2、BIN1/BIN2(控制电机转向)和PWMA/PWMB(控制电机速度)接STM32的普通IO口和PWM输出口。
- 循迹模块的DO(数字输出)口接STM32的IO口,并启用上拉或下拉电阻(根据模块输出逻辑,通常在代码中配置内部上拉即可)。
- 超声波传感器的Trig(触发)和Echo(回响)引脚接IO口。
- RFID模块的SPI接口(SCK, MISO, MOSI, NSS)接STM32对应的SPI引脚。
- 布线技巧:使用杜邦线时,尽量用不同颜色区分电源(红色5V/VCC)、地线(黑色GND)和信号线(黄、绿等)。线不要太长,避免缠绕,必要时用扎带固定。混乱的布线是调试时的噩梦。
实操心得:上电前,务必、务必、务必用万用表通断档检查所有电源线和地线连接,确保没有短路(特别是电池正负极直接相连)。可以先不接电机,只给控制部分上电,测试所有传感器读数是否正常,再连接电机进行调试。这个小习惯能避免至少50%的硬件损坏风险。
4. 核心控制逻辑与软件实现
4.1 开发环境与基础驱动
我们使用PlatformIO + STM32框架进行开发。首先需要为每个外设编写或移植基础驱动函数:
- 电机驱动函数:封装一个
Motor_SetSpeed(Motor_Left, speed)这样的函数,内部实现将speed值(正反转和速度)转换为对TB6612FNG控制引脚和PWM占空比的设置。 - 循迹传感器读取:编写一个函数读取多个红外传感器的状态,返回一个值或状态码,例如
0b00100表示中间传感器压线,小车应直行;0b00010表示略微右偏,应向左微调。 - 超声波测距函数:编写触发和测量回声高电平时间的函数,并换算为距离(厘米)。
- RFID读取函数:初始化SPI,调用MFRC522库函数循环读取卡号,当读到预设卡号时返回成功。
4.2 巡线算法:PID的引入与调参
最简单的巡线是“开关量控制”:哪个传感器检测到黑线,就向反方向打轮。但这样小车会剧烈摇摆,速度也快不起来。要让小车平滑、快速巡线,必须引入PID控制算法。 我们将多个循迹传感器的状态转化为一个“偏差值”。例如,5个传感器,从左到右编号为1-5。全部在白线上偏差为0,最左边压线为-2,最右边压线为+2,中间压线为0。这个偏差值就是PID的输入(Process Variable)。
- P(比例):与当前偏差成正比的控制量。偏差越大,转弯力度越大。这是主要作用项。
- I(积分):累积历史偏差,用于消除静态误差(比如小车始终有微小的固定偏向)。
- D(微分):根据偏差变化率进行控制,能预测偏差趋势,抑制振荡,让响应更平稳。
在STM32上实现一个离散PID并不难。核心是调参,这是一个“玄学”过程,但有一定章法:
- 先调P:将I和D设为0。逐渐增大P,直到小车能跟着线走,但会在线左右频繁振荡。这个P值就是临界振荡点。
- 再调D:保持P为临界值的50%-70%,逐渐加入D。D能有效抑制P引起的振荡。观察小车是否变得更平稳。D太大反而会引入高频抖动。
- 最后调I:如果小车在长直道上能走直,但在弯道后出现稳态误差(无法回到线中心),可以加入一个很小的I值来消除它。I值一定要小,否则容易积分饱和,导致控制失控。
注意事项:PID计算输出的控制量最终要映射到左右电机的速度差上。例如,
speed_left = base_speed + output; speed_right = base_speed - output;。base_speed是小车的基础速度,output是PID计算出的修正值。务必对output进行限幅,防止超过电机能接受的最大速度差。
4.3 多任务状态机设计
小车的行为不是单一的,它需要根据环境变化在不同状态间切换。用一个状态机(State Machine)来管理是最清晰的方法。我们定义了以下几个核心状态:
typedef enum { STATE_IDLE, // 空闲待命 STATE_LINE_FOLLOWING, // 巡线中 STATE_OBSTACLE_AVOID, // 避障中 STATE_AT_STATION, // 到达站点(识别到RFID) STATE_DELIVERING, // 执行交付动作(舵机动作) STATE_RETURNING // 返回起点 } SystemState_t;主循环中,根据当前状态执行相应的函数,并根据传感器输入进行状态转移。例如,在STATE_LINE_FOLLOWING状态下,持续运行PID巡线;当超声波检测到障碍物时,状态转移到STATE_OBSTACLE_AVOID,执行绕障例程;当RFID读到指定卡号,状态转移到STATE_AT_STATION,停车并准备交付。
这种设计使得程序结构清晰,易于调试和扩展。比如未来想增加一个“手动遥控”状态,只需要新增一个状态和对应的处理函数即可。
4.4 交付机构与精准停车控制
交付动作的可靠性取决于停车精度。单纯靠RFID触发停车,可能因为惯性滑过一点。我们采用了“RFID粗定位 + 巡线细调”的策略:
- 当RFID读到站点卡号时,立即进入
STATE_AT_STATION状态。 - 在该状态下,小车立即大幅减速(但不是急停),并切换到更灵敏的PID参数,对地面上的“T”型或“十”字型停车线进行精确对中。
- 当所有循迹传感器都检测到黑线(表示车头完全对准停车线)时,才真正停止电机。
- 延时稳定后,控制舵机执行推药动作,动作完成后等待2秒(模拟交付完成),然后舵机归位,小车根据任务状态进入下一个状态(如返回或前往下一站)。
舵机控制使用STM32的硬件PWM,确保角度控制精准。注意在程序初始化时给舵机一个明确的初始位置。
5. 系统集成调试与问题排查实录
5.1 分模块调试流程
不要试图一次性写好所有代码然后上电测试,那会让人崩溃。必须分模块调试:
- 电机单独测试:写一个简单程序,让两个电机正转、反转、变速,确认驱动板和接线正确,电机转向是否符合预期(如果转向反了,交换电机线或修改程序逻辑)。
- 循迹模块测试:将小车抬起,用手移动让传感器划过黑线,通过串口打印每个传感器的状态,确认其响应灵敏度和阈值是否合适(有些模块上有电位器可调灵敏度)。
- 超声波测试:在障碍物前后移动,打印测量距离,确认数值是否连续、准确。注意避开强噪声环境。
- RFID测试:分别读取不同地点的卡片,打印卡号,确保在有效距离(通常1-5cm)内能稳定读取。
- 舵机测试:编写程序让舵机在0度、90度、180度几个关键点转动,观察实际角度与程序设定是否一致。
每个模块都调通了,再开始写集成逻辑。
5.2 典型问题与解决方案速查表
以下是我们在调试中遇到的最具代表性的问题及解决方法:
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 上电后主控板无反应,或程序不运行 | 1. 电源问题(电压不足、接反) 2. Boot模式配置错误 3. 晶振不起振 | 1. 用万用表测量5V和3.3V电压是否正常。 2. 检查STM32的BOOT0和BOOT1引脚电平(通常都接地,从主Flash启动)。 3. 检查外部晶振电路,尝试使用内部晶振(HSI)启动测试。 |
| 电机不转或只单向转动 | 1. 电机驱动板供电不足 2. 控制信号线连接错误或虚焊 3. 程序PWM输出配置错误 | 1. 测量驱动板VM端电压,确保电池有电且连接牢固。 2. 用逻辑分析仪或示波器检查STM32给驱动板的控制引脚是否有信号变化。 3. 检查代码中对应GPIO和定时器PWM输出配置是否正确。 |
| 巡线时小车剧烈摇摆或跑飞 | 1. PID参数不当(P太大,D太小或为0) 2. 传感器安装高度不一致或离地太远/太近 3. 电机基础速度过高 | 1. 重新校准PID,遵循“先P后D再I”的原则,适当降低P增益。 2. 调整传感器支架,确保所有探头离地高度一致(通常3-10mm)。 3. 降低 base_speed,让小车慢下来先走稳。 |
| 超声波读数不稳定或始终为0 | 1. 触发和回声信号线接反或接触不良 2. 测量周期太短,上次回声未结束就触发下一次 3. 障碍物表面吸收声波(如海绵) | 1. 检查接线,确保Trig和Echo没有接错。 2. 在代码中增加两次测量之间的延时(建议至少60ms)。 3. 更换为表面平整的障碍物测试。 |
| RFID偶尔读不到卡 | 1. 读卡距离过远或卡片倾斜 2. 电源干扰(电机工作时拉低电压) 3. SPI通信速率过高 | 1. 确保卡片平行贴近读卡器天线中心区域。 2. 为读卡器模块的VCC增加一个100uF的电解电容进行滤波。 3. 尝试降低SPI时钟频率。 |
| 执行动作(如舵机转动)时主控复位 | 大电流负载导致电源电压瞬间跌落 | 1. 为舵机单独供电(使用另一组电池或大电流BEC)。 2. 在控制板电源入口处增加大容量(如1000uF)电容储能。 3. 在舵机电源线上加磁珠滤波。 |
5.3 场地适应性与最后优化
当小车在桌面上运行良好后,转移到实际比赛或演示场地,可能会遇到新问题:
- 地面反光:光滑地面可能导致红外循迹误判。解决方法:适当调低传感器灵敏度,或者在传感器探头处加装遮光罩(用热缩管或黑色电工胶带)。
- 光线干扰:强烈的日光灯或太阳光可能含有红外成分,干扰循迹模块。尝试使用调制型红外传感器(如灰度传感器)替代普通的数字式,或者用摄像头进行灰度巡线。
- 路径交叉口处理:在十字路口,小车需要判断直行还是转弯。这需要结合RFID或视觉标签,或者在程序逻辑中做特殊处理(例如,检测到连续多个传感器压线超过一定时间,则判定为十字路口,根据任务列表执行转弯动作)。
- 电池电量监测:长时间运行后电池电压下降,电机乏力,PID特性会变化。可以增加一个ADC读取电池电压的功能,当电压低于阈值时,让小车鸣笛或闪灯报警,并自动返回充电点(如果设计了的话)。
整个调试过程是对耐心和系统思维能力的极大考验。最有效的工具除了万用表、示波器,就是串口调试助手。将关键变量(如PID输出、传感器原始值、状态机当前状态)实时打印出来,是洞察小车“内心世界”的最佳窗口。
6. 项目总结与进阶思考
经过这次高强度的集训,一个功能完整的送药小车从图纸变成了现实。回顾整个过程,最重要的体会是:“简单的事情系统化,系统的事情模块化”。把一个复杂项目分解成感知、决策、执行、供电等独立模块,逐一攻克,最后进行系统集成和联调,这个方法论适用于绝大多数嵌入式开发项目。
对于想进一步深入的同学,这个项目还有巨大的扩展空间:
- 上位机监控与调度:通过蓝牙或Wi-Fi模块(如ESP-01S或HC-05)将小车状态实时发送到电脑或手机APP,并可以远程下发任务指令。
- SLAM建图与自主导航:升级为树莓派主控,搭配激光雷达(如RPLidar A1),使用ROS(机器人操作系统)实现自主构建环境地图和路径规划,彻底摆脱巡线。
- 多车协同:如果有两辆以上小车,可以研究简单的任务调度和交通避让算法,模拟更真实的物流场景。
- 机械臂集成:将固定的交付机构替换为多自由度机械臂,实现更灵活、更拟人的抓取和放置动作。
送药小车项目就像一把钥匙,它为你打开了机器人技术和嵌入式系统的大门。里面涉及的每一个知识点——电路设计、微控制器编程、传感器应用、控制算法、机械结构——都值得深入钻研。希望这份总结能为你提供一张清晰的“地图”,让你在动手实现自己小车的过程中,少走一些我们曾经走过的弯路。