主要内容

CAN 报文的多路复用和解复用

简介

此示例说明如何对 CAN 报文应用多路复用和解复用。

多路复用是一种在 CAN 总线通信中用于增加传输信号数量的方法,但其代价是降低了每个信号的有效采样率。

多路复用信号属于同一 CAN 帧,但其位布局可能重叠。位模式的解释是有条件的,取决于另一个信号的值,该信号称为多路复用器。

假设有以下使用 CAN 通信管理器检索的多路复用 OBD-II(板载诊断)帧序列:

前两个数据字节的解释取决于第三个字节的值,该字节对应于 OBD-II PID。

具体来说,该帧携带三个不同信号,具有重叠的位布局,如以下各图所示。

发动机扭矩,OBD-II PID = 98(十进制),62(十六进制)

Engine_Torque_bit_layout_diagram.jpg

加速踏板位置,OBD-II PID = 73(十进制),49(十六进制)

Accelerator_bit_layout_diagram.jpg

车速,OBD-II PID = 13(十进制),0D(十六进制)

VehicleSpeed_bit_layout_diagram.jpg

多路复用器信号

Multiplexor_bit_layout_diagram.jpg

请注意,多路复用器信号的位布局不与其他三个信号的位布局重叠。

在以下各节中,将使用 Simulink® 模型对实际记录的信号进行多路复用和传输。

然后,在 CAN 通信管理器中接收 CAN 帧,最后用几行 MATLAB® 代码进行解复用。

Simulink 中的多路复用和传输

实际发动机百分比扭矩、加速踏板位置和车速的记录信号在 MAT 文件中以时间序列形式提供。在 0 到 25 秒的时间内记录数据。

load("Logged_OBD2_Data.mat");

检查记录的信号很有意义;特别是,如下所示,当加速踏板位置变为 0 时,发动机扭矩为负值。这是一种称为发动机制动的常见情况,此时车速确实会相应降低。

figure;
yyaxis("left");
plot(Accelerator);
yyaxis("right");
plot(Engine_Torque);
title("Accelerator and Engine Torque");

Figure contains an axes object. The axes object with title Accelerator and Engine Torque, xlabel Time (seconds), ylabel Actual Engine Percent Torque (%) contains 2 objects of type line.

figure
plot(Vehicle_Speed);
title("Vehicle Speed");

Figure contains an axes object. The axes object with title Vehicle Speed, xlabel Time (seconds), ylabel Vehicle speed (mph) contains an object of type line.

此数据通过 From Workspace 模块输入到以下 Simulink 模型。

CAN Pack 模块是基于 DBC 文件 CAN_OBD2_Multiplexed.dbc 按如下方式配置的。该文件包含单个多路复用 CAN 帧的定义,具有一个名为 OBD2Mode 的多路复用器。

输入信号馈送到 Multiplexer 模块中,该模块是使用 Stateflow® 图实现的。这是一种特别方便的基于时间的多路复用方法。

此状态机包含三个互斥状态。当 Transmit_Engine_Torque 状态被激活时,系统会传输发动机扭矩信号及其对应的 OBD-II PID,而其他两个信号设置为零。类似的逻辑也适用于其他两个状态,即 Transmit_Accelerator 和 Transmit_Vehicle_Speed。

状态之间的切换遵循基于时间的逻辑:Transmit_Engine_Torque 状态持续两个仿真时间步,Transmit_Accelerator 状态持续 1 个时间步,Transmit_Vehicle_Speed 状态持续 3 个时间步,然后切换回第一个状态。Stateflow 中的 tick 关键字指在每个时间步激活一次图,该激活由 Simulink 求解器触发。

以下参数用于控制 Simulink 模型的仿真。要实现接近挂钟时间执行的效果,可以启用仿真调速。

Ts = 0.1; % [s]
StartTime = 0; % [s]
StopTime = 25; % [s]

运行仿真后,需要检查多路复用信号以及多路复用器。

多路复用器周期性地在值 98、73 和 13(对应于三个信号的 OBD-II PID)之间切换。

此图传达多路复用有效地引入原始时间序列的下采样的概念,如原始速度信号和多路复用速度信号的比较所示。请注意,尽管信号的值根据 OBD-II PID 有意设置为零,但并未引入新信息:多路复用信号无法“原样”解释,需要在下游使用之前进行解复用。

MATLAB 中的接收和解复用

打开并配置 CAN 通信管理器以在 MathWorks Virtual Channel 1 上接收报文。然后,运行 Simulink 模型以接收报文,并将其导出到 MATLAB 工作区变量。在此示例中,变量称为 canExplorerMsgs,在 canExplorerMsgs.mat 文件中提供。

为文件 CAN_OBD2_Multiplexed.dbc 创建一个 CAN 数据库对象。使用该数据库对象以及 canMessageTimetablecanSignalTimetable 函数对报文进行解码。

load("canExplorerMsgs.mat");
db = canDatabase("CAN_OBD2_Multiplexed.dbc");
msgsTT = canMessageTimetable(canExplorerMsgs, db);
sigsTT = canSignalTimetable(msgsTT)
sigsTT=251×4 timetable
       Time       Vehicle_Speed    Accelerator    OBD2Mode    Engine_Torque
    __________    _____________    ___________    ________    _____________

    12.557 sec          1            12.157          98              0     
    12.657 sec          1            12.157          98              0     
    12.882 sec          0                 0          73           -125     
    12.976 sec          0                 0          13           -125     
    13.07 sec           0                 0          13           -125     
    13.281 sec          0                 0          13           -125     
    13.797 sec          1            12.157          98              0     
    13.967 sec          1            12.157          98              0     
    14.057 sec          0                 0          73           -125     
    14.147 sec          0                 0          13           -125     
    14.237 sec          0                 0          13           -125     
    14.327 sec          0                 0          13           -125     
    14.417 sec          2            12.941          98              7     
    14.507 sec          2             14.51          98             23     
    14.597 sec          6            39.608          73             23     
    14.687 sec          0                 0          13           -125     
      ⋮

这些函数独立处理每个信号,因此不应用解复用。sigsTT 时间表中的信号需要根据多路复用器的值(即 OBD2Mode 信号)提取。为此,可以应用逻辑索引,如下所示。

Accelerator_Demultiplexed = sigsTT(sigsTT.OBD2Mode == 73, "Accelerator")
Accelerator_Demultiplexed=42×1 timetable
       Time       Accelerator
    __________    ___________

    12.882 sec           0   
    14.057 sec           0   
    14.597 sec      39.608   
    15.137 sec      95.294   
    15.677 sec      83.137   
    16.217 sec      67.843   
    16.757 sec      57.647   
    17.297 sec      58.039   
    17.837 sec      59.608   
    18.377 sec      71.373   
    18.917 sec      86.275   
    19.457 sec      96.078   
    20.004 sec      98.824   
    20.578 sec      98.824   
    21.158 sec      44.706   
    21.757 sec      14.902   
      ⋮

Engine_Torque_Demultiplexed = sigsTT(sigsTT.OBD2Mode == 98, "Engine_Torque")
Engine_Torque_Demultiplexed=84×1 timetable
       Time       Engine_Torque
    __________    _____________

    12.557 sec          0      
    12.657 sec          0      
    13.797 sec          0      
    13.967 sec          0      
    14.417 sec          7      
    14.507 sec         23      
    14.957 sec         95      
    15.047 sec         98      
    15.497 sec         75      
    15.587 sec         76      
    16.037 sec         79      
    16.127 sec         79      
    16.577 sec         71      
    16.667 sec         68      
    17.117 sec         63      
    17.207 sec         63      
      ⋮

Vehicle_Speed_Demultiplexed = sigsTT(sigsTT.OBD2Mode == 13, "Vehicle_Speed")
Vehicle_Speed_Demultiplexed=125×1 timetable
       Time       Vehicle_Speed
    __________    _____________

    12.976 sec          0      
    13.07 sec           0      
    13.281 sec          0      
    14.147 sec          0      
    14.237 sec          0      
    14.327 sec          0      
    14.687 sec          0      
    14.777 sec          0      
    14.867 sec          0      
    15.227 sec          2      
    15.317 sec          3      
    15.407 sec          4      
    15.767 sec          6      
    15.857 sec          7      
    15.947 sec          7      
    16.307 sec         10      
      ⋮

figure;
yyaxis("left");
plot(Accelerator_Demultiplexed.Time, Accelerator_Demultiplexed.Accelerator);
ylabel("Accelerator Percent Pedal Position (%)")
yyaxis("right");
plot(Engine_Torque_Demultiplexed.Time, Engine_Torque_Demultiplexed.Engine_Torque);
ylabel("Actual Engine Percent Torque (%)")
title("Accelerator and Engine Torque - Demultiplexed");

Figure contains an axes object. The axes object with title Accelerator and Engine Torque - Demultiplexed, ylabel Actual Engine Percent Torque (%) contains 2 objects of type line.

figure
plot(Vehicle_Speed_Demultiplexed.Time, Vehicle_Speed_Demultiplexed.Vehicle_Speed)
title("Vehicle Speed - Demultiplexed");

Figure contains an axes object. The axes object with title Vehicle Speed - Demultiplexed contains an object of type line.

请注意,信号实际上经过下采样,并且初始时间不同于仿真的初始时间,这是因为用户在启动 CAN 通信管理器和启动 Simulink 仿真之间引入了延迟。然而,由于仿真调速,大约 25 秒的时间范围与仿真时间范围一致。