Serial Half-Data
- Войдите на сайт для отправки комментариев
Доброго времени суток.
Для общения между МК <-> ПК через Serial порт использую байт массивы определённой структуры (некое подобие пакетов). Но есть одна маленькая проблема. Данные считываемые платой не соответствуют действительности.
Код МК:
void serialEvent() { while (Serial.available()) { byte a = Serial.read(); Serial.write(a); } }
Отправляю из программы следующий байт массив:
AA AA AA 07 00 42 00 7B 00 00 00 55 55 55
Получаю обратно следующее:
AA AA AA 07 00 42 00
Т.е. возвращается ровно (!) половина пакета. Пробовал менять скорости передачи - ноль эмоций. Иные настройки COM порта со стороны МК я не знаю, поэтому со стороны компьютера использую дефолтные для SerialPort() модуля .NET Framework.
Если не использвать serialEvent(), а делать собственный обработчик в loop() без цикла, то практически всегда буфер чтения начинается с 4-х байт F0. И также практически всегда не соответствует действительности. Но если буфер чтения пуст, то МК отправляет правильный пакет сформированный после полного перебора буфера чтения. И не имеет значение длина пакета. У меня были от 10 до 40 байт.
Плата Arduino/Genuino Uno R3 (оригинал).
Подскажите в чём может быть проблема и какие дефолтные настройки Serial у Aduino плат?
Данные считываемые платой не соответствуют действительности.
Иногда действительность не соответствует ожидаемой действительности.
Дефолтные настройки 8n1 их можно поменять когда делаете Serial.begin()
Выкините сериалэвент (он на некоторых платах вообще не поддерживается).
Если у Вас подобие пакета ну так и смотрите сигнатуру начала пакета, как нашли записываете пакет в буфер пока не встретили сигнатуру конца пакета.
Не знаю, чего вы там делаете, но уже пару лет как использую SerialPort на C# в связке с дуней - ничто никуда не пропадает, данные ходят в обе стороны.
Данные считываемые платой не соответствуют действительности.
Иногда действительность не соответствует ожидаемой действительности.
Дефолтные настройки 8n1 их можно поменять когда делаете Serial.begin()
Выкините сериалэвент (он на некоторых платах вообще не поддерживается).
Если у Вас подобие пакета ну так и смотрите сигнатуру начала пакета, как нашли записываете пакет в буфер пока не встретили сигнатуру конца пакета.
Если вы посмотрите внимательно, то сигнарура начала и конца пакета присутствует (3 одинаковых байта). Проблема в том, что очень часто пакет приходит в МК без конца. Это было выявлено отправкой байта в ПК виз каждой контрольной точки обработки пакета. Обработка состоит из 3-х частей: чтение преамбулы, чтение тела пакета и чтение хвоста. так вот чтение обрывается чаще всего на чтении тела и хвоста.
Причин влияющих на это я понять не могу. Точнее логики "проглатывания" окончания пакета. В старой реализации всё работает нормально. НО, первый входящий пакет в МК обрабатывался только с 5-20-го раза.
Не знаю, чего вы там делаете, но уже пару лет как использую SerialPort на C# в связке с дуней - ничто никуда не пропадает, данные ходят в обе стороны.
Можно посмотреть вашу реализацию со стороны МК? Со стороны C# приложения всё прозаично.
Вот для интереса глянул
читаем что пришло в буфер и отправляем обратно в C#, все прекрасно работает. С шарпа отправляется вот так
Может Вы по прерыванию уходите и теряете буфер или, например, не хватает оперативки и данные теряются. Да что угодно, без кода можно долго гадать.
Можно посмотреть вашу реализацию со стороны МК? Со стороны C# приложения всё прозаично.
Простейшая - вычитывание до признака конца пакета, потом - парсинг. Так же сделано у Nextion, например.
Вот мой тестовый пример для дебага интерфейса между МК <-> ПК.
Сам тестовый скетч:
C# код Program.cs:
Строение пакета следующее:
Лог работы программы следующий:
А теперь расскажите, пожалуйста, какая магия нужна чтобы получить обратно тело пакета?
Спасибо.
Я совсем не так получаю данные из порта в C# - я просто использую событие DataReceived в SerialPort. Разбираться в выложенных выше простынях - чой-то не хочется, т.к. я на 100500% уверен, что проблема не в UART, а в подходе к нему.
Я совсем не так получаю данные из порта в C# - я просто использую событие DataReceived в SerialPort. Разбираться в выложенных выше простынях - чой-то не хочется, т.к. я на 100500% уверен, что проблема не в UART, а в подходе к нему.
Это событие в MSDN описано как "негарантированное для каждого полученного байта". Смысл тогда от него?
The E:System.IO.Ports.SerialPort.DataReceived event is not guaranteed to be raised for every byte received. Use the P:System.IO.Ports.SerialPort.BytesToRead property to determine how much data is left to be read in the buffer.
Rootware, вы не с того начали. Заблудились в трех соснах. Зачем-то написали путанную машину состояний на стороне ардуины - не убедившись еще, что у вас байты правильно передаются...
Вам надо сделать отладлчный вывод ваших пакетов, причем независимый - не через сериал. Возьмите коротенький код Пенни из сообщения #5 и сразу по получении, без обработки выводите куда-нибудь все полученные ардуиной байты - в другой порт, на экран и тд
Ваша первая задача - выяснить, кто теряет - ваш код на С# при отправке, ваш код ардуины на приеме, код при отправке и тд
Я совсем не так получаю данные из порта в C# - я просто использую событие DataReceived в SerialPort. Разбираться в выложенных выше простынях - чой-то не хочется, т.к. я на 100500% уверен, что проблема не в UART, а в подходе к нему.
Это событие в MSDN описано как "негарантированное для каждого полученного байта". Смысл тогда от него?
The E:System.IO.Ports.SerialPort.DataReceived event is not guaranteed to be raised for every byte received. Use the P:System.IO.Ports.SerialPort.BytesToRead property to determine how much data is left to be read in the buffer.
Вы читать-то умеете? Там написано ровно следующее: Не гарантируется, что событие будет вызвано ДЛЯ КАЖДОГО принятого байта. Юзайте BytesToRead, чтобы узнать, сколько там байт лежит в буфере для чтения.
При приходе события - в приёмном буфере ГАРАНТИРОВАННО есть байты, вот только их кол-во - от 1 до N. Переводите с английского правильно.
Rootware, вы не с того начали. Заблудились в трех соснах. Зачем-то написали путанную машину состояний на стороне ардуины - не убедившись еще, что у вас байты правильно передаются...
Вам надо сделать отладлчный вывод ваших пакетов, причем независимый - не через сериал. Возьмите коротенький код Пенни из сообщения #5 и сразу по получении, без обработки выводите куда-нибудь все полученные ардуиной байты - в другой порт, на экран и тд
Ваша первая задача - выяснить, кто теряет - ваш код на С# при отправке, ваш код ардуины на приеме, код при отправке и тд
Я начал с того... Данная беда мне уже месяц покоя не давала. Просто настал момент когда нужно не каждый 5й - 20й пакет (хотя бы) обрабатывать, а каждый первый.
Спасибо что ответили. Всё вышеизложенной было проверено.
Уже исправил. Не актуально.
Я начал с того... Данная беда мне уже месяц покоя не давала. Просто настал момент когда нужно не каждый 5й - 20й пакет (хотя бы) обрабатывать, а каждый первый.
Спасибо что ответили. Всё вышеизложенной было проверено.
Уже исправил. Не актуально.
И что, работает? :)
Месяц отлажиливали передачу через сериал, которая у большинства новичков работает сразу... и тут раз - и исправили :)
Я начал с того... Данная беда мне уже месяц покоя не давала. Просто настал момент когда нужно не каждый 5й - 20й пакет (хотя бы) обрабатывать, а каждый первый.
Спасибо что ответили. Всё вышеизложенной было проверено.
Уже исправил. Не актуально.
И что, работает? :)
Месяц отлажиливали передачу через сериал, которая у большинства новичков работает сразу... и тут раз - и исправили :)
Месяц руки не доходили до экспериментов с иной моделью работы с буфером чтения. Да, я новичок в Arduino. И уже жалею, что не ухожу на STM32 и C++.
Месяц руки не доходили до экспериментов с иной моделью работы с буфером чтения. Да, я новичок в Arduino. И уже жалею, что не ухожу на STM32 и C++.
думаете, поможет? :) для справки - нет языка ардуино - это С++
Месяц руки не доходили до экспериментов с иной моделью работы с буфером чтения. Да, я новичок в Arduino. И уже жалею, что не ухожу на STM32 и C++.
Начнём с того, что ардуино программируется на С++, т.е. не надо уходить с С++ на С++, знаете ли. Про STM - попробуйте, и вы увидите, что ваши слова "уже жалею, что не ухожу" быренько сменят окраску. В STM свои фишки и грабли, и новичку в программировании там уж точно не легче, чем на ардуине.
Rootware, правильный совет Вам дал DIYMan еще в 6-м сообщении: Вы вычитываете буфер, не дожидаясь, пока придет последний байт сообщения. Т.е Вы считали 4, 5-й еще принимается, но т.к. его пока нет Serial.available() выдает 0.
Нужно принимать до конца пакета, а не до того момента, когда опустошится буфер.
Rootware, правильный совет Вам дал DIYMan еще в 6-м сообщении: Вы вычитываете буфер, не дожидаясь, пока придет последний байт сообщения. Т.е Вы считали 4, 5-й еще принимается, но т.к. его пока нет Serial.available() выдает 0.
Нужно принимать до конца пакета, а не до того момента, когда опустошится буфер.
Да работает уже всё. Спасибо. Проблема была в другом. Мои "портянки" выше на 99,8% рабочие и имеют несколько логических ошибок, т.к. писались "на скорую руку".
Да работает уже всё. Спасибо. Проблема была в другом. Мои "портянки" выше на 99,8% рабочие и имеют несколько логических ошибок, т.к. писались "на скорую руку".
Ваша проблема действительно в другом.
Вы, видимо, прошли теоретический курс по Си -С++. что создало у вас не вполне обоснованную уверенность в своих знаниях. Вам кажется, что в целом, то, что вы кодируете - правильно и проблемы лишь в мелких ошибках или в глюках железа. Вы задаете ответы. но ответов не слушаете, если они нарушают ваше "эго".
На самом деле практики. судя по коду - у вас мало и многих кардинальных вещей вы не понимаете. Те ошибки. про которые вам говорят - ключевые в вашем коде. И они все равно вылезут позже.
Да работает уже всё. Спасибо. Проблема была в другом. Мои "портянки" выше на 99,8% рабочие и имеют несколько логических ошибок, т.к. писались "на скорую руку".
Ваша проблема действительно в другом.
Вы, видимо, прошли теоретический курс по Си -С++. что создало у вас не вполне обоснованную уверенность в своих знаниях. Вам кажется, что в целом, то, что вы кодируете - правильно и проблемы лишь в мелких ошибках или в глюках железа. Вы задаете ответы. но ответов не слушаете, если они нарушают ваше "эго".
На самом деле практики. судя по коду - у вас мало и многих кардинальных вещей вы не понимаете. Те ошибки. про которые вам говорят - ключевые в вашем коде. И они все равно вылезут позже.
Никаких курсов я не проходил. Просто в детстве прочитал книжку "Basic - это просто". Это все мои знания в программировании.