%% Use DBC-Files in CAN Communication
% This example shows you how to create, receive and process messages using information stored in DBC-files. This example describes the workflow for a CAN network, but the concept demonstrated also applies to a CAN FD network.
%
%% Open the DBC-File
% Open file demoVNT_CANdbFiles.dbc using canDatabase.

db = canDatabase("demoVNT_CANdbFiles.dbc")

% Examine the Messages property to see the names of all messages defined in this file.

db.Messages

%
%% View Message Information
% Use messageInfo to view information for message EngineMsg, including the identifier, data length, and a signal list.

messageInfo(db, "EngineMsg")

% You can also query for information on all messages at once.

messageInfo(db)

%
%% View Signal Information
% Use signalInfo to view information for signal EngineRPM in message EngineMsg, including type, byte ordering, size, and scaling values that translate raw signals to physical values.

signalInfo(db, "EngineMsg", "EngineRPM")

% You can also query for information on all signals in message EngineMsg at once.

signalInfo(db, "EngineMsg")

%
%% Create a Message Using Database Definitions
% Create a new message by specifying the database and the message name EngineMsg to have the database definition applied. CAN signals in this message are represented in engineering units in addition to the raw data bytes.

msgEngineInfo = canMessage(db, "EngineMsg")

%
%% View Signal Information
% Use the Signals property to see signal values for this message. You can directly write to and read from these signals to pack and unpack data from the message.

msgEngineInfo.Signals

%
%% Change Signal Information
% Write directly to the signal EngineRPM to change its value.

msgEngineInfo.Signals.EngineRPM = 5500.25

% Read the current signal values back and note that EngineRPM has been updated with the written value.

msgEngineInfo.Signals

% When a value is written directly to the signal, it is translated, scaled, and packed into the message data using the database definition. Note the value change in the Data property after a new value is written to the VehicleSpeed signal.

msgEngineInfo.Signals.VehicleSpeed = 70.81
msgEngineInfo.Signals

%
%% Receive Messages with Database Information
% Attach a database to a CAN channel that receives messages to apply database definitions to incoming messages automatically. The database decodes only messages that are defined. All other messages are received in their raw form.

rxCh = canChannel("MathWorks", "Virtual 1", 2);
rxCh.Database = db

%
%% Receive Messages
% Start the channel, generate some message traffic, and receive messages with physical message decoding.

start(rxCh);
generateMsgsDb();
rxMsg = receive(rxCh, Inf, "OutputFormat", "timetable");

% View the first few rows of received messages.

head(rxMsg)

% Stop the receiving channel and clear it from the workspace.

stop(rxCh);
clear rxCh

%
%% Examine a Received Message
% Inspect a received message to see the applied database decoding.

rxMsg(10, :)
rxMsg.Signals{10}

%
%% Extract All Instances of a Specified Message
% Extract all instances of message EngineMsg.

allMsgEngine = rxMsg(strcmpi("EngineMsg", rxMsg.Name), :);

% View the first few instances of this specific message.

head(allMsgEngine)

%
%% Plot Physical Signal Values
% Use canSignalTimetable to repackage signal data from message EngineMsg into a signal timetable.

signalTimetable = canSignalTimetable(rxMsg, "EngineMsg");

% View the first few rows of the signal timetable.

head(signalTimetable)

% Plot the values of signal VehicleSpeed over time.

plot(signalTimetable.Time, signalTimetable.VehicleSpeed)
title("Vehicle Speed from EngineMsg", "FontWeight", "bold")
xlabel("Timestamp")
ylabel("Vehicle Speed")

%
%% Close the DBC-File
% Close access to the DBC-file by clearing its variable from the workspace.

clear db

%
% Copyright 2008-2021 The MathWorks, Inc.