Main Content

Log and Replay CAN Messages

This example shows you how to log and replay CAN messages using MathWorks® Virtual CAN channels in Simulink®. You can update this model to connect to supported hardware on your system.

Load the saved CAN message from SourceMsgs.mat file from the examples folder. The file contains CAN messages representing a 90 second drive cycle around a test track.

load SourceMsgs.mat

Alternatively, read the CAN messages from a BLF file using the blfread function. Notice that the output is a scalar cell, therefore the timetable needs to be extracted from the cell.

canMsgTimetable = blfread("SourceMsgs.blf");
canMsgTimetable = canMsgTimetable{1};

A similar approach can be used to read from MDF files, using the mdfRead function.

Notice that the initial time stamp of the recorded messages is not zero:

startTime = seconds(canMsgTimetable.Time(1))
startTime = 
88.6176
stopTime = seconds(canMsgTimetable.Time(end))
stopTime = 
177.2310

Define a simulation time step of 0.01 s, and round the values of startTime and stopTime to be compatible with it.

Ts = 0.01;
startTime = round(startTime, 2);
stopTime = round(stopTime, 2);

Convert the messages to a format compatible with the CAN Replay block and save them to a separate file.

canMsgs = canMessageReplayBlockStruct(canMsgTimetable);
save DriveReplay.mat canMsgs
whos
  Name                      Size               Bytes  Class        Attributes

  Ts                        1x1                    8  double                 
  canMsgTimetable      100000x8             38311075  timetable              
  canMsgs                   1x1              2400952  struct                 
  startTime                 1x1                    8  double                 
  stopTime                  1x1                    8  double                 

CAN Replay Model

This model contains:

  • A CAN Replay block that transmits to MathWorks Virtual Channel 1.

  • A CAN Receive block that receives the messages on a CAN network, through MathWorks Virtual Channel 2.

The CAN Receive block is configured to block all extended IDs and allow only the WheelSpeed message with the standard ID 1200 to pass.

Configure the model parameters for compatibility with the CAN messages timeseries. Click on the Modeling tab, then on Configuration Parameters. In the Solver pane, use the startTime, stopTime and Ts variables in the appropriate edit fields as shown.

Click OK to apply changes and close the window.

Wheel Speeds Subsystem

The Wheel Speeds subsystem unpacks the wheel speed information from the received CAN messages and plots them to a scope. The subsystem also logs the messages to a file.

Visualize Wheel Speed Information

Click Run to run the simulation. Depending on you computer configuration, the output shown in the scope may be zero.

This result is expected: model simulation and message transmission are executed on separate threads, and are not synchronized. Simulink attempts to execute the simulation as fast as possible, and the provided time series is very short; it is therefore likely that transmission of the first message had not been initiated before the simulation was completed.

A better approach to replaying logged signals is to use simulation pacing, which slows down model execution to achieve an approximately real-time simulation. To activate simulation pacing, click on Run -> Simulation Pacing, then activate the option via the tick box. Run the simulation again, then visualize the wheel speed for all wheels for the duration of the test drive.

demoVNTSL_CANReplayAndLog_Scope.png

Load the Logged Message File

The CAN Log block creates a unique file each time you run the model. Use dir in the MATLAB® Command Window to find the latest log file.

dir WheelSpeeds*.mat
WheelSpeeds_2023-Jun-20_150142.mat  
load WheelSpeeds_2023-Jun-20_150142.mat
whos
  Name                      Size               Bytes  Class        Attributes

  Ts                        1x1                    8  double                 
  canMsgTimetable      100000x8             38311075  timetable              
  canMsgs                   1x1              2400952  struct                 
  outMsgs                   1x1               240304  struct                 
  startTime                 1x1                    8  double                 
  stopTime                  1x1                    8  double                 

Convert Logged Messages

Offset the logged timestamps using the previously defined startTime variable.

outMsgs.Timestamp = startTime + outMsgs.Timestamp;

Use canMessageTimetable to convert messages logged during the simulation to a timetable that you can use in the command window.

To access message signals directly, use the appropriate database file in the conversion along with canSignalTimetable.

Use then the plot function to visualize the signals, and compare them to the output of the simulation.

db = canDatabase('VehicleInfo.dbc');
wheelSpeedMsgTimetable = canMessageTimetable(outMsgs, db);
wheelSpeedMsgTimetable(1:15, :)
ans=15×8 timetable
       Time        ID     Extended         Name                     Data                Length      Signals       Error    Remote
    __________    ____    ________    _______________    ___________________________    ______    ____________    _____    ______

    88.912 sec    1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 
    88.92 sec     1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 
    88.929 sec    1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 
    88.939 sec    1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 
    88.947 sec    1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 
    88.957 sec    1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 
    88.965 sec    1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 
    88.974 sec    1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 
    88.982 sec    1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 
    88.99 sec     1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 
    88.999 sec    1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 
    89.007 sec    1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 
    89.016 sec    1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 
    89.024 sec    1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 
    89.033 sec    1200     false      {'WheelSpeeds'}    {[39 16 39 16 39 16 39 16]}      8       {1x1 struct}    false    false 

wheelSpeedSignals = canSignalTimetable(wheelSpeedMsgTimetable);
wheelSpeedSignals(end-14:end, :)
ans=15×4 timetable
       Time       LR_WSpeed    RR_WSpeed    RF_WSpeed    LF_WSpeed
    __________    _________    _________    _________    _________

    177.38 sec      56.73        56.73        56.61        56.65  
    177.39 sec      56.76        56.69        56.64        56.66  
    177.4 sec       56.74        56.66        56.62        56.65  
    177.41 sec      56.72        56.73        56.56        56.64  
    177.42 sec      56.76        56.76        56.57        56.66  
    177.43 sec      56.78        56.69        56.66        56.72  
    177.44 sec      56.82        56.74        56.72        56.74  
    177.45 sec      56.85        56.81        56.77        56.72  
    177.45 sec      56.79        56.81        56.79        56.69  
    177.46 sec      56.76        56.83        56.78        56.66  
    177.47 sec      56.74        56.79        56.74        56.66  
    177.48 sec       56.7        56.74        56.68        56.69  
    177.49 sec      56.76        56.77        56.69        56.72  
    177.5 sec       56.76        56.81        56.72        56.77  
    177.51 sec      56.65        56.83        56.68        56.77  

plot(wheelSpeedSignals.Time, wheelSpeedSignals{:,:});

Figure contains an axes object. The axes object contains 4 objects of type line.

MathWorks CAN Virtual channels were used for this example. You can however connect your models to other supported hardware.

See Also

Tools

Related Examples

More About