В этом примере показано, как использовать основанную на событиях передачу сообщений CAN в Simulink with Vehicle Network Toolbox. Эта функция позволяет передавать сообщения CAN и CAN FD, когда обнаруживается изменение данных от одного временного шага к следующему.
Опция строения, доступная на блоках CAN и CAN FD Transmit, позволяет передавать при изменении данных. При включении сообщения с конкретными идентификаторами CAN передаются только тогда, когда данные изменяются для этого идентификатора. Каждое сообщение независимо обрабатывается в каждом временном шаге на основе его идентификатора. При отключении блок операции и периодическая операция передачи функционируют нормально. В сложение основанная на событиях передача может быть включена вместе с периодической передачей, чтобы обе работали вместе одновременно.
Модель, представленная в качестве примера, содержит два блоков CAN Pack, сконфигурированных в один блок CAN Transmit. Данные одного сообщения являются константой, а другого - счетчиком, который изменяется на каждом временном шаге.
Откройте пример модели.
open EventTransmit
Вы можете получить доступ к содержимому CAN DBC-файлов с помощью canDatabase
функция. С помощью этой функции доступны подробные сведения о узлах сети, сообщениях и сигналах. Этот DBC-файл используется в модели и используется для декодирования информации, отправленной из модели.
db = canDatabase("CANBusEvent.dbc")
db = Database with properties: Name: 'CANBusEvent' Path: '\\central-bgl\home$\aragarwa\Documents\MATLAB\Examples\vnt-ex59902587\CANBusEvent.dbc' Nodes: {'ECU'} NodeInfo: [1×1 struct] Messages: {2×1 cell} MessageInfo: [2×1 struct] Attributes: {} AttributeInfo: [0×0 struct] UserData: []
Тестовый узел определяется в DBC-файле.
node = nodeInfo(db,"ECU")
node = struct with fields:
Name: 'ECU'
Comment: ''
Attributes: {}
AttributeInfo: [0×0 struct]
Узел передает два сообщения CAN.
messageInfo(db,"Constant_Msg")
ans = struct with fields:
Name: 'Constant_Msg'
ProtocolMode: 'CAN'
Comment: ''
ID: 10
Extended: 0
J1939: []
Length: 4
DLC: 4
BRS: 0
Signals: {'Constant'}
SignalInfo: [1×1 struct]
TxNodes: {'ECU'}
Attributes: {}
AttributeInfo: [0×0 struct]
messageInfo(db,"Counter_Msg")
ans = struct with fields:
Name: 'Counter_Msg'
ProtocolMode: 'CAN'
Comment: ''
ID: 20
Extended: 0
J1939: []
Length: 4
DLC: 4
BRS: 0
Signals: {'Counter'}
SignalInfo: [1×1 struct]
TxNodes: {'ECU'}
Attributes: {}
AttributeInfo: [0×0 struct]
Включите передачу на основе событий в блоке CAN Transmit программно. Также отключите периодическую передачу.
db = canDatabase("CANBusEvent.dbc")
db = Database with properties: Name: 'CANBusEvent' Path: '\\central-bgl\home$\aragarwa\Documents\MATLAB\Examples\vnt-ex59902587\CANBusEvent.dbc' Nodes: {'ECU'} NodeInfo: [1×1 struct] Messages: {2×1 cell} MessageInfo: [2×1 struct] Attributes: {} AttributeInfo: [0×0 struct] UserData: []
set_param('EventTransmit/CAN Transmit', 'EnableEventTransmit', 'on'); set_param('EventTransmit/CAN Transmit', 'EnablePeriodicTransmit', 'off');
Обратите внимание, что отображение блока изменяется после применения настроек.
Создайте канал CAN с помощью связи с виртуальным устройством для взаимодействия с моделью Simulink. Кроме того, присоедините к ней базу данных CAN, чтобы автоматически декодировать входящие сообщения.
canCh = canChannel("Mathworks","Virtual 1",2)
canCh = 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: [0×0 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: [] UserData: []
canCh.Database = db;
Запустите канал CAN для подключения к сети.
start(canCh);
Назначьте время запуска симуляции и запустите модель.
t = "10"; set_param("EventTransmit","StopTime",t) set_param("EventTransmit","SimulationCommand","start");
Подождите, пока симуляция не начнется.
while strcmp(get_param("EventTransmit","SimulationStatus"),"stopped") end
Подождите, пока симуляция не закончится.
pause(2)
Извлеките все сообщения из шины, сгенерированной моделью.
msg = receive(canCh,inf,"OutputFormat","timetable")
msg=12×8 timetable
Time ID Extended Name Data Length Signals Error Remote
___________ __ ________ ________________ ___________ ______ ____________ _____ ______
0.26451 sec 10 false {'Constant_Msg'} {1×4 uint8} 4 {1×1 struct} false false
0.26452 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.26839 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.26841 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.26842 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.26843 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.26844 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.26845 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.26846 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.26847 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.26848 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.26849 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
Остановите канал CAN в MATLAB.
stop(canCh);
Количество раз, когда был получен идентификатор CAN, показано ниже. Сообщение «Constant_Msg» (CAN ID 10) принимается только один раз, поскольку его данные не изменяются после его начальной настройки. Сообщение «Counter_Msg» (CAN ID 20) принимается с каждого временного шага, потому что данные постоянно изменялись в нем во время работы модели.
% Define X and Y axis. x = 1:length(msg.ID); y = msg.ID; % Plot the graph for both the CAN IDs received. stem(x,y,'filled') hold on; yMax = max(msg.ID)+5; ylim([0 yMax]) % Label the graph. xlabel("Number of CAN messages"); ylabel("CAN ID"); legend("CAN ID","Location","northeast"); legend("boxoff"); hold off;
Затем позволяет построить график сигналов, полученных в каждом сообщении, в течение одного и того же запуска симуляции.
% Create a structure with signal details. signalTimeTable = canSignalTimetable(msg); % Plot the signal values of "Constant_Msg". x1 = 1:height(signalTimeTable.Constant_Msg); y1 = signalTimeTable.Constant_Msg.Constant; plot(x1, y1,"Marker","o"); hold on % Plot the signal values of "Counter_Msg". x2 = 1:height(signalTimeTable.Counter_Msg); y2 = signalTimeTable.Counter_Msg.Counter; plot(x2, y2,"Marker","o"); % Determine the maximum value for y-axis for scaling of graph. y1Max = max(signalTimeTable.Constant_Msg.Constant); y2Max = max(signalTimeTable.Counter_Msg.Counter); yMax = max(y1Max,y2Max)+5; ylim([0 yMax]); % Label the graph. xlabel("Number of Times Signals Received"); ylabel("CAN Signal Value"); legend("Constant","Counter","Location","northeastoutside"); legend("boxoff"); hold off
Сигнал «Константа» (в сообщении «Constant_Msg") строится только один раз, при этом сигнал» Счетчик «(в сообщении» Counter_Msg") строится для каждого временного шага. Это происходит из-за активизации передачи на основе событий в блоке CAN Transmit, который передает сообщение CAN только в том случае, если данные для этого CAN ID изменились по сравнению с ранее принятым сообщением.
Поскольку сигнал в сообщении «Counter_Msg» является счетчиком, который увеличивается на 1 на каждом временном шаге, для него можно увидеть линейную кривую.
Каждые точки данных представляют передачу с включенной основанной на событиях передачей, поэтому сигнал «Счетчик» принимается на каждом временном шаге, но сигнал «Константа» принимается только один раз.
Включите передачу события в блоке CAN Transmit программно. Кроме того, включите периодическую передачу и установите период сообщения.
set_param('EventTransmit/CAN Transmit', 'EnableEventTransmit', 'on'); set_param('EventTransmit/CAN Transmit', 'EnablePeriodicTransmit', 'on'); set_param('EventTransmit/CAN Transmit', 'MessagePeriod', '0.1');
Обратите внимание, что отображение блока изменяется после применения настроек.
Создайте канал CAN с помощью связи с виртуальным устройством для взаимодействия с моделью Simulink. Кроме того, присоедините к ней базу данных CAN, чтобы автоматически декодировать входящие сообщения.
canCh = canChannel("Mathworks","Virtual 1",2)
canCh = 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: [0×0 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: [] UserData: []
canCh.Database = db;
Запустите канал CAN для подключения к сети.
start(canCh);
Назначьте время запуска симуляции и запустите модель.
t = "20"; set_param("EventTransmit","StopTime",t) set_param("EventTransmit","SimulationCommand","start");
Подождите, пока симуляция не начнется.
while strcmp(get_param("EventTransmit","SimulationStatus"),"stopped") end
Подождите, пока симуляция не закончится.
pause(5);
Извлеките все сообщения из шины, сгенерированной моделью.
msg = receive(canCh,Inf,"OutputFormat","timetable")
msg=28×8 timetable
Time ID Extended Name Data Length Signals Error Remote
___________ __ ________ ________________ ___________ ______ ____________ _____ ______
0.29037 sec 10 false {'Constant_Msg'} {1×4 uint8} 4 {1×1 struct} false false
0.29037 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.29192 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.29194 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.29196 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.29197 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.29198 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.29199 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.292 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.29201 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.29202 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.29203 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.29204 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.29204 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.29205 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
0.29206 sec 20 false {'Counter_Msg' } {1×4 uint8} 4 {1×1 struct} false false
⋮
Остановите канал CAN в MATLAB.
stop(canCh);
Постройте график данных, полученных в каждом сообщении за тот же период.
% Create a structure with signal details. signalTimeTable = canSignalTimetable(msg); % Plot the signal values of "Constant_Msg". x3 = 1:height(signalTimeTable.Constant_Msg); y3 = signalTimeTable.Constant_Msg.Constant; plot(x3, y3,"Marker","o"); hold on % Plot the signal values of "Counter_Msg". x4 = 1:height(signalTimeTable.Counter_Msg); y4 = signalTimeTable.Counter_Msg.Counter; plot(x4, y4,"Marker","o"); % Determine the maximum value for y-axis for scaling of graph. y3Max = max(signalTimeTable.Constant_Msg.Constant); y4Max = max(signalTimeTable.Counter_Msg.Counter); yMax = max(y3Max,y4Max)+5; ylim([0 yMax]); % Label the graph. xlabel("Number of Times Signals Received"); ylabel("CAN Signal Value"); legend("Constant","Counter","Location","northeastoutside"); legend("boxoff"); hold off
График показывает, что сигнал «Константа» в сообщении «Constant_Msg» принимается всего несколько раз; один раз в начале из-за основанной на событиях передачи, а позже из-за периодического характера передачи. Это связано с тем, что входное значение сигнала остается постоянным.
В то время как значение сигнала «Counter» изменяется на каждом временном шаге в сообщении «Counter_Msg,», оно принимается постоянно из-за основанной на событиях передачи, и позже существует еще несколько передач, поскольку периодическая передача включена.