3. 自驱动实验平台的总体架构设计
自驱动实验平台不是“把仪器接上电脑”这么简单。它要同时解决四件事:实验任务如何被描述、设备如何被统一调度、数据如何从传感器流到算法、控制指令如何从算法回到执行器。总体架构设计的目标,就是把这四件事拆成稳定的层次和模块,并明确它们之间的接口与数据/控制流向,使平台在更换仪器、增加实验类型或替换算法时,改动范围可控。
一、分层架构:从物理到决策的四层
本平台采用四层架构,自下而上为物理设备层、设备抽象层、实验服务层、应用决策层。分层的判据是“变化频率”:越靠下越稳定,越靠上越易变。物理设备层包含可编程电源、电子负载、数据采集卡、温控台、机械臂等真实对象;设备抽象层把每种仪器的通信协议(SCPI、Modbus、串口帧)封装为统一方法;实验服务层负责实验流程编排、数据缓存与安全联锁;应用决策层运行优化算法、贝叶斯实验设计或强化学习策略,决定“下一步做什么实验”。
层间只允许相邻调用,禁止应用层直接操作串口。这样当把 RS-232 温控台换成以太网版本时,只需重写抽象层的一个驱动,上层实验脚本与算法完全不动。
二、模块划分与接口定义
在设备抽象层内部,进一步划分为驱动模块、资源管理模块、时钟同步模块。驱动模块对每台仪器暴露统一接口,例如:
class Instrument:
def open(self, addr: str) -> None
def set(self, param: str, value: float) -> None
def get(self, param: str) -> float
def close(self) -> None
资源管理模块维护“设备—通道—实验”的占用表,避免两个实验同时抢占同一电源通道。时钟同步模块为所有采集数据打上统一时间戳,时间基准取平台主时钟,单位为毫秒,约定 t=0 为实验启动时刻,全文与图示均采用该约定。
实验服务层对外提供三个核心接口:submit(experiment_spec) 提交实验、subscribe(stream_id) 订阅数据流、abort(experiment_id) 安全中止。接口采用“请求—确认”语义:提交后返回 experiment_id,只有收到确认才认为实验进入队列。
三、数据流与控制流设计
数据流是“自下而上”的:传感器 → 采集卡 → 驱动模块 → 数据总线 → 实验服务层缓存 → 应用层算法。控制流是“自上而下”的:算法输出设定值 → 实验服务层校验 → 资源管理模块检查占用 → 驱动模块下发 → 执行器动作。两条流在实验服务层交汇,形成闭环。
为避免控制指令与数据采集相互阻塞,平台采用双通道设计:数据通道走发布/订阅,控制通道走请求/响应。数据通道允许丢帧但要求低延迟;控制通道不允许丢指令,允许稍高延迟。这一权衡直接决定了后续消息中间件的选型。
四、架构权衡与决策记录
架构设计必然伴随取舍,以下三条决策记录(ADR)是本平台的关键权衡。
| 决策点 | 备选方案 | 选择与理由 |
|---|---|---|
| 设备通信方式 | 直连串口 / 统一抽象层 | 选统一抽象层。虽然初期开发量增加约 30%,但换型时上层零改动,长期维护成本更低。 |
| 数据通道语义 | 可靠队列 / 发布订阅 | 选发布订阅。采集数据允许丢帧,优先保证低延迟;控制指令单独走可靠通道。 |
| 安全联锁位置 | 算法层判断 / 服务层硬联锁 | 选服务层硬联锁。算法可能出错,联锁必须在算法之外独立生效,阈值校验不依赖上层。 |
以温度控制实验为例:算法层输出目标温度 85 ℃,实验服务层先校验该值是否落在安全区间 [20, 120] ℃内,再检查温控台通道是否被占用,通过后由驱动模块下发 SCPI 指令。采集卡以 10 Hz 回传实际温度,数据经总线进入缓存,算法据此决定下一轮设定值。若实测温度超过 110 ℃,服务层联锁直接切断加热输出,不等待算法响应。这一流程体现了“控制下行、数据上行、联锁旁路”的设计原则。
总体架构的价值不在于图有多复杂,而在于它能否回答三个问题:新增一台仪器要改哪里?新增一种实验要改哪里?算法出错时系统是否安全?本平台的分层与模块划分,正是围绕这三个问题给出的可执行答案。