Периодическая передача сообщений CAN

В этом примере показано, как использовать функции автоматической передачи сообщений CAN Vehicle Network Toolbox™ для отправки периодических сообщений. Он использует каналы MathWorks Virtual CAN, подключенные в строении закольцовывания. Поскольку этот пример основан на отправке и получении сообщений CAN в виртуальной сети, запуск CAN Explorer в сочетании может обеспечить более полное понимание того, что делает код. Чтобы запустить CAN Explorer, откройте и сконфигурируйте его, чтобы использовать тот же интерфейс, что и принимающий канал примера. Убедитесь, что запустили CAN Explorer, прежде чем начинать запускать пример в порядок, чтобы видеть все сообщения по мере их появления.

Создайте каналы CAN

Создайте каналы CAN, по которым можно использовать команды автоматической передачи сообщений.

txCh = canChannel('MathWorks', 'Virtual 1', 1);
rxCh = canChannel('MathWorks', 'Virtual 1', 2);

В этом примере вы будете использовать файл базы данных CAN для определения и декодирования сообщений. Откройте базу данных и присоедините ее к каналам CAN.

db = canDatabase('CANDatabasePeriodic.dbc');
txCh.Database = db;
rxCh.Database = db;

Создание сообщений CAN

Можно создать сообщения CAN для регистрации для периодической передачи с помощью информации базы данных.

msgFast = canMessage(db, 'EngineMsg')
msgFast = 
  Message with properties:

   Message Identification
    ProtocolMode: 'CAN'
              ID: 100
        Extended: 0
            Name: 'EngineMsg'

   Data Details
       Timestamp: 0
            Data: [0 0 0 0 0 0 0 0]
         Signals: [1x1 struct]
          Length: 8

   Protocol Flags
           Error: 0
          Remote: 0

   Other Information
        Database: [1x1 can.Database]
        UserData: []

msgSlow = canMessage(db, 'TransmissionMsg')
msgSlow = 
  Message with properties:

   Message Identification
    ProtocolMode: 'CAN'
              ID: 200
        Extended: 0
            Name: 'TransmissionMsg'

   Data Details
       Timestamp: 0
            Data: [0 0 0 0 0 0 0 0]
         Signals: [1x1 struct]
          Length: 8

   Protocol Flags
           Error: 0
          Remote: 0

   Other Information
        Database: [1x1 can.Database]
        UserData: []

Сконфигурируйте сообщения для периодической передачи

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

transmitPeriodic(txCh, msgFast, 'On', 0.100);
transmitPeriodic(txCh, msgSlow, 'On', 0.500);

Запуск периодической передачи сообщения

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

start(rxCh);
start(txCh);
pause(2);

Изменение Transmitted Data

Чтобы обновить live-сообщение или данные сигнала, отправленные на шину CAN, запишите новые значения в сообщение, которое вы первоначально создали, используя свойство данных или интерфейс сигналов.

msgFast.Signals.VehicleSpeed = 60;
pause(1);
msgFast.Signals.VehicleSpeed = 65;
pause(1);
msgFast.Signals.VehicleSpeed = 70;
pause(1);

Получение сообщений

Остановите каналы CAN и получите все периодически передаваемые сообщения для анализа.

stop(txCh);
stop(rxCh);
msgRx = receive(rxCh, Inf, 'OutputFormat', 'timetable');
msgRx(1:15, :)
ans=15×8 timetable
        Time        ID     Extended           Name                   Data            Length      Signals       Error    Remote
    ____________    ___    ________    ___________________    ___________________    ______    ____________    _____    ______

    0.014177 sec    100     false      {'EngineMsg'      }    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.014183 sec    200     false      {'TransmissionMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.11415 sec     100     false      {'EngineMsg'      }    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.21416 sec     100     false      {'EngineMsg'      }    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.31416 sec     100     false      {'EngineMsg'      }    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.41418 sec     100     false      {'EngineMsg'      }    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.51416 sec     100     false      {'EngineMsg'      }    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.51416 sec     200     false      {'TransmissionMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.61416 sec     100     false      {'EngineMsg'      }    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.71416 sec     100     false      {'EngineMsg'      }    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.81417 sec     100     false      {'EngineMsg'      }    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.91417 sec     100     false      {'EngineMsg'      }    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    1.0142 sec      100     false      {'EngineMsg'      }    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    1.0142 sec      200     false      {'TransmissionMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    1.1142 sec      100     false      {'EngineMsg'      }    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 

Анализируйте периодическое поведение передачи

Можно анализировать распределение сообщений путем построения графиков идентификаторов каждого сообщения относительно их временных меток. Заметьте различие между тем, как часто эти два сообщения появляются в соответствии с их периодическими тарифами.

plot(msgRx.Time, msgRx.ID, 'x')
ylim([0 400])
title('Message Distribution', 'FontWeight', 'bold')
xlabel('Timestamp')
ylabel('CAN Identifier')

Figure contains an axes. The axes with title Message Distribution contains an object of type line.

Для дальнейшего анализа разделите эти два сообщения на отдельные расписания.

msgRxFast = msgRx(strcmpi('EngineMsg', msgRx.Name), :);
msgRxFast(1:10, :)
ans=10×8 timetable
        Time        ID     Extended        Name                Data            Length      Signals       Error    Remote
    ____________    ___    ________    _____________    ___________________    ______    ____________    _____    ______

    0.014177 sec    100     false      {'EngineMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.11415 sec     100     false      {'EngineMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.21416 sec     100     false      {'EngineMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.31416 sec     100     false      {'EngineMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.41418 sec     100     false      {'EngineMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.51416 sec     100     false      {'EngineMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.61416 sec     100     false      {'EngineMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.71416 sec     100     false      {'EngineMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.81417 sec     100     false      {'EngineMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.91417 sec     100     false      {'EngineMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 

msgRxSlow = msgRx(strcmpi('TransmissionMsg', msgRx.Name), :);
msgRxSlow(1:10, :)
ans=10×8 timetable
        Time        ID     Extended           Name                   Data            Length      Signals       Error    Remote
    ____________    ___    ________    ___________________    ___________________    ______    ____________    _____    ______

    0.014183 sec    200     false      {'TransmissionMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.51416 sec     200     false      {'TransmissionMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    1.0142 sec      200     false      {'TransmissionMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    1.5142 sec      200     false      {'TransmissionMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    2.0142 sec      200     false      {'TransmissionMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    2.5142 sec      200     false      {'TransmissionMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    3.0142 sec      200     false      {'TransmissionMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    3.5142 sec      200     false      {'TransmissionMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    4.0142 sec      200     false      {'TransmissionMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    4.5143 sec      200     false      {'TransmissionMsg'}    {[0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 

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

avgPeriodFast = mean(diff(msgRxFast.Time))
avgPeriodFast = duration
   0.1 sec

avgPeriodSlow = mean(diff(msgRxSlow.Time))
avgPeriodSlow = duration
   0.50001 sec

График принятых данных сигнала отражает обновления в данных сообщения, отправленных на шине CAN.

signalTimetable = canSignalTimetable(msgRx, 'EngineMsg');
signalTimetable(1:10, :)
ans=10×2 timetable
        Time        VehicleSpeed    EngineRPM
    ____________    ____________    _________

    0.014177 sec         0             250   
    0.11415 sec          0             250   
    0.21416 sec          0             250   
    0.31416 sec          0             250   
    0.41418 sec          0             250   
    0.51416 sec          0             250   
    0.61416 sec          0             250   
    0.71416 sec          0             250   
    0.81417 sec          0             250   
    0.91417 sec          0             250   

plot(signalTimetable.Time, signalTimetable.VehicleSpeed)
title('Vehicle Speed from EngineMsg', 'FontWeight', 'bold')
xlabel('Timestamp')
ylabel('Vehicle Speed')
ylim([-5 75])

Figure contains an axes. The axes with title Vehicle Speed from EngineMsg contains an object of type line.

Просмотрите сообщения, настроенные для периодической передачи

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

transmitConfiguration(txCh)
Periodic Messages

ID  Extended      Name             Data        Rate (seconds)
--- -------- --------------- ----------------- --------------
100 false    EngineMsg       0 0 0 0 70 0 0 0  0.100000
200 false    TransmissionMsg 0 0 0 0 0 0 0 0   0.500000


Event Messages

None