Создание и обработка сообщений с использованием определений баз данных

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

Откройте файл базы данных

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

db = canDatabase('demoVNT_CANdbFiles.dbc')
db.Messages
db = 

  Database with properties:

             Name: 'demoVNT_CANdbFiles'
             Path: '/tmp/BR2021ad_1584584_202060/publish_examples0/tp21235eaf/ex80654288/demoVNT_CANdbFiles.dbc'
            Nodes: {}
         NodeInfo: [0x0 struct]
         Messages: {5x1 cell}
      MessageInfo: [5x1 struct]
       Attributes: {}
    AttributeInfo: [0x0 struct]
         UserData: []


ans =

  5x1 cell array

    {'DoorControlMsg'   }
    {'EngineMsg'        }
    {'SunroofControlMsg'}
    {'TransmissionMsg'  }
    {'WindowControlMsg' }

Просмотр информации о сообщении

Использование messageInfo для просмотра информации о сообщении, включая идентификатор, длину данных и список сигналов.

messageInfo(db, 'EngineMsg')
ans = 

  struct with fields:

             Name: 'EngineMsg'
     ProtocolMode: 'CAN'
          Comment: ''
               ID: 100
         Extended: 0
            J1939: []
           Length: 8
              DLC: 8
              BRS: 0
          Signals: {2x1 cell}
       SignalInfo: [2x1 struct]
          TxNodes: {0x1 cell}
       Attributes: {}
    AttributeInfo: [0x0 struct]

Можно также запросить информацию сразу по всем сообщениям.

messageInfo(db)
ans = 

  5x1 struct array with fields:

    Name
    ProtocolMode
    Comment
    ID
    Extended
    J1939
    Length
    DLC
    BRS
    Signals
    SignalInfo
    TxNodes
    Attributes
    AttributeInfo

Просмотр информации о сигнале

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

signalInfo(db, 'EngineMsg', 'EngineRPM')
ans = 

  struct with fields:

             Name: 'EngineRPM'
          Comment: ''
         StartBit: 0
       SignalSize: 32
        ByteOrder: 'LittleEndian'
           Signed: 0
        ValueType: 'Integer'
            Class: 'uint32'
           Factor: 0.1000
           Offset: 250
          Minimum: 250
          Maximum: 9500
            Units: 'rpm'
       ValueTable: [0x1 struct]
      Multiplexor: 0
      Multiplexed: 0
    MultiplexMode: 0
          RxNodes: {0x1 cell}
       Attributes: {}
    AttributeInfo: [0x0 struct]

Можно также запросить информацию обо всех сигналах в сообщении сразу.

signalInfo(db, 'EngineMsg')
ans = 

  2x1 struct array with fields:

    Name
    Comment
    StartBit
    SignalSize
    ByteOrder
    Signed
    ValueType
    Class
    Factor
    Offset
    Minimum
    Maximum
    Units
    ValueTable
    Multiplexor
    Multiplexed
    MultiplexMode
    RxNodes
    Attributes
    AttributeInfo

Создание сообщения с использованием определений баз данных

Укажите имя сообщения при создании нового сообщения для применения определения базы данных. Сигналы CAN в этих сообщениях представлены в технических модулях в дополнение к байтам необработанных данных.

msgEngineInfo = canMessage(db, 'EngineMsg')
msgEngineInfo = 

  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: []

Просмотр информации о сигнале

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

msgEngineInfo.Signals
ans = 

  struct with fields:

    VehicleSpeed: 0
       EngineRPM: 250

Изменение информации о сигнале

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

msgEngineInfo.Signals.EngineRPM = 5500.25
msgEngineInfo.Signals
msgEngineInfo = 

  Message with properties:

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

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

   Protocol Flags
           Error: 0
          Remote: 0

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


ans = 

  struct with fields:

    VehicleSpeed: 0
       EngineRPM: 5.5003e+03

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

msgEngineInfo.Signals.VehicleSpeed = 70.81
msgEngineInfo.Signals
msgEngineInfo = 

  Message with properties:

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

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

   Protocol Flags
           Error: 0
          Remote: 0

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


ans = 

  struct with fields:

    VehicleSpeed: 71
       EngineRPM: 5.5003e+03

Получение сообщений с информацией о базе данных

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

rxCh = canChannel('MathWorks', 'Virtual 1', 2);
rxCh.Database = db
rxCh = 

  Channel with properties:

   Device Information
            DeviceVendor: 'MathWorks'
                  Device: 'Virtual 1'
      DeviceChannelIndex: 2
      DeviceSerialNumber: 0
            ProtocolMode: 'CAN'

   Status Information
                 Running: 0
       MessagesAvailable: 0
        MessagesReceived: 0
     MessagesTransmitted: 0
    InitializationAccess: 1
        InitialTimestamp: [0x0 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: [1x1 can.Database]
                UserData: []

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

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

start(rxCh);
generateMsgsDb();
rxMsg = receive(rxCh, Inf, 'OutputFormat', 'timetable');
rxMsg(1:15, :)
ans =

  15x8 timetable

        Time        ID     Extended            Name                       Data              Length      Signals       Error    Remote
    ____________    ___    ________    _____________________    ________________________    ______    ____________    _____    ______

    0.038985 sec    100     false      {'EngineMsg'        }    {[     0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.038991 sec    200     false      {'TransmissionMsg'  }    {[     0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.038996 sec    400     false      {'DoorControlMsg'   }    {[     0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.038999 sec    600     false      {'WindowControlMsg' }    {[             0 0 0 0]}      4       {1x1 struct}    false    false 
    0.039 sec       800     false      {'SunroofControlMsg'}    {[                 0 0]}      2       {1x1 struct}    false    false 
    0.063955 sec    100     false      {'EngineMsg'        }    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.088956 sec    100     false      {'EngineMsg'        }    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.088958 sec    200     false      {'TransmissionMsg'  }    {[     4 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.11396 sec     100     false      {'EngineMsg'        }    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.13898 sec     100     false      {'EngineMsg'        }    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.13898 sec     200     false      {'TransmissionMsg'  }    {[     4 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.16398 sec     100     false      {'EngineMsg'        }    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.16399 sec     400     false      {'DoorControlMsg'   }    {[     1 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.18896 sec     100     false      {'EngineMsg'        }    {[177 131 0 0 55 0 0 0]}      8       {1x1 struct}    false    false 
    0.18896 sec     200     false      {'TransmissionMsg'  }    {[     4 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 

Остановите канал и очистите его из рабочей области.

stop(rxCh);
clear rxCh

Просмотр полученного сообщения

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

rxMsg(10, :)
rxMsg.Signals{10}
ans =

  1x8 timetable

       Time        ID     Extended        Name                   Data              Length      Signals       Error    Remote
    ___________    ___    ________    _____________    ________________________    ______    ____________    _____    ______

    0.13898 sec    100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 


ans = 

  struct with fields:

    VehicleSpeed: 50
       EngineRPM: 3.5696e+03

Извлечение всех образцов заданного сообщения

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

allMsgEngine = rxMsg(strcmpi('EngineMsg', rxMsg.Name), :);
allMsgEngine(1:15, :)
ans =

  15x8 timetable

        Time        ID     Extended        Name                   Data              Length      Signals       Error    Remote
    ____________    ___    ________    _____________    ________________________    ______    ____________    _____    ______

    0.038985 sec    100     false      {'EngineMsg'}    {[     0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.063955 sec    100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.088956 sec    100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.11396 sec     100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.13898 sec     100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.16398 sec     100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.18896 sec     100     false      {'EngineMsg'}    {[177 131 0 0 55 0 0 0]}      8       {1x1 struct}    false    false 
    0.21396 sec     100     false      {'EngineMsg'}    {[177 131 0 0 55 0 0 0]}      8       {1x1 struct}    false    false 
    0.23896 sec     100     false      {'EngineMsg'}    {[177 131 0 0 55 0 0 0]}      8       {1x1 struct}    false    false 
    0.26396 sec     100     false      {'EngineMsg'}    {[177 131 0 0 55 0 0 0]}      8       {1x1 struct}    false    false 
    0.28893 sec     100     false      {'EngineMsg'}    {[ 91 133 0 0 55 0 0 0]}      8       {1x1 struct}    false    false 
    0.31396 sec     100     false      {'EngineMsg'}    {[ 91 133 0 0 55 0 0 0]}      8       {1x1 struct}    false    false 
    0.33897 sec     100     false      {'EngineMsg'}    {[ 91 133 0 0 55 0 0 0]}      8       {1x1 struct}    false    false 
    0.36396 sec     100     false      {'EngineMsg'}    {[ 91 133 0 0 55 0 0 0]}      8       {1x1 struct}    false    false 
    0.38896 sec     100     false      {'EngineMsg'}    {[201 130 0 0 54 0 0 0]}      8       {1x1 struct}    false    false 

Постройте графики значений физического сигнала

Постройте график значений декодированных сигналов базы данных с течением времени. Ссылка на временные метки сообщения и значений сигналов в переменных.

signalTimetable = canSignalTimetable(rxMsg, 'EngineMsg');
signalTimetable(1:15, :)
plot(signalTimetable.Time, signalTimetable.VehicleSpeed)
title('Vehicle Speed from EngineMsg', 'FontWeight', 'bold')
xlabel('Timestamp')
ylabel('Vehicle Speed')
ans =

  15x2 timetable

        Time        VehicleSpeed    EngineRPM
    ____________    ____________    _________

    0.038985 sec          0             250  
    0.063955 sec         50          3569.6  
    0.088956 sec         50          3569.6  
    0.11396 sec          50          3569.6  
    0.13898 sec          50          3569.6  
    0.16398 sec          50          3569.6  
    0.18896 sec          55          3621.3  
    0.21396 sec          55          3621.3  
    0.23896 sec          55          3621.3  
    0.26396 sec          55          3621.3  
    0.28893 sec          55          3663.9  
    0.31396 sec          55          3663.9  
    0.33897 sec          55          3663.9  
    0.36396 sec          55          3663.9  
    0.38896 sec          54          3598.1