测试激励:让报文与信号按需变化
总线已经接通,下一步往往是让输入“动起来”:扫过一段报文 ID,检查过滤规则;让数据逐步变化,观察解析是否正确;让车速反复越过报警阈值,看看仪表的触发与恢复是否符合预期。本篇介绍如何借助 AI 和 BMCLI,把这些要求整理成可执行的测试激励。
与节点仿真相比,这里先聚焦一个更具体的问题:给被测设备什么输入,以及怎样确认这个输入符合设计。 报文级测试关注 ID 和原始字节,信号级测试关注车速、温度等工程值。选对层次,很多实验只需要几条命令或一份配置。
图 7-1 两条路径构造不同层次的输入,再通过独立采集与 DUT 响应检查效果。示意图,非实测结果。
先把激励规格说清楚
Section titled “先把激励规格说清楚”假设正在联调一款带 CAN 接口的显示控制器:底层只接收指定范围的 ID,上层根据车速显示数值并触发超速提示。可以先用原始报文检查接收通路,再用符合 DBC 定义的信号检查业务行为。
下表中的参数就是交给 AI 的任务规格。ID、范围和时长可按项目调整,波特率、接线及 DUT 反馈方式则应来自实际台架资料。
| 规格层次 | 需要说明的内容 | 本篇示例 |
|---|---|---|
| 台架 | 发送与采集通道、总线参数、允许的操作范围 | 已配置的隔离 CAN 台架;逻辑通道 stimulus-can 与 observe-can |
| 报文格式 | 标准/扩展帧、Classic CAN/CAN FD、长度 | 标准 ID、Classic CAN、8 字节 |
| 报文变化 | 变化对象、范围、步长,其他字段如何处理 | ID 为 0x600~0x60F;或负载前 4 字节为 0~255 |
| 时间安排 | 发送间隔、轮数、轮间切换和结束条件 | 硬件任务每 100 ms 一帧,每轮 32 帧,逐轮执行 |
| 信号定义 | DBC、报文名、信号名、单位、有效范围 | VehicleStatus.Speed,单位 km/h |
| 波形规格 | 类型、中心与幅度/阶跃点、周期、初始值 | 正弦 60±20 km/h,周期 2 秒,报文周期 50 ms |
| 结果判定 | 输入符合什么规律,DUT 应如何响应 | ID 不越界;信号接近目标曲线;报警阈值与恢复时间按项目要求判断 |
本篇接口按本机 BMCLI 1.6.5 帮助核对,随文波形配置经过离线校验。下面的效果表描述设计预期,实际发送时序与 DUT 结果请由台架采集确认。
案例一:检查 ID 过滤与原始数据接收
Section titled “案例一:检查 ID 过滤与原始数据接收”给 AI 的输入
Section titled “给 AI 的输入”请用 BMCLI 为我的显示控制器建立一组报文级测试。请先读取本项目 Bench,确认 stimulus-can 和 observe-can 的绑定、接线与 CAN 参数;本轮仅在已授权的隔离台架执行。使用标准 CAN 数据帧、8 字节负载,每轮分别测试:固定 ID/固定负载;ID 在 0x600~0x60F 递增;固定 ID 0x600,负载前 32 位按大端整数从 0 递增到 255;固定 ID 的前 32 位随机;随机 ID 加固定负载。硬件任务每 100 ms 一帧,每轮 32 帧,逐轮执行,采集先于发送启动。再用外层脚本增加一轮随机 ID 加完整 8 字节随机负载,保存生成的帧序列。请交付测试规格、执行脚本和输入检查报告,分别记录命令是否接受、观察端是否收到、DUT 是否按项目过滤规则处理。结束后仅删除本轮创建的任务;项目资料缺少 DUT 反馈定义时,请列出待补充项。
成品与效果:每种变化都能对应一个检查点
Section titled “成品与效果:每种变化都能对应一个检查点”| 激励 | BMCLI 实现方式 | 保持不变的部分 | 适合观察什么 |
|---|---|---|---|
| 固定报文 | txtask --type=fixed |
ID、负载 | 建立基线,检查周期接收 |
| ID 递增 | --type=incid |
负载 | 接收过滤范围、ID 分发逻辑 |
| 负载字段递增 | --type=incdata |
ID、字段外字节 | 字节序、数值解析、接收连续性 |
| 负载字段随机 | --type=random,亦可写 randomdata |
ID、字段外字节 | 数据组合变化下的健壮性 |
| ID 随机 | --type=randomid |
负载 | ID 分布变化下的处理行为 |
| ID 与完整负载同时随机 | 外层脚本生成每帧 ID 和字节,再调用 message send |
按需求固定长度和帧类型 | 混合输入下的解析与过滤;保存帧序列后可再次执行 |
这里的 random 指数据字段随机,randomdata 是它的别名。一个硬件任务选择一种模式;分别创建“ID 随机”和“数据随机”两个任务,得到的是两路报文,不能据此认为每一帧都同时随机了 ID 和负载。
对于负载递增与随机模式,当前接口要求 32 位、字节对齐、Motorola 大端字节序,并且这 4 字节必须完整落在负载内。比如 --inc-startbit=0 修改字节 0~3,后四字节保持模板值。DBC 中的 4 位 Counter、12 位温度等字段,适合使用后文的信号级方式。
下面是一份报告应表达的内容示意:
| 实验 | 预期输入特征 | 报告应展示的内容 |
|---|---|---|
| ID 扫描 | 0x600、0x601……0x60F | 实际 ID 集合、每个 ID 的帧数、范围外帧数 |
| 32 位递增 | 00 00 00 00 → 00 00 00 01 → 00 00 00 02 | 字段解码值、步长、其他字节是否改变 |
| 随机负载字段 | 取值位于设定范围,允许重复 | 最小/最大值、不同值数量、字段外字节一致性 |
| 双随机 | 每帧 ID 与 8 字节数据来自保存的序列 | 序列序号与采集结果对应、未观察到的帧 |
| DUT 过滤 | 接受哪些 ID、拒绝哪些 ID 由产品规则决定 | DUT 反馈与输入的对应关系 |
随机测试用于扩大组合覆盖,不保证有限次数内遍历所有值。要确认每个 ID 都被测试过,先做确定性的 ID 扫描更直接。
实现解析:硬件任务负责规律发送
Section titled “实现解析:硬件任务负责规律发送”以下为 AI 生成执行器时可采用的关键调用,并非需要一次性全部执行的脚本。请先按入门教程准备 daemon 和通道,将两个逻辑名称绑定到实际台架。每轮保存 add 返回的 handle,等采集结束后删除该任务,再进入下一轮。
# 固定 ID 和数据建立基线,共发送 32 帧。bmcli txtask add --channel=stimulus-can --message=0x600 --cycle=100 --rounds=32 --type=fixed --data="00 00 00 00 AA BB CC DD" --format=json
# 扫描 0x600~0x60F,负载保持不变。bmcli txtask add --channel=stimulus-can --message=0x600 --cycle=100 --rounds=32 --type=incid --inc-min=0x600 --inc-max=0x60F --inc-step=1 --data="00 00 00 00 AA BB CC DD" --format=json
# 前 4 字节按大端 32 位整数递增,后 4 字节保持 AA BB CC DD。bmcli txtask add --channel=stimulus-can --message=0x600 --cycle=100 --rounds=32 --type=incdata --inc-startbit=0 --inc-nbits=32 --inc-min=0 --inc-max=255 --inc-step=1 --data="00 00 00 00 AA BB CC DD" --format=json
# 只随机前 4 字节对应的整数,数值范围为 0~65535。bmcli txtask add --channel=stimulus-can --message=0x600 --cycle=100 --rounds=32 --type=random --inc-startbit=0 --inc-nbits=32 --inc-min=0 --inc-max=65535 --data="00 00 00 00 AA BB CC DD" --format=json
# 只随机 CAN ID,8 字节负载保持模板内容。bmcli txtask add --channel=stimulus-can --message=0x600 --cycle=100 --rounds=32 --type=randomid --inc-min=0x600 --inc-max=0x60F --data="00 00 00 00 AA BB CC DD" --format=json安装版 Reference 对已测试的三代固件说明:递增从最小值开始,到达最大值后停留在最大值,并非自动回卷。因此上面的 ID 扫描到 0x60F 后,余下轮次保持该值。若需要每轮重新扫一遍,可由执行器重新创建任务;协议要求 Counter 循环计数时,则使用相应的仿真与 E2E 配置。
采集与清理也是执行器的一部分:
# 在独立终端先启动采集,再由发送终端添加本轮任务;此命令运行 6 秒。bmcli message recv --channel=observe-can --duration=6 --format=jsonl
# 查询任务,核对本次 add 返回的 handle;有限轮次结束后仍应清理任务槽位。bmcli txtask list --channel=stimulus-can --format=json
# 将占位文本换成本轮 add 返回的完整 handle,只删除本轮任务。bmcli txtask remove --handle="<本轮返回的 handle>" --format=json“命令接受”“总线上观察到”“DUT 按预期处理”是三个不同的检查结果。接收分析仪可以确认激励是否到达总线;产品是否正确处理,还需要读取 DUT 的响应或观察其显示。
ID 与完整负载同时随机
Section titled “ID 与完整负载同时随机”这一轮由外层程序安排帧序列。随文提供双随机示例,默认只打印 JSONL,不发送;明确指定 --send 和通道后,才通过 BMCLI 逐帧发送。脚本使用固定种子生成 32 帧,同时保存序列供复查。
# 离线查看种子 2026 对应的 32 帧;输出包含每帧 ID 和完整负载。python random-frames.py --seed=2026
# 在已打开的隔离通道上发送;序列文件必须是一个尚不存在的新文件。python random-frames.py --seed=2026 --send --channel=stimulus-can --sequence=run-01.jsonl脚本内部,每帧对应的调用形式如下:
# ID 和 8 字节负载均来自外层生成的某一帧,此处仅展示调用形式。bmcli message send --channel=stimulus-can --message=0x607 --data="12 83 A4 00 FF 21 68 09" --count=1 --format=json这里的发送间隔由主机进程控制,还包含命令调用开销,适合低速功能测试。需要严格的周期与高负载时,请优先选硬件支持的模式;需要逐帧复现随机输入时,应保留原始帧序列和实际采集时间戳,再组织回放。
案例二:让车速走出不同的波形
Section titled “案例二:让车速走出不同的波形”通过接收通路检查之后,接下来可以让仪表看到有物理含义的输入。假设要观察车速显示是否平滑,以及跨过阈值后提示何时出现、何时恢复,就可以让同一条 Speed 信号分别走过阶跃、正弦和锯齿曲线。
给 AI 的输入
Section titled “给 AI 的输入”请用 BMCLI 和随文 vehicle-demo.dbc,为仪表台架生成车速激励。VehicleStatus 每 50 ms 发送一次,Gear 为 D,Counter 与 Checksum 使用随文演示 counter-sum 规则。请依次准备四种车速工况,每轮采集 10 秒:恒定 60 km/h;0、2、4 秒分别设为 40、80、40 km/h 并保持末值;中心 60、幅度 20、周期 2 秒的正弦波;同样范围与周期的锯齿波。另准备一个 40 与 80 km/h 每秒切换的方波变体。请生成可离线校验的配置,采集后绘制目标与实收车速曲线,按 DBC 分辨率比较数值,并记录周期偏差。报警阈值和允许响应时间请从我的产品规范读取,缺少时先只验证输入波形。请使用已确认的隔离台架,逐轮停止并卸载本轮资源后再切换,保留其他任务。
成品与效果:波形规格比“让数值变化”更明确
Section titled “成品与效果:波形规格比“让数值变化”更明确”| 信号激励 | 类型与主要参数 | 本例预期 | 工程用途 |
|---|---|---|---|
| 常量 | constant,value |
始终 60 km/h | 稳态显示、基准点 |
| 阶跃/分段保持 | step,时间—数值点 |
40 → 80 → 40,最后保持 40 | 阈值触发、跳变与恢复 |
| 正弦波 | sine,中心、幅度、周期、相位 |
60±20 km/h,周期 2 秒 | 平滑跟随、显示刷新 |
| 锯齿波 | sawtooth,中心、幅度、周期 |
从 40 上升,接近 80 后回到 40 | 范围扫描、回落响应 |
| 方波 | 重复的 step,两点加重复周期 |
40/80 各保持 1 秒 | 反复跨阈值、周期切换 |
| 自定义/随机信号序列 | 外层生成合法工程值,再组织 step 点或信号赋值 |
保存每个时间点与数值 | 指定工况组合;不是内置 random 波形 |
报文周期和波形周期各司其职:50 ms 是发一帧的间隔,2 秒是波形完成一轮的时间,名义上每周期有 40 个采样点。曲线应由实际接收数据绘制;视觉插值不能当作新增的总线采样。
随文的五份波形配置复用第二篇的教学 DBC。它们是可供 AI 继续扩展的输入,未包含产品的报警判定程序。
实现解析:按工程值描述,由 BMCLI 编码
Section titled “实现解析:按工程值描述,由 BMCLI 编码”例如正弦源的配置片段:
"Speed": { "type": "sine", "offset": 60, "amplitude": 20, "period_ms": 2000}这里的 60 和 20 使用 km/h,与 DBC 的物理单位一致。AI 无需把每个车速值手工换算成报文字节,BMCLI 负责按数据库编码,并更新配置的保护字段。
在随文示例目录中,可以先离线检查,再由 AI 按已确认的台架执行:
# 离线检查完整配置及其引用的 DBC,不连接硬件。bmcli simulation validate --file=speed-sine.json --format=json
# 加载本轮配置,但此时尚未发送。bmcli simulation load --file=speed-sine.json --name=tutorial-stimulus-wave --format=json
# 在另一终端先采集;启动命令应在采集就绪后执行。bmcli message recv --channel=observe-can --duration=10 --decode --dbc=../02-from-bus-to-signals/network/vehicle-demo.dbc --format=jsonl
# 在已打开的隔离 CAN 通道上启动本轮波形。bmcli simulation start tutorial-stimulus-wave --channel=stimulus-can
# 采集结束后停止本轮波形,再卸载资源。bmcli simulation stop tutorial-stimulus-wavebmcli simulation unload tutorial-stimulus-wave还可以对已加载、尚未启动的资源替换 Speed 的波形源。下面每条是一个可选变体,每次选择一条:
# 常量:车速保持为 60 km/h。bmcli simulation source set Speed --simulation=tutorial-stimulus-wave --task=vehicle --type=constant --value=60
# 阶跃:第 2 秒升至 80,第 4 秒降至 40,此后保持。bmcli simulation source set Speed --simulation=tutorial-stimulus-wave --task=vehicle --type=step --point=0:40 --point=2000:80 --point=4000:40
# 正弦:中心 60、幅度 20、周期 2000 ms,初始相位为零。bmcli simulation source set Speed --simulation=tutorial-stimulus-wave --task=vehicle --type=sine --offset=60 --amplitude=20 --period=2000 --phase=0
# 锯齿:同一范围内上升,每 2000 ms 回到起点。bmcli simulation source set Speed --simulation=tutorial-stimulus-wave --task=vehicle --type=sawtooth --offset=60 --amplitude=20 --period=2000
# 方波:用重复阶跃表达,前一秒为 40,后一秒为 80。bmcli simulation source set Speed --simulation=tutorial-stimulus-wave --task=vehicle --type=step --point=0:40 --point=1000:80 --repeat=true --period=2000阶跃到达时间点时取新值;重复周期应大于最后一个时间点。数值默认按有效范围检查,显式选择 --range=clip 才会截断越界值。测试中通常保留默认检查,更容易发现规格与 DBC 的矛盾。
信号仿真由主机调度,波形按计划时间计算。采集报告还应检查实际帧间隔与调度遗漏,避免只看到漂亮曲线,却忽略发送是否连续。演示用的 counter-sum 也应在真实项目中替换为产品规定的保护方案。
进一步探索:让激励服务于产品验证
Section titled “进一步探索:让激励服务于产品验证”把波形与阈值响应放在同一张图里
Section titled “把波形与阈值响应放在同一张图里”如果仪表规定了超速提示的触发阈值和回差,可以请 AI 在阈值附近构造阶跃点,安排足够的保持时间,并同步采集 DUT 的状态反馈。报告把输入车速与提示状态对齐,就能看清触发是否过早、恢复是否延迟。对于没有状态报文的设备,可另行提供显示识别或人工标记结果,而不把“输入已发送”直接当作测试通过。
保留随机输入,建立回归用例
Section titled “保留随机输入,建立回归用例”某次随机组合让产品出现异常时,最有价值的是保存当时的输入顺序、实际时间戳和设备响应。可以请 AI 将异常附近的帧段提取为独立用例,并逐步缩短序列,找出触发条件。下一版固件发布后,用同一段输入复测,比重新运行一轮随机数据更有针对性。
具体波形参数可通过 bmcli help simulation source set --format=json 查询。请在项目中指定激励范围和结束条件,并在隔离台架验证;这些输入可能触发 DUT 的实际控制行为。