Этот пример показывает вам, как к то, как сконфигурировать каналы CAN и сообщения для передачи, периодически обменивается сообщениями. Это использует MathWorks виртуальные каналы CAN, соединенные в петлевой настройке.
Когда этот пример основан на отправке и получении сообщений CAN в виртуальной сети, рабочий CAN Explorer в соединении может обеспечить больше полного понимания того, что делает код. Чтобы запустить CAN Explorer, откройте и сконфигурируйте его, чтобы использовать тот же интерфейс в качестве канала получения примера. Убедитесь, что запустили CAN Explorer прежде, чем начать запускать пример для того, чтобы видеть все сообщения, как они происходят.
Этот пример описывает рабочий процесс для сети CAN, но концепция, продемонстрированная также, применяется к сети CAN FD.
Создайте каналы CAN для передачи сообщения и приема.
txCh = canChannel("MathWorks", "Virtual 1", 1); rxCh = canChannel("MathWorks", "Virtual 1", 2);
Откройте файл DBC, который содержит сообщение и определения сигнала, и присоедините его к обоим каналам CAN.
db = canDatabase("CANDatabasePeriodic.dbc");
txCh.Database = db;
rxCh.Database = db;
Создайте сообщения CAN EngineMsg
и TransmissionMsg
использование информации о базе данных.
msgFast = canMessage(db, "EngineMsg")
msgFast = 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: []
msgSlow = canMessage(db, "TransmissionMsg")
msgSlow = Message with properties: Message Identification ProtocolMode: 'CAN' ID: 200 Extended: 0 Name: 'TransmissionMsg' 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: []
Чтобы включить сообщение для периодической передачи, используйте transmitPeriodic
команда, задающая канал передачи, сообщение, чтобы указать на канале, значении состояния и периодическом уровне.
transmitPeriodic(txCh, msgFast, "On", 0.100); transmitPeriodic(txCh, msgSlow, "On", 0.500);
Запустите канал получения.
start(rxCh);
Начните канал передачи с периодической передачи, сконфигурированной на предыдущем шаге. Передача периода сразу начинается. Позвольте каналам запускаться в течение двух секунд.
start(txCh); pause(2);
Чтобы обновить живые сообщения или данные сигнала, переданные на шину CAN, запишите новые значения непосредственно в VehicleSpeed
сигнал в сообщении EngineMsg
.
msgFast.Signals.VehicleSpeed = 60; pause(1); msgFast.Signals.VehicleSpeed = 65; pause(1); msgFast.Signals.VehicleSpeed = 70; pause(1);
В качестве альтернативы можно записать новые значения в Data
свойство созданных сообщений.
Остановите каналы CAN и получите все периодически передаваемые сообщения для анализа.
stop(txCh); stop(rxCh); msgRx = receive(rxCh, Inf, "OutputFormat", "timetable");
Просмотрите первые несколько строк полученных сообщений с помощью head
функция.
head(msgRx)
ans=8×8 timetable
Time ID Extended Name Data Length Signals Error Remote
____________ ___ ________ ___________________ ___________________ ______ ____________ _____ ______
0.011398 sec 100 false {'EngineMsg' } {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.011401 sec 200 false {'TransmissionMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.1114 sec 100 false {'EngineMsg' } {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.21142 sec 100 false {'EngineMsg' } {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.31141 sec 100 false {'EngineMsg' } {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.4114 sec 100 false {'EngineMsg' } {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.51141 sec 100 false {'EngineMsg' } {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.51141 sec 200 false {'TransmissionMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
Анализируйте распределение сообщений путем графического вывода идентификаторов каждого полученного сообщения против их меток времени. Отметьте различие между тем, как часто два сообщения появляются согласно сконфигурированным периодическим уровням.
plot(msgRx.Time, msgRx.ID, "x") ylim([0 400]) title("Message Distribution", "FontWeight", "bold") xlabel("Timestamp") ylabel("CAN Identifier")
Для последующего анализа разделите два сообщения на отдельные расписания.
msgRxFast = msgRx(strcmpi("EngineMsg", msgRx.Name), :);
head(msgRxFast)
ans=8×8 timetable
Time ID Extended Name Data Length Signals Error Remote
____________ ___ ________ _____________ ___________________ ______ ____________ _____ ______
0.011398 sec 100 false {'EngineMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.1114 sec 100 false {'EngineMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.21142 sec 100 false {'EngineMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.31141 sec 100 false {'EngineMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.4114 sec 100 false {'EngineMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.51141 sec 100 false {'EngineMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.61144 sec 100 false {'EngineMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.71141 sec 100 false {'EngineMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
msgRxSlow = msgRx(strcmpi("TransmissionMsg", msgRx.Name), :);
head(msgRxSlow)
ans=8×8 timetable
Time ID Extended Name Data Length Signals Error Remote
____________ ___ ________ ___________________ ___________________ ______ ____________ _____ ______
0.011401 sec 200 false {'TransmissionMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
0.51141 sec 200 false {'TransmissionMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
1.0114 sec 200 false {'TransmissionMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
1.5115 sec 200 false {'TransmissionMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
2.0114 sec 200 false {'TransmissionMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
2.5115 sec 200 false {'TransmissionMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
3.0115 sec 200 false {'TransmissionMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
3.5115 sec 200 false {'TransmissionMsg'} {[0 0 0 0 0 0 0 0]} 8 {1x1 struct} false false
Анализируйте метки времени каждого набора сообщений, чтобы видеть, как тесно среднее значение различий соответствует сконфигурированным периодическим уровням.
avgPeriodFast = mean(diff(msgRxFast.Time))
avgPeriodFast = duration
0.1 sec
avgPeriodSlow = mean(diff(msgRxSlow.Time))
avgPeriodSlow = duration
0.50001 sec
Используйте canSignalTimetable
данным сигнала перепакета из сообщения EngineMsg
в расписание сигнала.
signalTimetable = canSignalTimetable(msgRx, "EngineMsg");
head(signalTimetable)
ans=8×2 timetable
Time VehicleSpeed EngineRPM
____________ ____________ _________
0.011398 sec 0 250
0.1114 sec 0 250
0.21142 sec 0 250
0.31141 sec 0 250
0.4114 sec 0 250
0.51141 sec 0 250
0.61144 sec 0 250
0.71141 sec 0 250
Постройте полученные значения сигнала VehicleSpeed
в зависимости от времени и отметьте, как это отражает три обновления в данных о сообщении.
plot(signalTimetable.Time, signalTimetable.VehicleSpeed) title("Vehicle Speed from EngineMsg", "FontWeight", "bold") xlabel("Timestamp") ylabel("Vehicle Speed") ylim([-5 75])
Чтобы видеть сообщения, сконфигурированные на канале передачи для автоматической коробки передач, используйте transmitConfiguration
команда.
transmitConfiguration(txCh)
Periodic Messages ID Extended Name Data Rate (seconds) --- -------- --------------- ----------------- -------------- 100 false EngineMsg 0 0 0 0 70 0 0 0 0.100000 200 false TransmissionMsg 0 0 0 0 0 0 0 0 0.500000 Event Messages None
Закройте доступ к каналам и файлу DBC путем очищения их переменных из рабочей области.
clear rxCh txCh clear db