Talaria 电动越野车 CAN 信号:250 kbit/s 下 15 个 ID 与四处证伪

作者:

在

结论:Talaria 电动越野车的车载 CAN 是一条 250 kbit/s、11 位标准 ID、15 个报文 ID、约 92 帧每秒的总线,用一颗 3.3 V 收发器挂在 ESP32-S3 的 TWAI 控制器上即可只读取数。真正有复用价值的不是那张 14 项信号表,而是表里被明确证伪的四处:0x103[0] 不是电量、0x202[6:8] 不是里程、0x490 不是温度也不是单字段、节流需求偏移随固件而变。把这几条排除后再取数,才不会把「看起来像」当成「就是」。

总线前提与接入方式

这条总线在电机控制器处即可挂到 CAN_H 与 CAN_L,硬件侧只需要一个 3.3 V 的 SN65HVD230 收发器:发送脚接 GPIO7、接收脚接 GPIO8,直连而非交叉——这一点与同一块板上的 GPS 串口不同,后者是交叉的。CAN 外设用的是 ESP32-S3 自带的 TWAI 控制器,外部模块只承担物理层。

两个电气细节必须在上电前处理。第一,模块板上那个标着 121 的 120 欧终端电阻要拆掉:车辆总线两端已经各自终端,跨 CAN_H/CAN_L 量到的是 60 欧,再并一个电阻会掉到 40 欧,波形裕量直接被吃掉。第二,一旦 CAN 双线接入,设备的地就通过降压模块的负极与车辆共地,此时再插 USB 会把车辆电池负极接到保护地,同时 USB 的 5 V 与降压模块的 5 V 在 VUSB 上相撞;拔掉车端连接器可以同时隔离这两个风险,遥测数据改走无线链路读取。

总线默认是只读取模式:收发器从不驱动总线,甚至不应答,因此即便波特率猜错也不会扰动车辆。这一点是整套方案能从「只读」安全扩展到「可写」的前提。

参数 取值 备注
波特率 250 kbit/s 扫描子命令会遍历波特率与标准/扩展 ID 组合
ID 类型 11 位标准 ID 与整车厂常见的 29 位扩展 ID 不同
总线报文 ID 数 15 固件当前只解析其中 8 个
帧率 约 92 帧/秒 全总线合计
终端电阻 60 欧(熄火状态下测量) 读到 120 欧说明只挂到了单端
接地 无需单独地线 通过降压模块负极已与车辆共地
DBC 规模 9 条报文、26 条信号行 每条信号的验证过程写在 CM_ 注释里

已解码信号与字节定义

下面这张表是这份研究的核心产出。所有偏移都按小端处理,物理量的缩放因子在最后一列。值得注意的是,电芯最高/最低电压与序号共用同一帧的不同字节组,序号分别落在字节 4 与字节 5。

信号 帧 ID 字节与位 缩放
车速 0x303 字节 0–1,小端 0.1 km/h
电机转速 0x203 字节 0–1,小端 1 rpm
功率 0x203 字节 2–3,小端 1 W
电流 0x302 字节 4–5,小端 0.1 A
电池包电压 0x101 字节 0–1,小端 0.1 V
电量百分比 0x401 字节 0 1 %
最高电芯电压与序号 0x201 字节 0–1 小端,序号在字节 4 1 mV
最低电芯电压与序号 0x201 字节 2–3 小端,序号在字节 5 1 mV
边撑 0x202 字节 0 第 7 位 1 为放下
骑行模式 0x202 字节 0 第 5:4 位 1 节能、2 运动
动能回收等级 0x490 字节 0 第 2:0 位 1 至 4
骑行模式(仪表指令) 0x490 字节 0 第 5:3 位 1 节能、2 运动
里程 0x402 字节 2–3,小端 1 km
转把需求 0x202 字节 3–4,小端 单位未确认

交叉验证给了两个可信锚点:车速与转速在两次独立骑行中保持 5.887 的固定比值,相关系数 0.999,对车速积分也能还原出合理的骑行距离;最高与最低电芯电压的平均值乘以 16 能复现电池包电压到 0.02 V 以内,这坐实了 16 串的电池包结构。这两条把「解析对了」从感觉变成了可检验的判据。

遥测包里的 CAN 块与门控位

解码后的车辆数据占遥测包第 50 至 69 字节,配套一个状态字节:第 0 位表示总线存活,第 1 位是边撑,第 3:2 位是骑行模式,第 6:4 位是回收等级。规则只有一条但必须遵守——超过 2 秒没有收到任何帧时,整个字节块会被清零、存活位同时拉低,因此判空要门控在存活位上,而不能相信「速度为零」。否则一辆停着的车和一根拔掉的线在数据上完全一样。里程字段在第 88 字节,取的就是 0x402[2:4],读到 0 表示还没见过该帧。

四处已被证伪的字段

这份研究最值得照搬的不是结论,而是它把「曾经以为」逐条推翻并留下判据的过程。四条错误里前两条是典型的形状误导,第三条是位域切分错误,第四条是跨设备外推错误。

被误认的字段 为什么看起来像 证伪判据 正确取法
0x103[0] 当电量 数值形态像百分比 实际电量在别处变化时它恒为 100,几乎可以确定是健康度 取 0x401 字节 0
0x202[6:8] 当里程 单调递增,形态极像里程计 与车速的相关系数为负 0.0005,两次骑行的每公里计数相差 34% 取 0x402[2:4],整公里
0x490[0] 当温度或单字段 整字节与模式的相关系数 0.99,看起来整字节都是模式 第 5:3 位是模式、第 2:0 位是回收等级;节能模式下第 3 位被置起,回收 1 会读成 0x09 而非 0x01 掩 3 位而不是 4 位
转把需求偏移固定 同车型同帧 ID,默认偏移可复用 本车在 0x202[3:5],参考日志里那辆车在 0x202[2:4] 且根本不跟随转把 换车必须重新验证偏移

里程的发现过程有一条通用经验值得单独记:这份研究曾长期写着「总线上没有找到里程计」,而这个结论是从固件捕获的 8 个帧里得出的,0x402 恰恰属于没人解码的那 7 个。后来是照着车辆仪表自己显示的 400 km 去全总线捕获里找这个数,0x402[2:4] 正好读出 400。由于总线上存在 1200 这类整常数(同时出现在 0x101[4:6] 与 0x302[6:8]),单次对上整数只是提示而非证明,因此它被明确标注为待验证——需要一次实际骑行看它自增。

从只读到可控:0x490 是命令不是回声

0x490 长期被当作控制器的回声,直到一次按键对比实验才被推翻:连续五次按键里,0x490[0] 每次都先动,0x202 在 20 至 27 毫秒之后才跟着变,同时带上新的模式位与新的需求下限(运动 1100、节能 750)。在仪表持续以 5 Hz 发运动模式的同时注入节能,控制器在整个注入期间被钉在需求 750 上。结论是仪表与控制器是两个不同节点,控制器服从总线上最近一次 0x490,而且从不锁存。

这就决定了「覆盖」不能以命令的方式实现,只能以持续争论的方式实现:仪表下一帧在 200 毫秒后就会把单次发送的内容推翻,所以只要覆盖还生效,就必须应答仪表发出的每一个 0x490。实测差距很明显——自由运行在 20 Hz 注入会输掉 24% 的帧,而收到即回则在控制器自己的 297 帧里守住了 297 帧。决定成败的是延迟,不是发送频率。

机制 行为 后果
锁存 控制器不锁存,服从最近一帧 覆盖必须持续应答,发一次无效
注入方式 收到即回,守住 297/297;自由运行 20 Hz 丢失 24% 延迟是机制,频率不是
释放路径 无线断连、CAN 超时、车把按键任一触发 100 毫秒内回到仪表控制
可验证性 模式可见,回收等级无法验证 回收不带动总线上任何其他量,功率与电流都是无符号的
仪表显示 仪表不监听总线 覆盖期间仪表显示与实车状态真实不一致
回收限制 电量高于约 90% 时车辆自行抑制 指令发出但正确地不产生效果

另外,喇叭与灯光根本不上总线,它们是车把开关直接控制的 12 V 回路;刹车拉杆在部分车上有信号,改装的无传感器拉杆什么也发不出。这些边界决定了这套数据能覆盖到什么程度。

嗅探工具与验证命令

逆向过程被固化成四个子命令,全部跑在主机侧,配合一个串口转 CAN 适配器工作。 scan 负责扫波特率与 ID 类型组合,如果到处都是零帧,最常见的原因是 CAN_H 与 CAN_L 接反——无害,换过来即可;sniff 给出实时表格,包含解码后的物理量、每个 ID 的速率、逐字节变化图;events 先自学哪些字节会自行漂移,然后只打印真正的变化,使用时一次只操作一个控件,就能定位该控件落在哪个字节;log 落盘为 .asc、.blf 或 .csv 供离线分析。

子命令 用途 典型判据
scan 扫描波特率与标准/扩展 ID 全组合零帧通常是 CAN_H/CAN_L 反接
sniff 实时表格:物理量、每 ID 速率、逐字节变化图 用于确认波特率与帧清单
events 过滤自发漂移,只打印真实变化 一次只动一个控件
log 录制 .asc/.blf/.csv 供离线回归与跨骑行比对

配套环境搭建只需两条命令:先建虚拟环境并安装依赖,再用 250000 的波特率参数调用对应子命令,串口设备名按实际枚举结果传入。整个链路不需要改动车辆任何部件,这也是只读取数能长期稳定运行的底气。除了这套主机侧工具,固件侧还有一个专门的 CAN 探测程序,它把解码后的仪表直接输出到屏幕与无线链路上——之所以刻意走无线,是因为车辆与 USB 主机任何时候都不能同时连接。

最后补一条容易被忽略的经验:总线上的 15 个 ID 与实际解析的 8 个之间的落差,本身就是最大的风险来源。任何「总线上没有某个信号」的结论,只有在完整捕获全部 ID 之后才成立;而车辆仪表已经显示的数值,是验证解码结果最便宜的基准。

常见问题

这条总线能直接拿来读取车辆数据吗?

可以,但必须只读取:收发器不驱动总线也不应答,波特率猜错也不会扰动车辆。前提是先拆掉收发器模块上的 120 欧终端电阻,否则总线的 60 欧会变成 40 欧。另外不要同时接 USB 与车辆,两者会在 VUSB 上相撞并把车辆地接到保护地。

为什么我读到的电量一直是 100?

因为取的是 0x103 字节 0,那个字段在真实电量变化时保持不变,几乎可以确定是电池健康度。真实的电量百分比在 0x401 的字节 0,缩放为 1%。

里程到底在哪个帧?

在 0x402 的字节 2 至 3,小端,单位 1 公里。曾经被误认为里程的 0x202[6:8] 虽然单调递增,但与车速相关系数只有负 0.0005,两次骑行的每公里计数相差 34%,已被排除。由于总线上存在 1200 这类整常数,该结论仍标注为待一次自增骑行验证。

能不能通过总线改骑行模式?

可以,但不能用「发一次命令」的思路。控制器服从最近一次 0x490 且不锁存,仪表每 200 毫秒就会覆盖一次,因此必须持续应答仪表的每一帧;实测收到即回守住 297/297,自由运行 20 Hz 会丢失 24%。同时要注意仪表不监听总线,覆盖期间仪表显示与实车真实状态不一致,而回收等级发出后无法从总线验证。

换一辆同型号车能直接复用这套偏移吗?

不能。转把需求在本车位于 0x202[3:5],在参考日志那辆车上位于 0x202[2:4] 且完全不跟随转把。上游明确提示字节偏移随固件版本变化,换车必须重新验证,且这套解码本身是以另一份公开的 Talaria CAN 日志项目为地基的派生研究,并非独立来源。

延伸阅读

参考资料

  • 项目 01 —— public-can-dbc-datasets/additional/kbirand-talaria-tripper/README.md(总线参数、硬件接入、14 项解码信号表、四个字段证伪过程与覆盖机制实测)
  • 项目 01 —— public-can-dbc-datasets/additional/kbirand-talaria-tripper/SOURCE.md(DBC 的 9 报文 26 信号行规模、里程字段的待验证声明、派生来源与权利状态说明)

免责声明

本文所述的总线参数与信号定义均为社区研究报告产物,不代表车辆制造商的官方数据,文中数字均来自上述公开仓库的说明文件,未经独立实车验证。上游明确指出该解码是以另一份公开的骑行日志为地基的派生研究,适用车型、固件版本与其他车辆均未确立,字节偏移随固件变化,换车必须重新验证。该仓库快照中未发现任何许可证或逐文件再分发授权,仅可作私有离线研究副本,再分发或集成前须先行确认权利。涉及写入总线的操作请仅在封闭场地、由具备资质的人员执行,并以官方资料与实际测量为准。

更新记录

  • 2026-10-15 初稿

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注