Main Content

Event-Based CAN Message Transmission Behavior in Simulink

This example shows how to use event-based CAN message transmission in Simulink with Vehicle Network Toolbox. This feature allows for CAN and CAN FD message transmission when a change in data from one time step to the next is detected.

A configuration option available on the CAN and CAN FD Transmit blocks enables transmission on data change. When enabled, messages of particular CAN IDs transmit only when the data changes for that ID. Each message is independently processed in every time step based on its ID. When disabled, block operation and periodic transmit operation function normally. In addition, the event-based transmission can be enabled along with periodic transmission to have both work together simultaneously.

Prepare the Example Model

The included example model contains two CAN Pack blocks configured into a single CAN Transmit block. One message's data is a constant while the other is a counter that changes at every time step.

Open the example model.

open EventTransmit

Prepare the CAN Database File Access

You can access the contents of CAN DBC-files with the canDatabase function. Through this function, details about network nodes, messages, and signals are available. This DBC-file is used in the model and is used to decode information sent from the model.

db = canDatabase("CANBusEvent.dbc")
db = 
  Database with properties:

             Name: 'CANBusEvent'
             Path: 'C:\Users\jpyle\Documents\MATLAB\ExampleManager\jpyle.21bExampleBlitz\vnt-ex59902587\CANBusEvent.dbc'
            Nodes: {'ECU'}
         NodeInfo: [1×1 struct]
         Messages: {2×1 cell}
      MessageInfo: [2×1 struct]
       Attributes: {}
    AttributeInfo: [0×0 struct]
         UserData: []

A test node is defined in the DBC-file.

node = nodeInfo(db,"ECU")
node = struct with fields:
             Name: 'ECU'
          Comment: ''
       Attributes: {}
    AttributeInfo: [0×0 struct]

The node transmits two CAN messages.

messageInfo(db,"Constant_Msg")
ans = struct with fields:
             Name: 'Constant_Msg'
     ProtocolMode: 'CAN'
          Comment: ''
               ID: 10
         Extended: 0
            J1939: []
           Length: 4
              DLC: 4
              BRS: 0
          Signals: {'Constant'}
       SignalInfo: [1×1 struct]
          TxNodes: {'ECU'}
       Attributes: {}
    AttributeInfo: [0×0 struct]

messageInfo(db,"Counter_Msg")
ans = struct with fields:
             Name: 'Counter_Msg'
     ProtocolMode: 'CAN'
          Comment: ''
               ID: 20
         Extended: 0
            J1939: []
           Length: 4
              DLC: 4
              BRS: 0
          Signals: {'Counter'}
       SignalInfo: [1×1 struct]
          TxNodes: {'ECU'}
       Attributes: {}
    AttributeInfo: [0×0 struct]

Execute the Model with Event-Based Transmission

Enable Event-Based Transmission Only

Enable the event-based transmission in the CAN Transmit block programmatically. Also, disable periodic transmission.

db = canDatabase("CANBusEvent.dbc")
db = 
  Database with properties:

             Name: 'CANBusEvent'
             Path: 'C:\Users\jpyle\Documents\MATLAB\ExampleManager\jpyle.21bExampleBlitz\vnt-ex59902587\CANBusEvent.dbc'
            Nodes: {'ECU'}
         NodeInfo: [1×1 struct]
         Messages: {2×1 cell}
      MessageInfo: [2×1 struct]
       Attributes: {}
    AttributeInfo: [0×0 struct]
         UserData: []

set_param('EventTransmit/CAN Transmit', 'EnableEventTransmit', 'on');
set_param('EventTransmit/CAN Transmit', 'EnablePeriodicTransmit', 'off');

Note that the block display changes after applying the settings.

Configure a CAN Channel in MATLAB for Communication with the Model

Create a CAN channel using virtual device communication to interface with the Simulink model. Also, attach the CAN database to it to automatically decode incoming messages.

canCh = canChannel("Mathworks","Virtual 1",2)
canCh = 
  Channel with properties:

   Device Information
            DeviceVendor: 'MathWorks'
                  Device: 'Virtual 1'
      DeviceChannelIndex: 2
      DeviceSerialNumber: 0
            ProtocolMode: 'CAN'

   Status Information
                 Running: 0
       MessagesAvailable: 0
        MessagesReceived: 0
     MessagesTransmitted: 0
    InitializationAccess: 1
        InitialTimestamp: [0×0 datetime]
           FilterHistory: 'Standard ID Filter: Allow All | Extended ID Filter: Allow All'

   Channel Information
               BusStatus: 'N/A'
              SilentMode: 0
         TransceiverName: 'N/A'
        TransceiverState: 'N/A'
       ReceiveErrorCount: 0
      TransmitErrorCount: 0
                BusSpeed: 500000
                     SJW: []
                   TSEG1: []
                   TSEG2: []
            NumOfSamples: []

   Other Information
                Database: []
                UserData: []

canCh.Database = db;

Start the CAN channel to go online.

start(canCh);

Run the Model

Assign a simulation run time and start the model.

t = "10";
set_param("EventTransmit","StopTime",t)
set_param("EventTransmit","SimulationCommand","start");

Wait until the simulation starts.

while strcmp(get_param("EventTransmit","SimulationStatus"),"stopped")
end

Wait until the simulation ends.

pause(2)

Receive Messages in MATLAB

Receive all messages from the bus generated by the model.

msg = receive(canCh,inf,"OutputFormat","timetable")
msg=12×8 timetable
       Time       ID    Extended          Name              Data        Length      Signals       Error    Remote
    __________    __    ________    ________________    ____________    ______    ____________    _____    ______

    5.204 sec     10     false      {'Constant_Msg'}    {[ 5 0 0 0]}      4       {1×1 struct}    false    false 
    5.204 sec     20     false      {'Counter_Msg' }    {[ 0 0 0 0]}      4       {1×1 struct}    false    false 
    5.206 sec     20     false      {'Counter_Msg' }    {[ 1 0 0 0]}      4       {1×1 struct}    false    false 
    5.206 sec     20     false      {'Counter_Msg' }    {[ 2 0 0 0]}      4       {1×1 struct}    false    false 
    5.206 sec     20     false      {'Counter_Msg' }    {[ 3 0 0 0]}      4       {1×1 struct}    false    false 
    5.206 sec     20     false      {'Counter_Msg' }    {[ 4 0 0 0]}      4       {1×1 struct}    false    false 
    5.206 sec     20     false      {'Counter_Msg' }    {[ 5 0 0 0]}      4       {1×1 struct}    false    false 
    5.206 sec     20     false      {'Counter_Msg' }    {[ 6 0 0 0]}      4       {1×1 struct}    false    false 
    5.206 sec     20     false      {'Counter_Msg' }    {[ 7 0 0 0]}      4       {1×1 struct}    false    false 
    5.206 sec     20     false      {'Counter_Msg' }    {[ 8 0 0 0]}      4       {1×1 struct}    false    false 
    5.206 sec     20     false      {'Counter_Msg' }    {[ 9 0 0 0]}      4       {1×1 struct}    false    false 
    5.2061 sec    20     false      {'Counter_Msg' }    {[10 0 0 0]}      4       {1×1 struct}    false    false 

Stop the CAN channel in MATLAB.

stop(canCh);

Explore the Message and Signal Data Received

The number of times a CAN ID has been received is plotted below. The message "Constant_Msg" (CAN ID 10) is received only once because its data does not change after its initial setting. The message "Counter_Msg" (CAN ID 20) is received from every time step because the data changed continuously in it as the model ran.

% Define X and Y axis.
x = 1:length(msg.ID);
y = msg.ID;

% Plot the graph for both the CAN IDs received.
stem(x,y,'filled')
hold on;
yMax = max(msg.ID)+5;
ylim([0 yMax])

% Label the graph.
xlabel("Number of CAN messages");
ylabel("CAN ID");
legend("CAN ID","Location","northeast");
legend("boxoff");
hold off;

Next, plot the signals received in each message over the same simulation run.

% Create a structure with signal details.
signalTimeTable = canSignalTimetable(msg);

% Plot the signal values of "Constant_Msg".
x1 = 1:height(signalTimeTable.Constant_Msg);
y1 = signalTimeTable.Constant_Msg.Constant;
plot(x1, y1,"Marker","o");
hold on

% Plot the signal values of "Counter_Msg".
x2 = 1:height(signalTimeTable.Counter_Msg);
y2 = signalTimeTable.Counter_Msg.Counter;
plot(x2, y2,"Marker","o");

% Determine the maximum value for y-axis for scaling of graph.
y1Max = max(signalTimeTable.Constant_Msg.Constant);
y2Max = max(signalTimeTable.Counter_Msg.Counter);
yMax = max(y1Max,y2Max)+5;
ylim([0 yMax]);

% Label the graph.
xlabel("Number of Times Signals Received");
ylabel("CAN Signal Value");
legend("Constant","Counter","Location","northeastoutside");
legend("boxoff");
hold off

The signal "Constant" (in message "Constant_Msg") is plotted only once, while the signal "Counter" (in message "Counter_Msg") is plotted for every time step. This is due to event-based transmission being enabled in the CAN Transmit block, which transmits a CAN message only if data has changed for that CAN ID compared with the previously received message.

As the signal in message "Counter_Msg" is a counter, which increments by 1 at every time step, a linear curve can be seen for it.

Each data points represents a transmission with event-based transmission enabled, hence signal "Counter" is received at every time step, but signal "Constant" is received only once.

Execute the Model with Event-Based and Periodic Transmission

Enable Both Transmission Modes

Enable the event transmission in the CAN Transmit block programmatically. Also, enable the periodic transmission and set a message period.

set_param('EventTransmit/CAN Transmit', 'EnableEventTransmit', 'on');
set_param('EventTransmit/CAN Transmit', 'EnablePeriodicTransmit', 'on');
set_param('EventTransmit/CAN Transmit', 'MessagePeriod', '0.1');

Note that the block display changes after applying the settings.

Configure a CAN Channel in MATLAB for Communication with the Model

Create a CAN channel using virtual device communication to interface with the Simulink model. Also, attach the CAN database to it to automatically decode incoming messages.

canCh = canChannel("Mathworks","Virtual 1",2)
canCh = 
  Channel with properties:

   Device Information
            DeviceVendor: 'MathWorks'
                  Device: 'Virtual 1'
      DeviceChannelIndex: 2
      DeviceSerialNumber: 0
            ProtocolMode: 'CAN'

   Status Information
                 Running: 0
       MessagesAvailable: 0
        MessagesReceived: 0
     MessagesTransmitted: 0
    InitializationAccess: 1
        InitialTimestamp: [0×0 datetime]
           FilterHistory: 'Standard ID Filter: Allow All | Extended ID Filter: Allow All'

   Channel Information
               BusStatus: 'N/A'
              SilentMode: 0
         TransceiverName: 'N/A'
        TransceiverState: 'N/A'
       ReceiveErrorCount: 0
      TransmitErrorCount: 0
                BusSpeed: 500000
                     SJW: []
                   TSEG1: []
                   TSEG2: []
            NumOfSamples: []

   Other Information
                Database: []
                UserData: []

canCh.Database = db;

Start the CAN channel to go online.

start(canCh);

Run the Model

Assign a simulation run time and start the model.

t = "20";
set_param("EventTransmit","StopTime",t)
set_param("EventTransmit","SimulationCommand","start");

Wait until the simulation starts.

while strcmp(get_param("EventTransmit","SimulationStatus"),"stopped")
end

Wait until the simulation ends.

pause(5);

Receive Messages in MATLAB

Receive all messages from the bus generated by the model.

msg = receive(canCh,Inf,"OutputFormat","timetable")
msg=22×8 timetable
       Time       ID    Extended          Name              Data        Length      Signals       Error    Remote
    __________    __    ________    ________________    ____________    ______    ____________    _____    ______

    4.598 sec     10     false      {'Constant_Msg'}    {[ 5 0 0 0]}      4       {1×1 struct}    false    false 
    4.598 sec     20     false      {'Counter_Msg' }    {[ 0 0 0 0]}      4       {1×1 struct}    false    false 
    4.5987 sec    20     false      {'Counter_Msg' }    {[ 1 0 0 0]}      4       {1×1 struct}    false    false 
    4.5987 sec    20     false      {'Counter_Msg' }    {[ 2 0 0 0]}      4       {1×1 struct}    false    false 
    4.5987 sec    20     false      {'Counter_Msg' }    {[ 3 0 0 0]}      4       {1×1 struct}    false    false 
    4.5987 sec    20     false      {'Counter_Msg' }    {[ 4 0 0 0]}      4       {1×1 struct}    false    false 
    4.5987 sec    20     false      {'Counter_Msg' }    {[ 5 0 0 0]}      4       {1×1 struct}    false    false 
    4.5987 sec    20     false      {'Counter_Msg' }    {[ 6 0 0 0]}      4       {1×1 struct}    false    false 
    4.5987 sec    20     false      {'Counter_Msg' }    {[ 7 0 0 0]}      4       {1×1 struct}    false    false 
    4.5987 sec    20     false      {'Counter_Msg' }    {[ 8 0 0 0]}      4       {1×1 struct}    false    false 
    4.5988 sec    20     false      {'Counter_Msg' }    {[ 9 0 0 0]}      4       {1×1 struct}    false    false 
    4.5988 sec    20     false      {'Counter_Msg' }    {[10 0 0 0]}      4       {1×1 struct}    false    false 
    4.5988 sec    20     false      {'Counter_Msg' }    {[11 0 0 0]}      4       {1×1 struct}    false    false 
    4.5988 sec    20     false      {'Counter_Msg' }    {[12 0 0 0]}      4       {1×1 struct}    false    false 
    4.5988 sec    20     false      {'Counter_Msg' }    {[13 0 0 0]}      4       {1×1 struct}    false    false 
    4.5988 sec    20     false      {'Counter_Msg' }    {[14 0 0 0]}      4       {1×1 struct}    false    false 
      ⋮

Stop the CAN channel in MATLAB.

stop(canCh);

Explore the Data Received

Plot the data received in each message over the same period.

% Create a structure with signal details.
signalTimeTable = canSignalTimetable(msg);

% Plot the signal values of "Constant_Msg".
x3 = 1:height(signalTimeTable.Constant_Msg);
y3 = signalTimeTable.Constant_Msg.Constant;
plot(x3, y3,"Marker","o");
hold on

% Plot the signal values of "Counter_Msg".
x4 = 1:height(signalTimeTable.Counter_Msg);
y4 = signalTimeTable.Counter_Msg.Counter;
plot(x4, y4,"Marker","o");

% Determine the maximum value for y-axis for scaling of graph.
y3Max = max(signalTimeTable.Constant_Msg.Constant);
y4Max = max(signalTimeTable.Counter_Msg.Counter);
yMax = max(y3Max,y4Max)+5;
ylim([0 yMax]);

% Label the graph.
xlabel("Number of Times Signals Received");
ylabel("CAN Signal Value");
legend("Constant","Counter","Location","northeastoutside");
legend("boxoff");
hold off

The plot shows that the signal "Constant" in message "Constant_Msg" is received only a few times; once at the start due to the event-based transmission, and later due to the periodic nature of the transmission. This is because the input value to the signal is kept constant.

While the value for signal "Counter" changes at every time step in the message "Counter_Msg", it is received continuously due to the event-based transmission, and later there are a few more transmissions because periodic transmission is enabled.