嵌入式不只是写驱动:医疗自动化设备中的平台化控制系统实践
一、背景:嵌入式开发不只是点灯和调包
在很多人的印象里,嵌入式开发要么是“点灯、串口、SPI、I2C”,要么是“拿开发板跑 Demo”,再复杂一点就是 RTOS 多任务、通信协议和底层驱动。
但在医疗器械、生命科学仪器和实验室自动化设备中,嵌入式系统面对的往往不是一个简单外设,而是一整套复杂的机电控制系统。
一台典型的 IVD 仪器或科学仪器中,可能同时包含:
-
多个步进电机、柱塞泵、注射泵、隔膜泵;
-
多路电磁阀、旋转阀、切换阀;
-
压力、液位、温度、位置等传感器;
-
光学检测、温控、运动轴、通信接口;
-
上位机流程控制、参数配置和日志分析系统。
在这类系统中,嵌入式工程师真正面对的问题,已经不是“怎么把某个外设驱动起来”,而是:
如何把复杂硬件、动作流程、状态管理、异常处理和数据分析组织成一个长期可维护、可复用、可扩展的控制平台。
这也是趋盛科技在医疗自动化和科学仪器控制领域持续探索的方向:将传统高度依赖项目定制的嵌入式控制系统,逐步抽象为可配置、可编排、可分析的平台化控制系统。
二、传统开发模式的痛点:每个项目都从底层重新来一遍
以一台典型的医疗自动化设备为例,设备内部通常包含以下模块:
-
加样针运动控制;
-
注射泵定量吸排液;
-
多通阀、电磁阀液路切换;
-
温控模块;
-
光学检测模块;
-
压力、液位、位置等传感器;
-
上位机通信;
-
故障检测与恢复机制。
传统项目开发中,通常会按功能模块拆分代码:
motor_driver.c
valve_driver.c
pump_driver.c
sensor_driver.c
protocol.c
workflow.c
error_handler.c
这种模式在单个项目中是可行的,但随着产品数量增加,问题会逐渐暴露出来。
1. 驱动复用困难
不同项目使用的泵、阀、电机型号不同,即使控制逻辑相似,也往往需要重新写一套适配代码。
例如:
-
某项目使用 A 厂家的柱塞泵;
-
另一个项目换成 B 厂家的注射泵;
-
第三个项目需要同时控制多个泵和多个阀;
-
后续产品又增加了压力反馈、液位检测和异常保护。
底层驱动、通信协议、参数配置、初始化逻辑都可能发生变化。结果就是每个项目都要重新开发、重新调试、重新验证。
2. 业务流程和底层控制耦合严重
在医疗自动化设备中,真正复杂的往往不是单个电机转多少步,而是完整流程。
例如一次液路动作可能包含:
打开进液阀 → 注射泵吸液 → 关闭进液阀 → 打开出液阀 → 注射泵排液 → 等待压力稳定 → 触发检测
如果这些动作全部写死在 C 代码中,后期修改流程就必须改固件、重新编译、重新烧录,甚至重新做测试验证。
对于研发阶段来说,这会极大降低调试效率。
对于产品迭代来说,也会增加维护成本和质量风险。
3. 异常处理越来越复杂
医疗设备和科学仪器不能只考虑“正常流程能跑通”,还必须处理大量异常情况:
-
电机堵转;
-
阀未打开或响应延迟;
-
压力异常;
-
液路堵塞;
-
气泡干扰;
-
传感器数据漂移;
-
上位机通信中断;
-
运动过程被人为暂停或复位。
如果没有统一的状态管理和异常处理机制,项目越做越大,代码就越容易变成“补丁堆叠”。
三、平台化思路:把硬件抽象成“虚拟组件”
趋盛的核心思路不是把每个项目都写成一个完全独立的固件,而是先建立一个通用控制平台。
这个平台把复杂硬件抽象成一类类标准化的“虚拟组件”:
-
电机组件;
-
注射泵组件;
-
柱塞泵组件;
-
电磁阀组件;
-
旋转阀组件;
-
温控组件;
-
压力传感器组件;
-
光学检测组件;
-
通信组件;
-
流程组件。
每个组件背后仍然对应真实的嵌入式驱动,但对上层应用来说,它们不再是散乱的底层接口,而是具有统一参数、统一状态和统一动作模型的可配置模块。
例如,一个注射泵组件可以抽象为:
typedef struct {
uint8_t id;
uint32_t max_position;
uint32_t current_position;
uint32_t speed;
uint8_t status;
uint8_t error_code;
} PumpComponent;
typedef enum {
PUMP_IDLE,
PUMP_BUSY,
PUMP_ERROR,
PUMP_TIMEOUT
} PumpStatus;
上层不需要关心底层到底是步进电机、丝杆机构,还是某种串口协议控制的泵,只需要调用统一动作接口:
pump_move_to(pump_id, target_position, speed);
pump_aspirate(pump_id, volume);
pump_dispense(pump_id, volume);
pump_stop(pump_id);
pump_get_status(pump_id);
这样做的好处是:
底层硬件可以变化,但上层流程逻辑尽量不变。
为了让控制系统从“单项目定制开发”走向“可配置、可复用、可扩展”的平台化架构,可以将系统抽象为上位机编排层、平台软件层、控制运行时层、驱动组件层和硬件执行层。
图1 平台化控制系统总体架构图

图1展示了平台化控制系统的总体关系:
上位机侧完成设备流程编排、参数配置、运行监控和日志分析;TrendView、TrendCompile、TrendOptimize 分别承担流程编排、板卡/驱动配置和运行数据优化;控制板卡侧负责任务调度、状态机管理、通信管理和异常处理;底层则连接步进电机、注射泵、电磁阀、传感器、光学模块和温控模块等执行单元。
四、从“写代码”到“配置系统”
在传统模式中,嵌入式开发者需要手动完成:
-
选择 MCU;
-
配置 IO;
-
编写驱动;
-
配置通信;
-
编写业务流程;
-
编写状态机;
-
调试异常处理;
-
对接上位机。
趋盛平台将其中大量重复性工作做成配置化流程。
1. 硬件配置层
通过板卡配置工具,开发者可以定义:
-
哪个端口连接哪个电机;
-
哪个 IO 控制哪个阀;
-
哪个 ADC 采集哪个传感器;
-
哪个串口连接哪个模块;
-
每个执行器的默认参数;
-
每个传感器的采样周期和报警阈值。
配置完成后,系统可以生成对应的硬件映射和基础固件配置。
这一步的价值在于:
硬件资源不再散落在代码中,而是形成清晰、可视化、可复用的工程配置。
2. 驱动适配层
对于泵、阀、电机、传感器等常见器件,平台沉淀成熟驱动库。
不同项目只需要选择对应组件类型和参数,而不必每次从零开始写驱动。
例如:
组件类型:注射泵
控制方式:步进电机
行程范围:0-60000 step
默认速度:3000 step/s
加速度:8000 step/s²
零位检测:光电开关
异常检测:超时 + 堵转 + 压力异常
这些参数可以通过配置文件或上位机工具下发,而不是写死在代码中。
3. 流程编排层
医疗自动化设备中大量动作是流程型逻辑。
例如一次加样动作可能包含:
针移动到样本位
下降到吸样高度
打开吸液阀
注射泵吸样
关闭吸液阀
针移动到反应杯
打开排液阀
注射泵排样
清洗针外壁
复位
如果每一个动作都由嵌入式工程师写死在代码中,调试和维护都会很困难。
平台化系统采用图形化流程编排思路,将底层动作封装成标准指令节点,上层可以通过可视化方式组合流程。
例如:
MoveAxis(X, 12000)
MoveAxis(Z, 3500)
OpenValve(V1)
PumpAspirate(P1, 50uL)
CloseValve(V1)
MoveAxis(X, 30000)
OpenValve(V2)
PumpDispense(P1, 50uL)
CloseValve(V2)
这让嵌入式工程从“写死业务逻辑”,逐渐转向“提供可靠、可复用的动作能力”。
五、关键技术实现:多执行器协同调度
在真实设备中,多个动作并不是简单串行执行。为了提高效率,很多任务需要并行或半并行执行。
例如:
-
X 轴移动时,注射泵可以提前准备;
-
温控模块可以在液路动作期间持续稳定;
-
光学检测可以等待液体稳定后自动触发;
-
清洗流程可以和下一个样本准备流程交叠。
这就需要一个多执行器调度机制。
1. 任务模型
可以把每个动作抽象成一个任务:
typedef struct {
uint16_t task_id;
uint8_t component_id;
uint8_t command;
uint32_t param1;
uint32_t param2;
uint32_t timeout_ms;
uint8_t dependency_count;
uint16_t dependencies[8];
uint8_t status;
} ControlTask;
每个任务包含:
-
执行对象;
-
动作命令;
-
参数;
-
超时时间;
-
依赖关系;
-
当前状态。
2. 依赖调度
例如:
Task 1:X轴移动到样本位
Task 2:Z轴下降
Task 3:打开阀V1
Task 4:注射泵吸液
Task 5:关闭阀V1
其中 Task 2 依赖 Task 1,Task 4 依赖 Task 3。
但温控任务、压力采集任务、通信任务可以并行运行。
调度器需要根据依赖关系判断哪些任务可以立即执行,哪些任务必须等待。
3. 状态机设计
每个任务可以采用统一状态机:
READY → RUNNING → DONE
↘ ERROR
↘ TIMEOUT
↘ ABORTED
这样做可以避免不同驱动各自处理状态,导致系统行为不一致。
4. 阀动作延迟与压力反馈控制伪代码
在液路控制中,阀动作不是瞬时完成的。
如果阀还没有完全打开,注射泵就开始吸液或排液,可能会造成瞬时阻力异常、压力波动,甚至导致加样量偏差。
因此,系统中需要把阀延迟、泵动作、压力稳定判断和异常处理放入统一状态机中。
下面是一段简化后的伪代码示例:
typedef enum {
STEP_OPEN_INLET_VALVE,
STEP_WAIT_VALVE_READY,
STEP_PUMP_ASPIRATE,
STEP_CLOSE_INLET_VALVE,
STEP_OPEN_OUTLET_VALVE,
STEP_PUMP_DISPENSE,
STEP_WAIT_PRESSURE_STABLE,
STEP_TRIGGER_DETECT,
STEP_ERROR
} ProcessStep;
typedef struct {
ProcessStep step;
uint32_t timestamp;
uint32_t valve_delay_ms;
uint32_t stable_time_ms;
uint32_t timeout_ms;
uint32_t aspirate_volume_ul;
uint32_t dispense_volume_ul;
uint32_t aspirate_speed;
uint32_t dispense_speed;
float pressure_threshold;
} ProcessContext;
void process_run(ProcessContext *ctx)
{
switch (ctx->step) {
case STEP_OPEN_INLET_VALVE:
valve_open(V1);
ctx->timestamp = millis();
ctx->step = STEP_WAIT_VALVE_READY;
break;
case STEP_WAIT_VALVE_READY:
if (millis() - ctx->timestamp >= ctx->valve_delay_ms) {
pump_aspirate(P1,
ctx->aspirate_volume_ul,
ctx->aspirate_speed);
ctx->step = STEP_PUMP_ASPIRATE;
}
break;
case STEP_PUMP_ASPIRATE:
if (pump_is_done(P1)) {
valve_close(V1);
valve_open(V4);
ctx->timestamp = millis();
ctx->step = STEP_OPEN_OUTLET_VALVE;
}
break;
case STEP_OPEN_OUTLET_VALVE:
if (millis() - ctx->timestamp >= ctx->valve_delay_ms) {
pump_dispense(P1,
ctx->dispense_volume_ul,
ctx->dispense_speed);
ctx->step = STEP_PUMP_DISPENSE;
}
break;
case STEP_PUMP_DISPENSE:
if (pump_is_done(P1)) {
ctx->timestamp = millis();
ctx->step = STEP_WAIT_PRESSURE_STABLE;
}
break;
case STEP_WAIT_PRESSURE_STABLE:
if (pressure_is_stable(ctx->pressure_threshold,
ctx->stable_time_ms)) {
trigger_detect();
ctx->step = STEP_TRIGGER_DETECT;
} else if (millis() - ctx->timestamp > ctx->timeout_ms) {
ctx->step = STEP_ERROR;
}
break;
case STEP_TRIGGER_DETECT:
log_info("Detection triggered.");
break;
case STEP_ERROR:
emergency_stop();
valve_close_all();
log_error("Pressure not stable or valve timeout.");
break;
}
}
这段伪代码体现了几个关键点:
-
阀打开后增加延迟等待;
-
泵吸液和排液由状态机控制;
-
压力稳定后才触发检测;
-
超时或压力异常时进入安全处理;
-
所有动作均可记录日志,便于后续分析。
5. 压力反馈闭环微调
在部分高精度液体输送场景中,仅靠步数或速度参数并不能完全保证输送稳定性。
当液体黏度、管路阻力、阀响应时间发生变化时,可以引入压力反馈,对泵速度进行微调。
简化逻辑如下:
float pressure_feedback_adjust(float target_pressure,
float current_pressure,
float base_speed)
{
float error = target_pressure - current_pressure;
float adjust = 0.8f * error;
float new_speed = base_speed + adjust;
if (new_speed > MAX_PUMP_SPEED) {
new_speed = MAX_PUMP_SPEED;
}
if (new_speed < MIN_PUMP_SPEED) {
new_speed = MIN_PUMP_SPEED;
}
return new_speed;
}
这类反馈控制可以用于:
-
检测液路堵塞;
-
判断阀响应异常;
-
识别气泡或液路阻力变化;
-
在允许范围内微调泵速;
-
提高排液稳定性和重复性。
六、工程实践:以液路控制为例
在 IVD 和生命科学仪器中,液路控制是非常典型的复杂嵌入式场景。
一个常见液路单元可能包含:
-
一个注射泵;
-
多个电磁阀;
-
一个压力传感器;
-
多个液路通道;
-
一个反应池或检测池;
-
清洗液和废液通路。
一次完整动作可能是:
打开进液阀
注射泵后退吸液
关闭进液阀
打开出液阀
注射泵前进排液
关闭出液阀
等待压力稳定
触发检测
表面看只是几个动作,但真正工程化时会遇到很多问题。
图2 液路控制单元示意图

图2展示了一个典型液路控制单元。
样本从样本瓶经过进液阀进入注射泵,再通过压力传感器进入检测池或反应池,最终经排液阀进入废液瓶。清洗液可以通过独立阀路进入主流路,实现清洗、排空和检测前稳压。
这类液路单元虽然结构并不复杂,但对控制系统提出了较高要求:
1. 阀响应延迟
电磁阀并不是指令发出后立即完成动作。
如果泵动作过早启动,就可能出现阀尚未完全打开、液体阻力异常、压力波动等问题。
因此系统需要支持动作间延迟:
OpenValve(V1)
Delay(20ms)
PumpAspirate(P1, 50uL)
这个延迟不应该散落在业务代码里,而应该作为组件参数或流程节点参数进行统一管理。
2. 压力反馈
在高精度液体输送中,仅依靠步数或时间并不一定能保证液体稳定输送。
压力传感器可以用于判断:
-
是否堵塞;
-
是否有气泡;
-
阀是否打开异常;
-
液路是否存在阻力变化;
-
排液过程是否稳定。
平台可以将压力反馈作为流程判断条件:
如果压力超过阈值 → 停止泵 → 关闭阀 → 上报异常
如果压力稳定在目标范围 → 继续下一步检测
3. 参数可调
不同液体黏度、管路长度、泵规格、阀响应特性都会影响动作参数。
如果参数都写死在固件里,现场调试会非常低效。
平台化系统可以把关键参数配置化:
-
吸液速度;
-
排液速度;
-
阀动作延迟;
-
压力阈值;
-
稳定等待时间;
-
超时时间;
-
回零速度;
-
异常重试次数。
这些参数可以在上位机或配置工具中调整,减少反复修改固件的成本。
4. 调试数据闭环
平台化控制系统不仅要能执行流程,还要能分析流程。
例如在一次排液过程中,系统可以同时记录:
-
阀开启时间;
-
泵启动时间;
-
泵停止时间;
-
压力变化曲线;
-
压力稳定时间;
-
异常报警点;
-
当前参数版本;
-
当前流程节点。
图3 运行调试与优化分析界面示意

图3展示了一个典型的运行调试与优化分析思路。
左侧是流程执行日志,中间是压力/时序曲线,右侧是状态机和关键参数。通过日志、压力曲线和状态机联合分析,可以快速判断问题来源:
-
如果阀开启后压力迟迟不上升,可能是阀响应延迟或流路未导通;
-
如果泵启动后压力瞬间过高,可能是液路堵塞或阀未完全打开;
-
如果压力曲线波动过大,可能是气泡、管路弹性或速度参数不匹配;
-
如果压力稳定时间过长,可能需要优化泵速、阀延时或稳压等待时间。
这种分析方式使调试从“凭经验猜测”转向“基于日志和传感器数据定位问题”。
七、平台化带来的价值
1. 对嵌入式工程师的价值
平台化不是削弱嵌入式工程师的价值,而是让工程师从重复劳动中解放出来。
过去大量时间花在:
-
重复写驱动;
-
重复调 IO;
-
重复改流程;
-
重复处理通信协议;
-
重复定位状态异常。
平台化之后,工程师可以更多关注:
-
驱动稳定性;
-
调度机制;
-
实时性;
-
安全机制;
-
异常恢复;
-
系统架构;
-
工程复用。
这才是嵌入式全栈能力真正的体现。
2. 对产品研发的价值
对于医疗器械和科学仪器企业来说,平台化控制系统可以显著提升研发效率:
-
新产品开发周期缩短;
-
旧项目经验可以复用;
-
不同产品之间硬件和软件架构统一;
-
现场调试更方便;
-
后续维护成本降低;
-
质量体系和验证过程更清晰。
尤其对于小型研发团队和初创企业而言,平台化控制系统可以帮助其把有限资源集中在核心检测原理、试剂体系、算法和临床应用上,而不是长期陷入底层控制系统反复开发。
3. 对行业的价值
医疗自动化设备正在从单一功能设备,走向模块化、平台化和多项目联检。
这意味着嵌入式系统也必须升级:
从单板控制 → 多模块协同
从固定流程 → 可配置流程
从手写驱动 → 驱动库复用
从项目定制 → 平台化开发
从经验调试 → 数据化优化
这不仅是软件架构变化,也是嵌入式开发模式的变化。
八、趋盛的实践方向:Trend 系列平台
围绕上述思路,趋盛科技构建了面向医疗自动化和科学仪器的 Trend 系列平台,主要包括 TrendCompile、TrendView 和 TrendOptimize。
1. TrendCompile:板卡与驱动配置
TrendCompile 负责完成硬件资源、端口、驱动和器件参数的配置。
它解决的是:
这套设备有哪些硬件?每个硬件连接在哪里?应该用什么驱动和参数?
通过配置化方式,把硬件连接关系、驱动参数、执行器类型统一管理,减少大量重复固件适配工作。
2. TrendView:流程可视化编排
TrendView 负责把底层执行器动作组织成完整工艺流程。
它解决的是:
设备要按什么顺序执行动作?哪些动作可以并行?哪些动作需要等待条件?
对于注射泵、阀、运动轴、传感器、检测模块等组件,可以通过图形化方式进行流程编排,便于研发调试和方案验证。
3. TrendOptimize:运行分析与优化
TrendOptimize 面向运行数据分析。
它解决的是:
系统执行过程中是否稳定?动作是否存在延迟?压力、位置、时间参数是否需要优化?
通过采集运行日志、传感器数据和执行指令,可以帮助工程师分析流程瓶颈和异常原因。
九、一个典型开发流程
基于平台化模式,一个新设备的控制系统开发流程可以变成:
1. 确认设备功能和执行器清单
2. 选择控制板卡和扩展模块
3. 配置电机、泵、阀、传感器等组件
4. 生成基础固件和通信接口
5. 在可视化工具中编排动作流程
6. 下载流程并联机调试
7. 采集运行数据
8. 根据压力、时序、位置等数据优化参数
9. 固化稳定版本
10. 进入产品验证和量产导入
与传统模式相比,这种流程的核心变化是:
嵌入式工程不再只交付一份固件,而是交付一套可持续演进的控制平台。
十、思考:嵌入式全栈的未来不只是“更底层”,也是“更系统”
很多人理解嵌入式高手,往往想到:
-
会写驱动;
-
会看寄存器;
-
会调 RTOS;
-
会分析总线波形;
-
会优化中断和 DMA;
-
会处理内存和实时性问题。
这些能力当然重要。
但在复杂行业设备中,真正的全栈嵌入式能力,还包括:
-
对硬件系统的抽象能力;
-
对业务流程的建模能力;
-
对异常状态的管理能力;
-
对跨项目复用的架构能力;
-
对上位机、固件、硬件和工艺流程的协同能力;
-
对产品长期维护和迭代的工程判断能力。
医疗自动化设备、科学仪器、工业装备、汽车电子等领域,都会越来越需要这种系统级嵌入式能力。
未来的嵌入式开发,不会只是“Ctrl+C 调包”,也不会只是“拿电烙铁焊板子”。
它会越来越像一套完整的工程系统:
硬件可配置
驱动可复用
流程可编排
状态可追踪
数据可分析
异常可恢复
平台可演进
这也是趋盛科技希望推动的方向:
让复杂自动化设备的控制系统开发,从一次次重复造轮子,走向模块化、平台化和可持续复用。
结语
嵌入式开发的硬核,不只体现在某一段底层代码写得多漂亮,也体现在能否把复杂系统长期稳定地跑起来。
对于医疗器械和科学仪器这样的行业场景来说,每一个泵、每一个阀、每一个传感器、每一个状态机,最终都服务于一个更大的目标:
让设备更稳定,让研发更高效,让产品更快落地。
从写驱动,到搭系统;
从项目开发,到平台复用;
从单点控制,到全栈架构。
这或许正是嵌入式开发者下一阶段真正值得证明的硬实力。
更多推荐



所有评论(0)