Разработка Приложения App Designer для Модели Simulink использование CAN

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

  • Тестовое приложение связь поддержки пользовательского интерфейса с моделью алгоритма Simulink для тестирования через CAN

  • Тестовое приложение логгирование поддержки пользовательского интерфейса и воспроизведение данных о CAN

  • Модель алгоритма Simulink

Добавление виртуальной коммуникации канала CAN к пользовательскому интерфейсу

В этом разделе мы описываем функции ключа Vehicle Network Toolbox, используемые, чтобы добавить интерфейс канала CAN в модель тестового приложения алгоритма Круиз-контроля Simulink. Это затрагивает следующие темы:

  • Получение списка доступных каналов CAN

  • Форматирование информации о канале для создания канала

  • Создание канала в пользовательском интерфейсе

  • Сконфигурируйте пользовательский интерфейс, чтобы передать и получить сообщения CAN

  • Запуск и остановка канала

  • Извлечение выбранных сообщений

Открытие App Designer

Откройте тестовое приложение пользовательский интерфейс в App Designer. С тестовым приложением пользовательский интерфейс открывается в App Designer, который можно чередовать между представлениями "Проекта" и "Кода", чтобы следовать вперед, когда вы исследуете средства управления и соответствующий код MATLAB, чтобы связаться с моделью алгоритма Круиз-контроля Simulink через виртуальные каналы CAN. Используйте следующую команду, чтобы открыть пример пользовательский интерфейс: appdesigner('CruiseControlTestUI.mlapp').

Перечислите доступные каналы CAN

Во-первых, реализуйте механизм, чтобы найти и представить список доступных каналов CAN для пользователя, чтобы выбрать. Для этого мы добавили пункт меню "Channel Configuration" в главном левом угле тестового приложения пользовательский интерфейс. Это имеет подменю "Select CAN Channel".

Когда пользователь нажимает на подменю "Select CAN Channel", функция помощника getAvailableCANChannelInfo(app) называется через коллбэк подменю. getAvailableCANChannelInfo() использует функцию Vehicle Network Toolbox 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 в пользовательском интерфейсе

Когда пользовательский интерфейс открыт сначала и инициализирован, отформатированная строка конструктора канала 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 

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 использует следующие функции Vehicle Network Toolbox:

  • canChannel, чтобы инстанцировать объекта канала использование команды eval и строки конструктора канала CAN сохранил в приложении свойство UI app.canChannelConstructorSelected. Результирующий объект канала хранится в приложении свойство UI app.canChannelObj.

  • canDatabase, чтобы создать базу данных CAN (.DBC) объект, представляющий.DBC файл. Этот объект хранится в свойстве "Database" объекта канала.

Setup, чтобы передать сообщения CAN

После подготовки выбранного объекта канала 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

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 использует следующие функции Vehicle Network Toolbox:

  • canMessage, чтобы создать сообщение CAN, базирующееся заданный в объекте базы данных CAN.

  • transmitPeriodic, чтобы поставить в очередь сообщение, хранившее в свойстве UI app.cruiseControlCmdMessage для периодической передачи на канале, заданном объектом канала, хранившим в свойстве UI app.canChannelObj, на уровне, заданном последним аргументом, в этом случае каждую 0.1 секунды.

Setup, чтобы получить сообщения CAN

Пользовательский интерфейс должен получить сообщения 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:

  • получите, чтобы получить сообщения CAN из шины CAN. В этом случае функция сконфигурирована, чтобы получить все сообщения начиная с предыдущего вызова и вывести результаты как расписание MATLAB.

Извлечение избранных сообщений CAN

Функция помощника 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

Однажды канал 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:

  • начните запускать выполнение канала CAN. Канал останется в сети, пока команда остановки не будет дана.

Остановите канал 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:

  • остановитесь, чтобы остановить канал CAN. Канал останется оффлайновым, пока другие не запустят, команда дается.

Добавление возможности журнала и воспроизведения CAN

На этом шаге мы опишем функции ключа Vehicle Network Toolbox, используемые, чтобы добавить способность регистрировать, сохранить, и воспроизвести сообщения CAN. Чтобы реализовать эту функциональность, мы инстанцируем второго канала CAN, идентичного первому созданному. Поскольку второй объект канала CAN идентичен первому, он будет видеть и собирать те же сообщения как первый объект канала CAN. Второй канал CAN будет запущен, когда пользователь нажмет кнопку логгирования запуска на пользовательском интерфейсе как показано в снимке экрана пользовательского интерфейса ниже. Канал продолжает запускать и собирать сообщения, пока пользователь не нажимает кнопку логгирования остановки на пользовательском интерфейсе. Если пользователь прекращает регистрировать сообщения CAN, мы получим все сообщения, которые накопились в буфере сообщения для второго объекта канала CAN, извлеките сообщения, мы интересуемся воспроизведением и сохраняем их в.MAT файл. Если сообщения были сохранены, мы можем воспроизвести их использующий первый канал CAN, чтобы обеспечить входной стимул для модели алгоритма Круиз-контроля Simulink для отладки и целей верификации алгоритма.

Это описание затронет следующие темы:

  • Setup канал, чтобы регистрировать сообщения CAN

  • Запуск и Остановка канала

  • Получение и извлечение регистрируемых сообщений CAN

  • Сохранение извлеченных сообщений к файлу

  • Загрузка сохраненных сообщений из файла

  • Запустите воспроизведение регистрируемых сообщений CAN

  • Остановите воспроизведение регистрируемых сообщений CAN

Setup Объект канала 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

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 использует следующие функции Vehicle Network Toolbox:

  • canChannel, чтобы инстанцировать объекта канала использование команды eval и строки конструктора канала CAN сохранил в приложении свойство UI app.canChannelConstructorSelected. Результирующий объект канала хранится в приложении свойство UI app.canLogChannelObj.

  • canDatabase, чтобы создать базу данных CAN (.DBC) объект, представляющий.DBC файл. Этот объект хранится в свойстве "Database" объекта канала.

Запуск логарифмического канала CAN

Как с первым каналом 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:

  • начните запускать выполнение канала CAN. Канал останется в сети, пока команда остановки не будет дана.

Остановка логарифмического канала 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:

  • остановитесь, чтобы остановить канал 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:

  • получите, чтобы получить сообщения 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".

  • воспроизведите, чтобы воспроизвести регистрируемые данные о сообщении 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:

  • остановитесь, чтобы остановить канал CAN, чтобы остановить воспроизведение регистрируемых данных о сообщении CAN.

  • transmitPeriodic, чтобы повторно включить периодическую передачу сигналов команды, отправленных в модель алгоритма Круиз-контроля в сообщении "CruiseCtrlCmd".

  • начните перезапускать канал CAN, таким образом, пользователь может еще раз ввести тестовые сигналы стимула к модели алгоритма Круиз-контроля в интерактивном режиме от пользовательского интерфейса.

Добавление виртуальной коммуникации канала CAN к модели алгоритма круиз-контроля Simulink

На этом шаге мы описываем, как блоки Simulink Vehicle Network Toolbox использовались, чтобы добавить виртуальную коммуникационную возможность CAN в модель алгоритма Круиз-контроля Simulink.

Это описание затронет следующие темы:

  • Добавление сообщения CAN получает возможность

  • Добавление сообщения CAN передает возможность

  • Продвижение конфигурационной информации канала CAN от пользовательского интерфейса до модели Simulink

Откройте алгоритм круиз-контроля модель Simulink

Запустите функции помощника, чтобы сконфигурировать рабочую область необходимыми параметрами данных и затем открыть модель тестовой обвязки алгоритма Круиз-контроля. С открытой моделью Simulink можно исследовать фрагменты модели, объясненной в разделах ниже. Выполните helperPrepareTestBenchParameterData сопровождаемый helperConfigureAndOpenTestBench.

Добавление сообщения CAN получает возможность

Для модели 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 в отдельные сигналы, один для каждого элемента данных, заданного в сообщении.

Добавление возможности передачи сообщения 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 и настройки канала между пользовательским интерфейсом и моделью 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 от виртуальных каналов до физических каналов можно продолжить использовать пользовательский интерфейс, чтобы взаимодействовать с алгоритмом, запускающимся в платформе быстрого прототипирования или предназначаться для контроллера.