У меня не было опыта работы с Controller Area Networks (CAN) или ValueCAN3 до этого проекта, и я использовал пример из Intrepid для чтения сообщений. Однако у меня есть проблемы с эффективностью и частотой обновлений для моего графического интерфейса, который отображает аналоговые и цифровые сигналы, которые я читаю.
Мой графический интерфейс состоит из 16 числовых окон вверх / вниз для аналоговых каналов и 36 кнопок, которые изменяют цвет на зеленый в зависимости от того, включен цифровой сигнал (1) или выключен (0). Читая мои сообщения CAN, я обновляю элементы управления графическим интерфейсом, чтобы отобразить соответствующую обратную связь. Однако цифровые каналы реагируют почти мгновенно, когда я нажимаю кнопку на подключенном джойстике CAN, тогда как аналоговые сигналы не обновляются так быстро с помощью струнных горшков, которые я использую для изменения сигнала. Иногда для ответа требуется аналоговый сигнал 1 — 2 секунды.
В настоящее время я устанавливаю элементы управления GUI, а затем читаю значения из элементов управления GUI и отправляю значения через соединение через сокет в другое приложение через UDP. Я, вероятно, должен изменить это на отправку данных от сигналов, которые я получаю напрямую, а не на чтение из элементов управления GUI, которые я устанавливаю, но я не думаю, что это проблема.
Я использую объекты System :: Timers :: Timer для обновления, чтения сообщений и отправки пакетов данных. Мне нужна частота 50 Гц — 100 Гц, желательно ближе к 100 Гц. Используя сокет на другом конце, я вижу, что мои пакеты отправляются достаточно часто, но данные не изменяются плавно или часто для аналоговых каналов. Если у кого-то есть мысли о том, что я могу делать неправильно, или о том, как обрабатывать данные более эффективным способом, пожалуйста, укажите это.
Вот фрагмент кода из Intrepid, который читает сообщения CAN:
// Read the messages every timer event (1000 ms)
if (m_bPortOpen) // only if the port is open
{
// call icsneoGetMessages to read out the messages
lResult = icsneoGetMessages(hObject,stMessages,&lNumberOfMessages,&lNumberOfErrors);
if (lResult != 0)
{
// a successful read
mNumberOfErrorsRead = lNumberOfErrors;
mNumberOfMessagesRead = lNumberOfMessages; // store the number of messages in the current buffer
}
}
Моя форма запрашивает сообщение из моего объекта CanReader, используя:
msg = can->GetLatestMsg();
и этот метод захватывает последнее полученное сообщение.
public: icsSpyMessage* GetLatestMsg()
{
return &stMessages[mNumberOfMessagesRead - 1];
};
Я думаю, что этот GetLatestMsg () кажется плохим способом реализации повторного получения последнего сообщения, но я не совсем уверен, насколько это влияет на мою программу или как еще я мог бы сделать это, потому что CanReader отделен от формы, поэтому Я должен был бы передать массив сообщений, которые я считаю иначе. Я подозреваю, что это может быть пропуск сообщений, потому что он читает только последние захваченные сообщения, а не те, которые ведут к нему, что, если они были прочитаны, должно сделать вывод графического интерфейса более плавным для переходов.
Следует также отметить, что я читаю из 6 разных PGN, аналоговые сигналы соответствуют 4 из PGN, а 2 соответствуют цифровым сигналам.
После игры с моим приложением и использования струнных горшков на разных аналоговых каналах я замечаю, что некоторые каналы обновляются больше, чем другие. И проверив доступ к PGN, я обнаружил, что к некоторым обращаюсь чаще, чем к другим.
Разве CAN-устройство не передает данные с одинаковой скоростью для разных PGN? и если да, то мой метод GetLatestMsg () не должен эффективно считывать разные PGN. Он читает новое сообщение каждые 5 миллисекунд.
Кроме того, кто-нибудь знает, должен ли я сделать отдельные таймеры чтения для отдельного обнаружения различных PGN?
Если есть дополнительный код, который я могу предоставить для ясности, пожалуйста, дайте мне знать.
После многих испытаний и отладки я нашел стабильное решение. Я публикую этот ответ в надежде, что кому-то еще может пригодиться это объяснение.
При чтении сообщения по шине CAN сообщения передаются по шине, и вам нужно выбрать нужные сообщения на основе имен групп параметров (PGN). Каждый PGN должен быть определен для разных частей данных.
Например, число оборотов двигателя будет соответствовать конкретному PGN, а когда вы проверяете сообщения в своем буфере, вы будете искать сообщения с PGN, соответствующим оборотов двигателя.
В моем случае я читаю / хочу 6 разных PGN от устройства valueCAN3, которое я использую. Каждое из этих сообщений содержит разные данные, которые соответствуют аналоговым и цифровым сигналам. Ошибка с эффективностью была связана с тем, как я получал последнее сообщение из буфера.
Когда вы просто передаете все одинаковые данные в каждом пакете, имеет смысл просто получить самое последнее или самое последнее сообщение из вашего буфера. Тем не менее, в моем случае, поскольку мне требуется 6 различных PGN, это означает, что когда я извлекаю последнее сообщение из буфера, это соответствует только 1 из 6 PGN, а сообщения на моей шине CAN отправляются с постоянной скоростью и в том же порядке я все время читал около половины пакетов, а другую половину пропустил. Получив два последних пакета, я обнаружил, что все мои каналы теперь обновляются со скоростью, необходимой для моего приложения. Все мои сигналы меняются без заметного запаздывания и легко соответствуют диапазону 50–100 Гц, который мне необходим.
Однако я думаю, что оптимальным решением было бы прочитать последнее сообщение для каждого PGN при извлечении из буфера, а не только два последних сообщения, которые могут соответствовать любому из моих 6 PGN, поскольку я читаю чаще, чем получаю пакеты.
Других решений пока нет …