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)
Accelerator Pedal Position, OBD-II PID = 73 (dec) , 49 (hex)
Vehicle Speed, OBD-II PID = 13 (dec), 0D (hex)
Multiplexor Signal
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
plot(Vehicle_Speed);
title("Vehicle Speed");
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
plot(Vehicle_Speed_Demultiplexed.Time, Vehicle_Speed_Demultiplexed.Vehicle_Speed)
title("Vehicle Speed - Demultiplexed");
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.