Main Content

Multiplexing and Demultiplexing of CAN Messages

Introduction

This example shows how to apply multiplexing and demultiplexing to CAN messages.

Multiplexing is a method used in CAN bus communication to increase the number of transmitted signals, at the cost of reducing the effective sample rate of each signal.

Multiplexed signals belong to the same CAN frame, but may have overlapping bit layouts. The interpretation of the bit pattern is conditional, and it depends on the value of another signal, called multiplexor.

Consider, as an example, the following sequence of a multiplexed OBD-II (On-Board Diagnostics) frame, as retrieved using the CAN Explorer App:

The interpretation of the first two data bytes depends on the value of the third byte, which corresponds to the OBD-II PID.

Specifically, the frame carries three different signals, with overlapping bit layout, as shown in the following figures.

Engine Torque, OBD-II PID = 98 (dec), 62 (hex)

Engine_Torque_bit_layout_diagram.jpg

Accelerator Pedal Position, OBD-II PID = 73 (dec) , 49 (hex)

Accelerator_bit_layout_diagram.jpg

Vehicle Speed, OBD-II PID = 13 (dec), 0D (hex)

VehicleSpeed_bit_layout_diagram.jpg

Multiplexor Signal

Multiplexor_bit_layout_diagram.jpg

Note that the multiplexor signal has a bit layout that does not overlap with the other three signals.

In the following sections, actual recorded signals will be multiplexed and transmitted using a Simulink® model.

The CAN frames are then received in the CAN Explorer App, and eventually demultiplexed with a few lines of MATLAB® code.

Multiplexing and Transmission in Simulink

Recorded signals for the actual engine percent torque, the accelerator pedal position and the vehicle speed are available in the a MAT file, in the form of timeseries. Data has been recorded from 0 to 25 seconds.

load("Logged_OBD2_Data.mat");

It is interesting to inspect the recorded signals; in particular, as shown in the following, the engine torque is negative when the accelerator position goes to 0. This is a common situation known as engine braking, and indeed the vehicle speed decreases accordingly.

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.

This data is input to the following Simulink model via From Workspace blocks.

The CAN Pack block is configured as follows, based on the DBC file CAN_OBD2_Multiplexed.dbc. The file contains the definition of a single multiplexed CAN frame, with one multiplexor named OBD2Mode.

The input signals are fed into a Multiplexer block, which is implemented with a Stateflow® Chart. This is a particularly convenient approach for time-based multiplexing.

This state machine encompasses three mutually exclusive states. When the state Transmit_Engine_Torque is active, the engine torque signal as well as its corresponding OBD-II PID are transmitted, while the other two signals are set to zero. A similar logic applies to the other two states, namely, Transmit_Accelerator and Transmit_Vehicle_Speed.

Switching between states follows a time-based logic: the Transmit_Engine_Torque is active for two simulation time steps, the Transmit_Accelerator state for 1 time step, and the Transmit_Vehicle_Speed state is active for 3 time steps, before transitioning to the first state. The tick keyword in stateflow refers to an activation of the diagram at each time step, as triggered by the Simulink solver.

The following parameters are used to control the simulation of the Simulink model. Simulation pacing, to achieve near wall-clock time execution, is enabled.

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

After running the simulation, it is interesting to inspect the multiplexed signals, as well as the multiplexor.

The multiplexor periodically switches between the values of 98, 73 and 13, corresponding to the OBD-II PIDs of the three signals.

This graph conveys the notion that multiplexing effectively introduces a downsampling of the original time series, as shown by the comparison between the original and multiplexed velocity signal. Note that, even though the values of the signals are artificially set to zero depending on the OBD-II PID, there is not introduction of new information: the multiplexed signal cannot be interpreted 'as is', it needs to be demultiplexed before being used downstream.

Reception and Demultiplexing in MATLAB

Open and configure the CAN Explorer App to receive the messages on the MathWorks Virtual Channel 1. Then, run the Simulink model to receive the messages, and export them to a MATLAB workspace variable. In this example, the variable is called canExplorerMsgs, and it is available in the canExplorerMsgs.mat file.

Create a CAN database object for the file CAN_OBD2_Multiplexed.dbc. Decode the messages using the database object and the canMessageTimetable and canSignalTimetable functions.

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     
      ⋮

The functions treat each signal independently, so they do not apply demultiplexing. The signals in the sigsTT timetable need to be extracted according to the value of the multiplexor, i.e. the OBD2Mode signal. To that end, logical indexing can be applied as follows.

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.

Note that the signals are effectively downsampled, and that the initial time is different from that of the simulation, due to the delay introduced by the user between starting the CAN Explorer App and starting the Simulink simulation. The time range of about 25 seconds is, however, coherent with the simulation time range, due to simulation pacing.