В этом примере показано, как создать пользовательский интерфейс (UI) тестового приложения и соединить его с моделью Simulink с помощью виртуальных каналов CAN. Тестовое приложение пользовательский интерфейс создается с помощью Приложения MATLAB Designer™ наряду с несколькими функциями Vehicle Network Toolbox™, чтобы обеспечить виртуальный интерфейс шины CAN к модели Simulink автомобильного приложения круиз-контроля. Тестовое приложение, которое пользовательский интерфейс позволяет пользователю обеспечивать входному стимулу для модели алгоритма круиз-контроля, наблюдать результаты, возвращенные из модели, регистрировать сообщения CAN, чтобы получить тестовые стимулы и воспроизведение, регистрировало сообщения CAN, чтобы отладить и откорректировать проблемы с моделью алгоритма. Пример показывает функции ключа Vehicle Network Toolbox, и блоки раньше реализовывали коммуникацию CAN в следующих областях:
Тестовое приложение связь поддержки пользовательского интерфейса с моделью алгоритма Simulink для тестирования через CAN
Тестовое приложение логгирование поддержки пользовательского интерфейса и воспроизведение данных о CAN
Модель алгоритма Simulink
В этом разделе мы описываем функции ключа Vehicle Network Toolbox, используемые, чтобы добавить интерфейс канала CAN в модель тестового приложения алгоритма Круиз-контроля Simulink. Это затрагивает следующие темы:
Получение списка доступных каналов CAN
Форматирование информации о канале для создания канала
Создание канала в пользовательском интерфейсе
Сконфигурируйте пользовательский интерфейс, чтобы передать и получить сообщения CAN
Запуск и остановка канала
Извлечение выбранных сообщений
Откройте тестовое приложение пользовательский интерфейс в App Designer. С тестовым приложением пользовательский интерфейс открывается в App Designer, который можно чередовать между представлениями "Проекта" и "Кода", чтобы следовать вперед, когда вы исследуете средства управления и соответствующий код MATLAB, чтобы связаться с моделью алгоритма Круиз-контроля Simulink через виртуальные каналы CAN. Используйте следующую команду, чтобы открыть пример пользовательский интерфейс: appdesigner('CruiseControlTestUI.mlapp')
.
Во-первых, реализуйте механизм, чтобы найти и представить список доступных каналов CAN для пользователя, чтобы выбрать. Для этого мы добавили пункт меню "Channel Configuration" в главном левом угле тестового приложения пользовательский интерфейс. Это имеет подменю "Select CAN Channel".
Когда пользователь нажимает на подменю "Select CAN Channel", функция помощника getAvailableCANChannelInfo(app)
называется через коллбэк подменю. getAvailableCANChannelInfo()
использует Vehicle Network Toolbox function canChannelList
, чтобы обнаружить доступные каналы 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
Запустите canChannelList
чтобы видеть, как доступная информация о канале 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"
Список каналов возвращен в canChannelList
хранится в свойстве UI app.canChannelInfo
и затем отображенный пользователю в "Выборе канала CAN" listdlg
как показано в снимке экрана выше.
Пользователь выбирает канал CAN из "Выбора канала CAN" listdlg
. 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.canChannelInfo, чтобы собрать строку конструктора Object канала, соответствующую каналу, пользователь, выбранный из селектора канала, перечисляет диалоговое окно. Чтобы видеть пример строки конструктора канала CAN, выполните код, показанный ниже.
index = 1; canChannelConstructor = "canChannel(" + "'" + canChannels.Vendor(index) + "'" + ", " + "'" + canChannels.Device(index) + "'" + ", " + canChannels.Channel(index) + ")"
canChannelConstructor = "canChannel('MathWorks', 'Virtual 1', 1)"
Строка конструктора канала CAN хранится в приложении свойство UI app.canChannelConstructorSelected
и будет использоваться позже, чтобы создать выбранный объект канала CAN в приложении пользовательский интерфейс, а также обновить блоки Simulink Vehicle Network Toolbox, которые реализуют интерфейс канала CAN в модели алгоритма Круиз-контроля Simulink.
Когда пользовательский интерфейс открыт сначала и инициализирован, отформатированная строка конструктора канала CAN, сохраненная в app.canChannelConstructorSelected, используется функцией помощника setupCANChannel
чтобы создать экземпляр объекта канала CAN, соедините базу данных конфигурации сети (.DBC) файл и установите скорость шины как показано во фрагменте кода ниже. Получившийся объект канала хранится в свойстве UI app.canChannelObj.
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
Чтобы видеть объект базы данных CAN в качестве примера, выполните следующее:
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: []
Чтобы видеть объект канала CAN в качестве примера, выполните следующее:
% 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
использует следующие функции Vehicle Network Toolbox:
canChannel
инстанцировать объекта канала использование команды eval и строки конструктора канала CAN сохранило в приложении свойство UI app.canChannelConstructorSelected
.
Результирующий объект канала хранится в приложении свойство UI app.canChannelObj.
canDatabase
создать базу данных CAN (.DBC) объект, представляющий файл DBC. Этот объект хранится в свойстве "Database" объекта канала.
После подготовки выбранного объекта канала CAN и хранения его в свойстве UI app.canChannelObj, следующий шаг должен вызвать функцию помощника 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
Чтобы видеть, на что похож объект сообщения CAN, выполните следующее:
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
использует следующие функции Vehicle Network Toolbox:
canMessage
создавать сообщение CAN, базирующееся заданный в объекте базы данных CAN.
transmitPeriodic
поставить в очередь сообщение, хранившее в свойстве UI app.cruiseControlCmdMessage для периодической передачи на канале, заданном объектом канала, хранившим в свойстве UI app.canChannelObj, на уровне, заданном последним аргументом, в этом случае каждую 0.1 секунды.
Пользовательский интерфейс должен получить сообщения CAN на периодическом базисе, чтобы обновить графики с обратной связью от алгоритма Круиз-контроля в модели 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
использует следующие функции Vehicle Network Toolbox:
receive
получать сообщения CAN из шины CAN. В этом случае функция сконфигурирована, чтобы получить все сообщения начиная с предыдущего вызова и вывести результаты как расписание MATLAB.
Функция помощника getCruiseCtrlFBCANmessage
отфильтровывает сообщения "CruiseCtrlFB" из всех полученных сообщений CAN, извлекает tspeedFb и сигналы engagedFb из этих сообщений, и конкатенирует их к объектам timeseries MATLAB для сигналов engagedFb и tspeedFb. Эти объекты timeseries хранятся в свойствах UI app.tspeedFb и app.engagedFb, соответственно. Сохраненные сигналы timeseries используются, чтобы обновить графики для каждого сигнала на пользовательском интерфейсе. Отметьте использование seconds
метод, чтобы преобразовать данные времени, хранимые в расписании от массива длительности в эквивалентный числовой массив в модулях секунд в timeseries, возражает для каждого сигнала.
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
использует следующие функции Vehicle Network Toolbox:
canSignalTimetable
возвратить расписание MATLAB, содержащее сигналы из сообщения CAN CruiseCtrlFB.
Однажды канал CAN возражают, что app.canChannelObj инстанцировали, и сообщения были настроены, чтобы быть переданными и полученными, мы можем теперь запустить канал. Когда пользователь кликает по запуску 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
использует следующую функцию Vehicle Network Toolbox:
start
запустить выполнение канала CAN. Канал останется в сети, пока команда остановки не будет дана.
Когда пользователь кликает по остановке 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
использует следующую функцию Vehicle Network Toolbox:
stop
остановить канал CAN. Канал останется оффлайновым, пока другие не запустят, команда дается.
На этом шаге мы опишем функции ключа Vehicle Network Toolbox, используемые, чтобы добавить способность регистрировать, сохранить, и воспроизвести сообщения CAN. Чтобы реализовать эту функциональность, мы инстанцируем второго канала CAN, идентичного первому созданному. Поскольку второй объект канала CAN идентичен первому, он будет видеть и собирать те же сообщения как первый объект канала CAN. Второй канал CAN будет запущен, когда пользователь нажмет кнопку логгирования запуска на пользовательском интерфейсе как показано в снимке экрана пользовательского интерфейса ниже. Канал продолжает запускать и собирать сообщения, пока пользователь не нажимает кнопку логгирования остановки на пользовательском интерфейсе. Если пользователь прекращает регистрировать сообщения CAN, мы получим все сообщения, которые накопились в буфере сообщения для второго объекта канала CAN, извлеките сообщения, мы интересуемся воспроизведением и сохраняем их в MAT-файл. Если сообщения были сохранены, мы можем воспроизвести их использующий первый канал CAN, чтобы обеспечить входной стимул для модели алгоритма Круиз-контроля Simulink для отладки и целей верификации алгоритма.
Это описание затронет следующие темы:
Setup канал, чтобы регистрировать сообщения CAN
Запуск и Остановка канала
Получение и извлечение регистрируемых сообщений CAN
Сохранение извлеченных сообщений к файлу
Загрузка сохраненных сообщений из файла
Запустите воспроизведение регистрируемых сообщений CAN
Остановите воспроизведение регистрируемых сообщений CAN
Способом, непосредственно аналогичным тому, как первый канал CAN инстанцировали, отформатированная строка конструктора канала CAN, сохраненная в app.canChannelConstructorSelected, используется новой функцией помощника setupCANLogChannel
чтобы создать второй экземпляр объекта канала CAN, соедините ту же базу данных конфигурации сети (.DBC) файл, как использовался для первого канала и установил скорость шины как показано во фрагменте кода ниже. Получившийся объект канала хранится в свойстве UI app.canLogChannelObj.
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
Чтобы видеть объект базы данных CAN в качестве примера, выполните следующий код:
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: []
Чтобы видеть объект канала CAN в качестве примера, выполните следующий код:
% 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
использует следующие функции Vehicle Network Toolbox:
canChannel
инстанцировать объекта канала использование команды eval и строки конструктора канала CAN сохранило в приложении свойство UI app.canChannelConstructorSelected
.
Результирующий объект канала хранится в приложении свойство UI app.canLogChannelObj.
canDatabase
создать базу данных CAN (.DBC) объект, представляющий файл DBC. Этот объект хранится в свойстве "Database" объекта канала.
Как с первым каналом CAN, объектным app.canLogChannelOb канала CAN, был инстанцирован, когда тестовое приложение пользовательский интерфейс открыто. Когда пользователь нажимает кнопку 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
использует следующую функцию Vehicle Network Toolbox:
start
запустить выполнение канала 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
использует следующую функцию Vehicle Network Toolbox:
stop
остановить канал CAN. Канал останется оффлайновым, пока другие не запустят, команда дается.
Если канал CAN логгирования был остановлен, функция помощника retrieveLoggedCANMessages
, показанный во фрагменте кода ниже, называется, чтобы получить все сообщения CAN из второй шины канала. Сообщения CAN получены от второй шины канала с помощью receive
команда и логическая индексация используются, чтобы извлечь сообщения "CruiseCtrlCmd" из всего расписания сообщения, возвращенного 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
использует следующие функции Vehicle Network Toolbox:
receive
получать сообщения CAN из шины CAN. В этом случае функция сконфигурирована, чтобы получить все сообщения начиная с предыдущего вызова и вывести результаты как расписание MATLAB.
Когда пользователь нажимает кнопку "Save Logged Data" на пользовательском интерфейсе, функция помощника saveLoggedCANDataToFile
называется. Эта функция открывает окно файлового браузера с помощью uinputfile
функция. uinputfile
возвращает имя файла и путь, выбранный пользователем, чтобы хранить регистрируемые данные о сообщении CAN. Функция Vehicle Network Toolbox canMessageReplayBlockStruct
используется, чтобы преобразовать сообщения CAN из расписания MATLAB в форму, которую может использовать Блок CAN Replay. Если регистрируемые данные о сообщении CAN были преобразованы и сохранены в файл, их можно вспомнить и воспроизвели более позднее использование блока Simulink "Воспроизведения" Vehicle Network Toolbox. Воспроизводить сообщения в MATLAB с Vehicle Network Toolbox с 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
использует следующую функцию Vehicle Network Toolbox:
canMessageReplayBlockStruct
преобразовывать сообщения CAN сохранило в расписании MATLAB в форму, которая может использоваться Блоком Воспроизведения сообщения CAN.
Когда пользователь нажимает кнопку "Load Logged Data" на пользовательском интерфейсе функция помощника loadLoggedCANDataFromFile
называется. Эта функция открывает окно файлового браузера с помощью uigetfile
функция, которая возвращает регистрируемое имя файла сообщения, выбранное пользователем. Регистрируемые данные о сообщении CAN загружаются из файла и преобразованы назад в представление расписания для использования с Vehicle Network Toolbox replay
команда. Обратите внимание на то, что тот же файл данных мог использоваться непосредственно с блоком Simulink "Воспроизведения" Vehicle Network Toolbox, если бы пользователь желал воспроизвести данные из модели 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
использует следующую функцию Vehicle Network Toolbox:
canMessageTimetable
преобразовывать сообщения CAN, сохраненные в форме, совместимой с блоком Simulink "Воспроизведения" сообщения CAN назад в расписание MATLAB для использования с replay
функция.
После того, как регистрируемые данные о сообщении CAN загрузились в пользовательский интерфейс и переформатировали его, готово к воспроизведению с помощью Vehicle Network Toolbox replay
команда. Когда пользователь нажимает кнопку "Start Replay" на пользовательском интерфейсе функция помощника startPlaybackOfLoggedCANData
называется. Для того, чтобы воспроизвести регистрируемые данные о сообщении CAN по первому каналу CAN, все действие, сопоставленное с этим каналом, должно быть остановлено и любые буферизированные очищенные данные о сообщении. Как показано во фрагменте кода ниже, startPlaybackOfLoggedCANData
выключает периодическую передачу сообщений CAN, останавливает канал CAN, очищает любые данные о сообщении CAN, буферизованные в пользовательском интерфейсе, и очищает графики, отображающие данные сигнала, возвращенные из модели алгоритма Круиз-контроля. Канал 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
startPlaybackOfLoggedCANData использует следующие функции Vehicle Network Toolbox:
transmitPeriodic
отключить периодическую передачу сигналов команды, отправленных в модель алгоритма Круиз-контроля в сообщении "CruiseCtrlCmd".
replay
воспроизводить регистрируемые данные о сообщении CAN на первом канале CAN.
Когда пользователь нажимает кнопку "Stop Replay" на пользовательском интерфейсе функция помощника stopPlaybackOfLoggedCANData
называется. Для того, чтобы остановить воспроизведение регистрируемых данных о сообщении CAN канал CAN, где данные воспроизводятся, должен быть остановлен. Если это сделано, периодическая передача сообщения "CruiseCtrlCmd" может быть повторно включена, и канал перезапущен так, чтобы пользователь еще раз смог ввести тестовые сигналы стимула к модели алгоритма Круиз-контроля в интерактивном режиме от пользовательского интерфейса. Как показано во фрагменте кода ниже, stopPlaybackOfLoggedCANData
первые остановки канал, который останавливает воспроизведение регистрируемых данных о сообщении. Регистрируемые данные о сообщении очищены от локальных буферов на пользовательском интерфейсе, а также графиках, отображающих данные сигнала, возвращенные из модели алгоритма Круиз-контроля. Периодическая передача сообщения "CruiseCtrlCmd" повторно включена, и перезапущенный канал 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
использует следующие функции Vehicle Network Toolbox:
stop
остановить канал CAN, чтобы остановить воспроизведение регистрируемых данных о сообщении CAN.
transmitPeriodic
повторно включить периодическую передачу сигналов команды, отправленных в модель алгоритма Круиз-контроля в сообщении "CruiseCtrlCmd".
start
чтобы перезапустить канал CAN так, пользователь может еще раз ввести тестовые сигналы стимула к модели алгоритма Круиз-контроля в интерактивном режиме от пользовательского интерфейса.
На этом шаге мы описываем, как блоки Simulink Vehicle Network Toolbox использовались, чтобы добавить виртуальную коммуникационную возможность CAN в модель алгоритма Круиз-контроля Simulink.
Это описание затронет следующие темы:
Добавление сообщения CAN получает возможность
Добавление сообщения CAN передает возможность
Продвижение конфигурационной информации канала CAN от пользовательского интерфейса до модели Simulink
Запустите функции помощника, чтобы сконфигурировать рабочую область необходимыми параметрами данных и затем открыть модель тестовой обвязки алгоритма Круиз-контроля. С открытой моделью Simulink можно исследовать фрагменты модели, объясненной в разделах ниже. Выполните helperPrepareTestBenchParameterData
сопровождаемый helperConfigureAndOpenTestBench
.
Для модели Simulink алгоритма Круиз-контроля, чтобы получить данные о CAN из теста пользовательский интерфейс требует, чтобы блок соединил модель Simulink с определенным устройством CAN, блок, чтобы получить сообщения CAN от выбранного устройства и блок, чтобы распаковать полезную нагрузку данных сообщений, полученных в отдельные сигналы. Чтобы выполнить это, "Входная" подсистема добавляется к модели Simulink алгоритма Круиз-контроля. "Входная" подсистема использует Настройку CAN Vehicle Network Toolbox, CAN Получают, и CAN Распаковывает блоки, соединенные как показано в снимке экрана ниже.
Блок Configuration CAN позволяет пользователю определять который из доступных устройств CAN и каналов, чтобы соединиться с моделью Simulink. Блок CAN Receive получает сообщения CAN от устройства CAN и канала, выбранного в Блоке Configuration CAN. Это также позволяет пользователю получать все сообщения на шине или применять фильтр, чтобы получить только избранное сообщение (сообщения). Блок CAN Unpack был сконфигурирован, чтобы считать определяемую пользователем сетевую базу данных (.DBC) файл. Это позволяет пользователю определять имя сообщения, идентификатор сообщения и полезную нагрузку данных, чтобы распаковать сигналы с этим блоком. Входные порты Simulink автоматически добавляются к блоку для каждого сигнала, заданного в сообщении в файле сетевой базы данных.
"Входная" подсистема модели Simulink алгоритма Круиз-контроля использует следующие блоки Simulink Vehicle Network Toolbox, чтобы получить сообщения CAN:
Блок Configuration CAN, чтобы выбрать, который устройство канала CAN соединиться с моделью Simulink.
CAN Получает Блок, чтобы получить сообщения CAN от устройства CAN, выбранного в Блоке Configuration CAN.
CAN Распаковывает Блок, чтобы распаковать полезную нагрузку полученного сообщения (сообщений) CAN в отдельные сигналы, один для каждого элемента данных, заданного в сообщении.
Для модели Simulink алгоритма Круиз-контроля, чтобы передать данные о CAN к тесту пользовательский интерфейс требует, чтобы блок соединил модель Simulink с определенным устройством CAN, блок, чтобы упаковать Сигналы Simulink в полезную нагрузку данных одного или нескольких сообщений CAN и блок, чтобы передать сообщения CAN от выбранного устройства. Чтобы выполнить это, "Выходная" подсистема добавляется к модели Simulink алгоритма Круиз-контроля. "Выходная" подсистема использует пакет CAN Vehicle Network Toolbox и блоки Передачи CAN, соединенные как показано в снимке экрана ниже.
Блок CAN Pack был сконфигурирован, чтобы считать определяемую пользователем сетевую базу данных (.DBC) файл. Это позволяет пользователю определять имя сообщения, идентификатор сообщения и полезную нагрузку данных, чтобы упаковать сигнал этим блоком. Выходные порты Simulink автоматически добавляются к блоку для каждого сигнала, заданного в сообщении в файле сетевой базы данных. Блок CAN Transmit передаст сообщение, собранное Блоком Пакета на канале CAN и устройстве CAN, выбранном пользователем с Блоком Configuration. Обратите внимание на то, что второй Блок Configuration CAN не требуется, поскольку "Выходная" подсистема передает сообщения CAN на том же канале CAN, и устройство раньше получало сообщения CAN.
"Выходная" подсистема модели Simulink алгоритма Круиз-контроля использует следующие блоки Simulink Vehicle Network Toolbox, чтобы передать сообщения CAN:
Блок Пакета CAN, чтобы распаковать полезную нагрузку полученного сообщения (сообщений) CAN в отдельные сигналы, один для каждого элемента данных, заданного в сообщении.
Блок Передачи CAN, чтобы получить сообщения CAN от устройства CAN, выбранного в Блоке Configuration CAN.
Поскольку пользователь выбирает, какое из доступных устройств CAN и образовывает канал, чтобы использовать от пользовательского интерфейса, эта информация должна быть отправлена в модель Simulink алгоритма Круиз-контроля, чтобы сохранить устройство CAN и настройки канала между пользовательским интерфейсом и моделью Simulink в синхронизации. Для того, чтобы выполнить это, устройство CAN и информацию о канале, используемую Vehicle Network Toolbox "Настройка CAN", "Передача CAN" и "CAN Получают" блоки, должен быть сконфигурирован программно от пользовательского интерфейса. Каждый раз пользователь выбирает устройство CAN и канал CAN в меню "Channel Configuration/Select CAN Channel" пользовательского интерфейса, функция помощника updateModelWithSelectedCANChannel
называется. Как показано во фрагменте кода ниже, updateModelWithSelectedCANChannel
находит блок path для "Настройки CAN", "Передача CAN", и "CAN Получают" блоки в модели Simulink алгоритма Круиз-контроля. Используя set_param команды, "Устройство", "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 от виртуальных каналов до физических каналов можно продолжить использовать пользовательский интерфейс, чтобы взаимодействовать с алгоритмом, запускающимся в платформе быстрого прототипирования или предназначаться для контроллера.