STM32送药小车实战:PID巡线、RFID定位与状态机设计全解析
2026/9/20 17:34:14 网站建设 项目流程

1. 项目概述:从零到一的送药小车实战复盘

最近刚带着团队完成了一个送药小车的集训项目,从最初的方案构思到最后的场地调试,整个过程可以说是既烧脑又充满成就感。这个项目听起来简单——不就是一个小车把药从A点送到B点吗?但真正上手后你会发现,它融合了机械结构、电子控制、嵌入式编程、传感器应用甚至简单的路径规划算法,是一个典型的综合性创客或机器人入门项目。无论是用于高校的工程训练、科创比赛,还是作为个人学习嵌入式系统和自动化的练手项目,都非常有价值。它解决的问题很具体:在模拟的医院病房、养老院或隔离区域,实现无接触式的定点药品配送,减少人员接触和交叉感染风险,同时也能锻炼解决实际工程问题的能力。

接下来,我会把我们这次集训中趟过的路、踩过的坑以及最终验证可行的方案,进行一次彻底的梳理和复盘。内容会涵盖从整体设计思路、核心硬件选型、软件框架搭建,到具体的循迹、避障、抓取机构实现,以及调试过程中那些让人头疼的常见问题和解决技巧。目标是让你看完后,能自己动手复现一个基础功能完善的送药小车,或者至少能对其中涉及的技术点有一个清晰、落地的认识。

2. 整体设计与核心思路拆解

2.1 需求分析与功能定义

送药小车不是一个天马行空的概念,它的设计必须围绕核心需求展开。我们首先明确了几个关键功能点:

  1. 自主移动:这是基础。小车需要能在地面上稳定行走,并具备基本的循迹或导航能力,以沿着预设路径(如地面上的黑线)或通过坐标定位到达目标点。
  2. 精准送达:小车需要知道何时到达“发药点”和“送药点”,并准确停下。这通常通过识别地面标记(如十字线、AprilTag码)或到达指定坐标来实现。
  3. 药品载运与交接:小车需要一个机构来携带药品(模拟药盒),并在目的地完成“交付”。这个交付可以是简单的倾倒、推出,也可以是更复杂的机械臂抓取放置。
  4. 环境感知与避障:在实际环境中,路径上可能出现临时障碍(如行人、掉落的物品),小车需要能检测并安全绕行,避免碰撞。
  5. 状态指示与交互:最好能有简单的灯光或声音提示当前状态(如运行中、已到达、故障),方便观察。

基于这些功能,我们确定了以“巡线+信标识别”为主、辅以超声波避障的方案。选择巡线是因为它在室内结构化环境中简单可靠,成本极低;信标(如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 电路连接与布线规范

电路连接是故障高发区,务必仔细。

  1. 电源分区:如前所述,电机电源与控制电源最好分开。TB6612FNG的VM(电机电源)接7.4V电池,VCC(逻辑电源)接控制板的5V。控制板的5V再由电池通过降压模块提供。
  2. 共地:所有模块(主控板、驱动板、传感器)的GND必须连接在一起,形成共同的参考零电位,这是电路正常工作的基础。
  3. 信号线连接
    • TB6612FNG的AIN1/AIN2、BIN1/BIN2(控制电机转向)和PWMA/PWMB(控制电机速度)接STM32的普通IO口和PWM输出口。
    • 循迹模块的DO(数字输出)口接STM32的IO口,并启用上拉或下拉电阻(根据模块输出逻辑,通常在代码中配置内部上拉即可)。
    • 超声波传感器的Trig(触发)和Echo(回响)引脚接IO口。
    • RFID模块的SPI接口(SCK, MISO, MOSI, NSS)接STM32对应的SPI引脚。
  4. 布线技巧:使用杜邦线时,尽量用不同颜色区分电源(红色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并不难。核心是调参,这是一个“玄学”过程,但有一定章法:

  1. 先调P:将I和D设为0。逐渐增大P,直到小车能跟着线走,但会在线左右频繁振荡。这个P值就是临界振荡点。
  2. 再调D:保持P为临界值的50%-70%,逐渐加入D。D能有效抑制P引起的振荡。观察小车是否变得更平稳。D太大反而会引入高频抖动。
  3. 最后调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粗定位 + 巡线细调”的策略:

  1. 当RFID读到站点卡号时,立即进入STATE_AT_STATION状态。
  2. 在该状态下,小车立即大幅减速(但不是急停),并切换到更灵敏的PID参数,对地面上的“T”型或“十”字型停车线进行精确对中。
  3. 当所有循迹传感器都检测到黑线(表示车头完全对准停车线)时,才真正停止电机。
  4. 延时稳定后,控制舵机执行推药动作,动作完成后等待2秒(模拟交付完成),然后舵机归位,小车根据任务状态进入下一个状态(如返回或前往下一站)。

舵机控制使用STM32的硬件PWM,确保角度控制精准。注意在程序初始化时给舵机一个明确的初始位置。

5. 系统集成调试与问题排查实录

5.1 分模块调试流程

不要试图一次性写好所有代码然后上电测试,那会让人崩溃。必须分模块调试:

  1. 电机单独测试:写一个简单程序,让两个电机正转、反转、变速,确认驱动板和接线正确,电机转向是否符合预期(如果转向反了,交换电机线或修改程序逻辑)。
  2. 循迹模块测试:将小车抬起,用手移动让传感器划过黑线,通过串口打印每个传感器的状态,确认其响应灵敏度和阈值是否合适(有些模块上有电位器可调灵敏度)。
  3. 超声波测试:在障碍物前后移动,打印测量距离,确认数值是否连续、准确。注意避开强噪声环境。
  4. RFID测试:分别读取不同地点的卡片,打印卡号,确保在有效距离(通常1-5cm)内能稳定读取。
  5. 舵机测试:编写程序让舵机在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,让小车慢下来先走稳。
超声波读数不稳定或始终为01. 触发和回声信号线接反或接触不良
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(机器人操作系统)实现自主构建环境地图和路径规划,彻底摆脱巡线。
  • 多车协同:如果有两辆以上小车,可以研究简单的任务调度和交通避让算法,模拟更真实的物流场景。
  • 机械臂集成:将固定的交付机构替换为多自由度机械臂,实现更灵活、更拟人的抓取和放置动作。

送药小车项目就像一把钥匙,它为你打开了机器人技术和嵌入式系统的大门。里面涉及的每一个知识点——电路设计、微控制器编程、传感器应用、控制算法、机械结构——都值得深入钻研。希望这份总结能为你提供一张清晰的“地图”,让你在动手实现自己小车的过程中,少走一些我们曾经走过的弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询