Программное построение моделей для коммуникации CAN

Этот пример показывает, как программно создать модель Simulink, чтобы ввести коммуникацию CAN или CAN FD с помощью CAN DBC-файла. С помощью add_block и set_param функций Simulink можно добавить и полностью сконфигурировать блоки Vehicle Network Toolbox (VNT), чтобы взять основной алгоритм и добавить сетевые коммуникации. DBC-файл содержит сообщения CAN и информацию о сигнале. Основное особое внимание состоит в том, чтобы программно сконфигурировать CAN и CAN FD Pack и Unpack параметров блоков. Это может значительно повысить эффективность конструкции модели.

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

Пример модели (AlgorithmModel.slx) содержит блок подсистемы, называемый «Алгоритм». Этот блок представляет любой заданный алгоритм приложения, разработанный в Simulink. Блок Gain со значением 2 находится внутри этой подсистемы, например, в целях. Эта подсистема имеет вход сигнала CAN с именем «In1.» Это входное значение масштабируется на значение усиления. Масштабированное значение задается как выход этой подсистемы с именем «Out1.» Значение усиления изменяется или блок Gain заменяется другим алгоритмом пользователем для экспериментов.

Доступ к файлам базы данных CAN

Вы можете получить доступ к содержимому CAN DBC-файлов с помощью функции canDatabase. С помощью этой функции доступны подробные сведения о узлах сети, сообщениях и сигналах.

db = canDatabase("CANBus.dbc")
db = 
  Database with properties:

             Name: 'CANBus'
             Path: 'C:\Users\jpyle\Documents\MATLAB\Examples\vnt-ex60686316\CANBus.dbc'
            Nodes: {'ECU'}
         NodeInfo: [1×1 struct]
         Messages: {2×1 cell}
      MessageInfo: [2×1 struct]
       Attributes: {}
    AttributeInfo: [0×0 struct]
         UserData: []

Узел «ECU» определяется в примере CAN DBC-файла, как показано ниже.

node = nodeInfo(db,"ECU")
node = struct with fields:
             Name: 'ECU'
          Comment: ''
       Attributes: {}
    AttributeInfo: [0×0 struct]

Узел получает сообщение CAN «AlgInput», содержащее сигнал «InitialValue». Сигнал «InitialValue» является входом в алгоритм.

messageInfo(db,"AlgInput")
ans = struct with fields:
             Name: 'AlgInput'
     ProtocolMode: 'CAN'
          Comment: ''
               ID: 100
         Extended: 0
            J1939: []
           Length: 1
              DLC: 1
              BRS: 0
          Signals: {'InitialValue'}
       SignalInfo: [1×1 struct]
          TxNodes: {0×1 cell}
       Attributes: {}
    AttributeInfo: [0×0 struct]

Узел передает сообщение CAN «AlgOutput», содержащее сигнал «ScaledValue». Сигнал «ScaledValue» является выходом алгоритма.

messageInfo(db,"AlgOutput")
ans = struct with fields:
             Name: 'AlgOutput'
     ProtocolMode: 'CAN'
          Comment: ''
               ID: 200
         Extended: 0
            J1939: []
           Length: 2
              DLC: 2
              BRS: 0
          Signals: {'ScaledValue'}
       SignalInfo: [1×1 struct]
          TxNodes: {'ECU'}
       Attributes: {}
    AttributeInfo: [0×0 struct]

Программно создайте модель

Откройте модель примера

Откройте пример модели, которая будет сконфигурирована.

open AlgorithmModel

Добавьте и сконфигурируйте блок строения CAN

Добавьте и поместите блок Строение в модель.

add_block("canlib/CAN Configuration","AlgorithmModel/CAN Configuration")
set_param("AlgorithmModel/CAN Configuration","position",[50,330,250,410])

Установите параметр «Device», чтобы модель использовала виртуальное устройство CAN MathWorks.

set_param("AlgorithmModel/CAN Configuration","Device","MathWorks Virtual 1 (Channel 1)")

Добавьте и сконфигурируйте блок CAN Receive

Добавьте и поместите блок CAN Receive в модель.

add_block("canlib/CAN Receive","AlgorithmModel/CAN Receive")
set_param("AlgorithmModel/CAN Receive","position",[50,200,250,280])

Добавьте блок Terminator и поместите его. Это используется для подключения функционального порта блока CAN Receive. В этом примере выполняется простой прием сообщений. В целом размещение CAN Receive внутри Подсистемы вызова функций является предпочтительным подходом к моделированию с блоками CAN.

add_block("simulink/Sinks/Terminator","AlgorithmModel/Terminator")
set_param("AlgorithmModel/Terminator","position",[310,210,330,230])

Установите параметр «Device», чтобы модель использовала виртуальное CAN-устройство MathWorks.

set_param("AlgorithmModel/CAN Receive","Device","MathWorks Virtual 1 (Channel 1)")

Добавьте и сконфигурируйте CAN Unpack Block

Добавьте и поместите блок CAN Unpack в модель. По умолчанию блок находится в режиме «Необработанные данные».

add_block("canlib/CAN Unpack","AlgorithmModel/CAN Unpack")
set_param("AlgorithmModel/CAN Unpack","position",[350,220,600,300])

Установите следующие параметры в блоке CAN Unpack в один вызов функции:

  • DataFormat

  • CANdbFile

  • MsgList

set_param("AlgorithmModel/CAN Unpack","DataFormat","CANdb specified signals","CANdbFile",db.Path,"MsgList","AlgInput")

Если параметры «DataFormat» и «CANdbFile» уже установлены на блоке, выбранное сообщение может быть изменено только путем включения параметра «MsgList».

Добавьте и сконфигурируйте блок CAN Pack

Добавьте и поместите блок CAN Pack в модель.

add_block("canlib/CAN Pack","AlgorithmModel/CAN Pack")
set_param("AlgorithmModel/CAN Pack","position",[1000,220,1250,300])

Установите следующие параметры в блоке CAN Pack в один вызов функции:

  • DataFormat

  • CANdbFile

  • MsgList

set_param("AlgorithmModel/CAN Pack","DataFormat","CANdb specified signals","CANdbFile",db.Path,"MsgList","AlgOutput")

Добавьте и сконфигурируйте блок CAN Transmit

Добавьте и поместите блок CAN Transmit в модель.

add_block("canlib/CAN Transmit","AlgorithmModel/CAN Transmit")
set_param("AlgorithmModel/CAN Transmit","position",[1350,220,1550,300])

Установите параметр «Device», чтобы модель использовала виртуальное CAN-устройство MathWorks. Кроме того, периодическая передача включена с таймингом по умолчанию.

set_param("AlgorithmModel/CAN Transmit","Device","MathWorks Virtual 1 (Channel 1)")
set_param("AlgorithmModel/CAN Transmit", "EnablePeriodicTransmit", "on")

Соединения между блоками

Блоки CAN и блок алгоритма, добавленный в модель, теперь должны быть подключены. Необходимы координаты портов для всех блоков CAN.

canRxPort = get_param("AlgorithmModel/CAN Receive","PortConnectivity");
canUnpackPort = get_param("AlgorithmModel/CAN Unpack","PortConnectivity");
subSystemPort = get_param("AlgorithmModel/Subsystem","PortConnectivity");
canPackPort = get_param("AlgorithmModel/CAN Pack","PortConnectivity");
canTxPort = get_param("AlgorithmModel/CAN Transmit","PortConnectivity");
terminatorPort = get_param("AlgorithmModel/Terminator","PortConnectivity");

[canRxPortFunc,canRxPortMsg] = canRxPort.Position;
[canUnpackPortIn,canUnpackPortOut] = canUnpackPort.Position;
[subSystemPortIn,subSystemPortOut] = subSystemPort.Position;
[canPackPortIn,canPackPortOut] = canPackPort.Position;
canTxPortMsg = canTxPort.Position;
terminatorPortIn = terminatorPort.Position;

Добавьте линий для соединения всех блоков в соответствующем порядке.

add_line("AlgorithmModel",[canRxPortMsg ; canUnpackPortIn])
add_line("AlgorithmModel",[canUnpackPortOut ; subSystemPortIn])
add_line("AlgorithmModel",[subSystemPortOut ; canPackPortIn])
add_line("AlgorithmModel",[canPackPortOut ; canTxPortMsg])
add_line("AlgorithmModel",[canRxPortFunc ; terminatorPortIn])

Завершенная модель

Так выглядит модель после конструкции и строения.

Тестируйте построенную модель

Сконфигурируйте канал CAN в MATLAB для связи с моделью алгоритма

Создайте канал CAN в MATLAB с помощью канала 2 устройства MathWorks Virtual CAN. Он будет общаться с каналом CAN в модели. Кроме того, присоедините базу данных CAN к каналу MATLAB, чтобы она автоматически декодировала входящие данные CAN.

canCh = canChannel("MathWorks","Virtual 1",2);
canCh.Database = db;

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

algInputMsg = canMessage(canCh.Database,"AlgInput");

Запуск модели алгоритма

Назначьте время симуляции и запустите симуляцию

set_param("AlgorithmModel","StopTime","inf")
set_param("AlgorithmModel","SimulationCommand","start")

Пауза до полного запуска симуляции.

while strcmp(get_param("AlgorithmModel","SimulationStatus"),"stopped")
end

Запуск кода MATLAB

Запустите канал MATLAB CAN.

start(canCh);

Передайте несколько сообщений CAN с различными данными о сигнале в качестве входа в модель.

for value = 1:5
    algInputMsg.Signals.InitialValue = value*value;
    transmit(canCh,algInputMsg)
    pause(1)
end

Обратите внимание на образцы сообщений «AlgInput» и «AlgOutput», их временные и сигнальные значения.

msg = receive(canCh,Inf,"OutputFormat","timetable")
msg=10×8 timetable
        Time        ID     Extended        Name            Data        Length      Signals       Error    Remote
    ____________    ___    ________    _____________    ___________    ______    ____________    _____    ______

    0.009728 sec    100     false      {'AlgInput' }    {[      1]}      1       {1×1 struct}    false    false 
    0.15737 sec     200     false      {'AlgOutput'}    {1×2 uint8}      2       {1×1 struct}    false    false 
    1.0121 sec      100     false      {'AlgInput' }    {[      4]}      1       {1×1 struct}    false    false 
    1.1574 sec      200     false      {'AlgOutput'}    {1×2 uint8}      2       {1×1 struct}    false    false 
    2.0146 sec      100     false      {'AlgInput' }    {[      9]}      1       {1×1 struct}    false    false 
    2.1574 sec      200     false      {'AlgOutput'}    {1×2 uint8}      2       {1×1 struct}    false    false 
    3.0177 sec      100     false      {'AlgInput' }    {[     16]}      1       {1×1 struct}    false    false 
    3.1574 sec      200     false      {'AlgOutput'}    {1×2 uint8}      2       {1×1 struct}    false    false 
    4.0219 sec      100     false      {'AlgInput' }    {[     25]}      1       {1×1 struct}    false    false 
    4.1574 sec      200     false      {'AlgOutput'}    {1×2 uint8}      2       {1×1 struct}    false    false 

Функция canSignalTimetable обеспечивает эффективный способ разделения и организации значений сигналов сообщений CAN на отдельные расписания для каждого.

signalTimeTable = canSignalTimetable(msg)
signalTimeTable = struct with fields:
     AlgInput: [5×1 timetable]
    AlgOutput: [5×1 timetable]

signalTimeTable.AlgInput
ans=5×1 timetable
        Time        InitialValue
    ____________    ____________

    0.009728 sec          1     
    1.0121 sec            4     
    2.0146 sec            9     
    3.0177 sec           16     
    4.0219 sec           25     

signalTimeTable.AlgOutput
ans=5×1 timetable
       Time        ScaledValue
    ___________    ___________

    0.15737 sec         2     
    1.1574 sec          8     
    2.1574 sec         18     
    3.1574 sec         32     
    4.1574 sec         50     

Остановите канал CAN.

stop(canCh)

Остановите модель алгоритма

set_param("AlgorithmModel","SimulationCommand","stop")

Постройте график данных сигнала

Постройте график начальных и масштабированных значений сигналов сообщений CAN относительно временных меток, которые произошли на виртуальной шине. Обратите внимание на изменение значений, переданное MATLAB, и масштабирование данных, выполненное моделью.

plot(signalTimeTable.AlgInput.Time,signalTimeTable.AlgInput.InitialValue,"Marker","square","MarkerIndices",1:5)
hold on
plot(signalTimeTable.AlgOutput.Time,signalTimeTable.AlgOutput.ScaledValue,"Marker","square","MarkerIndices",1:5)
hold off
xlabel("TimeStamp");
ylabel("CAN Signal Value");
legend("Initial Value","Scaled Value","Location","northeastoutside");
legend("boxoff");