Проблема потери данных по UART
- Войдите на сайт для отправки комментариев
Пт, 24/11/2017 - 18:10
Здравствуйте. У меня возникла проблема следущего рода: по UART приходят данные большими пакетами 200-256 байт, я их считываю но конец обрывается, у меня подозрения что это из за буфера UART. Плата wemos D1
Код ниже, Serial запущен на скорости 115200
String msg; while (Serial.available() > 0) { byte inChar = Serial.read(); msg += inChar; } Serial.println(msg);
Как можно решить проблему потери данных?
P.S. в файле HardwareSerial.h буфер пробывал увеличивать до 256 и до 255, не помогло.
#define SERIAL_TX_BUFFER_SIZE 255
#define SERIAL_RX_BUFFER_SIZE 255
Возможности уменшить пакеты с отправителя тоже нету
А с чего вы взяли, что они обрываются именно при приеме? Может вы их просто правильно вывести на печать не можете?
Какие данные в пакете - текстовые или бинарные? Если бинарные - для их хранения и вывода на печать String и println() не подходят.
Данные бинарные, raw data с gps приемника пакет в HEX кодировке. Использовал String, потому что потом пересылаю их по ethernnet на сервер через команду client.println(). А какие инструменты лучше использовать для работы с бинарными данными?
А вы в цикле while делайте Serial.println( .. , HEX) байта, который приняли и всё поймете - буфер виноват или нет.
попробовал, отправляется по 200-256 байт, доходит 140-150. Интересно если бы дело было в буфере наверно дохлдило всегда бы одинаковое количество байт.
скриншот демонстрирует что происходит какая-то ерунда под конец посылки.
Может быть прерывания используете где-то и, пока обработчик выполняется, часть данных игнорируется.
ни каких прерываний вроде нет, код что выше, это весь скетч остальное я все пока закоментировал, ну еще в setup инициализируется serial.
а delay(5) зачем? попробуйте без него
Может у меня не увиличился буфер UART,
"P.S. в файле HardwareSerial.h буфер пробывал увеличивать до 256 и до 255, не помогло.
#define SERIAL_RX_BUFFER_SIZE 255 "
и эти изменения не заработали, и буфер так и остался 128 байт?
а delay(5) зачем? попробуйте без него
без него считывается первый байт и выходт из цикла while, и в следующем loop дочитываются остальные
Ну вот вам и проблема, если шлете пакетами то такого не должно быть. Значит кто-то куда-то отвлекает проц, как писали выше прерывания или еще что-то
без него считывается первый байт и выходт из цикла while, и в следующем loop дочитываются остальные
Так вам точно в этом лупе ничего не помешает кроме прерываний. GPS только TX-ом подключен, надеюсь?
да к gps идет только питание и линия с TX gps на RX arduino. Попробую, отпишусь.
Теперь вроде приходит все, ну беглым взглядом потерь нет.
Да уж как теперь мне организовать работу: нужно чтобы эти данные по ethernet уходили в облако, а если я добавлю, что то в код то снова появятся потери...
А если заменить контролер на Arduino due или на STM32F103? проблема останеться?
Как минимум - нужно знать длину пакета, если он у вас RAW и содержит 0x00. То есть как вы определяете, что он целиком принят?
Потом, лично я бы, если по простому писал алгоритм, складывал принятые байты в байтовый массив, по окончании передачи делал ethernetClient.write() этого буфера на длину пакета. Или, может, ваш ethernetClient дает доступ указателю на свой буфер? Тогда бы писал принятое сразу туда.
Длинна плавает в зависимости от количества спутников. Еще gps модуль может общаться по SPI и I2C может на нах попробовать?
Ну плавает - это понятно. Конец пакета как-то же ловится? Просто я сейчас абстракциями оперирую - мне неизвестно, какая у вас ethernet библиотека, формат пакета GPS, поэтому вы получаете общие рекомендации, которые подходят в большинстве случаев.
Длинна плавает в зависимости от количества спутников. Еще gps модуль может общаться по SPI и I2C может на нах попробовать?
А что за модуль? Интересен , если действительно имеет SPI и I2C.
Я посмотрел лог сообщений в программе для работы с UBLOX трекерами, там длина плавает от 160 до 304 байт с шагом в 24 байта.
Вот скриншот протокола, этого сообщения:
Ublox NEO 6T
Не совсем понятно, сколько занимает Length - если оно двубайтовое, то никакой памяти вам в ардуине не хватит, если резервировать ее под буфер максимального размера. Если же однобайтовое, то все просто: начинаете читать с сериала, инкрементируя i и одновременно записывая в байтовый массив, на i == 0 проверяете inByte == 0xB5, при i == 1 на inByte == 0x62, в случае неудачи на любой проверке скидываете i в 0 и начинаете всё сначала. Если всё ОК, то читаете еще 3 байта и в buffer[4] получаете длину пакета. Продолжаете читать/писать, (пока i < buffer[4]). Дошли до конца, CRC проверили, если совпадает - отсылаете в Ethernet, не совпадает - i=0 и ждете байтов из Serial. Проще всего такое сделать на "машине состояний".
Не совсем понятно, сколько занимает Length - если оно двубайтовое, то никакой памяти вам в ардуине не хватит, если резервировать ее под буфер максимального размера. Если же однобайтовое, то все просто: начинаете читать с сериала, инкрементируя i и одновременно записывая в байтовый массив, на i == 0 проверяете inByte == 0xB5, при i == 1 на inByte == 0x62, в случае неудачи на любой проверке скидываете i в 0 и начинаете всё сначала. Если всё ОК, то читаете еще 3 байта и в buffer[4] получаете длину пакета. Продолжаете читать/писать, (пока i < buffer[4]). Дошли до конца, CRC проверили, если совпадает - отсылаете в Ethernet, не совпадает - i=0 и ждете байтов из Serial. Проще всего такое сделать на "машине состояний".
Я так понял 2 байта под длину(
P.S Длину не с того байта посчитал HEX 110 = 272
Arduino DUE или STM32F103 справяться?)
Тогда гарантированного способа принять всё я не вижу.
Можно, конечно, взять некий максимально доступный объём памяти под буфер, зарезав буфер UART, к примеру, и не принимать пакет, если его длина превышает размер выделенной памяти, но тогда есть шанс, что при большом количестве спутников, ни один пакет не будет принят. Можно снизить скорость UART и попытаться закидывать в ethernet частями, но тогда CRC должен проверяться на удаленной стороне.
Посчитайте длину, которая может быть определена в двух байтах. И сравните ее с доступной памятью на других платформах.
Попробую частями, ну по сути памяти хватает, максимальная длина будет 400-500 байт это 20-25 спутников, что маловероятно. а вдвух байтах максимум 65 535 значений, мне кажется взяли два байта, потомучто одного байта с 255 значениями мало.
у платы wemos d1, она на базе ESP2866, при данной прошивке такие значения памяти:
Ну, вполне может быть и так, что 640 байт хватит всем. В этом случае вам поможет корректируемая при работе переменная "максимальная длина пакета" и какой-нибудь счётчик пропущенных пакетов, а так же статистика его роста.
Ublox NEO 6T
У этого модуля GLONASS есть или нет - не знаете? Даташит молчит что-то по этому поводу.
нету, у 7 и 8 серии вроде есть, 6 уже не выпускают вроде.
на али и в прочих магазинах популярен neo 6m, там и raw data нельзя вытащить.