3. 水下控制模块电气功能与通信链路测试

测试对象与链路构成

水下控制模块(SCM)的电气功能测试,核心不是“通电亮灯”,而是验证三条相互独立的通道:供电通道(从水面UPS经脐带缆到SCM内部电源分配)、绝缘通道(各导体对地及导体间的绝缘电阻)、通信通道(Modbus RTU over RS-485 与 CAN 总线,含冗余A/B链路)。长距离脐带缆带来的分布电容与线路衰减,是误码率上升和冗余切换变慢的主要物理原因,因此测试必须用可调模拟线缆(电感+电容网络)替代真实脐带缆,才能在水面完成可重复的验证。

水面测试台 可编程直流电源 0–300 V / 限流 2 A 绝缘电阻测试仪 500 VDC 档 / ≥100 MΩ 信号发生器 + 协议分析仪 Modbus RTU / CAN 2.0B 上位机:误码统计 / 切换计时 模拟脐带缆 可调 L / C 网络 L ≈ 1 mH/km · C ≈ 0.1 µF/km 模拟 0 / 5 / 10 / 20 km A/B 双链路并行引出 末端接 120 Ω 终端电阻 水下控制模块 SCM 电源分配单元 24 VDC 输出 / 隔离 通信主控板 Modbus 从站 / CAN 节点 A 链路收发器 RS-485 / CAN 主用 B 链路收发器 RS-485 / CAN 备用 冗余切换逻辑 + 心跳监视 判据:连续 3 帧超时 → 切 B 链路 测试点:TP-PWR / TP-ISO / TP-A / TP-B 关键判据(示例值,按规格书核定) 供电:24 V ±5% 纹波 ≤ 200 mVpp 限流点 2 A 不误触发 绝缘:≥ 100 MΩ 500 VDC 施加 60 s 导体对地 / 导体间 误码率:≤ 1×10⁻⁶ 20 km 模拟缆长下 连续 10⁵ 帧统计 切换:≤ 500 ms A 断 → B 接管 数据不中断丢失

测试用例设计(供电 / 绝缘 / 通信 / 冗余)

四类用例共用同一套夹具,但激励与判据完全不同。下表给出可直接执行的用例骨架,参数为教学示例值,实际执行前须以SCM规格书和API 17F条款核定。

用例编号测试项激励与连接观测点通过判据(示例)
SCM-E-01供电电压与纹波电源设 24 V,负载接 SCM 全部电气负载TP-PWR23.8–25.2 V,纹波 ≤200 mVpp
SCM-E-02过流保护限流从 2 A 缓升至 3 A电源告警 + TP-PWR2.2 A 前限流动作,SCM 不损坏
SCM-E-03绝缘电阻500 VDC,分别测各导体对地、导体间绝缘测试仪读数≥100 MΩ,60 s 内无击穿
SCM-E-04Modbus 基本收发0 km 模拟缆,9600 bps,读保持寄存器协议分析仪CRC 正确率 100%,响应 <100 ms
SCM-E-05长缆误码率模拟缆 5/10/20 km,连续发 10⁵ 帧误码统计20 km 下 BER ≤1×10⁻⁶
SCM-E-06CAN 链路误码250 kbps,20 km 模拟缆,10⁵ 帧CAN 分析仪错误帧率 ≤0.1%
SCM-E-07冗余切换时间A 链路物理断开,B 链路在线示波器双通道 + 时间戳切换 ≤500 ms,切换后首帧正确
SCM-E-08切换回切A 恢复后观察是否回切或保持链路状态字行为符合规格书定义,无反复抖动

关键实现:误码率与切换时间的测量方法

误码率不能靠“看着通信正常”判断,必须构造已知帧序列并统计。下面给出一个可运行的 Python 脚本,用串口向 SCM 发送递增序号帧,同时记录回读序号,统计丢帧/错帧率;切换时间则通过记录“A 链路断开时刻”与“B 链路首帧正确到达时刻”的差值得到。脚本中的串口对象需按实际测试台替换端口号。

import serial, time, struct

PORT = "COM3"          # 测试台实际串口
BAUD = 9600
N_FRAMES = 100000      # 10^5 帧
TIMEOUT = 0.05

def crc16(data: bytes) -> int:
    crc = 0xFFFF
    for b in data:
        crc ^= b
        for _ in range(8):
            crc = (crc >> 1) ^ 0xA001 if crc & 1 else crc >> 1
    return crc

def build_frame(seq: int) -> bytes:
    body = struct.pack(">H", seq & 0xFFFF)
    return body + struct.pack(">H", crc16(body))

def run_ber_test(ser, n=N_FRAMES):
    sent = recv_ok = 0
    t0 = time.time()
    for seq in range(n):
        frame = build_frame(seq)
        ser.write(frame)
        sent += 1
        ser.timeout = TIMEOUT
        echo = ser.read(4)
        if len(echo) == 4 and echo == frame:
            recv_ok += 1
    dt = time.time() - t0
    ber = (sent - recv_ok) / sent
    print(f"发送 {sent} 帧, 正确回读 {recv_ok} 帧, BER={ber:.2e}, 耗时 {dt:.1f}s")
    return ber

def measure_switch_time(ser, link_ctrl):
    # link_ctrl: 可调用对象,用于断开 A 链路
    t_disconnect = time.time()
    link_ctrl.disconnect_a()
    while True:
        ser.timeout = 0.01
        data = ser.read(4)
        if len(data) == 4 and data[2:] == struct.pack(">H", crc16(data[:2])):
            t_first_b = time.time()
            break
    switch_ms = (t_first_b - t_disconnect) * 1000
    print(f"冗余切换时间 = {switch_ms:.1f} ms")
    return switch_ms

if __name__ == "__main__":
    with serial.Serial(PORT, BAUD, timeout=TIMEOUT) as ser:
        run_ber_test(ser)
        # measure_switch_time(ser, link_ctrl)  # 接入链路控制夹具后启用
模拟缆长的选择应覆盖“标称长度”和“1.5 倍标称长度”两档,因为误码率对缆长呈非线性恶化;只测标称长度容易漏掉裕量不足的问题。切换测试至少重复 5 次,取最大值作为判据,避免单次偶然值。

结果判读与常见异常

  • 误码率随缆长陡增:多为终端电阻缺失或阻值不匹配(RS-485 应为 120 Ω),先用万用表在断电状态确认 A/B 线间电阻约 60 Ω(两端各 120 Ω 并联)。
  • 绝缘电阻偏低但未击穿:检查测试时是否已断开浪涌保护器与滤波器,这些器件在 500 VDC 下会拉低读数,属于测试方法问题而非 SCM 缺陷。
  • 切换时间超标:确认心跳超时判据(示例为连续 3 帧超时)与波特率匹配;波特率越低,3 帧超时本身耗时越长,切换时间预算需按最慢波特率核算。
  • 切换后首帧 CRC 错误:常见于 B 链路收发器使能时序与总线空闲间隔不足,需在切换逻辑中加入总线静默延时。
绝缘测试必须在 SCM 断电、所有通信接口拔除的条件下进行,500 VDC 直接施加在通信收发器上可能造成永久损伤。测试顺序建议:绝缘 → 供电 → 通信 → 冗余切换,前一项不合格不进入后一项。