Этот пример показывает, как программно создать модель 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 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
Добавьте и поместите блок Строение в модель.
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 в модель.
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 в модель. По умолчанию блок находится в режиме «Необработанные данные».
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 в модель.
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 в модель.
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 с помощью канала 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 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");