标签: CAN总线

  • Kia Soul OSCC 档案:归一化命令与 200 ms 保活接口

    结论:这份档案的对象是一套面向 2014 年及以后 Kia Soul(汽油与纯电)的开源车辆控制项目(OSCC),它把「读取车辆状态」和「下发控制命令」拆成 API 与固件两层:固件侧用专门的模块通过转向力矩/油门位置/制动位置传感器与 OBD-II CAN 交互,API 侧用归一化数值下发命令、并通过回调接收回报。它的数据特征是命令归一化 + 200 ms 保活:制动与油门为 [0.0, 1.0]、转向为 [-1.0, 1.0],且每个发布函数必须至少每 200 ms 调用一次,否则模块判为通信丢失并自行禁用。源文档未给出比特率、寻址方式与逐字节定义,其结论仅限 2014 年起的 Kia Soul 平台。

    车辆与适用范围

    源文档是一个软硬件项目仓库的说明:它描述 API、固件与硬件三部分,以及可扩展的车型头文件机制。数据来自项目文档,不是某台实车的采集记录。

    项 内容
    车型 Kia Soul(2014 年及以后,汽油与纯电);构建目标另含 Kia Niro
    年款 / 市场版本 源文档以「Kia Soul PS(2014–2018)」指代已整理信息的平台;其他年款与市场版本未确认
    ECU / 改装状态 加装 OSCC 模块:传感器接口板(转向/油门)、整车控制模块(纯电制动)或执行器控制板(汽油制动),外加 CAN 网关
    采集跨度 源文档未提供(无日志数或事务数)
    适用范围 源文档明确「目前仅支持 2014 年起的 Kia Soul」,API 与固件按易扩展设计,但其他车型属未来扩展

    总线与寻址

    源文档把总线分成「车辆 OBD-II CAN」与「OSCC 控制 CAN」两条,固件用 CAN 网关模块在两段之间转发;但未描述物理层与标识符细节。

    项 内容
    物理层 / 比特率 源文档未给出
    总线划分 车辆 OBD-II CAN 网络(读状态、发命令、接收回报);OSCC 控制 CAN(API 与固件模块之间)
    寻址方式 源文档未给出;API 以「CAN 通道 + 标准化信号名」抽象,不暴露标识符
    CAN FD 源文档未提供
    接口形态 固件以 Arduino + 专用扩展板实现,经 USB 串口烧写与监控

    已解码信号

    下表登记源文档明确给出的接口面(命令、回报与关键参数)。位置列写接口名而非字节偏移,因为源文档只以标准化信号与回调形式暴露它们;「证据」一列注明其出处为 API 说明、固件说明或构建选项。

    信号 / 接口 位置(API / 模块) 取值与含义 证据
    制动位置命令 publish_brake_position() 归一化 [0.0, 1.0],转发到制动固件模块 API 说明
    转向力矩命令 publish_steering_torque() [-1.0, 1.0],-1 为逆时针、+1 为顺时针 API 说明
    油门位置命令 publish_throttle_position() 归一化 [0.0, 1.0] API 说明
    制动回报 oscc_brake_report_s 通过 subscribe_to_brake_reports() 回调 API 说明
    转向回报 oscc_steering_report_s 含转向角;通过 subscribe_to_steering_reports() 回调 API 说明
    油门回报 oscc_throttle_report_s 通过 subscribe_to_throttle_reports() 回调 API 说明
    故障回报 oscc_fault_report_s 通过 subscribe_to_fault_reports() 回调 API 说明
    OBD 原始帧 subscribe_to_obd_messages() 转发车辆 OBD-II CAN 上的非 OSCC 帧,按帧 ID 自行解析 API 说明
    轮速 车辆回报(当前控制状态) 源文档以「转向角与轮速」为例说明可回报的车辆控制状态 项目说明
    使能 / 禁用 oscc_enable() / oscc_disable() 只影响是否可发送命令;回报随时可收 API 说明
    通道开关 oscc_open(channel) / oscc_close() 打开/关闭与 OSCC 控制 CAN 的套接字连接 API 说明
    保活超时 三个发布函数 每个须至少每 200 ms 调用一次,否则模块判失联并自禁用 API 说明
    转向过载阈值 TORQUE_DIFFERENCE_OVERRIDE_THRESHOLD 调整转向人工接管灵敏度;过低会误判、过高难接管 构建/配置说明
    电压范围检查 API 内部安全校验 拒绝发送超出车辆预期范围的电压 API 说明

    读取方法与注意事项

    生命周期由三组调用界定:oscc_open(channel) 打开控制 CAN 的套接字,oscc_enable() / oscc_disable() 决定是否允许发送命令,oscc_close() 结束。源文档提示 API 会捕获 CAN 帧到达时的 SIGIO 信号并注册处理器转发有效帧,因此在容易被中断冲突的代码段应临时屏蔽该信号、之后再解除。

    最关键的运行约束是节拍:三个发布函数每个都必须至少每 200 ms 调用一次,否则固件模块会判定与上位机失去通信并自行禁用。也就是说,「不发命令」本身是一种保护动作;程序崩溃或卡顿时会自动退出控制,这是设计意图而非缺陷。

    人工接管方面,源文档默认对所有模块启用接管检测,但明确提示:系统激活时试图抓方向盘可能造成严重伤害,推荐用制动踏板或急停按钮作为转向接管手段;如需关闭转向接管检测,可在构建时传 -DSTEERING_OVERRIDE=OFF。构建还需按车型选择标志(-DVEHICLE=kia_soul、kia_soul_ev 或 kia_niro);对早于 1.2.0 的执行器控制板,需加 -DBRAKE_STARTUP_TEST=OFF 以跳过与该板不兼容的启动测试。

    证据等级与边界

    本文的证据等级是「项目文档级」:命令取值区间、回调接口、200 ms 保活与构建标志都可在源文档逐条核对,属于直接证据;但源文档没有逐信号解码表,也没有实车日志,因此本文不提供标识符、字节偏移或缩放系数。要落到具体字节,需回到固件与车型头文件(本快照未包含逐字节定义)。

    两点不能外推。第一,源文档明确「目前仅支持 2014 年及以后的 Kia Soul」(汽油与纯电),Kia Niro 为构建目标;把接口面外推到其他起亚车型或其他品牌属于超范围。第二,各模块的板卡版本与固件版本需按源文档的对应表配套使用,混用可能触发已知安全问题的旧版本;源文档特别强调应及时更新。关于安全访问,源文档未提供任何绕过方法,且不建议尝试;项目自述其设计不改变厂方安全用例、不伪造 CAN 消息、不入侵 ADAS 功能,本档案仅描述这一接口面。

    常见问题

    为什么命令必须每 200 ms 发一次?

    因为固件模块以 200 ms 作为与上位机的通信存活判据:任一发布函数连续超过该时间未被调用,模块就判为失联并自行禁用。这是有意的失效保护——程序卡死时会自动退出控制,而不是保持最后一个命令。

    转向接管该怎么做?

    源文档建议用制动踏板或急停按钮,而不是直接抓方向盘——后者在系统激活时可能造成严重伤害。若确实要关闭转向接管检测,可用 -DSTEERING_OVERRIDE=OFF 构建;保留检测时,灵敏度由 TORQUE_DIFFERENCE_OVERRIDE_THRESHOLD 调整,过低会在大扭矩区误判、过高则难以手动接管。

    能从这套系统直接读到车辆的所有信号吗?

    不能仅凭本文判断。API 提供的是结构化回报(制动/转向/油门/故障)与一个 subscribe_to_obd_messages() 回调,后者转发车辆 OBD-II CAN 上的非 OSCC 帧,需要按帧 ID 自行解析。源文档未给出这些帧的逐字节定义。

    这套接口能套用到别的起亚车型吗?

    源文档明确目前仅支持 2014 年起的 Kia Soul(汽油与纯电),Kia Niro 为构建目标;API 与固件按易扩展设计,但新增车型需按车型头文件格式补齐信息。直接外推到其他车型超出源文档证据范围。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/polysync-oscc/README.md(本项目车型档案主来源:API 与固件接口、命令归一化范围、200 ms 保活、构建标志与支持车型)。
    • 项目 01 —— public-can-dbc-datasets/additional/polysync-oscc/LICENSE.md(硬件为 CC BY-SA 4.0、固件与软件为 MIT 的许可划分)。

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • WebRTC 数据桥:bridge_services_in 是请求不是授权

    结论:WebRTC cereal 数据桥的核心边界是——bridge_services_in 只能是「请求」,不是授权结果;/schema 只是结构提示,不是权限清单。出站代理按请求里的主题列表订阅 SubMaster,仅对 updated 的主题发送 {type, logMonoTime, valid, data} JSON;入站代理只取 JSON 的 type/data,用本地 monotonic() 生成新时间、valid 默认 False。因此 sendcan、carControl 与固件配置主题都不应作为通用桥写入目标。

    一、出站:消息内容、时间与编码

    入口 源码行为 边界
    CerealOutgoingMessageProxy.__init__()、update() 按请求主题列表建立 SubMaster;每轮 sm.update(0),仅对 updated 的主题发送 JSON 到所有开放通道。 sm.update(0) 在 asyncio 任务中同步执行;多个服务同轮发布时逐一编码/发送,没有本地有界队列或每主题独立带宽限额。
    to_json()、run() struct 用 to_dict(),list 元素递归处理,顶层 bytes 用默认 UTF-8 decode();异常在任务外层记录后下一轮继续。 任意二进制 Data 不保证是 UTF-8;解码异常会使当前轮 update() 中断。

    出站 logMonoTime 与 valid 来自本地 SubMaster,属于原 cereal 事件的元信息;这两个字段会作为 JSON 呈现给对端,但它们不是入站代理会原样恢复的字段。仅用 updated 判断发送,也不代表服务消息通过了有效性或新鲜度门。

    二、入站:允许列表与重新发布

    入口 源码行为 边界
    StreamSession.message_handler()、run() 内建控制命令单独处理;普通 type 仅在会话的 bridge_services_in 列表里才转给入站代理,并在共享 DynamicPubMaster 创建发布 socket。 允许列表来自本地 /stream 请求体;本机服务没有按主题风险等级的固定全局许可表。
    CerealIncomingMessageProxy.send()、messaging.new_message() JSON 的 type、data 决定新事件类型与负载;非 dict 的 data 用 len(data) 作为 list/Data 大小;新事件 logMonoTime 取本机 monotonic(),valid 默认 False。 入站 JSON 里的 logMonoTime、valid 不被复制;调用点无消息体字节上限、数值范围白名单或单主题频率限制。
    DynamicPubMaster.add_services_if_needed() asyncio.Lock 保护动态加 socket,同一进程的 shared_pub_master 跨会话复用已注册主题。 锁保护的是同进程 socket 注册,不是来源认证或 msgq 主题授权;旧会话注册的 socket 仍可能留在共享实例。

    一个反直觉但重要的边界:valid=False 不等于所有消费端都会丢弃消息。源文档举例 joystickd_thread() 对 testJoystick 只检查接收帧年龄是否超过 0.2 秒,然后取 axes 形成 carControl,该路径没有检查 sm.valid['testJoystick']。这不是「普通远端请求能控制实车」的证明——还受进程模式、selfdriveState、车型参数、card 与 panda 安全门约束——但足以说明 valid 不能替代主题权限判定。

    入站侧还有两处与「成功」语义有关的边界。其一,动态发布器探针确认:同一次和跨次重复主题只建一个 socket,注册序列中后项失败时前项仍留在 socket 里、没有回滚,未知名称会直接下传给 messaging.pub_sock(),实际服务名能否注册由底层决定。其二,handle_post_notify() 向当前会话逐个发送原 JSON,某通道异常被跳过;没有会话或部分发送失败时仍返回 HTTP 200 OK。二者都说明「HTTP 成功」不等于「通知已被远端接收」,也不证明任意名称能成为真实 msgq 主题。

    三、/schema 是结构提示,不是权限清单

    handle_get_schema() 按逗号解析请求服务名,只检查它们是 log.Event 字段且不以 DEPRECATED 结尾,再调用 generate_field()。其中 generate_type() 把 struct 展开为字段映射,list 表示为单元素模板,enum 只写 "text",基础类型写 Cap’n Proto 类型名;generate_struct() 过滤废弃字段。它不包含字段编号、单位、频率、枚举成员、最大长度、schema 版本或读写权限。非法服务触发 assert,由 HTTP handler 的通用异常路径返回 500,而不是专门的 4xx 校验错误。

    源文档的五项原 schema 函数/假类型树探针确认:基础类型保留类型名,枚举压成 text,列表压成单元素模板;struct 和 group 都跳过名为 deprecated 或以 DEPRECATED 结尾的字段。这些输入是合成 Cap’n Proto 类型树,不能证明所有真实 schema 分支都能导出,或其结果能作为授权清单。

    四、硬件与插件重构验收

    普通诊断插件只应授予明确的只读主题 + 字段;写主题必须由宿主按调用方身份、会话、车型状态和安全等级批准。桥接协议应保留原始事件的采样时戳与传输时戳之区别,显式定义 valid 的重建策略、二进制编码方式、schema 版本、最大消息长度、速率和背压;下游不能以 valid=False 自动假设无执行副作用。

    回归覆盖应包含非 UTF-8 Data、嵌套字节字段、未知字段/服务、错误 list 长度、极大负载、重复主题注册、桥接重连,以及 testJoystick 无效位但新鲜消息的隔离行为。现有 WebRTC 会话测试只用 ASCII Data、一组结构/list 输入和单次代理发送,没有 schema 版本、任意二进制、外层有效位/时间戳保留或风险主题授权回归;本篇未运行上游测试,所有写入仍须经过车端独立安全链。

    常见问题

    valid=false 是不是等于消息一定被丢弃?

    不等于。入站代理生成的新事件 valid 默认 False,但消费端未必检查它:joystickd_thread() 对 testJoystick 只检查接收帧年龄是否超过 0.2 秒,不检查有效位。所以不能用 valid 替代主题权限判定,也不应假定无执行副作用。

    bridge_services_in 是授权结果吗?

    不是。它来自本地 /stream 请求体,只是「请求」,本机服务没有按主题风险等级的固定全局许可表。写主题必须由宿主按调用方身份、会话、车型状态和安全等级批准,sendcan、carControl 和固件配置主题不作为通用桥写入目标。

    /schema 能当权限清单用吗?

    不能。它只检查服务名是 log.Event 字段且不以 DEPRECATED 结尾,输出 struct 字段映射、list 单元素模板和 enum 的 "text",不含字段编号、单位、频率、枚举成员、最大长度、schema 版本或读写权限;非法服务还会触发 assert 返回 500。

    桥接协议该保留哪些时间字段?

    应显式区分原始事件的采样时戳与传输时戳。出站的 logMonoTime 来自本地 SubMaster,入站却改用本机 monotonic() 且不复制传入值;若不加区分,下游无法判断数据新鲜度,也无法重建 valid 语义。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/WEBRTC_CEREAL_SCHEMA_BRIDGE_CONTRACT_DEEP_DIVE.md(取用了出站/入站桥接语义、/schema 表达能力边界与插件验收要求)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • cereal 消息契约:schema、服务表、valid 与落盘各管什么

    结论:cereal 的消息契约必须拆成四层看:schema 定义、services.py 服务表配置、运行消息有效性、loggerd 落盘结果。union 分支存在不表示进程正在发布,也不表示 loggerd 会记录;logMonoTime 是消息封装时间,valid 也只表示运行有效位,不承诺车辆总线帧通过车型解析或 panda 安全检查。把「字段存在」当作「数据已发布或已记录」是这份契约最常见的误读。

    四层契约各管一段

    schema 层,Event 有 logMonoTime、valid 与 union,carState、carControl、carParams 指向 opendbc 的 car.capnp,customReserved* 保留固定 field ID。服务表层,SERVICE_LIST 声明服务名、期望频率、should_log、qlog decimation 和队列容量,build_header() 生成对应的 C++ 表——频率是配置与健康检查依据,不等于真实发布速率。

    消息构建层,new_message() 默认 valid=False,把 logMonoTime 设为单调时钟纳秒并初始化主题,发布者通常再赋有效位。日志订阅层,loggerd_thread() 订阅 should_log 服务、非直播 EncodeData 和可选原始音频;普通消息按配置写 rlog,按计数抽样写 qlog。因此收到消息、valid=True、内容可信和时戳新鲜是四个不同判断。

    层 源码与含义 不能推出的结论
    schema Event 有 logMonoTime/valid/union;车型消息指向 car.capnp union 分支存在不表示进程正在发布或 loggerd 会记录
    服务表 SERVICE_LIST 声明频率、should_log、decimation、队列容量 频率是配置依据,不等于真实发布速率;should_log=False 也可能有专门编码路径
    消息构建 new_message() 默认 valid=False,设置单调时间 收到、有效、可信、时戳新鲜是不同判断
    日志订阅 loggerd_thread() 按 should_log 与计数抽样写盘 qlog 不是每个主题的完整回放数据

    关键主题与字段语义

    CAN 接入侧,Event 的 can 是从车接收帧,sendcan 是主机候选发送帧;CarState.canValid/canTimeout/canErrorCounter 表示车型解析健康,不能只取上次解码值。services.py 为 can 设大队列与 qlog 高抽样率,因此完整 CAN 分析应使用 rlog。执行决策侧,enabled、latActive、longActive 不等价,Actuators 的扭矩/转角/曲率属互斥横向命令语义,纵向 accel 为 m/s²。

    模型到规划侧,modelV2 的 qlog 抽样未配置,不应拿 qlog 复原所有推理帧;LateralManeuverPlan 是调试覆盖曲率,不是一般模型输出。使能与监督侧,enabled 与 active 分开,警报文本/声音、人机监督策略与注意力状态在独立消息中。摄像头与编码侧,帧标识、曝光时间戳、编码索引/时间戳和视频字节是不同层,图像主数据经 VisionIPC,EncodeData 由 loggerd 分离写媒体文件。

    链路 载荷定义 核心字段与边界
    CAN 接入 Event.can/sendcan、CarState canValid/canTimeout/canErrorCounter 表示解析健康
    执行决策 CarControl、CarParams enabled/latActive/longActive 不等价;safetyConfigs/dashcamOnly/passive 决定执行边界
    模型到规划 ModelDataV2、LongitudinalPlan、LateralManeuverPlan 模型含帧 ID、EOF 时间、耗时、轨迹;modelV2 qlog 抽样未配置
    使能与监督 SelfdriveState、DriverMonitoringState enabled 与 active 分开;监督策略独立消息
    panda 安全状态 PandaState controlsAllowed、模式/参数、RX 无效、TX 阻断、心跳丢失分列
    摄像头与编码 FrameData、EncodeIndex、EncodeData 帧标识、时间戳与视频字节分层;EncodeData 分离写媒体文件

    需要单独记住:Event 的 logMonoTime 是消息封装时间;相机 timestampEof、模型 timestampEof、GNSS Unix 时间和 IMU 自有时间字段并不自动相等。传感器/定位插件必须显式声明时钟域、单位、采样时点和迟到处理。

    Route 与 Segment 文件如何落盘

    元数据由 logger_build_init_data() 记录版本、设备、内核、Git 信息、参数和部分硬件日志,参数值只有不带 DONT_LOG 标志才写入。命名/开段阶段,路由名由递增计数与随机后缀组成,段目录为 <route>--<part>;开段创建 rlog.lock、rlog.zst、qlog.zst,写 initData 与 START sentinel,结束段/路由写 END sentinel 并移除锁。

    压缩阶段,rlog.zst、qlog.zst 是 zstd 压缩的连续 Cap’n Proto Event 字节流,qlog 只在抽样命中时附写。切段时,rotate_if_needed() 与 handle_encoder_msg() 等已出现的编码器进入新段后切段,相机/编码器异常时按时间回退切段;新段编码数据须等关键帧,先于关键帧的帧被丢弃。媒体文件按相机表写 fcamera.hevc、ecamera.hevc、可选 dcamera.hevc 与 qcamera.ts;RecordAudio 打开时 rawAudioData 还会写入 rlog(decimation=None,不进 qlog),这涉及额外的数据保留与隐私审查。

    抽样率是理解落盘差异的关键:can 的 qlog 抽样率为 2053、sendcan 为 139、carState 为 10、modelV2 为 None。编码索引虽通常 should_log=False,但在 write_encode_data() 中专门转写且始终进 qlog。不要用 qlog 作为控制/安全故障分析的唯一依据。

    对插件化与硬件的最低要求

    1. 插件 schema 需要版本、字段号与兼容策略;Cap’n Proto union 的固定编号不能任意复用,customReserved* 约束也不能未经全链路兼容评估就改控制主契约。
    2. 发布权限应按主题分级:观测只读、规划候选、carControl 和 sendcan 分开授权;valid、新鲜度、总线校验与硬件许可各自独立。
    3. 存储插件需保留元数据、段边界、单调时钟、媒体索引、丢帧及部分文件状态;为取证保留 rlog,不可用 qlog 抽样代替。

    常见问题

    消息字段存在,是否说明该数据一定被记录?

    不代表。四层契约是分开的:schema 里 union 分支存在,不表示受管进程正在发布,也不表示 loggerd 会记录;服务表里的频率是配置与健康检查依据,不等于真实发布速率;只有 loggerd_thread() 按 should_log 与抽样配置实际写盘的内容才在日志里。

    为什么不能用 qlog 复原所有推理帧?

    因为 modelV2 的 qlog 抽样配置为 None,carState 抽样率为 10,can 为 2053,各主题抽样并不一致,qlog 只在抽样命中时附写。源文档明确 qlog 不是每个主题的完整回放数据,控制/安全故障分析不要以它作为唯一依据。

    Event 的 logMonoTime 就是传感器采样时间吗?

    不是。logMonoTime 是消息封装时间;相机 timestampEof、模型 timestampEof、GNSS Unix 时间和 IMU 自有时间字段并不自动相等。传感器/定位插件必须显式声明时钟域、单位、采样时点和迟到处理。

    valid=True 是否表示这一帧数据可信?

    不等于。valid 只是运行有效位,源文档明确它「不承诺车辆总线帧通过车型解析或 panda 安全检查」。车端数据是否可信还要看 CarState 的解析健康字段、时间戳新鲜度以及 PandaState 中的许可与故障分列。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/MESSAGE_LOG_CONTRACTS_DEEP_DIVE.md(取用了四层契约、关键主题字段语义、Route/Segment 落盘流程与 qlog 抽样率)。
    • 项目 02 —— openpilot-research/LOGGERD_SERVICE_SAMPLING_POLL_CONTRACT_DEEP_DIVE.md(仅用于确认 loggerd 逐服务订阅与计数抽样相位的边界)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • Ioniq 5 电池预热的 CAN 报文:两段最小可复用样本

    结论:这份档案记录的是现代 Ioniq 5 / 6 / EV6(E-GMP 第一代)电池预热(preconditioning)手动开关背后的最小可用 CAN 报文集合(MWE)。源文档把 2021–2024 年 E-GMP 车上的「触发预热」与「取消预热」压缩成两份可回放的报文集,其中主触发报文 ID 为 0x4ED,取消报文涉及 0x0C7。要点在于:预热可以只用少数几条报文、靠被动旁听加回放实现,不需要车机越狱。需要注意,随本快照归档的是作者过滤后的回放样例,不是原始全总线抓包,也没有配套 DBC。

    车辆与适用范围

    源文档是一个硬件改装的公开文档仓库,围绕「给 Ioniq 5/6/EV6 增加一个手动预热按钮」展开,CAN 报文逆向是其中一环。

    项 内容
    车型 Hyundai Ioniq 5 / Ioniq 6 / Kia EV6(E-GMP 第一代,带电池 PTC 加热器)
    年款 / 市场版本 源文档讨论 2021–2024 年 E-GMP 车;这两份 CSV 的采集车年款/配置/市场/固件未指定
    ECU / 改装状态 加装微控制器注入 CAN 报文(WiCAN 系硬件)+ 线束;也用 WiCAN 网页远程开关
    采集跨度 两份最小可用样本:MWE_preconditioning.csv(230 行)与 MWE_cancel_preconditioning.csv(5 行)
    适用范围 仅限带 PTC 加热器且已启用预热模式的 E-GMP 车;源文档称必要报文于 2026 年 3 月分离出来

    总线与寻址

    源文档的样本以 SavvyCAN 兼容文本保存(时间戳单位为微秒),列含 ID、扩展帧标志、方向、长度与数据字节。抓取工具为 WiCAN Pro(另一份清单说明还用了 SavvyCAN)。下表按这两份 CSV 可确认的内容填写,未给出的一律标注「源文档未给出」。

    项 内容
    物理层 源文档未给出(经 OBD 形态的 WiCAN 接入)
    链路层 / 比特率 源文档未给出
    寻址方式 样本中报文均为 11 位标准帧(Extended=false)
    CAN FD 样本未包含 CAN FD 帧;文档另提及第二代原型机才有一个 CAN FD 接口
    时间戳单位 微秒(SOURCE 说明)

    已解码信号

    下表登记的是这两份 CSV 里可核对到的报文与字段模式,逐条纹目均给出证据(文件名与行数)。源文档把整份材料定位为「MWE 回放样例」,因此没有更细的位域命名与缩放系数;相关的 DBC 由另一项目维护,不在本快照内。

    条目 位置(ID / 字节) 观测载荷(十六进制) 证据
    触发预热帧 0x4ED(8 字节) 00 00 00 00 00 FF FF 1F MWE_preconditioning.csv(230 行)
    触发帧的充电态变体 0x4ED D6–D8 00 00 00 00 00 09 90 00 同上
    取消预热帧 0x0C7(8 字节) 00 00 00 E0 07 00 00 00 MWE_cancel_preconditioning.csv(5 行)
    取消帧的状态字段 0x0C7 D4–D5 E0 07 同上
    触发日志中的另一变体 0x0C7 D4–D5 40 03 MWE_preconditioning.csv
    空闲/复位帧 0x0C7(全零) 00 00 00 00 00 00 00 00 两份 CSV 首帧
    采样工具 — SavvyCAN + WiCAN Pro README「Contents」
    样本规模 — 触发 230 行 / 取消 5 行 SOURCE 说明表

    读取方法与注意事项

    源文档给出一条很实用的方法论主张:一两份好日志比十份可疑日志更有价值。作者建议把日志采集当成一次科学实验——设计「测试条件」与「对照条件」,例如把导航设到附近的充电桩 vs. 设到附近的学校。若都没把握,就对大范围报文画时间曲线找线索。

    数据清理同样关键:作者提到清洗日志(例如剔除带缓冲数据造成的超范围时间戳)后才取得更好效果。文档还列出成套公开工具(含 SavvyCAN 社区分支、DBC 结构入门、基于 DBC 的绘图库等)。

    工程实现上,这套方案由五部分构成:CAN 报文、注入报文的微控制器、该微控制器的固件、把微控制器接到车的线束、以及触发预热的用户界面。触发方式从「用笔记本」到「用 panda 上的星形按钮」都有演示,当前用户界面支持映射到车上既有按钮,物理按钮仍在开发。作者也提醒:另一条「车机越狱」路线更偏技术、没有恢复出厂设置的兜底,且可能被后续 OTA 封堵。

    证据等级与边界

    本档案的证据层级需要分清。可核对的是文件与行数(230 行、5 行)、报文 ID 与字节(0x4ED、0x0C7 的观测载荷),以及工具链(SavvyCAN、WiCAN Pro)。而「这些报文在另一台车上就能触发预热」属于作者自述、未被本归档独立验证——来源说明明确写道:上游称这些报文能在带 PTC 的 Ioniq 5 上启动/取消预热,但本归档未独立复核解码、回放行为或兼容性。

    三处不能外推。第一,这是作者过滤后的回放样例,不是原始全总线抓包,也不是 DBC,因此不能据此推出整车信号全集。第二,采集车的具体年款/配置/市场/固件未指定,不能默认对所有 E-GMP 车成立。第三,文档提到后续 E-GMP 平台与软件版本可能变化,且越狱路线曾多次被封堵,说明结论有时效性。

    关于「安全访问」类问题:本文只整理公开文档登记的回放样例,未涉及安全访问的绕过;源文档未提供绕过方法,且不建议尝试。

    常见问题

    预热功能是主动问出来的还是被动听到的?

    这份材料记录的是可回放的最小报文集合:两段日志里反复出现的少数几条报文,被整理成可发送的样例。它不涉及对某个 ECU 的主动诊断轮询。

    0x4ED 和 0x0C7 分别是什么?

    按样本,0x4ED 出现在触发预热日志里(230 行,载荷在 FF FF 1F 与 09 90 00 之间切换),0x0C7 出现在取消日志里(5 行,含 E0 07)。本档案只登记观测到的载荷,不代填位域语义。

    能不能套用到其他 E-GMP 车?

    不能默认成立。来源说明指出,这两份 CSV 的采集车年款、配置、市场与固件均未指定,且本归档未独立复核解码与回放行为;要用于其他车辆须自行在实车上验证。

    这套方案需要车机越狱吗?

    不需要。源文档给出的主线是「微控制器 + 线束 + 用户界面」注入报文;文档另提到一条车机越狱路线,但指出它更偏技术、缺少恢复兜底,且可能被后续 OTA 封堵。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/tylerharvey-ioniq5-preconditioning/README.md(本项目车型档案主来源:项目背景、MWE 报文、方法论与工具清单)。
    • 项目 01 —— public-can-dbc-datasets/additional/tylerharvey-ioniq5-preconditioning/SOURCE.md(两份 CSV 的行数、校验值,以及「未独立验证」的边界声明)。
    • 项目 01 —— public-can-dbc-datasets/additional/tylerharvey-ioniq5-preconditioning/preconditioning_messages/MWE_preconditioning.csv(触发预热的最小可用样本)。

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • Ram ProMaster 2022:三总线与 19 个 UDS 模块

    结论:Ram ProMaster(2022 款,3.6 L Pentastar 配 ZF 948TE 变速箱)是典型的「三总线 + 安全网关」结构:C-CAN / HS-CAN(500 kbit/s,引脚 6/14)、B-CAN / CAN IHS(125 kbit/s,引脚 3/11)、CAN CH(500 kbit/s,引脚 12/13)三条总线速率与用途各不相同,OBD 口后面还有 SGW 安全网关。车速与整车里程在两条不同总线上各有来源,且源文档记录了两者不一致的验证结果。以下所有结论仅限源文档记录的这一台车。

    车辆与适用范围

    本文数据来自第三方开源项目对一台 2022 款 Ram ProMaster 的总线映射与信号分析。项目先用双通道适配器分别接入不同总线,再通过 UDS 读取模块内的数据块,并对同一物理量在不同总线上的表现做交叉验证。

    项 内容
    车型 Ram ProMaster,2022 款
    动力总成 3.6 L Pentastar 发动机(PCM);ZF 948TE 变速箱(TCM)
    采集硬件 双通道 USBCANFD 适配器,两路分别映射到不同总线(源文档记录了通道与总线的对应关系)
    采集跨度 多次行车与静态采集,涵盖车速、里程、挡位与机油寿命等验证
    适用范围 仅限源文档记录的这一台车;不同年款或不同配置的总线拓扑与 UDS 地址都可能不同

    总线与寻址

    这辆车的接入难点在于「多条总线、多个速率,且后面有网关」。只有先确定每个物理接口对应哪条总线,后续的波形才有意义。

    项 内容
    C-CAN / HS-CAN 500 kbit/s,OBD-II 引脚 6 / 14;OBD 口后面存在 SGW(安全网关)
    B-CAN / CAN IHS 125 kbit/s,OBD-II 引脚 3 / 11
    CAN CH 500 kbit/s,OBD-II 引脚 12 / 13
    诊断寻址 29 位 ISO-TP 物理寻址,形如 18DAxxF1;源文档记录了 19 个模块的地址
    网关 SGW 位于 OBD 口之后;源文档中部分内部总线需要物理接入方式才能观察到,本文不复述具体做法,也不建议尝试

    已解码信号

    下表从源文档的行车分析与离线验证记录中抽取。项目对每一条都注明了验证方式(载体验证、相关系数或读取值),本文原样保留;被否决的条目也一并列出,以说明边界。

    信号 位置(ID / DID / 字节) 解码 证据
    车速 C-CAN 0x101 B0:B2 speed_raw = ((B0 & 0x01) << 11) | (B1 << 3) | (B2 >> 5) 已确认(轮速载体验证)
    车速(第二来源) C-CAN 0x0EE 约等于 8 × speed_raw 已确认(相关 r=0.9999919)
    输出轴转速 0x1F7 rpm 标定记录
    涡轮转速 0x1F7 rpm 标定记录
    整车里程 0x760(从位 8 起的 17 位大端) km 标定记录
    整车里程(ICS) B-CAN,UDS 服务 22 / DID 0x2001 u24 大端 × 0.1 km 已确认(与 0x760 交叉对照)
    机油寿命 PCM,UDS 服务 22 / DID 0x2185 百分比读数 已确认(读取值显示 82%)
    帧校验 0x101 B7 CRC-8 / SAE-J1850 标定记录
    变速箱挡位(候选) 0x1F4 内的 nibble 枚举 被否决(源文档否定该位置)

    读取方法与注意事项

    第一条是「先认总线,再看信号」。三条总线的速率分别是 500、125、500 kbit/s,若适配器接错引脚或用错速率,会直接抓不到帧。源文档为此专门记录了双通道适配器的角色映射,把每一路固定到指定总线。

    第二条是同一物理量的多来源问题。车速在 C-CAN 的 0x101 与 0x0EE 上都有表现(后者约为前者的 8 倍,相关系数 0.9999919),整车里程同时在 0x760 与 B-CAN 的 ICS 数据块里出现(后者由 UDS 服务 22 读 DID 0x2001 得到,u24 大端 × 0.1 km)。使用前应确定以哪一路为准,并核对两路是否一致。

    第三条是负向结果同样重要。源文档明确指出,CAN CH 上的七个高速 ID 都没有通过轮速载体验证——也就是说它们看起来像车速信号,但不能被证实。类似地,0x1F4 里被怀疑是挡位的那个 nibble 已被否决。这些「证伪」结论能避免后续误用。

    证据等级与边界

    源文档的验证手段主要有两类:一类用「轮速载体」做参照,把候选信号与已知的轮速做一致性比对;另一类用 UDS 读取模块自身的数据块(如机油寿命、ICS 里程)作为可信基准。通过比对的标为已确认,未通过的明确记为被否决,处于中间状态的则作为候选保留。

    关于网关,需要格外谨慎:OBD 口后的 SGW 会限制可观察范围,源文档记录的部分内部总线访问方式涉及对车辆网络的物理改动,本文不复述具体做法,也不建议尝试——这类改动有损坏车辆网络的风险,且可能不符合当地法规。

    边界上必须强调:以上总线拓扑、UDS 地址与信号刻度都限定在这一台 2022 款 ProMaster 上。不同年款、不同市场版本的模块地址、总线划分与信号位置都可能变化,跨车使用前必须重新验证。

    常见问题

    为什么这辆车要在三条总线上分别接线?

    因为三条总线的速率与用途不同:C-CAN / HS-CAN 是 500 kbit/s(引脚 6/14),B-CAN / CAN IHS 是 125 kbit/s(引脚 3/11),CAN CH 是 500 kbit/s(引脚 12/13)。用单一速率接单一引脚只能看到其中一部分数据,必须按总线分别接入并设置正确速率。

    车速信号有两个来源,该信哪个?

    0x101 与 0x0EE 上的车速高度相关(r=0.9999919,后者约为前者的 8 倍)。理论上两者一致即可互换使用,但源文档并未就此给出统一建议,使用前应自行在本车上核对两路是否始终一致,并确定以哪一路为准。

    被否决的信号还有参考价值吗?

    有。被否决说明「某位置不是挡位」这类边界已被排除,能避免后来者重复踩坑。源文档同时记录了「CAN CH 上七个高速 ID 均未通过轮速载体验证」这样的负向结论,同样缩小了搜索空间。

    这些 UDS 地址能直接用于别的 ProMaster 吗?

    不能。源文档记录的 19 个模块地址限定在这一台车上,不同年款或市场版本的模块地址可能不同。换车使用前必须重新枚举并复核。

    延伸阅读

    参考资料

    • 项目 05 —— public-can-dbc-datasets/additional/jakeiwen-promaster-2022/docs/bus-map.md(本项目车型档案主来源:三总线映射与 UDS 模块地址表)
    • 项目 05 —— public-can-dbc-datasets/additional/jakeiwen-promaster-2022/findings/2026-07-19_ccan_drive_signal_analysis.md(C-CAN 车速信号与 CRC 分析)
    • 项目 05 —— public-can-dbc-datasets/additional/jakeiwen-promaster-2022/findings/2026-09-22_gear_and_oil_life_offline.md(挡位否决与机油寿命读取)

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • ECU 探测与 ISO-TP:在场、固件候选与可执行是三件事

    结论:诊断链上的三个结论必须严格分开——「探测到响应」「解析到固件」「车型可执行」是三件不同的事。tester present 收到单帧响应只说明该地址在场,返回固件候选只说明查询有结果,二者都不构成车型可执行的许可。此外 get_ecu_addrs() 的 timeout 是循环条件而非硬墙钟上界,0x78 的 pending 判断只看第三个字节、是宽松的超时延长条件而非已认证的 UDS pending 状态。本文为固定源码快照 c8fb906 的静态阅读,未连接 CAN 设备、未发送任何诊断请求。

    发现链路:从在场探测到品牌排序

    make_tester_present_msg() 生成 0x3e 0x00 服务请求,诊断 RX 地址由 get_rx_addr_for_tx_addr() 按 11-bit 偏移或 29-bit 地址字节交换计算。get_ecu_addrs() 先排空接收,再批量发送 tester present,在时间窗口内收集允许的响应地址与总线。

    函数/组件 输入与实际行为 输出边界
    get_present_ecus() 从各品牌 FwQueryConfig 取 ECU 地址,按 OBD 复用模式分组;无子地址并行、有子地址逐个查询 返回已响应的 (rx_addr, subaddr, bus) 集合;未响应不等于 ECU 不存在
    get_ecu_addrs() 排空接收、批量发 tester present,在时间窗口内收集允许的响应地址/总线 异常被记录后返回已收集的局部集合,不是全有或全无事务
    _is_tester_present_response() 验证短单帧格式;接受 SID 0x7e 正响应或 0x7f 0x3e 负响应 「ECU 在场」不表示该 ECU 接受诊断会话或会返回固件
    get_brand_ecu_matches() 将探测地址与各品牌预期 RX 地址比较 只作查询顺序启发;实现明确未比较 bus
    get_fw_versions_ordered() 按已命中 ECU 数与比例排序,仅查询有命中的品牌,单一固件候选即停止 不是全品牌全 ECU 的完整清单;早停可由 fuzzy 单一候选触发

    这里有两个容易被忽略的边界。其一,get_ecu_addrs() 的 timeout 是循环条件,而 can_recv(wait_for_one=True) 可阻塞,因此该值不是整个扫描过程的硬墙钟上界;经 card 的回调使用时订阅端设置了 timeout=20。其二,OBD 复用切换由参数写入及 pandad 确认构成,回调内没有独立握手超时。

    独立开发工具 get_all_ecu_addrs() 枚举 11-bit 与 29-bit 发送地址,但直接把 queries 复用为 responses:11-bit 枚举覆盖整个 0x700..0x7ff 范围,29-bit 通常需要交换后的 RX 地址。因此按代码推导,该工具的 29-bit 响应多数不会通过白名单,并非可靠的完整 ECU 清单;生产用的 get_present_ecus() 是单独计算预期 RX 地址的另一条路径。

    ISO-TP 查询状态机

    IsoTpParallelQuery 把 TX 地址映射成预期 RX 地址,按总线与地址过滤,子地址再逐条筛选;get_data() 用每地址计数器校验多阶段请求的响应前缀,最终只返回成功完成的 (tx_addr, subaddr) -> payload。VIN 的功能寻址先发广播请求,随后由物理寻址的 ISO-TP 对象接收/发流控;固件查询通常用物理地址。

    层 职责 边界
    CanClient 按 bus/RX 地址过滤,处理子地址和发送节拍 只对匹配地址的帧做后续处理
    IsoTpMessage 单帧、多帧、连续帧序号及流控;固件查询设为非阻塞接收、10 ms separation time 发送与接收错误可被上层记录并使对应地址结束
    get_data() 每地址计数器校验多阶段响应前缀 只返回成功完成的结果,部分成功不返回
    pending 分支 响应第三字节为 0x78 时延长该地址等待 只看第三字节,不先要求完整负响应前缀,属宽松条件

    正常多帧进展会刷新单地址截止时间;响应的第三字节为 0x78 时走 pending 分支并延长等待。关键在于 pending 判断仅按第三字节,不先要求完整负响应前缀 0x7f ... 0x78,所以它是宽松的超时延长条件,而非已认证的 UDS pending 状态。另外 total_timeout=60 也在循环尾检查,不能约束本次阻塞式 can_recv() 的耗时。

    固件数据契约

    get_fw_versions() 为每个成功响应创建 CarFw,记录 ECU 类型、固件字节、TX/RX 地址、请求、品牌、bus、OBD 复用模式及 logging。请求配置允许白名单、特殊 RX offset、子地址,以及需记录但不参与指纹匹配的 ECU。个别查询异常被捕获并继续,因此返回值可以是部分固件清单。build_fw_dict() 丢弃 logging 响应;匹配函数用地址/子地址与固件版本来判定,而不是把 CarFw 中的 bus 和响应地址都作为唯一身份校验条件。

    自制硬件与插件边界

    以下是改造建议,不是现有运行时的保证。应将 ECU 探测器、VIN 解码器、固件查询器拆成可替换的证据提供者,但对外只暴露受限的诊断代理;插件不得直接持有原始 sendcan 发布权限。诊断代理应对 bus、地址、服务 ID、速率、总时长、同时请求数和点火/行车状态实施硬限制,物理网关/MCU 独立保留 CAN 输出安全门。状态建模上,应把正/负响应、部分超时、未查询、OBD 模式切换失败分成不同状态,不以空集合或空固件列表直接推断「该车型不受支持」;每条证据应附采集时间、硬件拓扑和本次启动标识,缓存或早停结果不得自动获得执行许可。

    常见问题

    收到 tester present 响应就说明 ECU 支持诊断吗?

    不说明。_is_tester_present_response() 只验证短单帧格式并接受 0x7e 正响应或 0x7f 0x3e 负响应。「ECU 在场」不表示它接受诊断会话或会返回固件。

    0x78 的 pending 判断是标准 UDS pending 吗?

    不是。pending 分支仅按第三个字节是否为 0x78 判断,不先要求完整的负响应前缀,因此它是宽松的超时延长条件,而非已认证的 UDS pending 状态。

    get_fw_versions_ordered() 会返回全部 ECU 固件吗?

    不会。它按已命中 ECU 数与比例排序,只查询有命中的品牌,并在拿到单一固件候选时即停止,因此返回的是候选子集而非全品牌全 ECU 的完整清单。

    为什么 get_all_ecu_addrs() 的 29-bit 结果不可靠?

    因为它把 queries 直接复用为 responses,而 29-bit 通常需要交换后的 RX 地址,多数响应不会通过白名单。可靠路径是单独计算预期 RX 地址的 get_present_ecus()。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/ECU_DIAGNOSTIC_TRANSPORT_DEEP_DIVE.md(取用了 ECU 发现链、ISO-TP 查询状态机、固件数据契约、插件边界与离线探针结论)。
    • 项目 02 —— openpilot-research/CAR_MESSAGES_FIELD_CONTRACT_DEEP_DIVE.md(仅用于确认诊断结果进入车型识别与安全配置的衔接位置)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • Honda 控制输出:Bosch/Nidec 构帧与 50/10 Hz 节拍

    结论:Honda 控制输出分 Bosch 与 Nidec 两条构帧路径,并叠加三层节拍:转向每轮一条候选、纵向 50 Hz、仪表 10 Hz。Nidec 的正加速并不在 50 Hz 制动帧里,而由 10 Hz ACC_HUD 携带 PCM_SPEED/PCM_GAS,所以仪表链本身就是纵向执行链的一部分。Python 侧的限幅不等于 MCU 的安全保证:CarController 的 STEER_MAX 与变化率处理、panda honda_tx_hook() 的独立检查、继电器故障阻断是不同层次。下述 100/50/10 Hz 均以目标 100 Hz、每轮调用控制器一次且无丢周期为前提,只表示软件名义节拍;未做 DBC 回放、台架或实车验证。

    关键函数与组件

    入口 源码 作用
    CarController.update() carcontroller.py 读取控制目标与车况缓存,限幅、调度并返回候选 CAN 帧和软件回报值。
    compute_gas_brake() carcontroller.py Nidec 把加速度转换成 gas/brake;Bosch 分支当前返回两个零,实际纵向另由 ACC 帧表示。
    actuator_hysteresis() / brake_pump_hysteresis() carcontroller.py Nidec 制动去抖与泵请求;泵计时基于 frame * DT_CTRL。
    CarControllerParams / CanBus values.py、hondacan.py 车型扭矩上限、变化率及 PT/radar/camera/LKAS 路由。
    create_steering_control() / create_acc_commands() hondacan.py 转向和 Bosch 纵向字段编码。
    create_brake_command() / create_acc_hud() hondacan.py Nidec 制动、PCM 加速及仪表字段编码。
    honda_tx_hook() / honda_nidec_fwd_hook() honda.h MCU 独立检查候选帧并决定相机制动帧转发。

    公共转向与回报语义

    每轮先对归一化 actuators.torque 以 STEER_DELTA_UP/DOWN * DT_CTRL 限变化率,再取负号、夹到 [-1, 1] 并乘车型 STEER_MAX 构造 CAN 扭矩。create_steering_control() 始终生成一条 STEERING_CONTROL 候选;CC.latActive 为假时其扭矩和请求位都为零,BOSCH_TJA_CONTROL 还设置 STEER_DOWN_TO_ZERO。这段 Python 限制不替代 MCU 的未使能零转向规则,也不能从 latActive 为真推定车辆接受转向。

    new_actuators 中的 torque 是软件限速后的归一化值,torqueOutputCan 是编码前的整数;accel/gas/brake/speed 有部分字段只在对应分支更新,可能保持上轮值。它们是软件目标回报,不是 panda 发送回执或车辆执行测量。控制器仅在车控存活检查通过时才被调用并发布 sendcan;消息的 valid 使用 CS.canValid,具体总线发送仍需再经过 pandad/panda。

    纵向与按钮分支

    分支 触发条件 生成的候选帧
    原车纵向 未启用自控纵向 偶数轮 BOSCH_SUPPLEMENTAL_1;取消或恢复请求时 SCM_BUTTONS(radarless 发相机总线,其余用 PT 总线)
    自控纵向 Bosch 启用自控纵向 偶数轮 ACC_CONTROL;有雷达版再加 ACC_CONTROL_ON
    自控纵向 Nidec 启用自控纵向 50 Hz BRAKE_COMMAND + 10 Hz ACC_HUD 携带 PCM_SPEED/PCM_GAS

    若未启用自控纵向,偶数轮对非 radarless/CAN FD 平台尝试生成 BOSCH_SUPPLEMENTAL_1,取消或恢复请求则生成 SCM_BUTTONS;radarless 把按钮发到相机总线,其他平台用 PT 总线。源码的 supplemental 条件没有显式限定 Bosch,不能据此推定所有进入该分支的车型都获安全白名单许可。spam_buttons_command() 只生成一条候选,调用处没有独立按钮节流,实际发送还受当前模式的 TX 白名单和按钮安全门制约。

    启用自控纵向时偶数轮生成纵向候选。Bosch 把加速度夹在 BOSCH_ACCEL_MIN/MAX,用独立查表得到 gas;有雷达版同时生成 ACC_CONTROL_ON 与 ACC_CONTROL,无雷达版只生成 ACC_CONTROL。gas_command 在不活动或低于阈值时为 -30000,ACCEL_COMMAND 在不活动时为零;STANDSTILL 由 LongControlState.stopping 连续计数而来,无雷达版 IDLESTOP_ALLOW 要计数超过 200 个 50 Hz 周期。enabled、longActive、stopping 是不同条件,不能合并成单一「已启用」位。

    Nidec 的 compute_gb_honda_nidec() 在低于 2.3 m/s 时引入蠕行制动,再经刹车迟滞、每轮变化率限制、风阻扣减和 NIDEC_BRAKE_MAX - 1 上界量化为 BRAKE_COMMAND。泵请求在制动增大或超过 20 秒后重置计时,正制动下保持至少 0.2 秒。编码器把 AEB 执行相关字段显式置零,FCW 只映射警告和原车 chime。Nidec 正加速不是每个 50 Hz 制动周期的独立油门帧,而是在 10 Hz ACC_HUD 中携带 PCM_SPEED/PCM_GAS,因此 HUD 链也是其纵向执行链的一部分,应分别回放替代与普通分支。

    HUD、总线与 MCU 边界

    每 10 轮:自控纵向才生成 ACC_HUD,所有模式生成一个或两个 LKAS_HUD 候选;有雷达 Bosch 自控纵向还生成 RADAR_HUD,特定 Civic Bosch 补 LEGACY_BRAKE_COMMAND。原车纵向且 BOSCH_EXT_HUD 时 LKAS_HUD_A/B 分开发送。hud_v_cruise 在不可见时取 255,可见时除以 CS.v_cruise_factor,此值依赖 CarState 所选单位。create_acc_hud() 对 Bosch/Nidec 使用不同字段,Nidec 还复制原车 acc_hud 的若干 FCM/图标位;无新鲜度检查时不应将复制成功当作原车功能健康。

    CanBus 不能假定 PT 永远是 bus 0:有雷达 Bosch 的 PT 为 offset+1、radar 为 offset,LKAS 依据自控纵向决定去 PT 还是 radar;radarless/CAN FD 与 Nidec 的 PT 为 offset。panda honda_nidec_init() / honda_bosch_init() 选择地址、总线、长度白名单及 RX 检查;Bosch 自控纵向的 safetyParam 分支仍受 ALLOW_DEBUG 编译门约束,不能因 Python 能构帧就推定量产固件可发。

    honda_tx_hook() 对 Nidec BRAKE_COMMAND 的制动幅度、AEB 位和 ACC_HUD 的速度/gas 作检查;对 Bosch ACC_CONTROL 的加速度、gas 和 AEB 位作检查;未允许控制时转向输出必须为零。诊断地址只允许固定 tester-present 载荷,Bosch 原车纵向的按钮在控制不允许时只能取消。Nidec honda_nidec_fwd_hook() 还按相机原车 AEB 制动力与自控制动请求比较动态转发 0x1FA,不是简单的「总是屏蔽原车制动」。

    插件与硬件验收

    车型输出插件应分别声明转向、纵向、按钮、HUD、诊断保活和原车 ADAS 影响权限;每项绑定 DBC、车型指纹、物理总线、消息周期、数据年龄和 panda safety 模式。只允许插件产生候选控制帧,最终 TX 白名单、力矩/加速度/AEB 约束与超时失效仍在独立 MCU。对 Nidec 要单测 10 Hz ACC_HUD 与 50 Hz 制动的耦合、泵保持和原车 AEB 转发;对 Bosch 要单测雷达/无雷达、原车/自控纵向、ALLOW_DEBUG 配置和 ECU 静默失败。当前没有可用实板、目标车型回放或车辆执行证据,本文不能作为上车许可。

    常见问题

    Nidec 的加速信号在哪条帧里?

    不在 50 Hz 制动帧里。Nidec 正加速是在 10 Hz ACC_HUD 中携带 PCM_SPEED/PCM_GAS,因此 HUD 链也是其纵向执行链的一部分,不能只看 BRAKE_COMMAND。

    Bosch 的 gas 是怎么算出来的?

    自控纵向时 Bosch 把加速度夹在 BOSCH_ACCEL_MIN/MAX,再用独立查表得到 gas;gas_command 在不活动或低于阈值时为 -30000。compute_gas_brake() 的 Bosch 分支当前返回两个零,实际纵向另由 ACC 帧表示。

    PT 总线一定是 bus 0 吗?

    不是。有雷达 Bosch 的 PT 为 offset+1、radar 为 offset,LKAS 依据自控纵向决定去 PT 还是 radar;radarless/CAN FD 与 Nidec 的 PT 为 offset,因此不能假定固定编号。

    Python 的转向限幅算安全保证吗?

    不算。CarController 的 STEER_MAX 与变化率处理只是软件层;MCU 的 honda_tx_hook() 独立检查候选帧,未允许控制时转向输出必须为零,最终还受继电器故障阻断。

    延伸阅读

    参考资料

    • 项目 02 —— openpilot-research/HONDA_CONTROLLER_CAN_OUTPUT_DEEP_DIVE.md(Bosch/Nidec 构帧、50/10 Hz 节拍、HUD 与 MCU 边界)。
    • 项目 02 —— openpilot-research/ 同目录 Honda CarState 与接口专题(输入侧与雷达通信控制作为相邻边界参考)。

    说明:本文为对固定源码快照的静态结构分析,未运行完整测试套件、未连接硬件、未验证目标车型的真实参数组合。文中所有阈值、行号索引与配置均出自源文档,标注为未验证的结论保留其原有边界。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • Tesla iBooster Gen1 CAN 档案:两总线与只读踏板信号

    结论:这份档案的对象不是整车,而是一台 Bosch iBooster Gen1 制动助力器的 CAN 输出(Tesla 件号 1037123-00-B,清单标注适配 2016–2020 Model S),被装在 1987 年款的一台改装车上只读采集。它的数据特征是两条 500 kbps 总线、全部只读、状态藏在位置报文里:25/16 引脚的「Vehicle CAN」承载 16 位踏板行程 0x39D,18/10 引脚的「YAW CAN」承载 12 位位置 0x38E 与状态字节 0x38F;助力器只要接通 12V、地、点火即自行助力,不需要任何 CAN 输入。所有数值均为该实物单元的台架实测,不外推到其他 iBooster 变体、其他件号或其他车辆。

    车辆与适用范围

    源文档明确:这里的每一项都在本台实物上测得,不是从社区资料继承的;未验证的内容另列在待验证清单里。以下范围仅对应这一台助力器。

    项 内容
    车型 Bosch iBooster Gen1,Tesla 件号 1037123-00-B(清单标注适配 2016–2020 Model S);采集对象是助力器本身,非整车
    年款 / 市场版本 件号适配范围由源文档以清单形式标注;具体车辆年款未确认
    ECU / 改装状态 改装车(1987 年款)上的助力器,只读旁听,永不向助力器发送
    采集跨度 多份台架日志:0x38E 46,960 帧 + 0x38F 23,478 帧(合计 70,438 帧,跨四次上电);0x39D 校验在 2,250 帧上 100% 通过
    适用范围 仅本台实物;触点、装配与固件版本变化都可能改变结论

    总线与寻址

    两条独立总线均为 500 kbps、经典 CAN、11 位标识符,助力器对两条总线都不做内部终端。源文档特别强调:总线要靠内容识别,不能靠适配器索引或 USB 顺序。

    项 内容
    物理层 / 比特率 两条总线均 500 kbps;无内部终端
    「Vehicle CAN」 引脚 25 = CAN-H,16 = CAN-L,静止 36 fps,静止 4 个 ID、踏板活动时 11 个
    「YAW CAN」 引脚 18 = CAN-H,10 = CAN-L,静止约 149.5 fps,2 个 ID
    寻址 / 帧格式 经典 CAN,11 位标识符;0x39D 为 DLC 4,其余多见 DLC 8
    CAN FD 源文档未使用
    供电引脚 引脚 1 = 12V,引脚 9 = GND,引脚 20 = 点火

    已解码信号

    下表抽取源文档中最有代表性的条目,位置与解码保留原文写法(含位运算)。证据一列保留源文档的实测口径:有精确帧数、运行次数与相关系数,也有明确标注为「未解析」「受污染不可引用」的项。

    信号 位置(ID / 字节) 解码 证据
    踏板行程 0x39D b2:b3,DLC 4,25.0 Hz uint16 小端;静止约 262,最大观测 14070;端位 13606 = 43.4 mm 双点标定;mm=(counts-3.3)/320.68(合并拟合)
    行程校验 0x39D b0 (b1+b2+b3+0xA0) & 0xFF 2,250 帧 100% 通过
    存活计数 0x39D b1 每帧 +1 取模 16,高半字节恒 0 实测
    位置(12 位) 0x38E b3 与 b4 低半字节 position = b3 | ((b4 & 0x0F) << 8);静止 320,满行程约 3052 与 0x39D 两次运行 r=0.999627 / 0.999853
    位置换算 mm 0x38E mm = 0.015207 * position - 4.072(静止 320 → 0.79;满 3052 → 42.34) 偏置为负,为已验证的两种形式之一
    状态枚举 0x38E b4 高半字节 0=初始化、1=正常、2=故障闭锁 断开行程传感器诱导故障确认
    制动标志 0x38E b6 1 位制动应用标志;上沿 2.18–2.42 mm,下沿 1.72–1.75 mm 约 0.55 mm 回差;四次上电下沿复现到 2 counts
    状态字节 0x38F b2 bit 0 = 第二个制动标志(1.45–1.66 mm);bits 5:3 = 行程/健康状态 四种状态值实测;释放沿受速率限制、不可引用数值
    消息校验 0x38E/0x38F b0 CRC-8/SAE-J1850,poly 0x1D、init 0x00、xorout 0x0A,覆盖 b1..b7 70,438 帧 100% 通过,两个 ID 参数相同
    峰值行程(事件) 0x38D b5:b6 uint16 小端,129.3 counts/mm r=0.99975;与标定行程在 34 mm 内吻合 0.66 mm(n=10)
    制动持续时长 0x37D b0:b1 uint16 小端,27.50 ticks/s r=0.99877;tick 非整数倍,未定(n=10)
    运行时长 0x31D/0x3AD b0:b1 uint16 小端计数,9.99 ticks/s(100 ms) 四次运行确认;分析中作对照列,防伪相关
    静态身份 0x32D(b0 多路复用,0.5 Hz) 五帧按 b0 轮转,四次上电逐字节相同 件号/标定 ID 类数据,与踏板无关
    踩下后事件 0x33D 9.5 Hz,99.8% 时间为全 FF;触发为松开制动后 0.64–2.20 s 与 0x31D 等构成「踩后突发」组,n=10
    故障哨兵值 0x39D 行程 故障时钉在 16354(0x3FE2),校验仍有效 物理不可达,可按范围直接拒绝

    读取方法与注意事项

    三条工程纪律都来自实测教训。第一,必须在 ACK 模式采集:这是一个两节点总线,若用只听(listen-only)模式,没有人应答会导致错误计数每次尝试 +8、约 32 ms 进入 bus-off 后自动恢复并循环,同一 12 秒窗口下表现为 1006 fps 的单 ID 重传风暴,并且会掩盖四个 ID 中的三个;改用 ACK 模式则为 37 fps、四个 ID。ACK 是链路层比特、不是命令,只读采集仍会应答。

    第二,先确认连接可靠。源文档记录:六轮排查(比特率扫描、极性互换、主机供电、ACK 模式)最终发现是助力器端接触不良。要用万用表从适配器接线端子一直通断到助力器引脚,而不是只看夹子「搭在上面」。

    第三,别把总线识别挂在索引上。USB 索引会随重新插拔重排,适配器名称跟随适配器而非线束;识别哪块适配器在哪条总线要按内容——看到 0x39D 的就是 25/16。另一条独立现象是:已供电的收发器在 ECU 未运行时也会停在 2.5V,这只能证明收发器有电,不能证明 ECU 在跑。传感器上电后约 1.47 s 才初始化完成,此前的读数应视为无效。台架接线时,助力器两侧都不做终端,适配器一侧 R120 置 ON。

    证据等级与边界

    本档案是本台实物的台架观测,不是文档推测,也不是外部旁证。最硬的证据是校验与拟合:0x39D 的加和校验在 2,250 帧上 100% 通过;0x38E/0x38F 的 CRC-8 在 70,438 帧上零失败;位置与行程两条独立总线的拟合两次运行在斜率上仅差 0.13%、截距差 0.12%,远紧于它们与标尺的一致度,反过来证明「运行间标定冲突」是测量误差而非传感器问题。

    三处必须原样保留的边界。其一,行程标定精度约 ±2 mm,瓶颈在标尺不在数据:单次保持内信号重复到约 ±20 counts = 0.062 mm,而两次运行之间最多相差 4.4 mm;死区(约 3.5 mm 自由行程)既未被确认也未被否证,因为差额被运行间误差淹没。其二,「踩后突发」组的每个结论都建立在 n=10 的事件上,候选字节远多于事件数;两个 0.999 拟合通过了 20,000 次置换检验,但低于 |r|≈0.9 的一律只作线索,且峰值与时长在本次采集里部分混淆(深踩往往也踩得久)。0x37D b5 与 0x34D b5 因与运行时长混淆,源文档明确不得引用。其三,status == 2 表示「助力不可用」,不是「位置无效」:传感器重连后位置恢复更新而状态仍为 2、助力仍关闭;0x38E 这时是唯一的活动位置来源,0x39D 仍钉在哨兵值。故障会闭锁,只有循环点火才能恢复。

    不能外推的部分:以上数值只对应本台件号的这台实物;源文档列出的踏板传感器引脚(2、8、22、23)等条目来自其他 iBooster 变体的社区资料,属未验证假设,不能写进固件、DBC 或线束。另一个平台(GM Volt)的制动力命令/状态 ID 也被源文档明确标注「不可用于本机」。关于安全访问,源文档未提供任何绕过方法,且不建议尝试;本文只描述只读采集。最后须重申:这是制动执行器,本档案的一切都是读取,没有任何一项是向它下命令。

    常见问题

    为什么不能用只听(listen-only)模式采集?

    因为这是两节点总线:没有 ACK 就没有人应答,助力器的错误计数每次尝试上升 8、约 32 ms 进入 bus-off 后自动恢复并循环。同一 12 秒窗口下,只听模式表现为 1006 fps 的单 ID 重传风暴,并掩盖四个 ID 中的三个;ACK 模式则为 37 fps、四个 ID。ACK 是链路层比特而非命令,只读采集仍会应答。

    故障状态 2 是不是「位置数据无效」?

    不是。它表示「助力不可用」。源文档通过重连实验证明二者不同:传感器重连后位置恢复更新,但状态仍为 2、助力仍关闭,只有循环点火才恢复。因此位置的有效性要按范围单独判断——例如直接拒绝 0x39D 行程大于 13700 的读数。

    踩下踏板的峰值行程与持续时长可信吗?

    在 n=10 事件下,两者拟合分别为 r=0.99975(129.3 counts/mm)与 r=0.99877,且通过了 20,000 次置换检验,可作结论使用;但峰值与时长在本次采集中部分混淆(深踩往往也久),0x37D b5、0x34D b5 与运行时长混淆、源文档明确不得引用。低于 |r|≈0.9 的只算线索。

    12 位位置 0x38E 与 16 位行程 0x39D 该用哪个?

    0x39D 分辨率更高(约 0.003 mm/count 对约 0.016 mm/count),但只有 25.0 Hz;0x38E 为 99.7 Hz、快约 4 倍。对速率敏感的场景,频率比分辨率更重要。另须注意 0x38E 的换算偏置是负的:mm = 0.015207 * position - 4.072。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/pelosim-tesla-ibooster/docs/DECODE.md(本项目车型档案主来源:已确认信号定义、标定与故障信号)。
    • 项目 01 —— public-can-dbc-datasets/additional/pelosim-tesla-ibooster/README.md(只读设计、两条总线的引脚与帧率、采集模式与接线要点)。
    • 项目 01 —— public-can-dbc-datasets/additional/pelosim-tesla-ibooster/docs/PINOUT.md 与 VERIFY_FIRST.md(引脚实测与未验证条目清单、置信度边界)。

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • Waterloo 2024CAR DBC 档案:115 个报文与 890 条信号

    结论:这份档案记录的是滑铁卢大学电动方程式的整车固件仓库,以及其中归档的一份 2024CAR.dbc:115 条报文、890 条信号,另含一份 Vector 独立信号伪报文与逆变器、绝缘监测(IMD)等第三方部件的报文。它不是某一辆车的逐条解码结果,而是「一支学生车队把整车 CAN 定义放进一个固件 monorepo」的处置样本。需要明确两点边界:本快照只包含 README 与来源说明,DBC 本体未包含在内;且来源方声明车辆赛季、硬件装配、物理标度与原始数据权利均未独立核实。

    车辆与适用范围

    源文档来自一支 Formula Student 电动赛车队(UW Formula Electric)的固件主仓库。这里没有「某台实车采集了多少时长」的信息,只有一份被归档的整车 DBC 与它的来源记录。

    项 内容
    车型 车队 2024 赛季电动方程式赛车(由 2024CAR.dbc 文件名标识)
    年款 / 市场版本 源文档未确认具体赛季;命名为 2024,但「车辆赛季未被独立核实」
    ECU / 改装状态 车队自研整车固件,含车辆/HIL 板固件、电池单体测试固件与固件验证台架
    采集跨度 源文档未给出日志数或帧数;仅给出 DBC 的规模数字
    适用范围 仅限该队列的这份 DBC 快照;源文档明确「硬件装配与物理标度未独立验证」,不得当作通用定义

    总线与寻址

    源文档不描述物理层与寻址方式的细节,只在来源说明里交代 DBC 的规模与内容构成。因此下表大部分项标注为「源文档未给出」,而不是代填。

    项 内容
    物理层 源文档未给出(README 仅指向一份通用 CAN 协议教程)
    链路层 / 比特率 源文档未给出
    寻址方式 源文档未给出
    CAN FD 源文档未提及
    规模 2024CAR.dbc:115 条报文行、890 条信号行
    完整性校验 Git blob 6f64218…;SHA-256 b2901a5c…(源文档给出前段)

    已解码信号

    本快照不包含 DBC 本体,只有 README 与来源说明,因此无法提供逐字节解码。为守住「只抄源文档里有证据的条目」这条线,下表登记来源说明中明确写出的数据资产与部件类别,并逐条注明证据页;任何具体字节、位域与缩放系数,源文档均未提供。

    条目 承载 / 归属 说明 证据
    2024CAR.dbc(整车) — 115 条报文、890 条信号 SOURCE 说明
    Vector 独立信号伪报文 DBC 内 上游工具约定的伪报文,非真实总线流量 SOURCE 说明
    逆变器(inverter)报文 DBC 内 第三方部件流量 SOURCE 说明
    绝缘监测(IMD)报文 DBC 内 第三方部件流量 SOURCE 说明
    ChargerMessages.dbc 仓库内另存 充电机相关,未随本快照复制 SOURCE 说明
    HIL 测试 DBC 仓库内另存 硬件在环测试用,未随本快照复制 SOURCE 说明
    VCU 板固件 make vcu 整车控制单元构建目标 README「Quick start」
    BMU 板固件 make load LOAD_TARGET=bmu 电池管理单元构建/烧录目标 README「Quick start」
    单体测试固件 / 验证台架 仓库内 电池单体测试与固件验证 README 首段

    读取方法与注意事项

    源文档给出的可用操作集中在开发与构建层面:贡献者通过预构建的多架构 dev container 获得统一工具链(ARM GCC、Python 依赖),Windows 走 WSL2 + Dev Containers,构建用 make <board>、make all、make clean,烧录用宿主机的 make load LOAD_TARGET=<board> 或 STM32CubeProgrammer。这一层能保证固件可编译,但不等于能解出实车信号。

    要真正解析这份 DBC,需要把 DBC 文件本身载入基于 DBC 的解析库(README 提到仓库环境使用 cantools,并要求其特定版本)。由于本快照未包含 DBC,本文无法代做任何逐字节解析。标度与物理单位必须以 DBC 文件内容为准,源文档特意提醒「物理标度未独立验证」。

    还有一层法律与合规注意:来源说明指出,在该版本上未找到任何顶级许可证文件或声明的 GitHub 许可证,因此应把它保留为私有离线研究副本,再分发或集成交付前须先确认来源与权利。

    证据等级与边界

    本档案属于项目登记,既不是实车观测,也不是第三方旁证。可以核对的是数字本身(115 条报文、890 条信号、blob 与 SHA-256),以及仓库确是这支车队的固件 monorepo;不能据此认定这些定义能套用到任何一辆实车。

    三处不能外推。第一,「2024CAR」是文件名推断,源文档明确车辆赛季、硬件装配与原始数据的厂商权利均未被独立验证。第二,DBC 里混有第三方部件(逆变器、IMD)与 Vector 伪报文,这些条目代表部件厂商或工具的约定,不是整车厂的车身定义,不能与自研 VCU/BMU 信号混为一谈。第三,快照不完整:ChargerMessages.dbc 与 HIL 测试 DBC 未复制进来,因此不能对整车网络做「全覆盖」结论。

    关于「安全访问」类问题:本文只整理公开文档登记的数据资产,未涉及任何诊断会话或安全访问;源文档未提供绕过方法,且不建议尝试。

    常见问题

    2024CAR.dbc 里有多少报文和信号?

    据来源说明,这份 DBC 有 115 条报文行与 890 条信号行,另含一条 Vector 独立信号伪报文以及逆变器、IMD 等第三方部件报文。

    这份档案为什么没有逐条信号解码?

    因为本快照只包含 README 与来源说明,DBC 本体未包含在内。逐字节、位域与缩放系数都在 DBC 文件里,不在文档中,这是素材边界而非解析遗漏。

    能不能直接用于实车?

    不能。来源方声明车辆赛季、硬件装配与物理标度均未独立核实;同时该版本未声明任何许可证,应仅作为私有离线研究副本,复用前须确认来源与权利。

    这份固件怎么构建和烧录?

    用预构建 dev container 提供统一工具链,构建命令为 make vcu、make all 等;烧录在宿主机用 make load LOAD_TARGET=bmu 或 STM32CubeProgrammer。这只是构建流程,与解析实车信号无关。

    延伸阅读

    参考资料

    • 项目 01 —— public-can-dbc-datasets/additional/uwaterloo-2024car/README.md(本项目车型档案主来源:固件 monorepo 的结构、构建与烧录流程)。
    • 项目 01 —— public-can-dbc-datasets/additional/uwaterloo-2024car/SOURCE.md(DBC 规模、blob/SHA-256、以及「未独立验证」的边界声明)。

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11

  • Mazda MX-5 ND2:HS-CAN 开放字段与逐字节标定

    结论:Mazda MX-5 ND2 的 CAN 档案有一个鲜明特征:总线本身是可抓的——HS-CAN、500 kbit/s——但相当一部分字段仍处于「逐字节标定」阶段。源文档对 0x420 这一个 ID 内的不同字节分别拟合出不同刻度(油耗计数、行驶距离、环境温度各一套),并用 `_maybe` 后缀与「负向发现」明确标出哪些结论尚未闭环。以下所有结论仅限源文档记录的这一台车。

    车辆与适用范围

    本文数据来自第三方开源项目对一台 Mazda MX-5 ND2 的运行日志与字段标定记录。项目以第三方整理的 DBC 为起点,再用实测日志逐字段校验,并把未闭环的字段单独列成「开放字段」清单。

    项 内容
    车型 Mazda MX-5(ND2)
    年款 / 市场版本 源文档未确认
    数据来源 源文档为德文运行日志,记录 2026-09-27 至 09-30 的状态;DBC 派生自第三方公开整理的第六代 Mazda CAN 数据库
    采集状态 日志中记录了一次采集通道冲突:某个高频轮询脚本与手机端的采集适配器争用,影响了部分时段的采样
    适用范围 仅限源文档记录的这一台车;ND2 之外的年款、以及同款不同配置,字段位置与刻度都可能不同

    总线与寻址

    这辆车的接入相对直接:HS-CAN 上没有出现「必须主动问」的情形,字段基本来自周期广播或用已知 ID 关联。难点不在能不能抓,而在于抓到之后如何确定每个字节的物理含义。

    项 内容
    总线 HS-CAN
    速率 / 帧格式 500 kbit/s;11 位标准帧
    编解码基础 以第三方整理的 DBC 为起点,字段用实测日志逐条校验
    字段状态标注 未闭环字段加 `_maybe` 后缀;用相关系数与「负向发现」区分「有信号」与「没有该信号」

    已解码信号

    下表从源文档的「开放字段」清单与运行日志中抽取。项目对未闭环条目统一加 `_maybe` 后缀,并给出拟合依据(相关系数、阈值或确认比例),本文原样保留这些标注。

    信号 位置(ID / DID / 字节) 解码 证据
    ReverseGear(倒挡) 0x445 bit7 位标志 99.7% 确认
    DCDC_Voltage 0x08A 位 19|10 0.02 V/LSB 标定记录
    BCM_SupplyVoltage 0x43F 位 19|10 0.016 V/LSB 标定记录
    FuelConsumption_Counter(油耗计数) 0x420 B2 约 4834 步/升 逐字节标定
    Travel_distance_related(行驶距离) 0x420 B1 0.1992 m/步 逐字节标定
    AmbientTemp(环境温度) 0x420 B7 raw ÷ 4 ℃ 逐字节标定
    DistanceToService_related(保养距离) 0x3D1 位 47|14 km 候选
    CruiseActive_Inv(巡航激活,反相) 0x0FD bit61 50 Hz;0 = 巡航中 标定记录
    CRU_CON_SW1(巡航开关) 0x09D B0 bit5 / bit0 / bit3 位标志组 候选
    TCS_Active_maybe(牵引力控制激活) 0x211 bit40 位标志 候选(`_maybe`)
    HighDecel_maybe(大减速度) 0x211 bit43 位标志,阈值约 0.55–0.6 g 候选(`_maybe`)

    读取方法与注意事项

    第一条是「逐字节标定」的必要性。同一个 ID(例如 0x420)内部,不同字节承载的是完全不同的物理量,刻度也各不相同:一个字节对应油耗计数(约 4834 步每升),一个字节对应行驶距离(0.1992 米每步),还有一个字节对应环境温度(raw 除以 4)。把整条帧当作单一信号处理,会得到没有意义的数值。要按字节甚至按位分别标定。

    第二条是采集通道的争用。日志记录了一次冲突:一个高频轮询脚本与手机端采集适配器争用同一个接口,导致部分时段采样不完整。做周期统计或相关分析前,应先确认采集链路不存在争用,否则得到的「频率」其实是硬件带宽被挤占后的结果。

    第三条是位序与位号约定。源文档使用「位 19|10」这类跨字节的位号表示法,含义与常见的「起始位 + 长度」不同,解析时要先统一约定,否则容易把两个相邻字段读成同一个值。

    证据等级与边界

    项目用两类手段区分结论强度。一是「确认比例」,例如倒挡信号给出了 99.7% 确认;二是「负向发现」——源文档明确指出,在这辆车的日志里没有找到垂直加速度、侧倾、俯仰这类信号。负向发现同样是有价值的信息:它说明这些量要么不通过 CAN 广播,要么需要从别的传感器获取。

    未闭环字段一律加 `_maybe` 后缀,例如 TCS_Active_maybe 与 HighDecel_maybe。这表明它们只是「看起来像」某个物理量的候选位,尚未经过独立验证。使用时应把它们当作待验证假设,而不是可用字段。

    边界上必须强调:以上字段位置与刻度都来自这一台车与这一版 DBC。不同年款、不同配置的 MX-5,甚至同一车型的不同固件,都可能让字节偏移或刻度变化。跨车使用前必须重新标定。

    常见问题

    为什么同一个 ID 里的三个字节刻度完全不同?

    因为 CAN 帧是按位打包的字节流,一个 ID 内部的不同字节可以被车厂分配给毫不相干的物理量。源文档对 0x420 就是分别处理的:油耗计数约 4834 步每升、行驶距离 0.1992 米每步、环境温度 raw 除以 4。按整帧处理会得到无意义数值。

    `_maybe` 后缀是什么意思?

    表示该字段尚未闭环验证,只是「看起来像」某个物理量的候选位。例如 TCS_Active_maybe 与 HighDecel_maybe。使用时应把它们当作待验证假设,先自行复核再引用。

    「负向发现」为什么值得记录?

    因为它同样缩小了搜索空间。源文档明确指出这辆车没有找到垂直加速度、侧倾、俯仰信号,说明这些量要么不经 CAN 广播,要么需另求来源——这能避免后来者把时间花在并不存在的信号上。

    这些字段能直接用于别的 MX-5 吗?

    不能。源文档的结论限定在这一台车与这一版 DBC 上,不同年款或配置的字节偏移与刻度都可能变化。换车使用前必须重新标定。

    延伸阅读

    参考资料

    • 项目 04 —— public-can-dbc-datasets/additional/mainbrain-mx5-nd2-can/docs/status/can-open-fields.md(本项目车型档案主来源:开放字段清单与标定依据)
    • 项目 04 —— public-can-dbc-datasets/additional/mainbrain-mx5-nd2-can/docs/status/can-bus.md(运行日志与采集状态)
    • 项目 04 —— public-can-dbc-datasets/additional/mainbrain-mx5-nd2-can/SOURCE.md(DBC 版本与来源说明)

    说明:本文整理自第三方开源项目的公开文档,仅代表该文档所记录的单个车辆样本,不代表同型号全系车型。CAN 与诊断操作存在风险,任何实车操作前请自行复核并遵守当地法规。

    更新记录

    首次发布 2026-10-11 最近核对:2026-10-11