Этот пример показывает вам, как импортировать и декодировать данные о CAN из MDF-файлов в MATLAB для анализа. MDF-файл, используемый в этом примере, был сгенерирован от Векторного CANoe™ с помощью "CAN - Общая Конфигурация системы (CAN)" выборка. Этот пример также использует файл базы данных CAN, PowerTrain.dbc
, предоставленный Векторную демонстрационную настройку.
Открытый доступ к MDF-файлу с помощью mdf
функция.
m = mdf("Logging_MDF.mf4")
m = MDF with properties: File Details Name: 'Logging_MDF.mf4' Path: '/tmp/BR2021ad_1655202_62692/mlx_to_docbook1/tp4da62608/vnt-ex42187575/Logging_MDF.mf4' Author: '' Department: '' Project: '' Subject: '' Comment: '' Version: '4.10' DataSize: 1542223 InitialTimestamp: 2020-06-25 20:41:13.133000000 Creator Details ProgramIdentifier: 'MDF4Lib' Creator: [1x1 struct] File Contents Attachment: [5x1 struct] ChannelNames: {62x1 cell} ChannelGroup: [1x62 struct] Options Conversion: Numeric
Согласно сопоставленному стандарту ASAM MDF для логгирования шины, типы событий, заданные для системы шины CAN, могут быть "CAN_DataFrame", "CAN_RemoteFrame", "CAN_ErrorFrame" или "CAN_OverloadFrame". Это особое внимание в качестве примера при извлечении систем координат данных о CAN, таким образом, стандарт логгирования шины будет обсужден с помощью типа события "CAN_DataFrame" в качестве примера. Кроме того, обратите внимание, что стандартная система координат данных о CAN имеет до 8 байтов для своей полезной нагрузки и используется, чтобы передать значения сигналов.
Стандарт указывает, что названия канала структуры события должны быть снабжены префиксом именем типа события, например, "CAN_DataFrame". Обычно точка используется в качестве символа разделителя, чтобы задать каналы члена, например, "CAN_DataFrame.ID" или "CAN_DataFrame.DataLength".
Используйте channelList
функционируйте, чтобы отфильтровать на названиях канала, точно совпадающих с "CAN_DataFrame". Таблица с информацией о совпадающих каналах возвращена.
channelList(m, "CAN_DataFrame", "ExactMatch", true)
ans=2×9 table
ChannelName ChannelGroupNumber ChannelGroupNumSamples ChannelGroupAcquisitionName ChannelGroupComment ChannelDisplayName ChannelUnit ChannelComment ChannelDescription
_______________ __________________ ______________________ ___________________________ ___________________ __________________ ___________ ______________ __________________
"CAN_DataFrame" 17 8889 CAN1 <undefined> "" <undefined> bus event data "bus event data"
"CAN_DataFrame" 29 7648 CAN2 <undefined> "" <undefined> bus event data "bus event data"
powetrain данные интереса регистрировались от сети CAN 2. channelList
выведите выше показов, что данные из сети CAN 2 хранились в группе 29 канала MDF-файла. Посмотрите детали группы канала с помощью ChannelGroup
свойство.
m.ChannelGroup(29)
ans = struct with fields:
AcquisitionName: 'CAN2'
Comment: ''
NumSamples: 7648
DataSize: 206496
Sorted: 1
Channel: [14x1 struct]
В группе канала хранятся детали о каждом канале. Посмотрите детали о канале 2 в группе 29 канала.
m.ChannelGroup(29).Channel(2)
ans = struct with fields:
Name: 'CAN_DataFrame.Flags'
DisplayName: 'Flags'
ExtendedNamePrefix: 'CAN2'
Description: 'Combination of bit flags for the message.'
Comment: 'Combination of bit flags for the message.'
Unit: ''
Type: FixedLength
DataType: IntegerUnsignedLittleEndian
NumBits: 8
ComponentType: StructureMember
CompositionType: None
ConversionType: None
Считывайте все данные от всех каналов в группе 29 канала в расписание с помощью read
функция. Расписание структурировано, чтобы следовать стандарту ASAM MDF логгирование формата. Каждая строка представляет одну необработанную систему координат CAN от шины, в то время как каждый столбец представляет канал в заданной группе канала. Каналы, такие как "CAN_DataFrame.Dir", называют, чтобы следовать стандарту логгирования шины. Однако, потому что имена столбцов расписания должны быть допустимыми именами переменной MATLAB, они не могут быть идентичны названиям канала. Большинство неподдерживаемых символов преобразовано в символы нижнего подчеркивания. С тех пор"." не поддерживается на имя переменной MATLAB, "CAN_DataFrame.Dir" изменен к "CAN_DataFrame_Dir" в таблице.
canData = read(m, 29, m.ChannelNames{29})
canData=7648×14 timetable
Time CAN_DataFrame_BusChannel CAN_DataFrame_Flags CAN_DataFrame_Dir CAN_DataFrame_SingleWire CAN_DataFrame_WakeUp CAN_DataFrame_ID CAN_DataFrame_IDE CAN_DataFrame_FrameDuration CAN_DataFrame_BitCount CAN_DataFrame_DLC CAN_DataFrame_DataLength CAN_DataFrame_DataBytes CAN_DataFrame t
__________ ________________________ ___________________ _________________ ________________________ ____________________ ________________ _________________ ___________________________ ______________________ _________________ ________________________ ______________________________ ____________________________________________________________ ______
2.2601 sec 2 1 1 0 0 103 0 128000 67 2 2 {[ 1 0]} {[ 1 2 103 0 0 0 1 0 0 0 8 0 0 0 0 244 1 0 67]} 2.2601
2.2801 sec 2 1 1 0 0 103 0 128000 67 2 2 {[ 1 0]} {[ 1 2 103 0 0 0 1 0 0 0 6 0 0 0 0 244 1 0 67]} 2.2801
2.3002 sec 2 1 1 0 0 100 0 232000 119 8 8 {[ 238 2 25 1 0 0 238 2]} {[ 1 8 100 0 0 0 238 2 25 1 0 0 238 2 64 138 3 0 119]} 2.3002
2.3005 sec 2 1 1 0 0 102 0 240000 123 8 8 {[ 0 128 59 68 0 0 0 0]} {[ 1 8 102 0 0 0 0 128 59 68 0 0 0 0 128 169 3 0 123]} 2.3005
2.3006 sec 2 1 1 0 0 103 0 128000 67 2 2 {[ 1 0]} {[ 1 2 103 0 0 0 1 0 0 0 6 0 0 0 0 244 1 0 67]} 2.3006
2.3008 sec 2 1 1 0 0 201 0 196000 101 6 6 {[ 0 0 0 0 172 38]} {[ 1 6 201 0 0 0 0 0 0 0 172 38 0 0 160 253 2 0 101]} 2.3008
2.3009 sec 2 1 1 0 0 1020 0 110000 58 1 1 {[ 1]} {[ 1 1 252 3 0 0 1 0 0 0 8 0 0 0 176 173 1 0 58]} 2.3009
2.3201 sec 2 1 1 0 0 103 0 128000 67 2 2 {[ 1 0]} {[ 1 2 103 0 0 0 1 0 0 0 6 0 0 0 0 244 1 0 67]} 2.3201
2.3401 sec 2 1 1 0 0 103 0 128000 67 2 2 {[ 1 0]} {[ 1 2 103 0 0 0 1 0 0 0 6 0 0 0 0 244 1 0 67]} 2.3401
2.3502 sec 2 1 1 0 0 100 0 234000 120 8 8 {[ 4 0 25 2 119 1 238 2]} {[ 1 8 100 0 0 0 4 0 25 2 119 1 238 2 16 146 3 0 120]} 2.3502
2.3505 sec 2 1 1 0 0 102 0 228000 117 8 8 {[53 127 119 64 0 128 187 67]} {[1 8 102 0 0 0 53 127 119 64 0 128 187 67 160 122 3 0 117]} 2.3505
2.3507 sec 2 1 1 0 0 201 0 198000 102 6 6 {[ 0 0 0 0 35 40]} {[ 1 6 201 0 0 0 0 0 0 0 35 40 0 0 112 5 3 0 102]} 2.3507
2.3508 sec 2 1 1 0 0 1020 0 110000 58 1 1 {[ 1]} {[ 1 1 252 3 0 0 1 0 0 0 9 0 0 0 176 173 1 0 58]} 2.3508
2.3601 sec 2 1 1 0 0 103 0 128000 67 2 2 {[ 1 0]} {[ 1 2 103 0 0 0 1 0 0 0 9 0 0 0 0 244 1 0 67]} 2.3601
2.3801 sec 2 1 1 0 0 103 0 128000 67 2 2 {[ 1 0]} {[ 1 2 103 0 0 0 1 0 0 0 6 0 0 0 0 244 1 0 67]} 2.3801
2.4002 sec 2 1 1 0 0 100 0 234000 120 8 8 {[ 10 0 25 3 119 1 238 2]} {[ 1 8 100 0 0 0 10 0 25 3 119 1 238 2 16 146 3 0 120]} 2.4002
⋮
Откройте файл базы данных с помощью canDatabase
функция.
canDB = canDatabase("PowerTrain_MDF.dbc")
canDB = Database with properties: Name: 'PowerTrain_MDF' Path: '/tmp/BR2021ad_1655202_62692/mlx_to_docbook1/tp4da62608/vnt-ex42187575/PowerTrain_MDF.dbc' Nodes: {2x1 cell} NodeInfo: [2x1 struct] Messages: {12x1 cell} MessageInfo: [12x1 struct] Attributes: {11x1 cell} AttributeInfo: [11x1 struct] UserData: []
canMessageTimetable
функционируйте использует базу данных, чтобы декодировать имена сообщения и сигналы. Расписание стандартных данных о формате регистрации ASAM преобразовано в расписание сообщения CAN Vehicle Network Toolbox™.
msgTimetable = canMessageTimetable(canData, canDB)
msgTimetable=7648×8 timetable
Time ID Extended Name Data Length Signals Error Remote
__________ ____ ________ __________________ ______________________________ ______ ____________ _____ ______
2.2601 sec 103 false {'Ignition_Info' } {[ 1 0]} 2 {1x1 struct} false false
2.2801 sec 103 false {'Ignition_Info' } {[ 1 0]} 2 {1x1 struct} false false
2.3002 sec 100 false {'EngineData' } {[ 238 2 25 1 0 0 238 2]} 8 {1x1 struct} false false
2.3005 sec 102 false {'EngineDataIEEE'} {[ 0 128 59 68 0 0 0 0]} 8 {1x1 struct} false false
2.3006 sec 103 false {'Ignition_Info' } {[ 1 0]} 2 {1x1 struct} false false
2.3008 sec 201 false {'ABSdata' } {[ 0 0 0 0 172 38]} 6 {1x1 struct} false false
2.3009 sec 1020 false {'GearBoxInfo' } {[ 1]} 1 {1x1 struct} false false
2.3201 sec 103 false {'Ignition_Info' } {[ 1 0]} 2 {1x1 struct} false false
2.3401 sec 103 false {'Ignition_Info' } {[ 1 0]} 2 {1x1 struct} false false
2.3502 sec 100 false {'EngineData' } {[ 4 0 25 2 119 1 238 2]} 8 {1x1 struct} false false
2.3505 sec 102 false {'EngineDataIEEE'} {[53 127 119 64 0 128 187 67]} 8 {1x1 struct} false false
2.3507 sec 201 false {'ABSdata' } {[ 0 0 0 0 35 40]} 6 {1x1 struct} false false
2.3508 sec 1020 false {'GearBoxInfo' } {[ 1]} 1 {1x1 struct} false false
2.3601 sec 103 false {'Ignition_Info' } {[ 1 0]} 2 {1x1 struct} false false
2.3801 sec 103 false {'Ignition_Info' } {[ 1 0]} 2 {1x1 struct} false false
2.4002 sec 100 false {'EngineData' } {[ 10 0 25 3 119 1 238 2]} 8 {1x1 struct} false false
⋮
Просмотрите сигналы, сохраненные в сообщении "EngineData".
msgTimetable.Signals{3}
ans = struct with fields:
PetrolLevel: 1
EngPower: 7.5000
EngForce: 0
IdleRunning: 0
EngTemp: 0
EngSpeed: 750
Используйте canSignalTimetable
функционируйте, чтобы повторно группировать данные сигнала из каждого уникального сообщения на шине в расписание сигнала. Этот пример создает три отдельных расписания сигнала для трех сообщений интереса, "ABSdata", "EngineData" и "GearBoxInfo", из расписания сообщения CAN.
signalTimetable1 = canSignalTimetable(msgTimetable, "ABSdata")
signalTimetable1=1147×4 timetable
Time AccelerationForce Diagnostics GearLock CarSpeed
__________ _________________ ___________ ________ ________
2.3008 sec -100 0 0 0
2.3507 sec 275 0 0 0
2.4008 sec 275 0 0 0
2.4507 sec 275 0 0 0
2.5008 sec 275 0 0 0
2.5507 sec 275 0 0 0
2.6008 sec 275 0 0 0
2.6507 sec 275 0 0 0
2.7008 sec 350 0 0 0
2.7507 sec 425 0 0 0.5
2.8008 sec 425 0 0 0.5
2.8507 sec 500 0 0 0.5
2.9008 sec 575 0 0 0.5
2.9507 sec 575 0 0 0.5
3.0008 sec 650 0 0 0.5
3.0507 sec 725 0 0 0.5
⋮
signalTimetable2 = canSignalTimetable(msgTimetable, "EngineData")
signalTimetable2=1147×6 timetable
Time PetrolLevel EngPower EngForce IdleRunning EngTemp EngSpeed
__________ ___________ ________ ________ ___________ _______ ________
2.3002 sec 1 7.5 0 0 0 750
2.3502 sec 2 7.5 375 0 0 4
2.4002 sec 3 7.5 375 0 0 10
2.4502 sec 4 7.5 375 0 0 17
2.5002 sec 5 7.5 375 0 0 23
2.5502 sec 6 7.5 375 0 0 30
2.6002 sec 7 7.5 375 0 0 36
2.6502 sec 8 7.5 375 0 0 43
2.7002 sec 9 9 450 0 0 50
2.7502 sec 10 10.5 525 0 0 59
2.8002 sec 10 10.5 525 0 0 69
2.8502 sec 11 12 600 0 0 80
2.9002 sec 11 13.5 675 0 0 92
2.9502 sec 12 13.5 675 0 0 106
3.0002 sec 13 15 750 0 0 121
3.0502 sec 13 16.5 825 0 0 136
⋮
signalTimetable3 = canSignalTimetable(msgTimetable, "GearBoxInfo")
signalTimetable3=1147×3 timetable
Time EcoMode ShiftRequest Gear
__________ _______ ____________ ____
2.3009 sec 0 0 1
2.3508 sec 0 0 1
2.4009 sec 0 0 1
2.4508 sec 0 0 1
2.5009 sec 0 0 1
2.5508 sec 0 0 1
2.6009 sec 0 0 1
2.6508 sec 0 0 1
2.7009 sec 0 0 1
2.7508 sec 0 0 1
2.8009 sec 0 0 1
2.8508 sec 0 0 1
2.9009 sec 0 0 1
2.9508 sec 0 0 1
3.0009 sec 0 0 1
3.0508 sec 0 0 1
⋮
Чтобы визуализировать сигналы интереса, столбцы из расписаний сигнала могут строиться в зависимости от времени для последующего анализа.
subplot(3, 1, 1) plot(signalTimetable1.Time, signalTimetable1.CarSpeed, 'r') title('{\itCarSpeed} Signal from {\itABSdata} Message', 'FontWeight', 'bold') xlabel('Timestamp') ylabel('Car Speed') subplot(3, 1, 2) plot(signalTimetable2.Time, signalTimetable2.EngSpeed, 'b') title('{\itEngSpeed} Signal from {\itEngineData} Message', 'FontWeight', 'bold') xlabel('Timestamp') ylabel('Engine Speed') subplot(3, 1, 3) plot(signalTimetable3.Time, signalTimetable3.Gear, 'y') title('{\itGear} Signal from {\itGearBoxInfo} Message', 'FontWeight', 'bold') xlabel('Timestamp') ylabel('Gear')
Закройте доступ к MDF-файлу и файлу DBC путем очищения их переменных из рабочей области.
clear m clear canDB