ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于STM32的智能输液监护系统:滴速检测与闭环调控设计

基于STM32的智能输液监护系统:滴速检测与闭环调控设计 1. 从医院场景痛点说起为什么需要一套智能输液监护系统输液是临床治疗里最基础也最高频的手段但直到今天很多医院的输液监护仍然停留在“患者盯滴壶、家属盯液面、护士挨床巡查”的状态。做过医疗电子或者跟临床打过交道的人都知道这个流程有几个天然的隐患滴速完全靠护士手动数滴、按秒表估算误差大且无法持续监测液面下降过程缺乏自动感知空气栓塞风险全靠人眼兜底输液泵、注射泵价格昂贵基层医院很难大规模普及患者输液时活动受限输液过程中出现渗液、堵塞也难以及时发现。这个项目的定位很明确做一套成本可控、开环/闭环可切换、具备掉电记忆和声光报警功能的智能输液监护调控系统。它基于STM32F103系列主控配合红外对管滴速检测、电容式液位检测、蠕动泵执行机构、按键与OLED人机交互、无线数据传输模块实现从“检测”到“调控”再到“上报”的完整链路。这次的“升级版”在上一版基础上重点增加了多节点组网与上位机监控拆解起来更有代表性。适合参考这个项目的人群也正好三类一是正在做STM32课程设计/毕业设计的在校生二是想了解医用电子基础设计流程的嵌入式爱好者三是有实际输液监控产品开发需求的工程师。无论你是想直接复刻一套可运行的Demo还是想理解整个系统的设计取舍这篇拆解都能给你一条完整的主线。2. 系统的功能边界与总体架构先画清楚框图再动手写代码2.1 功能需求清单不只是一个“会报警的滴速计”很多初学者拿到这类项目就开始写代码这是一个常见的误区。做医疗相关的电子系统第一步应该是把功能需求表格化把“要做什么”和“做到什么程度”划清楚。这套系统我按优先级把需求拆成了四层优先级功能项具体要求实现手段P0必做滴速实时检测0~150滴/分钟范围内误差≤±2滴/分钟红外对管定时器输入捕获P0必做滴速异常报警超过设定阈值上下限1秒内触发声光报警GPIO驱动蜂鸣器LEDP0必做液位下限检测液面低于设定位置立刻报警并停止执行机构电容式非接触液位传感器P1重点滴速闭环调控实测滴速与设定滴速偏差时自动调整电机转速增量式PID控制蠕动泵P1提升参数掉电保存设定滴速、PID参数掉电不丢失STM32内部Flash模拟EEPROMP2升级无线数据上报输液状态实时上传至上位机ESP8266 Wi-Fi模块/串口透传P2升级多节点组网一个护士站主机管理多个输液节点广播应答式轻量协议这套需求分级方式值得借鉴先保证“输液安全”这个核心底线再去追求“调控精度”和“联网管理”。很多失败的项目恰恰是把优先级搞反了——一上来就搞App、搞云平台结果连滴速都测不准。2.2 硬件拓扑选型的底层逻辑硬件选型方面主控我选了STM32F103C8T6原因很直接72MHz主频足够跑滴速检测和PID运算不需要上F4系列64KB Flash 20KB RAM存放RTOS或者裸机状态机都绰绰有余定时器资源丰富可以同时满足输入捕获滴速检测、PWM输出电机驱动、编码器接口等多路需求便宜、购买渠道多、参考资料海量方便后续有人复现。液位检测这块很多人会用浮子开关或者电极式传感器但我建议用非接触式电容液位传感器原因是它不需要和药液直接接触不存在污染和电化学腐蚀问题而且贴装在墨菲斯滴管外壁就能工作安装和维护都非常方便。执行机构选择了微型蠕动泵而不是普通的直流电机加调节阀方案。蠕动泵的优势在于液体只接触泵管不接触泵体符合医用卫生要求而且通过调节泵头转速就能线性调节流量天然适合做闭环控制。通信模块这里有一个设计上的取舍虽然是“升级版”我仍然预留了串口和Wi-Fi两套方案。串口方便调试和有线组网Wi-Fi则适合后续对接护士站或病房物联网。方案上保留灵活性比直接焊死某一种通信方式要靠谱得多。2.3 软件状态机的总体设计整个下位机软件我采用了一个简洁的四状态状态机待机态 → 运行态 → 报警态 → 停止态。待机态开机自检等待“开始输液”按键 运行态滴速检测 PID调节 液位监测 数据上报 报警态滴速异常或液位过低 - 声光报警按需停止电机 停止态一次输液完成参数保存等待新一轮开始软件架构上滴速检测、PID调节、UI刷新、通信上报这四个任务是严格分时调度的。我在SysTick中断里用时间片轮转的方式给每个功能分配不同的时间槽滴速检测因为要求实时性最高放在5ms周期PID调节50ms周期OLED刷新和按键扫描200ms周期无线数据上报1s周期。这种设计不需要上RTOS又能保证关键路径的实时性非常适合这类资源有限的单片机应用。3. 硬件设计详解原理图的每一路信号都要说得出理由3.1 主控最小系统和电源树STM32F103C8T6的最小系统需要注意几个细节复位电路采用10kΩ上拉电阻0.1μF下拉电容NRST引脚不建议直接接地避免干扰导致频繁复位启动模式BOOT0和BOOT1都要预留跳线或电阻选择位调试和量产下载需要用不同模式VDD/VDDA引脚分别就近放置0.1μF去耦电容VDDA还需要额外加一个1μF钽电容10μH电感做模拟电源滤波否则ADC采样值会明显抖动8MHz晶振的负载电容用20pF两个引脚对地各接一只电容注意走线尽量短远离高频信号线。电源树这块是这个项目的重点因为我需要同时给主控、传感器、电机驱动、无线模块供电电源质量直接决定模拟检测信号的信噪比。外部输入12V/1A直流电源适配器或适配电源第一级降压LM2596-5.0模块将12V降至5V给滴速检测电路、液位传感器、无线模块供电第二级LDOAMS1117-3.3将5V降到3.3V给MCU、OLED屏供电电机电源直接采用12V由MOS管或电机驱动芯片做PWM调压调速。这里特别提醒一点滴速检测的红外对管和MCU必须做电源隔离处理。红外对管如果直接和MCU共用3.3V电源电机启停瞬间的电流脉动会通过地线噪声耦合到红外接收管的信号上导致滴速误计数。我的做法是红外对管供电单独走5V接收管信号通过光耦隔离后再送入MCU的输入捕获引脚效果立竿见影。3.2 滴速检测电路红外对管的“对射式”布局与信号调理滴速检测是整个系统的感知核心它的原理并不复杂输液滴管两侧分别放置红外发射管和红外接收管液滴落下时会遮挡红外光线接收管输出电平发生跳变MCU通过测量跳变沿之间的时间间隔计算出滴速。但真正工程化的时候有几个坑必须处理发射管驱动电流要稳定。红外LED的正向电流决定了发射光强而发射光强直接影响接收管的导通深度。如果直接用GPIO串联电阻驱动电源波动会造成发射光强变化产生虚假触发。我用了一个三极管恒流驱动电路基准电阻决定电流实测电流稳定在20mA信号一致性非常好。接收管输出要整形。红外接收管在滴液边沿时信号不会瞬间跳变而是有一个渐变过程直接送MCU会频繁触发沿中断。我在接收管输出端加了一级电压比较器LM393通过电位器调节阈值电压把渐变信号整形成干净的数字方波。调试时用示波器观察LM393输出调节电位器让波形边沿最陡这一步对检测稳定性至关重要。检测窗口要抗干扰。液滴下落过程中可能会有微小的回弹或飞溅导致一个液滴产生多个脉冲。硬件上整形解决了边沿变缓的问题软件上还需要做窗口保护——检测到下降沿后进入15ms的屏蔽窗口窗口内忽略所有边沿触发实测能滤掉绝大部分毛刺。3.3 执行机构驱动蠕动泵的H桥与PWM调速细节蠕动泵的电机是普通的直流有刷电机额定电压12V堵转电流约600mA。驱动方案我选择了L9110S双H桥驱动芯片原因有两点L9110S内部集成续流二极管不需要额外搭二极管桥支持PWM调速和正反转控制方便做电机的软启停和反转排空。接线方式也比较直观INA引脚接STM32的PWM输出引脚INB引脚接普通GPIO控制方向OUTA/OUTB接电机两端。实际使用时有一个经验电机启动瞬间不要直接给100%占空比而是用软件做两阶段启动——先给40%占空比让电机低速爬行100ms再逐步提升到目标占空比。这种软启动方式可以减少电流冲击同时避免蠕动泵泵管在突然高速旋转时产生气泡。3.4 液位检测与报警电路非接触式传感器和声光告警液位检测这个模块我花了比较多心思。墨菲斯滴管内的液面下降到底部时如果不及时发现空气会进入输液管这是输液过程中最危险的情况。我采用的电容式非接触液位传感器型号是XKC-Y25它利用液体和空气的介电常数差异来感应液位变化安装在管道外壁即可工作。传感器输出的是开关量信号高/低电平直接接MCU的GPIO读取。这里有个容易忽略的细节传感器需要一段上电稳定时间约3秒上电后如果立刻读取状态可能读到的是无效电平。所以系统状态机里“待机态”自检时必须等待传感器稳定再开始正常输液监测。报警电路用的是有源蜂鸣器加红色高亮LED。有源蜂鸣器只要通电就会响不需要MCU输出PWM驱动接线简单且响度足够。由于蜂鸣器工作电流约30mA不能直接由GPIO驱动我用了S8050三极管做开关驱动基极串1kΩ限流电阻。报警逻辑分为两级滴速偏差超过阈值但未到危险值蜂鸣器间歇鸣响响0.5s停1s液位过低或严重超速蜂鸣器持续鸣响同时电机停止运行。这套分级报警的好处是护士听到不同节奏的声音就能初步判断故障等级不需要凑到设备跟前看屏幕。4. 软件核心逻辑滴速计算、PID调节与掉电存储4.1 滴速计算定时器输入捕获的正确打开方式滴速检测的软件实现是整个系统最容易被“跑通但不准确”的部分。我的方案是使用TIM2的通道1做输入捕获工作在上升沿下降沿都触发的方式这样可以得到一个完整脉冲的周期。初始化参数 - 预分频器72-11MHz计数频率分辨率为1μs - 自动重载0xFFFF65535最大测量周期65.5ms - 捕获通道TIM_CH_1双边沿触发 中断处理逻辑 1. 读取CCR1寄存器计算本次边沿与上次边沿的时间差Delta 2. 若Delta在合理范围10ms ~ 2000ms认为是一个有效液滴 3. 若Delta小于10ms判定为干扰脉冲丢弃 4. 计算滴速Rate 60000 / Delta滴/分钟 5. 将最近10个有效Delta做滑动平均得到稳定滴速为什么一定要做滑动平均因为实际输液时液滴滴落并不是绝对均匀的蠕动泵的脉动、药液黏度变化、输液管高度差都会让连续两滴的间隔有波动。采用10次平均后滴速显示值会平滑很多PID控制器的输入也不会出现剧烈跳动。4.2 PID闭环调速双环结构让“设定速度”真正锁得住PID调节是本系统和普通“输液报警器”最大的区别。普通输液报警器只做监测滴速快慢全靠护士手动调节输液器上的滚轮而本系统通过实时比较“设定滴速”和“实测滴速”自动调节蠕动泵转速实现闭环控制。控制结构上我采用了速度环滴速环的双环串联结构从原理上讲就是外环根据设定滴速和实测滴速的偏差计算目标电机转速内环根据目标转速和实际转速的偏差计算PWM占空比。这里要特别说明一下之所以不直接用“滴速-PWM”单环是因为输液管道的弹性形变、泵管的老化会造成同一PWM占空比在不同时期产生不同的流量引入转速内环可以有效消除执行机构的非线性影响。PID参数我给出了一套实际跑通的参考值控制环KpKiKd输出限幅滴速外环1.20.050.3目标转速0~150rpm转速内环0.80.100.1PWM占空比0~100%参数整定方法是先断开内环直接用PWM开环驱动蠕动泵记录不同占空比对应的稳定滴速找到系统的近似线性区间然后从小到大调节外环Kp观察滴速阶跃响应直到临界振荡最后在此基础上加入Ki消除稳态误差。这套方法就是工程上常用的临界比例度法比盲目试凑要高效得多。4.3 触摸按键、OLED界面与掉电存储的实现人机交互方面我用了4个独立按键确认、加、减、返回/停止和一块0.96寸OLED屏幕I2C接口。界面上分成三屏主界面显示当前滴速、设定滴速、输液剩余量估算值设置界面设定滴速目标值10~100滴/分钟、报警上下限系统信息界面显示PID参数版本号、运行累计时间。OLED驱动的实现没什么特别的关键是UI刷新策略。一开始我直接在200ms定时中断里全屏刷新OLED结果发现数字更新时会出现残影且主循环被刷屏拖慢。后来改成局部刷新——只更新变化区域的坐标缓冲区刷新时间从原来的80ms降到15ms整个界面流畅很多。掉电保存这块用的是STM32片内Flash模拟EEPROM的方案。F103C8T6没有硬件EEPROM但片内Flash有64KB我专门划出最后一页1KB存储配置参数。写Flash前需要先擦除整个扇区所以不能频繁写入我采取的策略是设置参数时只在确认按键按下后擦写一次正常运行中不做任何Flash写入。实测这样既保证了掉电保存功能又不会影响Flash寿命。4.4 无线数据上报和简单组网协议升级版引入无线功能后软件上新增了一个轻量级通信协议。考虑到大多数病房环境下的实际需求我选择串口转Wi-Fi模块ESP8266方式每个输液终端有一个固定节点ID通过透明传输模式与上位机建立TCP连接。数据帧格式定义如下帧头(0xAA) 节点ID(1字节) 命令字(1字节) 数据长度(1字节) 数据区(N字节) 校验字节(1字节累加和)命令字定义了三种0x01心跳上报滴速、液位状态、报警标志0x02参数下发从护士站远程调整输液速度0x03强制停止。心跳上报周期为1秒若超过10秒没有收到某一节点的数据上位机界面会将该节点标记为“离线”。这个功能在实地验证中非常实用护士站可以同时监控多个输液节点哪个床位报警一目了然。5. 仿真验证与实测数据从Proteus到实物的完整校验链路5.1 Proteus仿真设计先验证逻辑再动硬件很多人觉得Proteus仿真在嵌入式项目里可有可无我持不同态度。对于这种带执行机构和传感器的系统仿真可以在不焊板子的情况下把控制逻辑跑通省掉大量调试时间。在Proteus里搭建仿真工程时核心元件包括STM32F103C8T6主控、L9110S电机驱动芯片、直流电机、LM393比较器、红外发射/接收管、蜂鸣器和按键。滴速信号在仿真里用一个信号发生器替代——设置频率为1Hz的方波模拟滴速60滴/分钟的状态MCU通过输入捕获检测频率PID输出PWM占空比驱动虚拟电机。Proteus自带的虚拟示波器可以同时观察PWM波形和滴速频率波形调试PID参数时非常直观。仿真阶段的注意点有两个Proteus的STM32外设模型对定时器输入捕获支持得比较好但ADC模型有时候不太准涉及模拟量采集的功能建议还是到实物上去验证仿真里蜂鸣器、电机这类负载的工作电压和实物有差异仿真能验证逻辑正确性但电流和功率参数必须以实测为准。5.2 实物联调一套可复现的硬件调试流程从仿真转到实物后我的调试顺序是“电源 → 最小系统 → 传感器 → 执行机构 → 通信”每一级验证通过再进入下一级避免多故障并发时无法定位。第一步先通电测试电源树各级电压12V输入、5V输出、3.3V输出是否正常。这个步骤很多人会跳过但电源异常是一切诡异问题的根源必须优先排除。第二步用ST-LINK烧录一个GPIO翻转的裸机程序确认MCU最小系统工作正常。如果这一步都过不去后面所有调试都无从谈起。第三步外接红外对管信号发生模块用示波器观察LM393输出波形确认滴速检测链路计数准确。第四步空载测试蠕动泵在不同占空比下的转速曲线记录数据用于PID前馈补偿。第五步联调Wi-Fi模块通过手机串口助手或PC端网络调试助手验证数据帧收发。5.3 实际测试中出现的关键问题和修复记录这个项目里最值得写的一笔是实际输液测试时遇到的一个诡异问题滴速显示值周期性偏大且误差和输液瓶高度明显相关。现象是这样的把输液瓶挂在1.2米高度时设定滴速60滴/分钟系统显示在62~64之间波动而当把输液瓶抬高到1.8米时显示值变成了68~72。理论上输液瓶越高滴速应该越快但我的PID闭环应该会调整电机转速来抵消这个偏差才对为什么控制不住呢排查过程让我意识到问题不在软件而在硬件安装位置。红外对管安装在滴管中下部而液滴从滴管滴出时会产生速度的抛物线当液位高度差异导致滴落初速度不同时液滴通过检测窗口的时间相差很大。液滴速度快时红外光线被遮挡的时间变短接收管输出的低电平宽度变窄但仍然会被判定为一个有效脉冲——单从脉冲周期来看液滴确实是以更快的频率落下。问题出在电机和滴速之间的延迟特性上。蠕动泵的流量变化需要经过一段软管之后才能反映到滴管处的滴速而这个延迟随着输液瓶高度、管径和药液黏度不同而不同。我的PID控制周期是50ms采样和控制频率远高于系统的物理响应带宽导致控制器频繁误判“误差未减小”而超调。解决方案是在PID控制上做一个Smith预估器——相当于在控制器内部建立一个输液管道的延迟模型让控制器知道“当前的滴速变化其实对应的是2秒前的电机转速调整”从而避免过度调节。实际实现时简化处理测量得到系统的纯延迟时间约1.6秒在PID输出路径上增加一个一阶惯性滤波并把外环采样周期从50ms放宽到200ms。修改后测试滴速波动范围从±4滴/分钟收敛到±1滴/分钟效果非常明显。6. 开发过程中踩过的坑与排查思路给后来者提个醒6.1 ST-LINK连接失败“no stm32 target found”的常见原因网上关于STM32开发最常出现的报错就是“error: no stm32 target found! if your product embeds debug authentication, please...”这句话。我刚开始调试这个项目时也踩过这个坑一上来就怀疑芯片坏了其实绝大多数情况是下面几个原因接线不当SWDIO、SWCLK两条线没接对或者杜邦线接触不良。ST-LINK的SWD接口只需要4根线3.3V、GND、SWDIO、SWCLK逐一确认导通性目标板没有独立供电如果ST-LINK只接SWDIO和SWCLK而没有接3.3V输出某些低功耗目标板会无法进入调试模式解决方法是让ST-LINK给目标板供电或两端共地复位引脚被拉死如果NRST引脚被外接设备强制拉低MCU一直处于复位状态自然无法连接调试接口被复用如果代码里把PA13/PA14即SWDIO/SWCLK重映射成普通GPIO了程序运行后调试口就失效了。解决办法是按住复位键的同时点击下载在芯片复位瞬间擦除程序。6.2 滴速检测抖动误触发从硬件滤波到软件去抖的完整链路滴速检测精度是这个项目的生命线我在实际测试中遇到的主要干扰源有三个环境光干扰、电机EMI干扰、药液挂壁残留干扰。环境光干扰红外接收管对阳光和节能灯光都有响应。硬件上的应对是给红外对管套上黑色热缩管做遮光同时接收管前面加红外滤光片。这一招非常有效实测在100W白炽灯直射下也能稳定检测电机EMI干扰电机启动和换向瞬间产生的EMI会耦合到滴速检测信号线上。除了在电机两端并联0.1μF瓷片电容和10μH电感之外我还在PCB布线时把电机驱动线和信号线分开了两个区域并且信号线采用地线包边处理药液挂壁残留输液过程中滴管内壁会附着液体形成薄膜红外对管检测到薄膜遮挡也会产生误触发。这个问题的软件应对是设置脉冲宽度判决——有效液滴的低电平时间应该在1~10ms范围内挂壁薄膜产生的信号通常电平时间更长且幅度更小通过脉冲宽度过滤可以识别并丢弃。6.3 蠕动泵低速脉动对滴速均匀性的影响蠕动泵在小流量工况下有一个固有缺陷泵头每转一圈会经历数次“挤压-释放”的循环导致输出流量脉动。当设定滴速很低比如15滴/分钟时脉动会直接造成相邻两滴之间的时间间隔差异巨大滴速检测值剧烈波动PID控制器也随之振荡。解决思路有两个一是机械层面选用更多滚轮的泵头比如6滚轮替代3滚轮减少单个滚轮周期的流量脉动幅度二是软件层面在PID控制目标值上增加“等间隔滴落”约束——不追求每个控制周期都相等而是控制电机相位尽量让每次挤出的液滴间隔一致。第二个方案实现起来比较复杂我在这个版本里做了简化把滴速环的输出经过一个10点的滑动平均滤波再送入转速环让电机转速变化尽量平缓实测低速均匀性提升了约35%。6.4 无线模块在病房环境下的掉线恢复策略ESP8266模块在实验室调试时一切正常但只要一到实际病房环境就会出现周期性的连接断开和重连。排查发现病房里的2.4G频段干扰源非常多Wi-Fi信号拥挤会导致ESP8266的TCP连接经常被重置。我采取的应对措施包括硬件上Wi-Fi模块远离电机驱动板至少5cm外接2.4G频段专用天线PCB天线在金属床架附近严重衰减协议上上位机增加了“连续丢失5个心跳包即判定离线”的容错逻辑下位机采用“断线自动重连”机制重连周期从原来的每500ms检测一次优化为指数退避1s、2s、4s……最大30s避免在信号差时疯狂重连导致模块崩溃数据上每个节点本地缓存最近100条告警记录恢复通信后优先补传保证护士站端数据不缺失。这套容错机制上线后病房实测连续运行72小时掉线次数从平均每小时8次降低到整个周期的2次效果显著。7. 开源文件结构与二次开发建议7.1 工程目录说明这个项目的开源文件按功能做了清晰的分目录目录内容说明/Doc项目设计文档、用户手册、测试报告/Hardware原理图AD格式、PCB图、BOM清单/Software/CoreSTM32标准外设库的启动文件与内核文件/Software/User主函数、中断服务、状态机逻辑/Software/Module滴速检测、PID控制、OLED显示、按键扫描等外设驱动模块/SimulationProteus仿真工程文件/Host_Computer上位机监控程序源码PythonPyQt拿到开源代码后我建议不要急着烧录先把 /Doc 下的设计文档通读一遍重点关注需求规格和系统架构章节理解每一个模块的存在意义。然后从 /Software/Module 里单独挑出滴速检测模块配合 /Simulation 工程做单元测试跑通了再整机联调。7.2 在这套系统上还能扩展什么这个项目的框架是开放的如果你有精力继续深化我认为下面几个方向最有价值输液余量精确估算在现有滴速基础上结合药液密度和输液管规格推算剩余时间并在OLED和上位机同时显示多路输液控制一个主控控制两路甚至四路输液通道适用于需要同时输注多种药液的重症患者医院信息系统对接将输液数据通过HL7协议或MQTT网关接入医院现有的护理呼叫系统这是产品化落地的关键环节异常检测算法升级通过分析滴速的时间序列特征提前识别渗液、堵塞、静脉回血等异常状态而不只是简单的阈值报警。我个人在实际操作中的体会是这套系统最被低估的部分其实是“预测给药偏差”的潜力。现有输液泵普遍采用的闭环方案是基于电机转数和管道压力的间接估算而基于光电滴速检测的闭环方案为医疗输液监护提供了一个更加直观的、以“液滴”为基本单位的技术路径。如果你沿着这条技术路径继续挖下去会发现它能延伸出很多值得做的东西。最后再分享一个调试心得做这类带闭环控制和执行机构的项目不要相信“仿真通过就等于实物正常”。仿真拉通了控制逻辑之后尽快进入实物验证阶段并且全程把示波器探头挂在关键信号点上养成“看波形、不信猜测”的习惯所有疑难问题最后都会回到波形上找到答案。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进