Этот пример показывает вам, как создать, получить и обработать сообщения с помощью информации, хранившей в файлах базы данных 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