This example shows you how to create, receive and process messages using information stored in CAN database files. This example uses the CAN database file, demoVNT_CANdbFiles.dbc
.
Open the database file and examine the Messages
property to see the names of all message defined in this database.
db = canDatabase('demoVNT_CANdbFiles.dbc')
db.Messages
db = Database with properties: Name: 'demoVNT_CANdbFiles' Path: '/tmp/Bdoc20b_1465442_260350/tpd1cb374b/ex80654288/demoVNT_CANdbFiles.dbc' Nodes: {} NodeInfo: [0x0 struct] Messages: {5x1 cell} MessageInfo: [5x1 struct] Attributes: {} AttributeInfo: [0x0 struct] UserData: [] ans = 5x1 cell array {'DoorControlMsg' } {'EngineMsg' } {'SunroofControlMsg'} {'TransmissionMsg' } {'WindowControlMsg' }
Use messageInfo
to view message information, including the identifier, data length, and a signal list.
messageInfo(db, 'EngineMsg')
ans = struct with fields: Name: 'EngineMsg' ProtocolMode: 'CAN' Comment: '' ID: 100 Extended: 0 J1939: [] Length: 8 DLC: 8 BRS: 0 Signals: {2x1 cell} SignalInfo: [2x1 struct] TxNodes: {0x1 cell} Attributes: {} AttributeInfo: [0x0 struct]
You can also query for information on all messages at once.
messageInfo(db)
ans = 5x1 struct array with fields: Name ProtocolMode Comment ID Extended J1939 Length DLC BRS Signals SignalInfo TxNodes Attributes AttributeInfo
Use signalInfo
to view signal definition information, including type, byte ordering, size, and scaling values that translate raw signals to physical values.
signalInfo(db, 'EngineMsg', 'EngineRPM')
ans = struct with fields: Name: 'EngineRPM' Comment: '' StartBit: 0 SignalSize: 32 ByteOrder: 'LittleEndian' Signed: 0 ValueType: 'Integer' Class: 'uint32' Factor: 0.1000 Offset: 250 Minimum: 250 Maximum: 9500 Units: 'rpm' ValueTable: [0x1 struct] Multiplexor: 0 Multiplexed: 0 MultiplexMode: 0 RxNodes: {0x1 cell} Attributes: {} AttributeInfo: [0x0 struct]
You can also query for information on all signals in the message at once.
signalInfo(db, 'EngineMsg')
ans = 2x1 struct array with fields: Name Comment StartBit SignalSize ByteOrder Signed ValueType Class Factor Offset Minimum Maximum Units ValueTable Multiplexor Multiplexed MultiplexMode RxNodes Attributes AttributeInfo
Specify the name of the message when you create a new message to have the database definition applied. CAN signals in this messages are represented in engineering units in addition to the raw data bytes.
msgEngineInfo = canMessage(db, 'EngineMsg')
msgEngineInfo = Message with properties: Message Identification ProtocolMode: 'CAN' ID: 100 Extended: 0 Name: 'EngineMsg' Data Details Timestamp: 0 Data: [0 0 0 0 0 0 0 0] Signals: [1x1 struct] Length: 8 Protocol Flags Error: 0 Remote: 0 Other Information Database: [1x1 can.Database] UserData: []
Use the Signals
property to see signal values for this message. You can directly write to and read from these signals to pack or unpack data from the message.
msgEngineInfo.Signals
ans = struct with fields: VehicleSpeed: 0 EngineRPM: 250
Write directly to the signal to change a value and read its current value back.
msgEngineInfo.Signals.EngineRPM = 5500.25 msgEngineInfo.Signals
msgEngineInfo = Message with properties: Message Identification ProtocolMode: 'CAN' ID: 100 Extended: 0 Name: 'EngineMsg' Data Details Timestamp: 0 Data: [23 205 0 0 0 0 0 0] Signals: [1x1 struct] Length: 8 Protocol Flags Error: 0 Remote: 0 Other Information Database: [1x1 can.Database] UserData: [] ans = struct with fields: VehicleSpeed: 0 EngineRPM: 5.5003e+03
When you write directly to the signal, the value is translated, scaled, and packed into the message data using the database definition.
msgEngineInfo.Signals.VehicleSpeed = 70.81 msgEngineInfo.Signals
msgEngineInfo = Message with properties: Message Identification ProtocolMode: 'CAN' ID: 100 Extended: 0 Name: 'EngineMsg' Data Details Timestamp: 0 Data: [23 205 0 0 71 0 0 0] Signals: [1x1 struct] Length: 8 Protocol Flags Error: 0 Remote: 0 Other Information Database: [1x1 can.Database] UserData: [] ans = struct with fields: VehicleSpeed: 71 EngineRPM: 5.5003e+03
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
rxCh = 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: [0x0 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: [1x1 can.Database] UserData: []
Start the channel, generate some message traffic and receive messages with physical message decoding.
start(rxCh); generateMsgsDb(); rxMsg = receive(rxCh, Inf, 'OutputFormat', 'timetable'); rxMsg(1:15, :)
ans = 15x8 timetable Time ID Extended Name Data Length Signals Error Remote _____________ ___ ________ _____________________ ___________ ______ ____________ _____ ______ 0.0044775 sec 100 false {'EngineMsg' } {1x8 uint8} 8 {1x1 struct} false false 0.0045086 sec 200 false {'TransmissionMsg' } {1x8 uint8} 8 {1x1 struct} false false 0.0045279 sec 400 false {'DoorControlMsg' } {1x8 uint8} 8 {1x1 struct} false false 0.0045373 sec 600 false {'WindowControlMsg' } {1x4 uint8} 4 {1x1 struct} false false 0.0045425 sec 800 false {'SunroofControlMsg'} {1x2 uint8} 2 {1x1 struct} false false 0.029506 sec 100 false {'EngineMsg' } {1x8 uint8} 8 {1x1 struct} false false 0.054494 sec 100 false {'EngineMsg' } {1x8 uint8} 8 {1x1 struct} false false 0.0545 sec 200 false {'TransmissionMsg' } {1x8 uint8} 8 {1x1 struct} false false 0.079461 sec 100 false {'EngineMsg' } {1x8 uint8} 8 {1x1 struct} false false 0.1045 sec 100 false {'EngineMsg' } {1x8 uint8} 8 {1x1 struct} false false 0.10451 sec 200 false {'TransmissionMsg' } {1x8 uint8} 8 {1x1 struct} false false 0.1295 sec 100 false {'EngineMsg' } {1x8 uint8} 8 {1x1 struct} false false 0.12951 sec 400 false {'DoorControlMsg' } {1x8 uint8} 8 {1x1 struct} false false 0.15446 sec 100 false {'EngineMsg' } {1x8 uint8} 8 {1x1 struct} false false 0.15447 sec 200 false {'TransmissionMsg' } {1x8 uint8} 8 {1x1 struct} false false
Stop the channel and clear it from the workspace.
stop(rxCh);
clear rxCh
Inspect a received message to see the applied database decoding.
rxMsg(10, :) rxMsg.Signals{10}
ans = 1x8 timetable Time ID Extended Name Data Length Signals Error Remote __________ ___ ________ _____________ ___________ ______ ____________ _____ ______ 0.1045 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false ans = struct with fields: VehicleSpeed: 50 EngineRPM: 3.5696e+03
Use MATLAB notation to extract all instances of a specified message by name.
allMsgEngine = rxMsg(strcmpi('EngineMsg', rxMsg.Name), :);
allMsgEngine(1:15, :)
ans = 15x8 timetable Time ID Extended Name Data Length Signals Error Remote _____________ ___ ________ _____________ ___________ ______ ____________ _____ ______ 0.0044775 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false 0.029506 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false 0.054494 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false 0.079461 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false 0.1045 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false 0.1295 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false 0.15446 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false 0.17947 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false 0.20447 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false 0.2295 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false 0.25451 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false 0.27943 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false 0.30447 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false 0.32949 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false 0.35453 sec 100 false {'EngineMsg'} {1x8 uint8} 8 {1x1 struct} false false
Plot the values of database decoded signals over time. Reference the message timestamps and the signal values in variables.
signalTimetable = canSignalTimetable(rxMsg, 'EngineMsg'); signalTimetable(1:15, :) plot(signalTimetable.Time, signalTimetable.VehicleSpeed) title('Vehicle Speed from EngineMsg', 'FontWeight', 'bold') xlabel('Timestamp') ylabel('Vehicle Speed')
ans = 15x2 timetable Time VehicleSpeed EngineRPM _____________ ____________ _________ 0.0044775 sec 0 250 0.029506 sec 50 3569.6 0.054494 sec 50 3569.6 0.079461 sec 50 3569.6 0.1045 sec 50 3569.6 0.1295 sec 50 3569.6 0.15446 sec 55 3621.3 0.17947 sec 55 3621.3 0.20447 sec 55 3621.3 0.2295 sec 55 3621.3 0.25451 sec 55 3663.9 0.27943 sec 55 3663.9 0.30447 sec 55 3663.9 0.32949 sec 55 3663.9 0.35453 sec 55 3663.9