Comments 18
У Вас используется протокол с фиксированным размером блока и разделением передачи по времени. По-хорошему вам нужно ждать пакет заданного размера в течении гарантированного времени, т.е. ввести тайм-аут на ожидание приема определенного кол-ва байт. Если не дожидаетесь приема ваших 6 байт за это время, считаете, что все что приняли - "битый" пакет и отбрасываете. Дальше выясняете, почему процент битых пакетов выше ожидаемого. Может быть плохой контакт, длинный неэкранированный провод рядом с источником помех, ошибка в программе контроллера. Еще хорошо бы ввести контрольную сумму в пакет, чтобы гарантировать корректность содержимого, а не только количества байт. Смотрите как устроен modbus rtu.
Я в свое время написал простой протокол, в котором отказался от таймаутов и перешел на квитирование пакета специальным символом и вставку спец. байтов (byte stuffing), что упрощает общую реализацию. Есть реализация мастера для LabVIEW и Python, слейва для arduino / teensy. https://github.com/Chupakabra303/SerialFrameProtocol
стрим c COMпорта какой нибуть другой программой мониторился/записывался ? А то окажется что это источник данных мудрит. Похоже на какой то байт-стаффинг и в любом случае это не шум, а в общем то сбой, аномалия
Я обычно говорю в таких случаях, что любому наблюдаемому феномену есть рациональное объяснение и чудес на свете не бывает. Сколько я с RS232 не работал, вот ни разу не встречал ситуации, когда просто так появлялись бы "мусорные" байты из ниоткуда. Думаю, что их железка шлёт, ну или помехи на линии. Хардкорный метод - подцепиться на Tx Rx осциллографом с памятью прямо у порта, и записать и проанализировать все сигналы, которые пролетают через интерфейс.
Вы несколько нетипично используете комбинацию Wait (ms) вкупе с Wait Until Next ms Multiple c довольно близкими значениями задержек (8 и 10 мс). Это может приводить к тому, что время между чтением и записью будет "плавать", возможно железка ещё не готова принять байт - команду на чтение и реагирует на это дополнительным "мусорным" байтом. Возможно "двухцикловый" дизайн с очередью чуть меняет тайминги и эффект пропадает. Теоретически можно Timed Loop попробовать, хотя там можно налететь на другие "подводные камни".
Ну и чтение из порта - обычно если ждут определённого количества байт, то можно это количество сразу заказать при чтении и ждать с таймаутом, либо вставать в цикл опроса количества байт и по достижении необходимого количества читать, а тут я проверки количества полученных байт нигде не видно - если прилетит пять, то они и будут читаться, но формально это ошибка.
"... стрим c COM порта" проверен. Например, как сказано в статье, если синусоидальные показания одного из датчиков заменить константой (пропадает периодичность суммарного сигнала), то шумы (или аномалия) исчезают, сигнал другого датчика отображается чистым синусом и LabVIEW показывает на мониторе, что принимает каждый такт только 6 байт. Чтобы выделить проблему приема периодических фрагментов в LabVIEW (повторяемости аномалии), вместо показаний датчиков, контроллер (по запросу LabVIEW) выдавал два эталонных синусоидальных сигнала (int16 и int32).
это не совсем то, если проверка осуществлялась по сути теми же средствами, с которыми возникали проблеммы. по хорошему нужен сторонний мониторинг. хоть второй комп в паралель подсоединить
Да не, я много всякой "мистики" видел, но тут явно дело не в периодичности сигнала.
LabVIEW добавляет “заголовок” (свои байты) если последовательность данных носит периодический характер
Я вот смотрю - проблема возникает, когда вам прилетает байт 10. По умолчанию это терминирующий байт и он включён. Попробуйте выключить этот режим при открытии порта:

Я не уверен, что это причина такого поведения, но я абсолютно уверен, что если я возьму ардуинку и начну генерить синус в COM порт, и принимать его в LabVIEW, то ничего лишнего там вставляться не будет.
Вы правы. "Termination = F" решило проблему. Большое спасибо за дельный совет.
неплохо бы добавить статью счастливым эпилогом
Согласны ли Вы со следующими рассуждениями?
При наличии
1. терминала (устанавливается по дефолту) в модуле “VISA Configure Serial Port VI”;
2. в принимаемой последовательности байтов, равных терминалу;
3. и повторяющихся фрагментов данных
LabVIEW может искажать принимаемую последовательность, например, как показано в таблице 1.
Пункт 3 надо заменить на "и наличии железки, не поддерживающей терминирующий символ".
Вообще учебник пишет, что "Keep in mind that termination on the physical hardware needs to comply with the appropriate Serial standard. If the termination on the physical component is incorrect then it will cause issues with termination characters on the software side".
Так что там не всё так просто. У меня не было проблем с терминирующим байтом, но там это было заложено в самих железках (сканер штрих кодов обычно так работает, но там никогда не будет этого байта в нормальных данных, поскольку там просто ASCII текст штрих-кода прилетает, а не двоичные данные).
Ну и опять же "When performing binary communication, the read can terminate prematurely if one binary data value has the same binary representation as the termination character. Therefore, disable the termination character by setting Termination Character Enabled to false and Serial End Modes for Reads to None (0), as shown below. You must rely on a different method of terminating the read, such as a hardware line or byte count".
Тот факт, что вы таки получаете терминируюий символ в данных и размер пакета увеличивается с 6 до 7, дополняясь двумя нулями - любопытен (я бы ожидал, что LabVIEW проглотит байт 10 и не отдаст его наружу).
Но это утверждение легко проверить - собирается тестовый стенд, пересылаются байты в последовательный порт и смотрится, что там получается и так и сяк, заодно с ASRL End In/Out поиграть.
С проблемой СЛУЧАЙНЫХ выбросов сигнала столкнулся, когда LabVIEW принимал от реальных датчиков зашумленные (не идеальные) синусоидальные сигналы (отображающие дыхание) с переменными амплитудами, периодами и паузами .
На стенде с платформой Teensy 4.1 и смоделированными (вычислялись контроллером) идеальными синусоидальными сигналами получил повторяющийся (не случайный) описанный в статье эффект. Эффект с этими сигналами в точности повторяется и с Arduino UNO.
Помимо отключения терминала, решением (устранением выбросов) является и использование очереди при взаимодействии LabVIEW как c Teensy 4.1 так и с Arduino UNO. Об этом сказано в статье.
"... дополнительным "мусорным" байтом." Дополнительный байт и "выбросы" создаются в одни и те же моменты по отношению к ПЕРИОДУ сигнала, как показано на графиках. Преобразования, показанные в таблице, также привязаны к ПЕРИОДУ сигнала, и неизменно повторяются каждый период.
Проверьте потоки запросов и ответов сниффером последовательного порта. И на разных последовательностях. Будет более понятно, кто чудит - железо, настройки порта в ос, лабвью, или программист.
Всякое бывает - и usb/com глючит (особенно на чипах СРхххх), и ось в данные свои правки вставляет (особенно в CR/LF, 13/10), и таймауты меньше 10 мс может не выдерживать ни ос, ни usb/com. Ну а в софте 99% хабра умеют профессионально лажать. И я тоже)
Исходные сырые данные - это святое! Не надо их "устранять" - можно пропустить что-то важное.
Устранение “шумов” LabVIEW при приеме USB/СОМ данных