Main Content

Decoding CAN Data from MDF-Files

This example shows you how to import and decode CAN data from MDF-files in MATLAB for analysis. The MDF-file used in this example was generated from Vector CANoe™ using the "CAN - General System Configuration (CAN)" sample. This example also uses the CAN database file, PowerTrain.dbc, provided with the Vector sample configuration.

Open the MDF-File

Open access to the MDF-file using the mdf function.

m = mdf("Logging_MDF.mf4")
m = 
  MDF with properties:

   File Details
                 Name: 'Logging_MDF.mf4'
                 Path: '/tmp/Bdoc20b_1465442_10305/tpe5f574e0/vnt-ex42187575/Logging_MDF.mf4'
               Author: ''
           Department: ''
              Project: ''
              Subject: ''
              Comment: ''
              Version: '4.10'
             DataSize: 1542223
     InitialTimestamp: 2020-06-25 20:41:13.133000000

   Creator Details
    ProgramIdentifier: 'MDF4Lib'
              Creator: [1x1 struct]

   File Contents
           Attachment: [5x1 struct]
         ChannelNames: {62x1 cell}
         ChannelGroup: [1x62 struct]

Identify CAN Data Frames

According to the ASAM MDF associated standard for bus logging, the event types defined for a CAN bus system can be "CAN_DataFrame", "CAN_RemoteFrame", "CAN_ErrorFrame" or "CAN_OverloadFrame". This example focuses on extracting the CAN data frames, so the bus logging standard will be discussed using "CAN_DataFrame" event type as example. Additionally, note that a standard CAN data frame has up to 8 bytes for its payload and is used to transfer signal values.

The standard specifies that the channel names of the event structure should be prefixed by the event type name, for instance, "CAN_DataFrame". Typically a dot is used as separator character to specify the member channels, for instance, "CAN_DataFrame.ID" or "CAN_DataFrame.DataLength".

Use the channelList function to filter on channel names exactly matching "CAN_DataFrame". A table with information on matched channels is returned.

channelList(m, "CAN_DataFrame", "ExactMatch", true)
ans=2×9 table
      ChannelName      ChannelGroupNumber    ChannelGroupNumSamples    ChannelGroupAcquisitionName    ChannelGroupComment    ChannelDisplayName    ChannelUnit    ChannelComment    ChannelDescription
    _______________    __________________    ______________________    ___________________________    ___________________    __________________    ___________    ______________    __________________

    "CAN_DataFrame"            17                     8889                        CAN1                    <undefined>                ""            <undefined>    bus event data     "bus event data" 
    "CAN_DataFrame"            29                     7648                        CAN2                    <undefined>                ""            <undefined>    bus event data     "bus event data" 

The powetrain data of interest was logged from the CAN 2 network. The channelList output above shows that the data from CAN 2 network has been stored in channel group 29 of the MDF-file. View the channel group details using the ChannelGroup property.

m.ChannelGroup(29)
ans = struct with fields:
    AcquisitionName: 'CAN2'
            Comment: ''
         NumSamples: 7648
           DataSize: 206496
             Sorted: 1
            Channel: [14x1 struct]

Within a channel group, details about each channel are stored. View details about channel 2 within channel group 29.

m.ChannelGroup(29).Channel(2)
ans = struct with fields:
                  Name: 'CAN_DataFrame.Flags'
           DisplayName: 'Flags'
    ExtendedNamePrefix: 'CAN2'
           Description: 'Combination of bit flags for the message.'
               Comment: 'Combination of bit flags for the message.'
                  Unit: ''
                  Type: FixedLength
              DataType: IntegerUnsignedLittleEndian
               NumBits: 8
         ComponentType: StructureMember
       CompositionType: None

Read CAN Data Frames From the MDF-File

Read all data from all channels in channel group 29 into a timetable using the read function. The timetable is structured to follow the ASAM MDF standard logging format. Every row represents one raw CAN frame from the bus, while each column represents a channel within the specified channel group. The channels, such as "CAN_DataFrame.Dir", are named to follow the bus logging standard. However, because timetable column names must be valid MATLAB variable names, they may not be identical to the channel names. Most unsupported characters are converted to underscores. Since "." is not supported in a MATLAB variable name, "CAN_DataFrame.Dir" is altered to "CAN_DataFrame_Dir" in the table.

canData = read(m, 29, m.ChannelNames{29})
canData=7648×14 timetable
       Time       CAN_DataFrame_BusChannel    CAN_DataFrame_Flags    CAN_DataFrame_Dir    CAN_DataFrame_SingleWire    CAN_DataFrame_WakeUp    CAN_DataFrame_ID    CAN_DataFrame_IDE    CAN_DataFrame_FrameDuration    CAN_DataFrame_BitCount    CAN_DataFrame_DLC    CAN_DataFrame_DataLength    CAN_DataFrame_DataBytes    CAN_DataFrame      t   
    __________    ________________________    ___________________    _________________    ________________________    ____________________    ________________    _________________    ___________________________    ______________________    _________________    ________________________    _______________________    _____________    ______

    2.2601 sec               2                         1                     1                       0                         0                     103                  0                     1.28e+05                        67                      2                       2                      {1x2 uint8}          {1x19 uint8}     2.2601
    2.2801 sec               2                         1                     1                       0                         0                     103                  0                     1.28e+05                        67                      2                       2                      {1x2 uint8}          {1x19 uint8}     2.2801
    2.3002 sec               2                         1                     1                       0                         0                     100                  0                     2.32e+05                       119                      8                       8                      {1x8 uint8}          {1x19 uint8}     2.3002
    2.3005 sec               2                         1                     1                       0                         0                     102                  0                      2.4e+05                       123                      8                       8                      {1x8 uint8}          {1x19 uint8}     2.3005
    2.3006 sec               2                         1                     1                       0                         0                     103                  0                     1.28e+05                        67                      2                       2                      {1x2 uint8}          {1x19 uint8}     2.3006
    2.3008 sec               2                         1                     1                       0                         0                     201                  0                     1.96e+05                       101                      6                       6                      {1x6 uint8}          {1x19 uint8}     2.3008
    2.3009 sec               2                         1                     1                       0                         0                    1020                  0                      1.1e+05                        58                      1                       1                      {[      1]}          {1x19 uint8}     2.3009
    2.3201 sec               2                         1                     1                       0                         0                     103                  0                     1.28e+05                        67                      2                       2                      {1x2 uint8}          {1x19 uint8}     2.3201
    2.3401 sec               2                         1                     1                       0                         0                     103                  0                     1.28e+05                        67                      2                       2                      {1x2 uint8}          {1x19 uint8}     2.3401
    2.3502 sec               2                         1                     1                       0                         0                     100                  0                     2.34e+05                       120                      8                       8                      {1x8 uint8}          {1x19 uint8}     2.3502
    2.3505 sec               2                         1                     1                       0                         0                     102                  0                     2.28e+05                       117                      8                       8                      {1x8 uint8}          {1x19 uint8}     2.3505
    2.3507 sec               2                         1                     1                       0                         0                     201                  0                     1.98e+05                       102                      6                       6                      {1x6 uint8}          {1x19 uint8}     2.3507
    2.3508 sec               2                         1                     1                       0                         0                    1020                  0                      1.1e+05                        58                      1                       1                      {[      1]}          {1x19 uint8}     2.3508
    2.3601 sec               2                         1                     1                       0                         0                     103                  0                     1.28e+05                        67                      2                       2                      {1x2 uint8}          {1x19 uint8}     2.3601
    2.3801 sec               2                         1                     1                       0                         0                     103                  0                     1.28e+05                        67                      2                       2                      {1x2 uint8}          {1x19 uint8}     2.3801
    2.4002 sec               2                         1                     1                       0                         0                     100                  0                     2.34e+05                       120                      8                       8                      {1x8 uint8}          {1x19 uint8}     2.4002
      ⋮

Decode CAN Messages Using the DBC-File

Open the database file using the canDatabase function.

canDB = canDatabase("PowerTrain_MDF.dbc")
canDB = 
  Database with properties:

             Name: 'PowerTrain_MDF'
             Path: '/tmp/Bdoc20b_1465442_10305/tpe5f574e0/vnt-ex42187575/PowerTrain_MDF.dbc'
            Nodes: {2x1 cell}
         NodeInfo: [2x1 struct]
         Messages: {12x1 cell}
      MessageInfo: [12x1 struct]
       Attributes: {11x1 cell}
    AttributeInfo: [11x1 struct]
         UserData: []

The canMessageTimetable function uses the database to decode the message names and signals. The timetable of ASAM standard logging format data is converted into a Vehicle Network Toolbox™ CAN message timetable.

msgTimetable = canMessageTimetable(canData, canDB)
msgTimetable=7648×8 timetable
       Time        ID     Extended           Name              Data        Length      Signals       Error    Remote
    __________    ____    ________    __________________    ___________    ______    ____________    _____    ______

    2.2601 sec     103     false      {'Ignition_Info' }    {1x2 uint8}      2       {1x1 struct}    false    false 
    2.2801 sec     103     false      {'Ignition_Info' }    {1x2 uint8}      2       {1x1 struct}    false    false 
    2.3002 sec     100     false      {'EngineData'    }    {1x8 uint8}      8       {1x1 struct}    false    false 
    2.3005 sec     102     false      {'EngineDataIEEE'}    {1x8 uint8}      8       {1x1 struct}    false    false 
    2.3006 sec     103     false      {'Ignition_Info' }    {1x2 uint8}      2       {1x1 struct}    false    false 
    2.3008 sec     201     false      {'ABSdata'       }    {1x6 uint8}      6       {1x1 struct}    false    false 
    2.3009 sec    1020     false      {'GearBoxInfo'   }    {[      1]}      1       {1x1 struct}    false    false 
    2.3201 sec     103     false      {'Ignition_Info' }    {1x2 uint8}      2       {1x1 struct}    false    false 
    2.3401 sec     103     false      {'Ignition_Info' }    {1x2 uint8}      2       {1x1 struct}    false    false 
    2.3502 sec     100     false      {'EngineData'    }    {1x8 uint8}      8       {1x1 struct}    false    false 
    2.3505 sec     102     false      {'EngineDataIEEE'}    {1x8 uint8}      8       {1x1 struct}    false    false 
    2.3507 sec     201     false      {'ABSdata'       }    {1x6 uint8}      6       {1x1 struct}    false    false 
    2.3508 sec    1020     false      {'GearBoxInfo'   }    {[      1]}      1       {1x1 struct}    false    false 
    2.3601 sec     103     false      {'Ignition_Info' }    {1x2 uint8}      2       {1x1 struct}    false    false 
    2.3801 sec     103     false      {'Ignition_Info' }    {1x2 uint8}      2       {1x1 struct}    false    false 
    2.4002 sec     100     false      {'EngineData'    }    {1x8 uint8}      8       {1x1 struct}    false    false 
      ⋮

View the signals stored in the "EngineData" message.

msgTimetable.Signals{3}
ans = struct with fields:
    PetrolLevel: 1
       EngPower: 7.5000
       EngForce: 0
    IdleRunning: 0
        EngTemp: 0
       EngSpeed: 750

Repackage and Visualize Signal Values of Interest

Use the canSignalTimetable function to repackage signal data from each unique message on the bus into a signal timetable. This example creates three individual signal timetables for the three messages of interest, "ABSdata", "EngineData" and "GearBoxInfo", from the CAN message timetable.

signalTimetable1 = canSignalTimetable(msgTimetable, "ABSdata")
signalTimetable1=1147×4 timetable
       Time       AccelerationForce    Diagnostics    GearLock    CarSpeed
    __________    _________________    ___________    ________    ________

    2.3008 sec          -100                0            0            0   
    2.3507 sec           275                0            0            0   
    2.4008 sec           275                0            0            0   
    2.4507 sec           275                0            0            0   
    2.5008 sec           275                0            0            0   
    2.5507 sec           275                0            0            0   
    2.6008 sec           275                0            0            0   
    2.6507 sec           275                0            0            0   
    2.7008 sec           350                0            0            0   
    2.7507 sec           425                0            0          0.5   
    2.8008 sec           425                0            0          0.5   
    2.8507 sec           500                0            0          0.5   
    2.9008 sec           575                0            0          0.5   
    2.9507 sec           575                0            0          0.5   
    3.0008 sec           650                0            0          0.5   
    3.0507 sec           725                0            0          0.5   
      ⋮

signalTimetable2 = canSignalTimetable(msgTimetable, "EngineData")
signalTimetable2=1147×6 timetable
       Time       PetrolLevel    EngPower    EngForce    IdleRunning    EngTemp    EngSpeed
    __________    ___________    ________    ________    ___________    _______    ________

    2.3002 sec         1            7.5          0            0            0         750   
    2.3502 sec         2            7.5        375            0            0           4   
    2.4002 sec         3            7.5        375            0            0          10   
    2.4502 sec         4            7.5        375            0            0          17   
    2.5002 sec         5            7.5        375            0            0          23   
    2.5502 sec         6            7.5        375            0            0          30   
    2.6002 sec         7            7.5        375            0            0          36   
    2.6502 sec         8            7.5        375            0            0          43   
    2.7002 sec         9              9        450            0            0          50   
    2.7502 sec        10           10.5        525            0            0          59   
    2.8002 sec        10           10.5        525            0            0          69   
    2.8502 sec        11             12        600            0            0          80   
    2.9002 sec        11           13.5        675            0            0          92   
    2.9502 sec        12           13.5        675            0            0         106   
    3.0002 sec        13             15        750            0            0         121   
    3.0502 sec        13           16.5        825            0            0         136   
      ⋮

signalTimetable3 = canSignalTimetable(msgTimetable, "GearBoxInfo")
signalTimetable3=1147×3 timetable
       Time       EcoMode    ShiftRequest    Gear
    __________    _______    ____________    ____

    2.3009 sec       0            0           1  
    2.3508 sec       0            0           1  
    2.4009 sec       0            0           1  
    2.4508 sec       0            0           1  
    2.5009 sec       0            0           1  
    2.5508 sec       0            0           1  
    2.6009 sec       0            0           1  
    2.6508 sec       0            0           1  
    2.7009 sec       0            0           1  
    2.7508 sec       0            0           1  
    2.8009 sec       0            0           1  
    2.8508 sec       0            0           1  
    2.9009 sec       0            0           1  
    2.9508 sec       0            0           1  
    3.0009 sec       0            0           1  
    3.0508 sec       0            0           1  
      ⋮

To visualize the signals of interest, columns from the signal timetables can be plotted over time for further analysis.

subplot(3, 1, 1)
plot(signalTimetable1.Time, signalTimetable1.CarSpeed, 'r')
title('{\itCarSpeed} Signal from {\itABSdata} Message', 'FontWeight', 'bold')
xlabel('Timestamp')
ylabel('Car Speed')
subplot(3, 1, 2)
plot(signalTimetable2.Time, signalTimetable2.EngSpeed, 'b')
title('{\itEngSpeed} Signal from {\itEngineData} Message', 'FontWeight', 'bold')
xlabel('Timestamp')
ylabel('Engine Speed')
subplot(3, 1, 3)
plot(signalTimetable3.Time, signalTimetable3.Gear, 'y')
title('{\itGear} Signal from {\itGearBoxInfo} Message', 'FontWeight', 'bold')
xlabel('Timestamp')
ylabel('Gear')