В этом примере показано, как создавать, получать и обрабатывать сообщения с помощью информации, хранящейся в файлах базы данных CAN. Этот пример использует файл базы данных CAN, demoVNT_CANdbFiles.dbc.
Откройте файл базы данных и исследуйте Messages свойство для просмотра имен всех сообщений, определенных в этой базе данных.
db = canDatabase('demoVNT_CANdbFiles.dbc')
db.Messages
db =
Database with properties:
Name: 'demoVNT_CANdbFiles'
Path: '/tmp/BR2021ad_1584584_202060/publish_examples0/tp21235eaf/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' }
Использование messageInfo для просмотра информации о сообщении, включая идентификатор, длину данных и список сигналов.
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]
Можно также запросить информацию сразу по всем сообщениям.
messageInfo(db)
ans =
5x1 struct array with fields:
Name
ProtocolMode
Comment
ID
Extended
J1939
Length
DLC
BRS
Signals
SignalInfo
TxNodes
Attributes
AttributeInfo
Использование signalInfo для просмотра информации об определении сигнала, включая тип, упорядоченное расположение байтов, размер и масштабирование значений, которые преобразуют необработанные сигналы в физические значения.
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]
Можно также запросить информацию обо всех сигналах в сообщении сразу.
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
Укажите имя сообщения при создании нового сообщения для применения определения базы данных. Сигналы CAN в этих сообщениях представлены в технических модулях в дополнение к байтам необработанных данных.
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: []
Используйте Signals свойство для просмотра значений сигналов для этого сообщения. Вы можете непосредственно записать и считать из этих сигналов, чтобы упаковать или распаковать данные из сообщения.
msgEngineInfo.Signals
ans =
struct with fields:
VehicleSpeed: 0
EngineRPM: 250
Запись непосредственно в сигнал, чтобы изменить значение и считать его текущее значение назад.
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
При записи непосредственно в сигнал значение переводится, масштабируется и упаковывается в данные сообщения с помощью определения базы данных.
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
Присоедините базу данных к каналу CAN, который получает сообщения для автоматического применения определений баз данных к входящим сообщениям. База данных декодирует только определенные сообщения. Все остальные сообщения поступают в необработанном виде.
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(rxCh); generateMsgsDb(); rxMsg = receive(rxCh, Inf, 'OutputFormat', 'timetable'); rxMsg(1:15, :)
ans =
15x8 timetable
Time ID Extended Name Data Length Signals Error Remote
____________ ___ ________ _____________________ ________________________ ______ ____________ _____ ______
0.038985 sec 100 false {'EngineMsg' } {[ 0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.038991 sec 200 false {'TransmissionMsg' } {[ 0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.038996 sec 400 false {'DoorControlMsg' } {[ 0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.038999 sec 600 false {'WindowControlMsg' } {[ 0 0 0 0]} 4 {1x1 struct} false false
0.039 sec 800 false {'SunroofControlMsg'} {[ 0 0]} 2 {1x1 struct} false false
0.063955 sec 100 false {'EngineMsg' } {[172 129 0 0 50 0 0 0]} 8 {1x1 struct} false false
0.088956 sec 100 false {'EngineMsg' } {[172 129 0 0 50 0 0 0]} 8 {1x1 struct} false false
0.088958 sec 200 false {'TransmissionMsg' } {[ 4 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.11396 sec 100 false {'EngineMsg' } {[172 129 0 0 50 0 0 0]} 8 {1x1 struct} false false
0.13898 sec 100 false {'EngineMsg' } {[172 129 0 0 50 0 0 0]} 8 {1x1 struct} false false
0.13898 sec 200 false {'TransmissionMsg' } {[ 4 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.16398 sec 100 false {'EngineMsg' } {[172 129 0 0 50 0 0 0]} 8 {1x1 struct} false false
0.16399 sec 400 false {'DoorControlMsg' } {[ 1 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.18896 sec 100 false {'EngineMsg' } {[177 131 0 0 55 0 0 0]} 8 {1x1 struct} false false
0.18896 sec 200 false {'TransmissionMsg' } {[ 4 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
Остановите канал и очистите его из рабочей области.
stop(rxCh);
clear rxCh
Смотрите полученное сообщение, чтобы увидеть примененное декодирование базы данных.
rxMsg(10, :)
rxMsg.Signals{10}
ans =
1x8 timetable
Time ID Extended Name Data Length Signals Error Remote
___________ ___ ________ _____________ ________________________ ______ ____________ _____ ______
0.13898 sec 100 false {'EngineMsg'} {[172 129 0 0 50 0 0 0]} 8 {1x1 struct} false false
ans =
struct with fields:
VehicleSpeed: 50
EngineRPM: 3.5696e+03
Используйте обозначение MATLAB, чтобы извлечь все образцы указанного сообщения по имени.
allMsgEngine = rxMsg(strcmpi('EngineMsg', rxMsg.Name), :);
allMsgEngine(1:15, :)
ans =
15x8 timetable
Time ID Extended Name Data Length Signals Error Remote
____________ ___ ________ _____________ ________________________ ______ ____________ _____ ______
0.038985 sec 100 false {'EngineMsg'} {[ 0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.063955 sec 100 false {'EngineMsg'} {[172 129 0 0 50 0 0 0]} 8 {1x1 struct} false false
0.088956 sec 100 false {'EngineMsg'} {[172 129 0 0 50 0 0 0]} 8 {1x1 struct} false false
0.11396 sec 100 false {'EngineMsg'} {[172 129 0 0 50 0 0 0]} 8 {1x1 struct} false false
0.13898 sec 100 false {'EngineMsg'} {[172 129 0 0 50 0 0 0]} 8 {1x1 struct} false false
0.16398 sec 100 false {'EngineMsg'} {[172 129 0 0 50 0 0 0]} 8 {1x1 struct} false false
0.18896 sec 100 false {'EngineMsg'} {[177 131 0 0 55 0 0 0]} 8 {1x1 struct} false false
0.21396 sec 100 false {'EngineMsg'} {[177 131 0 0 55 0 0 0]} 8 {1x1 struct} false false
0.23896 sec 100 false {'EngineMsg'} {[177 131 0 0 55 0 0 0]} 8 {1x1 struct} false false
0.26396 sec 100 false {'EngineMsg'} {[177 131 0 0 55 0 0 0]} 8 {1x1 struct} false false
0.28893 sec 100 false {'EngineMsg'} {[ 91 133 0 0 55 0 0 0]} 8 {1x1 struct} false false
0.31396 sec 100 false {'EngineMsg'} {[ 91 133 0 0 55 0 0 0]} 8 {1x1 struct} false false
0.33897 sec 100 false {'EngineMsg'} {[ 91 133 0 0 55 0 0 0]} 8 {1x1 struct} false false
0.36396 sec 100 false {'EngineMsg'} {[ 91 133 0 0 55 0 0 0]} 8 {1x1 struct} false false
0.38896 sec 100 false {'EngineMsg'} {[201 130 0 0 54 0 0 0]} 8 {1x1 struct} false false
Постройте график значений декодированных сигналов базы данных с течением времени. Ссылка на временные метки сообщения и значений сигналов в переменных.
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.038985 sec 0 250
0.063955 sec 50 3569.6
0.088956 sec 50 3569.6
0.11396 sec 50 3569.6
0.13898 sec 50 3569.6
0.16398 sec 50 3569.6
0.18896 sec 55 3621.3
0.21396 sec 55 3621.3
0.23896 sec 55 3621.3
0.26396 sec 55 3621.3
0.28893 sec 55 3663.9
0.31396 sec 55 3663.9
0.33897 sec 55 3663.9
0.36396 sec 55 3663.9
0.38896 sec 54 3598.1
