В этом примере показано, как создать пользовательский интерфейс тестового приложения (UI) и подключить его к модели Simulink с помощью виртуальных каналов CAN. Пользовательский интерфейс тестового приложения создан с использованием приложения MATLAB App Designer™, а также нескольких функций Toolbox™ сети транспортных средств (VNT) для обеспечения виртуального интерфейса шины CAN к модели Simulink автомобильного приложения круиз-контроля. Пользовательский интерфейс тестового приложения позволяет пользователю предоставлять входной стимул для модели алгоритма круиз-контроля, наблюдать за результатами, полученными из модели, регистрировать сообщения CAN для захвата тестовых стимулов и воспроизводить зарегистрированные сообщения CAN для отладки и устранения проблем с моделью алгоритма. В примере показаны ключевые функции и блоки панели инструментов сети транспортных средств, используемые для реализации связи CAN в следующих областях:
Пользовательский интерфейс тестового приложения, поддерживающий связь с моделью алгоритма Simulink для тестирования через CAN
Пользовательский интерфейс тестового приложения, поддерживающий ведение журнала и воспроизведение данных CAN
Модель алгоритма Simulink

В этом разделе описываются ключевые функции панели инструментов сети транспортных средств, используемые для добавления интерфейса канала CAN к модели тестового приложения алгоритма Simulink Cruise Control. Он охватывает следующие темы:
Получение списка доступных каналов CAN
Форматирование информации о канале для создания канала
Создание канала в пользовательском интерфейсе
Настройка пользовательского интерфейса для передачи и приема сообщений CAN
Запуск и остановка канала
Извлечение выбранных сообщений
Откройте пользовательский интерфейс тестового приложения в App Designer. С помощью пользовательского интерфейса тестового приложения, открытого в App Designer, вы можете чередовать ракурсы «Дизайн» и «Код», чтобы следовать наряду с изучением элементов управления и соответствующего кода MATLAB для связи с моделью алгоритма Simulink Cruise Control через виртуальные каналы CAN. Для открытия примера пользовательского интерфейса используйте следующую команду: appdesigner('CruiseControlTestUI.mlapp').
Сначала реализуют механизм для поиска и представления списка доступных каналов CAN для выбора пользователем. Для этого мы добавили пункт меню «Channel Configuration» в левом верхнем углу пользовательского интерфейса тестового приложения. Он имеет подменю «Select CAN Channel».

Когда пользователь нажимает на подменю «Select CAN Channel», функция помощника getAvailableCANChannelInfo(app) вызывается посредством обратного вызова подменю. getAvailableCANChannelInfo() использует функцию Vehicle Network Toolbox canStartList для обнаружения доступных каналов CAN, как показано в приведенном ниже фрагменте кода:
function getAvailableCANChannelInfo(app) % Get a table containing all available CAN channels and devices. app.canChannelInfo = canChannelList; % Format CAN channel information for display on the UI. app.availableCANChannelsForDisplay = formatCANChannelEntryForDisplay(app); % Save the number of available constructors. app.numConstructors = numel(app.canChannelInfo.Vendor); end
Запустите canStartList, чтобы увидеть, как хранится доступная информация канала CAN.
canChannels = canChannelList
canChannels=12×6 table
Vendor Device Channel DeviceModel ProtocolMode SerialNumber
___________ ___________ _______ ___________ _____________ ____________
"MathWorks" "Virtual 1" 1 "Virtual" "CAN, CAN FD" "0"
"MathWorks" "Virtual 1" 2 "Virtual" "CAN, CAN FD" "0"
"Vector" "VN1610 1" 1 "VN1610" "CAN, CAN FD" "46457"
"Vector" "VN1610 1" 2 "VN1610" "CAN, CAN FD" "46457"
"Vector" "VN1610 3" 1 "VN1610" "CAN, CAN FD" "46456"
"Vector" "VN1610 3" 2 "VN1610" "CAN, CAN FD" "46456"
"Vector" "VN1610 2" 1 "VN1610" "CAN, CAN FD" "48599"
"Vector" "VN1610 2" 2 "VN1610" "CAN, CAN FD" "48599"
"Vector" "Virtual 1" 1 "Virtual" "CAN, CAN FD" "0"
"Vector" "Virtual 1" 2 "Virtual" "CAN, CAN FD" "0"
"Kvaser" "Virtual 1" 1 "Virtual" "CAN, CAN FD" "0"
"Kvaser" "Virtual 1" 2 "Virtual" "CAN, CAN FD" "0"
Список каналов, возвращаемых из canStartList, сохраняется в свойстве UI app.canChannelInfo и затем отображается пользователю в списке «CAN Channel Selection», как показано на снимке экрана выше.
Пользователь выбирает канал CAN из списка «CAN Channel Selection». Listdlg возвращает индекс, соответствующий выбору пользователя. Этот индекс передается функции помощника formatCANChannelConstructor.
function canChannelConstructor = formatCANChannelConstructor(app, index) canChannelConstructor = "canChannel(" + "'" + app.canChannelInfo.Vendor(index) + "'" + ", " + "'" + app.canChannelInfo.Device(index) + "'" + ", " + app.canChannelInfo.Channel(index) + ")"; end
Как показано в приведенном выше фрагменте кода, formatCANChannelConstructor использует строки, хранящиеся в таблице CAN-каналов, app.canStartInfo, для сборки строки конструктора объекта канала, соответствующей каналу, выбранному пользователем из диалогового окна списка селекторов каналов. Чтобы увидеть пример строки конструктора канала CAN, выполните код, показанный ниже.
index = 1; canChannelConstructor = "canChannel(" + "'" + canChannels.Vendor(index) + "'" + ", " + "'" + canChannels.Device(index) + "'" + ", " + canChannels.Channel(index) + ")"
canChannelConstructor =
"canChannel('MathWorks', 'Virtual 1', 1)"
Строка конструктора канала CAN хранится в свойстве пользовательского интерфейса приложения app.canChannelConstructorSelected и будет использоваться позже для создания выбранного объекта канала CAN в пользовательском интерфейсе приложения, а также для обновления блоков Simulink панели инструментов сети транспортных средств, которые реализуют интерфейс канала CAN в модели алгоритма Simulink Cruise Control.
Когда пользовательский интерфейс впервые открыт и инициализирован, отформатированная строка конструктора канала CAN, сохраненная в app.canStartConstraseSelected, используется вспомогательной функцией. setupCANChannel чтобы создать экземпляр объекта канала CAN, подключите файл базы данных конфигурации сети (.DBC) и задайте скорость шины, как показано в приведенном ниже фрагменте кода. Результирующий объект канала сохраняется в свойстве UI app.canStartObj.
function setupCANChannel(app) % Open CAN database file. db = canDatabase('CruiseControl.dbc'); % Create a CAN channel for sending and receiving messages. app.canChannelObj = eval(app.canChannelConstructorSelected); % Attach CAN database to channel for received message decoding. app.canChannelObj.Database = db; % Set the baud rate (can only do this if the UI has channel initialization access). if app.canChannelObj.InitializationAccess configBusSpeed(app.canChannelObj, 500000); end end
To see an example CAN database object, execute the following:
db = canDatabase('CruiseControl.dbc')db =
Database with properties:
Name: 'CruiseControl'
Path: '\\fs-01-mi\shome$\rollinb\Documents\MATLAB\Examples\vnt-ex00964061\CruiseControl.dbc'
Nodes: {2×1 cell}
NodeInfo: [2×1 struct]
Messages: {2×1 cell}
MessageInfo: [2×1 struct]
Attributes: {'BusType'}
AttributeInfo: [1×1 struct]
UserData: []
To see an example CAN channel object, execute the following:
% Instantiate the CAN channel object using the channel constructor string. canChannelObj = eval(canChannelConstructor); % Attach the CAN database to the channel object. canChannelObj.Database = db
canChannelObj =
Channel with properties:
Device Information
DeviceVendor: 'MathWorks'
Device: 'Virtual 1'
DeviceChannelIndex: 1
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: [1×1 can.Database]
UserData: []
setupCANChannel использует следующие функции панели инструментов сети транспортных средств:
canChannel для создания экземпляра объекта канала с помощью команды eval и строки конструктора канала CAN, хранящейся в свойстве пользовательского интерфейса приложения app.canChannelConstructorSelected. Результирующий объект канала хранится в свойстве пользовательского интерфейса приложения app.canChannelObj.
canDatabase для создания объекта базы данных CAN (.DBC), представляющего файл .DBC. Этот объект хранится в свойстве «База данных» объекта канала.
После настройки выбранного объекта CAN-канала и сохранения его в свойстве UI app.canStartObj, следующим шагом будет вызов функции помощника. setupCANTransmitMessages, показан в приведенном ниже фрагменте кода. setupCANTransmitMessages defines сообщение CAN для передачи от пользовательского интерфейса, заполняет полезную нагрузку сообщения сигналами, назначает каждому сигналу значение и ставит сообщение в очередь для периодической передачи после запуска канала CAN.
function setupCANTransmitMessages(app) % Create a CAN message container. app.cruiseControlCmdMessage = canMessage(app.canChannelObj.Database, 'CruiseCtrlCmd'); % Fill the message container with signals and assign values to each signal. app.cruiseControlCmdMessage.Signals.S01_CruiseOnOff = logical2Numeric(app, app.cruisePowerCheckBox.Value); app.cruiseControlCmdMessage.Signals.S02_Brake = logical2Numeric(app, app.brakeOnOffCheckBox.Value); app.cruiseControlCmdMessage.Signals.S03_VehicleSpeed = app.vehicleSpeedSlider.Value; app.cruiseControlCmdMessage.Signals.S04_CoastSetSw = logical2Numeric(app, app.cruiseCoastSetCheckBox.Value); app.cruiseControlCmdMessage.Signals.S05_AccelResSw = logical2Numeric(app, app.cruiseAccelResumeCheckBox.Value); % Set up periodic transmission of this CAN message. Actual transmission starts/stops with CAN channel start/stop. transmitPeriodic(app.canChannelObj, app.cruiseControlCmdMessage, 'On', 0.1); end
To see what the CAN message object looks like, execute the following:
cruiseControlCmdMessage = canMessage(canChannelObj.Database, 'CruiseCtrlCmd')cruiseControlCmdMessage =
Message with properties:
Message Identification
ProtocolMode: 'CAN'
ID: 256
Extended: 0
Name: 'CruiseCtrlCmd'
Data Details
Timestamp: 0
Data: [0 0]
Signals: [1×1 struct]
Length: 2
Protocol Flags
Error: 0
Remote: 0
Other Information
Database: [1×1 can.Database]
UserData: []
cruiseControlCmdMessage.Signals
ans = struct with fields:
S03_VehicleSpeed: 0
S05_AccelResSw: 0
S04_CoastSetSw: 0
S02_Brake: 0
S01_CruiseOnOff: 0
setupCANTransmitMessages использует следующие функции панели инструментов сети транспортных средств:
canMessage для создания сообщения CAN, определенного в объекте базы данных CAN.
TransmendPeriodic, чтобы поставить в очередь сообщение, хранящееся в свойстве UI app.cruityControlCmdMessage, для периодической передачи по каналу, определенному объектом канала, хранящимся в свойстве UI app.canStartObj, со скоростью, заданной последним аргументом, в данном случае каждые 0,1 секунды.
Пользовательскому интерфейсу необходимо периодически получать CAN-сообщения для обновления графиков с помощью обратной связи с алгоритмом Cruise Control в рамках модели Simulink. Для этого сначала создается объект таймера MATLAB, как показано в приведенном ниже фрагменте кода.
% create a timer to receive CAN msgs app.receiveCANmsgsTimer = timer('Period', 0.5,... 'ExecutionMode', 'fixedSpacing', ... 'TimerFcn', @(~,~)receiveCANmsgsTimerCallback(app));
Объект таймера вызовет функцию обратного вызова таймера receiveCANmsgsTimerCallback каждые 0,5 секунды. receiveCANmsgsTimerCallback, показанный в приведенном ниже фрагменте кода, извлекает все сообщения CAN из шины, использует функцию помощника getCruiseCtrlFBCANmessage для извлечения сообщений CAN, возвращаемых из модели Cruise Control Algorithm, и обновления графиков пользовательского интерфейса извлеченными данными сообщений CAN.
% receiveCANmsgsTimerCallback Timer callback function for GUI updating function receiveCANmsgsTimerCallback(app) try % Receive available CAN messages. msg = receive(app.canChannelObj, Inf, 'OutputFormat', 'timetable'); % Update Cruise Control Feedback CAN message data. newFbData = getCruiseCtrlFBCANmessage(app, msg); if ~newFbData return; end % Update target speed and engaged plots with latest data from CAN bus. updatePlots(app); catch err disp(err.message) end end
Чтобы увидеть, какие сообщения были возвращены из receive , выполните следующий код:
% Queue periodic transmission of a CAN message to generate some message data once the channel % starts. transmitPeriodic(canChannelObj, cruiseControlCmdMessage, 'On', 0.1); % Start the channel. start(canChannelObj); % Wait 1 second to allow time for some messages to be generated on the bus. pause(1); % Retrieve all messages from the bus and output the results as a timetable. msg = receive(canChannelObj, Inf, 'OutputFormat','timetable')
msg=31×8 timetable
Time ID Extended Name Data Length Signals Error Remote
_____________ ___ ________ _________________ ___________ ______ ____________ _____ ______
0.0066113 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.059438 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.16047 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.26045 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.36045 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.46046 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.56046 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.66046 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.75945 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.86044 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.95945 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
1.0594 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
1.1594 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
1.2594 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
1.3595 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
1.4605 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
⋮
% Stop the channel.
stop(canChannelObj)receiveCANmsgsTimerCallback использует следующие функции панели инструментов сети транспортных средств:
получение сообщений CAN с шины CAN. В этом случае функция конфигурируется для извлечения всех сообщений с момента предыдущего вызова и вывода результатов в виде расписания MATLAB.
Вспомогательная функция getCruiseCtrlFBCANmessage Фильтрация сообщений «Cruire»« »« »« »« »« »из всех полученных сообщений CAN« », извлечение сигналов« »tspeFb« »и« »Fb« »из этих сообщений и объединение их с объектами временных рядов MATLAB для сигналов« »tspyFb« »и« »Fb« ». Эти объекты временных рядов хранятся в свойствах пользовательского интерфейса app.tspedFb и app.engagedFb соответственно. Запомненные сигналы временных интервалов используются для обновления графиков для каждого сигнала на UI. Обратите внимание на использование seconds способ преобразования временных данных, хранящихся в расписании, из массива длительности в эквивалентный числовой массив в единицах секунд в объектах временных рядов для каждого сигнала.
function newFbData = getCruiseCtrlFBCANmessage(app, msg) % Exit if no messages were received as there is nothing to update. if isempty(msg) newFbData = false; return; end % Extract signals from all CruiseCtrlFB messages. cruiseCtrlFBSignals = canSignalTimetable(msg, "CruiseCtrlFB"); % if no messages then just return as there is nothing to do if isempty(cruiseCtrlFBSignals) newFbData = false; return; end if ~isempty(cruiseCtrlFBSignals) % Received new Cruise Control Feedback messages, so create time series from CAN signal data % save the Target Speed feedback signal. if isempty(app.tspeedFb) % cCeck if target speed feedback property has been initialized. app.tspeedFb = cell(2,1); % It appears Simulink.SimulationData.Dataset class is not % compatible with MATLAB Compiler, so change the way we store data % from a Dataset format to cell array. % Save target speed actual data. app.tspeedFb = timeseries(cruiseCtrlFBSignals.F02_TargetSpeed, seconds(cruiseCtrlFBSignals.Time),... 'Name','CruiseControlTargetSpeed'); else % Add to existing data. % Save target speed actual data. app.tspeedFb = timeseries([app.tspeedFb.Data; cruiseCtrlFBSignals.F02_TargetSpeed], ... [app.tspeedFb.Time; seconds(cruiseCtrlFBSignals.Time)],'Name','CruiseControlTargetSpeed'); end % Save the Cruise Control Engaged actual signal. % Check if Cruise engaged property has been initialized. if isempty(app.engagedFb) app.engagedFb = cell(2,1); % It appears Simulink.SimulationData.Dataset class is not % compatible with MATLAB Compiler, so change the way we store data % from a Dataset format to cell array. % Save cruise engaged command data. app.engagedFb = timeseries(cruiseCtrlFBSignals.F01_Engaged,seconds(cruiseCtrlFBSignals.Time),... 'Name','CruiseControlEngaged'); else % Add to existing logsout. % Save cruise engaged command data. app.engagedFb = timeseries([app.engagedFb.Data; cruiseCtrlFBSignals.F01_Engaged], ... [app.engagedFb.Time; seconds(cruiseCtrlFBSignals.Time)],'Name','CruiseControlEngaged'); end newFbData = true; end end
Вспомогательная функция getCruiseCtrlFBCANmessage использует следующие функции панели инструментов сети транспортных средств:
canSignalSchedule, чтобы вернуть расписание MATLAB, содержащее сигналы из CAN-сообщения CruityStartFB.
После того, как объект канала CAN app.canStartObj был создан и сообщения были настроены для передачи и приема, мы теперь можем запустить канал. Когда пользователь нажимает кнопку запуска sim на пользовательском интерфейсе, канал запускается непосредственно перед запуском модели Simulink. Для этого функция помощника startSimApplication вызывается. startSimApplication, показанный в фрагменте кода ниже, проверяет, используем ли мы виртуальный канал CAN, потому что это единственный тип, который имеет смысл, если вы используете только моделирование рабочего стола. Затем он проверяет, загружена ли в память модель Simulink, к которой мы хотим подключиться bdIsLoaded команда. Если модель загружена и еще не запущена, графики пользовательского интерфейса очищаются, чтобы принять новые данные сигнала, канал CAN запускается с помощью вспомогательной функции startCANChannel и запускается модель.
function startSimApplication(app, index) % Start the model running on the desktop. % Check to see if hardware or virtual CAN channel is selected, otherwise do nothing. if app.canChannelInfo.DeviceModel(index) == "Virtual" % Check to see if the model is loaded before trying to run. if bdIsLoaded(app.mdl) % Model is loaded, now check to see if it is already running. if ~strcmp('running',get_param(app.mdl,'SimulationStatus')) % Model is not already running, so start it % flush the CAN Receive message buffers. app.tspeedFb = []; app.engagedFb = []; % Clear figure window. cla(app.tspeedPlot) cla(app.engagedPlot) % Start the CAN channels and update timer if it isn't already running. startCANChannel(app); % Start the model. set_param(app.mdl, 'SimulationCommand', 'start'); % Set the sim start/stop button icon to the stop icon indicating the model has % been successfully started and is ready to be stopped at the next button press. app.SimStartStopButton.Icon = "IconEnd.png"; app.StartSimLabel.Text = "Stop Sim"; else % Model is already running, inform the user. warnStr = sprintf('Warning: Model %s is already running', app.mdl); warndlg(warnStr, 'Warning'); end else % Model is not yet loaded, so warn the user. warnStr = sprintf('Warning: Model %s is not loaded\nPlease load the model and try again', app.mdl); warndlg(warnStr, 'Warning'); end end end
Вспомогательная функция startCANChannel показан в приведенном ниже фрагменте кода. Эта функция проверяет, не работает ли канал до его запуска. Затем запускается объект таймера MATLAB, так что функция обратного вызова таймера receiveCANmsgsTimerCallback, описанный в предыдущем разделе, вызывается каждые 0,5 секунды для извлечения данных сообщения CAN из шины.
function startCANChannel(app) % Start the CAN channel if it isn't already running. try if ~app.canChannelObj.Running start(app.canChannelObj); end catch % do nothing. end % Start the CAN receive processing timer - check to see if it is already running. This allows us to change CAN channels % with or without starting and stopping the model running on the real time target. if strcmpi(app.receiveCANmsgsTimer.Running, 'off') start(app.receiveCANmsgsTimer); end end
startCANchannel использует следующую функцию панели инструментов сети транспортных средств:
Запуск для запуска канала CAN. Канал останется в оперативном режиме до тех пор, пока не будет выдана команда остановки.
Когда пользователь нажимает кнопку stop sim на интерфейсе пользователя, мы хотим остановить модель Simulink непосредственно перед остановкой канала CAN. Для этого функция помощника stopSimApplication вызывается. stopSimApplication, показанный в фрагменте кода ниже, проверяет, используем ли мы виртуальный канал CAN, потому что это единственный тип, который имеет смысл, если вы используете только моделирование рабочего стола. Затем останавливает модель Simulink и вызывает функцию помощника stopCANChannel для остановки канала CAN.
function stopSimApplication(app, index) % Stop the model running on the desktop. try % Check to see if hardware or virtual CAN channel is selected. if app.canChannelInfo.DeviceModel(index) == "Virtual" % Virtual channel selected, so issue a stop command to the % the simulation, even if it is already stopped. set_param(app.mdl, 'SimulationCommand', 'stop') % Stop the CAN channels and update timer. stopCANChannel(app); end % Set the sim start/stop button text to Start indicating the model has % been successfully stopped and is ready to start again at the next % button press. app.SimStartStopButton.Icon = "IconPlay.png"; app.StartSimLabel.Text = "Start Sim"; catch % Do nothing at the moment. end end
Вспомогательная функция stopCANChannel показан в приведенном ниже фрагменте кода. Эта функция останавливает канал CAN, затем останавливает объект таймера MATLAB, так что функция обратного вызова таймера receiveCANmsgsTimerCallback, описанный ранее, больше не вызывается для извлечения сообщений из шины.
function stopCANChannel(app) % Stop the CAN channel. stop(app.canChannelObj); % Stop the CAN message processing timer. stop(app.receiveCANmsgsTimer); end
stopCANchannel использует следующую функцию панели инструментов сети транспортных средств:
для остановки канала CAN. Канал останется в автономном режиме до тех пор, пока не будет выдана другая команда запуска.
На этом шаге мы рассмотрим ключевые функции панели инструментов сети транспортных средств, используемые для добавления возможности регистрации, сохранения и воспроизведения сообщений CAN. Для реализации этой функции создается экземпляр второго канала CAN, идентичного первому созданному. Поскольку второй объект CAN-канала идентичен первому, он будет видеть и собирать те же сообщения, что и первый объект CAN-канала. Второй канал CAN запускается, когда пользователь нажимает кнопку запуска регистрации на пользовательском интерфейсе, как показано на экране пользовательского интерфейса, снятом ниже. Канал продолжает работать и собирать сообщения до тех пор, пока пользователь не нажмет кнопку stop logging на интерфейсе пользователя. Как только пользователь перестанет регистрировать сообщения CAN, мы извлекем все сообщения, накопленные в буфере сообщений для второго объекта CAN-канала, извлекем сообщения, которые мы заинтересованы в воспроизведении, и сохраните их в MAT-файле. Как только сообщения будут сохранены, мы сможем воспроизвести их, используя первый канал CAN, чтобы обеспечить входной стимул для модели алгоритма Simulink Cruise Control для отладки и проверки алгоритма.

Это описание будет охватывать следующие темы:
Настройка канала для регистрации сообщений CAN
Запуск и остановка канала
Извлечение и извлечение зарегистрированных сообщений CAN
Сохранение извлеченных сообщений в файл
Загрузка сохраненных сообщений из файла
Начать воспроизведение зарегистрированных сообщений CAN
Остановить воспроизведение зарегистрированных сообщений CAN
Способом, прямо аналогичным тому, как был создан первый CAN-канал, отформатированная строка конструктора CAN-канала, сохраненная в app.can setupCANLogChannel чтобы создать второй экземпляр объекта канала CAN, подключите тот же файл базы данных конфигурации сети (.DBC), который использовался для первого канала, и установите скорость шины, как показано в приведенном ниже фрагменте кода. Результирующий объект канала сохраняется в свойстве UI app.canLogStartObj.
function setupCANLogChannel(app) % Open CAN database file. db = canDatabase('CruiseControl.dbc'); % Create a CAN channel for sending and receiving messages. app.canLogChannelObj = eval(app.canChannelConstructorSelected); % Attach CAN database to channel for received message decoding. app.canLogChannelObj.Database = db; % Set the baud rate (can only do this if the UI has channel initialization access). if app.canLogChannelObj.InitializationAccess configBusSpeed(app.canLogChannelObj, 500000); end end
To see an example CAN database object, execute the following code:
db = canDatabase('CruiseControl.dbc')db =
Database with properties:
Name: 'CruiseControl'
Path: '\\fs-01-mi\shome$\rollinb\Documents\MATLAB\Examples\vnt-ex00964061\CruiseControl.dbc'
Nodes: {2×1 cell}
NodeInfo: [2×1 struct]
Messages: {2×1 cell}
MessageInfo: [2×1 struct]
Attributes: {'BusType'}
AttributeInfo: [1×1 struct]
UserData: []
To see an example CAN channel object, execute the following code:
% Instantiate the CAN channel object using the channel constructor string. canLogChannelObj = eval(canChannelConstructor); % Attach the CAN database to the channel object. canLogChannelObj.Database = db
canLogChannelObj =
Channel with properties:
Device Information
DeviceVendor: 'MathWorks'
Device: 'Virtual 1'
DeviceChannelIndex: 1
DeviceSerialNumber: 0
ProtocolMode: 'CAN'
Status Information
Running: 0
MessagesAvailable: 0
MessagesReceived: 0
MessagesTransmitted: 0
InitializationAccess: 0
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: [1×1 can.Database]
UserData: []
setupCANLogChannel использует следующие функции панели инструментов сети транспортных средств:
canChannel для создания экземпляра объекта канала с помощью команды eval и строки конструктора канала CAN, хранящейся в свойстве пользовательского интерфейса приложения app.canChannelConstructorSelected. Результирующий объект канала хранится в свойстве пользовательского интерфейса приложения app.canLogChannelObj.
canDatabase для создания объекта базы данных CAN (.DBC), представляющего файл .DBC. Этот объект хранится в свойстве «База данных» объекта канала.
Как и в случае первого канала CAN, объект канала CAN app.canLogStartOb был создан при открытии пользовательского интерфейса тестового приложения. При нажатии кнопки start Logging на пользовательском интерфейсе, как показано на приведенном выше экране, вызывается функция помощника startCANLogChannel, показано в приведенном ниже фрагменте кода. Эта функция проверяет, работает ли второй канал CAN, и запускает его, если нет.
function startCANLogChannel(app) % Start the CAN Log channel if it isn't already running. try if ~app.canLogChannelObj.Running start(app.canLogChannelObj); end catch % Do nothing. end end
startCANLogChannel использует следующую функцию панели инструментов сети транспортных средств:
Запуск для запуска канала CAN. Канал останется в оперативном режиме до тех пор, пока не будет выдана команда остановки.
Когда пользователь нажимает кнопку «Stop logging» на интерфейсе пользователя, кнопка обратного вызова вызывает функцию помощника stopCANLogging, показан в приведенном ниже фрагменте кода. stopCANLogging останавливает канал CAN и извлекает все сообщения, накопленные в буфере второго канала с момента запуска второго канала CAN, при нажатии кнопки «Start Logging».
function stopCANLogging(app) % Stop the CAN Log channel. stop(app.canLogChannelObj); % Get the messages from the CAN log message queue. retrieveLoggedCANMessages(app); % Update the button icon and label. app.canLoggingStartStopButton.Icon = 'IconPlay.png'; app.StartLoggingLabel.Text = "Start Logging"; end
stopCANLogging использует следующую функцию панели инструментов сети транспортных средств:
для остановки канала CAN. Канал останется в автономном режиме до тех пор, пока не будет выдана другая команда запуска.
Как только канал CAN регистрации остановлен, функция помощника retrieveLoggedCANMessages, показанный в приведенном ниже фрагменте кода, вызывается для извлечения всех сообщений CAN со второй шины канала. Сообщения CAN поступают со второй шины канала с помощью receive Команда и логическая индексация используется для извлечения сообщений «Cruase»« Cmd »из всех расписаний сообщений, возвращаемых receive команда.
function retrieveLoggedCANMessages(app) try % Receive available CAN message % initialize buffer to make sure it is empty. app.canLogMsgBuffer = []; % Receive available CAN messages. msg = receive(app.canLogChannelObj, Inf, 'OutputFormat', 'timetable'); % Fill the buffer with the logged Cruise Control Command CAN message data. app.canLogMsgBuffer = msg(msg.Name == "CruiseCtrlCmd", :); catch err disp(err.message) end end
Чтобы увидеть, какие сообщения были возвращены из receive в формате расписания выполните следующий код:
% Queue periodic transmission of CAN messages to generate sample message data once the channel starts. cruiseControlFbMessage = canMessage(db, 'CruiseCtrlFB'); transmitPeriodic(canChannelObj, cruiseControlFbMessage, 'On', 0.1); transmitPeriodic(canChannelObj, cruiseControlCmdMessage, 'On', 0.1); % Start the first channel. start(canChannelObj); % Start the second (logging) channel. start(canLogChannelObj); % Wait 1 second to allow time for some messages to be generated on the bus. pause(1); % Stop the channels. stop(canChannelObj) stop(canLogChannelObj) % Retrieve all messages from the logged message bus and output the results as a timetable. msg = receive(canLogChannelObj, Inf, 'OutputFormat','timetable')
msg=20×8 timetable
Time ID Extended Name Data Length Signals Error Remote
____________ ___ ________ _________________ ___________ ______ ____________ _____ ______
0.077716 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.07772 sec 512 false {'CruiseCtrlFB' } {1×2 uint8} 2 {1×1 struct} false false
0.1777 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.17771 sec 512 false {'CruiseCtrlFB' } {1×2 uint8} 2 {1×1 struct} false false
0.27673 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.27674 sec 512 false {'CruiseCtrlFB' } {1×2 uint8} 2 {1×1 struct} false false
0.37673 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.37674 sec 512 false {'CruiseCtrlFB' } {1×2 uint8} 2 {1×1 struct} false false
0.47773 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.47773 sec 512 false {'CruiseCtrlFB' } {1×2 uint8} 2 {1×1 struct} false false
0.57674 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.57674 sec 512 false {'CruiseCtrlFB' } {1×2 uint8} 2 {1×1 struct} false false
0.67673 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.67673 sec 512 false {'CruiseCtrlFB' } {1×2 uint8} 2 {1×1 struct} false false
0.77771 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.77771 sec 512 false {'CruiseCtrlFB' } {1×2 uint8} 2 {1×1 struct} false false
⋮
% Extract only the Cruise Control Command CAN messages. msgCmd = msg(msg.Name == "CruiseCtrlCmd", :)
msgCmd=10×8 timetable
Time ID Extended Name Data Length Signals Error Remote
____________ ___ ________ _________________ ___________ ______ ____________ _____ ______
0.077716 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.1777 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.27673 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.37673 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.47773 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.57674 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.67673 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.77771 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.87776 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
0.97769 sec 256 false {'CruiseCtrlCmd'} {1×2 uint8} 2 {1×1 struct} false false
retrieveLoggedCANMessages использует следующие функции панели инструментов сети транспортных средств:
получение сообщений CAN с шины CAN. В этом случае функция конфигурируется для извлечения всех сообщений с момента предыдущего вызова и вывода результатов в виде расписания MATLAB.
Когда пользователь нажимает кнопку «Save Logged Data» на интерфейсе пользователя, функция помощника saveLoggedCANDataToFile вызывается. Эта функция открывает окно браузера файлов с помощью uinputfile функция. uinputfile возвращает имя файла и путь, выбранные пользователем для хранения данных зарегистрированного сообщения CAN. Функция инструментария сети транспортных средств canMessageReplayBlockStruct используется для преобразования CAN-сообщений из расписания MATLAB в форму, которую может использовать блок воспроизведения CAN. Как только записанные в журнал данные CAN сообщения будут преобразованы и сохранены в файле, их можно будет отозвать и воспроизвести позже с помощью блока Simulink панели инструментов сети транспортных средств «Replay». Воспроизведение сообщений в MATLAB с помощью панели инструментов сети транспортных средств с помощью replay само расписание передается в качестве входных данных функции.
function savedLoggedCANDataToFile(app) % Raise dialog box to prompt user for a CAN log file to store the logged data. [FileName,PathName] = uiputfile('*.mat','Select a .MAT file to store logged CAN data'); if FileName ~= 0 % User did not cancel the file selection operation, so OK to save % convert the CAN log data from Timetable to struct of arrays so the data is compatible % with the VNT Simulink Replay block. canLogStructOfArrays = canMessageReplayBlockStruct(app.canLogMsgBuffer); save(fullfile(PathName, FileName), 'canLogStructOfArrays'); % Clear the buffer after saving it. app.canLogMsgBuffer = []; end end
saveLoggedCANDataToFile использует следующую функцию панели инструментов сети транспортных средств:
для преобразования сообщений CAN, сохраненных в расписании MATLAB, в форму, которая может использоваться блоком воспроизведения сообщений CAN.
Когда пользователь нажимает кнопку «Load Logged Data» на пользовательском интерфейсе, функция помощника loadLoggedCANDataFromFile вызывается. Эта функция открывает окно браузера файлов с помощью uigetfile функция, которая возвращает имя файла зарегистрированного сообщения, выбранное пользователем. Данные зарегистрированного сообщения CAN загружаются из файла и преобразуются обратно в представление расписания для использования с панелью инструментов сети транспортных средств. replay команда. Следует отметить, что один и тот же файл данных можно использовать непосредственно с блоком Simulink панели инструментов сети транспортных средств «Replay», если пользователь хочет воспроизвести данные из модели Simulink. Можно выбрать воспроизведение данных с помощью блока «Воспроизведение», а не из пользовательского интерфейса с помощью replay потому что блок «Replay» работает с отладчиком Simulink, приостанавливая воспроизведение при остановке моделирования в точке останова. replay напротив, команда не распознает, когда модель Simulink останавливается в точке останова, и будет просто воспроизводить сохраненные данные сообщения из файла. Для целей примера мы будем воспроизводить данные с помощью replay команда.
function loadLoggedCANDataFromFile(app) % Raise dialog box to prompt user for a CAN log file to load. [FileName,PathName] = uigetfile('*.mat','Select a CAN log file to load'); % Return focus to main UI after dlg closes. figure(app.UIFigure) if FileName ~= 0 % User did not cancel the file selection operation, so OK to load % make sure the message buffer is empty before loading in the logged CAN data. app.canLogMsgBuffer = []; % Upload the saved message data from the selected file. canLogMsgStructOfArrays = load(fullfile(PathName, FileName), 'canLogStructOfArrays'); % Convert the saved message data into timetables for the replay command. app.canLogMsgBuffer = canMessageTimetable(canLogMsgStructOfArrays.canLogStructOfArrays); end end
loadLoggedCANDataFromFile использует следующую функцию панели инструментов сети транспортных средств:
для преобразования сообщений CAN, хранящихся в форме, совместимой с блоком Simulink сообщения CAN «Replay», в расписание MATLAB для использования с replay функция.
После загрузки данных зарегистрированного сообщения CAN в пользовательский интерфейс и его переформатирования он готов для воспроизведения с помощью панели инструментов сети транспортных средств. replay команда. Когда пользователь нажимает кнопку «Start Replay» на интерфейсе пользователя, функция помощника startPlaybackOfLoggedCANData вызывается. Для воспроизведения зарегистрированных данных сообщения CAN по первому каналу CAN все операции, связанные с этим каналом, должны быть остановлены, а все буферизованные данные сообщения очищены. Как показано в приведенном ниже фрагменте кода, startPlaybackOfLoggedCANData отключает периодическую передачу сообщений CAN, останавливает канал CAN, очищает любые данные сообщения CAN, буферизованные в UI, и очищает графики, отображающие данные сигнала, подаваемые обратно из модели алгоритма Cruise Control. Затем канал CAN перезапускается, и данные зарегистрированного сообщения CAN воспроизводятся.
function startPlaybackOfLoggedCANData(app) % Turn off periodic transmission of CruiseCtrlCmd CAN message from UI controls. transmitPeriodic(app.canChannelObj, app.cruiseControlCmdMessage, 'Off'); % Stop the UI CAN channel so we can instead use if for playback. stopCANChannel(app) % Flush the existing CAN messages stored for plotting. flushCANFbMsgQueue(app) % Clear the existing plots. cla(app.tspeedPlot) cla(app.engagedPlot) % Start the CAN Channel and replay the logged CAN message data. startCANChannel(app) % Replay the logged CAN data on the UI CAN Channel. replay(app.canChannelObj, app.canLogMsgBuffer); end
startPlaybackOfCANData использует следующие функции панели инструментов сети транспортных средств:
TransmissionPeriodic, чтобы отключить периодическую передачу командных сигналов, посылаемых на модель алгоритма Cruise Control в сообщении «Cruity».
воспроизведение для воспроизведения зарегистрированных данных сообщения CAN по первому каналу CAN.
Когда пользователь нажимает кнопку «Stop Replay» на интерфейсе пользователя, функция помощника stopPlaybackOfLoggedCANData вызывается. Чтобы остановить воспроизведение зарегистрированных данных CAN, канал CAN, в котором воспроизводятся данные, должен быть остановлен. После этого может быть повторно активизирована периодическая передача сообщения «Cruase», и канал будет перезапущен, так что пользователь снова сможет вводить сигналы тестового стимула в модель алгоритма круиз-контроля в интерактивном режиме из пользовательского интерфейса. Как показано в приведенном ниже фрагменте кода, stopPlaybackOfLoggedCANData сначала останавливает канал, который останавливает воспроизведение данных зарегистрированного сообщения. Данные зарегистрированного сообщения удаляются из локальных буферов пользовательского интерфейса, а также из графиков, отображающих данные сигнала, подаваемые из модели алгоритма Cruise Control. Периодическая передача сообщения «Cruire»« Cmd »повторно включена, и канал CAN перезапущен.
function stopPlaybackOfLoggedCANData(app) % Stop the playback CAN channel. stopCANChannel(app) % Flush the existing CAN messages stored for plotting. flushCANFbMsgQueue(app) % Clear the existing plots. cla(app.tspeedPlot) cla(app.engagedPlot) % Re-enable periodic transmission of CruiseCtrlCmd CAN message from UI controls. transmitPeriodic(app.canChannelObj, app.cruiseControlCmdMessage, 'On', 0.1); % Restart the CAN Channel from/To UI. startCANChannel(app) end
stopPlaybackOfLoggedCANData использует следующие функции панели инструментов сети транспортных средств:
остановка для остановки канала CAN для остановки воспроизведения зарегистрированных данных сообщения CAN.
TransmissionPeriodic, чтобы повторно включить периодическую передачу командных сигналов, посылаемых на модель алгоритма Cruise Control в сообщении «Cruase».
начать повторный запуск канала CAN, чтобы пользователь мог снова вводить сигналы тестового стимула в модель алгоритма Cruise Control в интерактивном режиме из пользовательского интерфейса.
На этом шаге описывается использование блоков Simulink панели инструментов сети транспортных средств для добавления возможностей виртуальной связи CAN в модель алгоритма Simulink Cruise Control.

Это описание будет охватывать следующие темы:
Добавление возможности приема сообщений CAN
Добавление возможности передачи сообщения CAN
Передача информации о конфигурации канала CAN из пользовательского интерфейса в модель Simulink
Запустите вспомогательные функции для настройки рабочей области с необходимыми параметрами данных, а затем откройте тестовую модель электрического жгута алгоритма Cruise Control. При открытой модели Simulink можно исследовать части модели, описанные в разделах ниже. Выполнить helperPrepareTestBenchParameterData за которым следует helperConfigureAndOpenTestBench.
Для того, чтобы модель Simulink алгоритма Cruise Control получала данные CAN от тестового пользовательского интерфейса, требуется блок для подключения модели Simulink к конкретному устройству CAN, блок для приема сообщений CAN от выбранного устройства и блок для распаковки полезной нагрузки данных принятых сообщений в отдельные сигналы. Для этого к модели Simulink алгоритма Cruise Control добавляется подсистема «Inputs». Подсистема «Inputs» использует блоки CAN Configuration, CAN Receive и CAN Unpack, соединенные между собой, как показано на рисунке ниже.
Блок конфигурации CAN позволяет пользователю определить, какое из доступных устройств и каналов CAN следует подключить к модели Simulink. Блок приема CAN получает сообщения CAN от устройства CAN и канала, выбранного в блоке конфигурирования CAN. Он также позволяет пользователю принимать все сообщения на шине или применять фильтр для приема только сообщений выбора. Блок распаковки CAN настроен на чтение файла пользовательской сетевой базы данных (.DBC). Это позволяет пользователю определить имя сообщения, идентификатор сообщения и полезную нагрузку данных для распаковки сигналов с этим блоком. Входные порты Simulink автоматически добавляются в блок для каждого сигнала, определенного в сообщении в файле сетевой базы данных.

Подсистема «Inputs» алгоритма Cruise Control модели Simulink использует следующие блоки CAN для приема CAN-сообщений:
Блок конфигурации CAN для выбора устройства канала CAN для подключения к модели Simulink.
Блок приема CAN для приема сообщений CAN от устройства CAN, выбранного в блоке конфигурирования CAN.
Блок распаковки CAN для распаковки полезной нагрузки принятого сообщения (сообщений) CAN на отдельные сигналы, по одному для каждого элемента данных, определенного в сообщении.
Для того, чтобы модель Simulink алгоритма Cruise Control передавала данные CAN тестовому пользовательскому интерфейсу, требуется блок для подключения модели Simulink к конкретному устройству CAN, блок для упаковки сигналов Simulink в полезную нагрузку данных одного или нескольких сообщений CAN и блок для передачи сообщений CAN от выбранного устройства. Для этого в модель Simulink алгоритма Cruise Control добавляется подсистема «Outputs». Подсистема «Outputs» использует блоки CAN pack и CAN Transmit, связанные между собой, как показано на рисунке ниже.
Блок CAN Pack настроен на чтение файла пользовательской сетевой базы данных (.DBC). Это позволяет пользователю определить имя сообщения, идентификатор сообщения и полезную нагрузку данных для упаковки сигнала с этим блоком. Выходные порты Simulink автоматически добавляются в блок для каждого сигнала, определенного в сообщении в файле сетевой базы данных. Блок CAN Transmit передает сообщение, собранное блоком Pack Block по каналу CAN и устройству CAN, выбранному пользователем с блоком Configuration. Следует отметить, что второй блок конфигурации CAN не требуется, поскольку подсистема «Outputs» передает сообщения CAN по тому же каналу CAN и устройству, которое используется для приема сообщений CAN.

В подсистеме «Outputs» алгоритма Cruise Control Simulink модели для передачи CAN-сообщений используются следующие блоки панели инструментов Vehicle Network Toolbox Simulink:
Блок CAN Pack Block для распаковки полезной нагрузки принятого сообщения CAN на отдельные сигналы, по одному для каждого элемента данных, определенного в сообщении.
Блок передачи CAN для приема сообщений CAN от устройства CAN, выбранного в блоке конфигурации CAN.
Поскольку пользователь выбирает, какие из доступных CAN-устройств и каналов использовать из пользовательского интерфейса, эта информация должна быть отправлена в модель Simulink алгоритма Cruise Control, чтобы поддерживать синхронизированные конфигурации CAN-устройств и каналов между пользовательским интерфейсом и моделью Simulink. Для этого блоки CAN устройства и канала, используемые панелью инструментов сети транспортных средств «CAN Configuration», «CAN Transmit» и «CAN Receive», должны быть сконфигурированы программно из пользовательского интерфейса. Каждый раз, когда пользователь выбирает устройство CAN и канал CAN из меню пользовательского интерфейса «Channel Configuration/Select CAN Channel», функция помощника updateModelWithSelectedCANChannel вызывается. Как показано в приведенном ниже фрагменте кода, updateModelWithSelectedCANChannel находит путь к блоку для блоков «CAN Configuration», «CAN Transmit» и «CAN Receive» в рамках модели Simulink алгоритма Cruise Control. Используя set_param команды, свойства блоков «Device», «DeviceMenu» и «ObjConstructor» для каждого из этих трех блоков задаются соответствующими свойствами из выбранного пользователем устройства CAN и канала CAN.
function updateModelWithSelectedCANChannel(app, index) % Check to see if we are using a virtual CAN channel and whether the model is loaded. if app.canChannelInfo.DeviceModel(index) == "Virtual" && bdIsLoaded(app.mdl) % Using a virtual channel. % Find path to CAN configuration block. canConfigPath = find_system(app.mdl,'Variants', 'AllVariants', 'LookUnderMasks', 'all',... 'FollowLInks', 'on', 'Name', 'CAN Configuration'); % Find path to CAN transmit block. canTransmitPath = find_system(app.mdl,'Variants', 'AllVariants', 'LookUnderMasks', 'all',... 'FollowLInks', 'on', 'Name', 'CAN Transmit'); % Find path to CAN receive block. canReceivePath = find_system(app.mdl,'Variants', 'AllVariants', 'LookUnderMasks', 'all',... 'FollowLInks', 'on', 'Name', 'CAN Receive'); % Push the selected CAN channel into the simulation model CAN Configuration block. set_param(canConfigPath{1}, 'Device', app.canChannelDeviceSelected); set_param(canConfigPath{1}, 'DeviceMenu', app.canChannelDeviceSelected); set_param(canConfigPath{1}, 'ObjConstructor', app.canChannelConstructorSelected); % Push the selected CAN channel into the simulation model CAN Receive block. set_param(canReceivePath{1}, 'Device', app.canChannelDeviceSelected); set_param(canReceivePath{1}, 'DeviceMenu', app.canChannelDeviceSelected); set_param(canReceivePath{1}, 'ObjConstructor', app.canChannelConstructorSelected); % Push the selected CAN channel into the simulation model CAN Transmit block. set_param(canTransmitPath{1}, 'Device', app.canChannelDeviceSelected); set_param(canTransmitPath{1}, 'DeviceMenu', app.canChannelDeviceSelected); set_param(canTransmitPath{1}, 'ObjConstructor', app.canChannelConstructorSelected); end end
Открыв модель и пользовательский интерфейс, можно изучить взаимодействие с моделью в пользовательском интерфейсе. Нажмите кнопку «Start Sim», чтобы перевести модель и пользовательский интерфейс в оперативный режим. Поэкспериментируйте с секциями «Входы водителя» и «Калибровки» пользовательского интерфейса для управления моделью и включения алгоритма круиз-контроля. Вы увидите информацию о вовлеченности круиз-контроля и значениях скорости, отображенных в пользовательском интерфейсе. Также можно использовать функции ведения журнала и воспроизведения, описанные ранее, с помощью элементов управления пользовательского интерфейса.
Создание пользовательского интерфейса таким образом дает вам мощный и гибкий тестовый интерфейс, настраиваемый для вашего приложения. Он полезен при отладке и оптимизации алгоритма при моделировании. Изменяя выбранные CAN-устройства с виртуальных каналов на физические, можно продолжать использовать пользовательский интерфейс для взаимодействия с алгоритмом, работающим на платформе быстрого прототипирования или целевом контроллере.