|
3 / 3 / 1
Регистрация: 27.02.2014
Сообщений: 103
|
|||||||||||
COM-порт прием данных и парсинг11.01.2017, 19:49. Показов 24645. Ответов 27
Метки нет (Все метки)
Всем привет.
Прикупил arduino и не могу разобраться с COM портом. Пытаюсь принять данные отправленные из программы написанной на C#. Вроде прием идет, но в ответ прилетает полный бред. Принимаю таким образом.
Все бы ничего и можно было бы банально каждый следующий байт закидывать сразу в переменную, но количество меняется - может быть как 11 байт, так и 8. Причем первый байт говорит о том, что будем делать (читать\писать), а последний говорит о конце строки. Хоть убейте, но долблюсь уже 3 дня, а так и не смог разложить все по полкам. Помогите разобраться..
0
|
|||||||||||
| 11.01.2017, 19:49 | |
|
Ответы с готовыми решениями:
27
СОМ порт прием данных Прием данных через COM порт Прием данных через COM - порт |
|
Модератор
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
|
|||
| 11.01.2017, 20:39 | |||
а 0 это вообще в Си означает конец строкииспользуй массив unsigned char
0
|
|||
|
techpriest
634 / 213 / 57
Регистрация: 27.02.2014
Сообщений: 1,180
|
|
| 12.01.2017, 04:52 | |
|
Уточняющий вопрос. Вы справились с передачей и у вас проблемы с парсингом пакета, или пооблемы с самой передачей данных. Код, который вы привели вполне рабочий. Serial.flush, правда, лишний и обнуления строки перед следующей посылкой нехватает.
П.С. Тип String умеет хранить бинарные нули. Добавлено через 7 минут Расскажите подробнее, почему посылки могут быть разной длины, и какова природа передаваеммых данных?
1
|
|
|
Модератор
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
|
|
| 12.01.2017, 05:33 | |
|
0
|
|
|
techpriest
634 / 213 / 57
Регистрация: 27.02.2014
Сообщений: 1,180
|
|
| 12.01.2017, 05:52 | |
|
Ну... Тут я могу разве что заметить, что в таком уважаемом фреймворке, как Qt тип QString является синонимом типа QByteArray, а язык программирования perl вообще не имеет нуль-терминированных строки и спокойно относится к нулям в строках. Так же поступают C#, Java , Lua etc.
А на Arduino очень глубокий отпечаток положила именно Java... Даже тип std::string, вроде бы (могу ошибаться) может хранить нулевые байты.
1
|
|
|
3 / 3 / 1
Регистрация: 27.02.2014
Сообщений: 103
|
|||
| 12.01.2017, 07:00 [ТС] | |||
|
1. Почему Serial.flush лишний? Он же очищает содержимое буффера, а это нам необходимо. 2. Я же строку обнуляю в самом начале loop - String InputData = ""; или я что-то не понимаю? В посылке передаются настройки для блока с несколькими реле. Каждое реле имеет свою логику работы и могут настраиваться по разному - собственно по этой причине и меняется длина посылки. Посылка примерно выглядит так: 1 байт - что необходимо сделать (читать\писать) 2 байт - С каким реле будем работать 3 байт - Общий для всех реле 4 байт - Общий для всех реле 5 байт - Общий для всех реле 6 байт - Отсутствует у некоторых реле 7 байт - Отсутствует у некоторых реле 8 байт - Общий для всех реле 9 байт - Отсутствует у некоторых реле 10 байт - Общий для всех реле 11 байт - Признак окончания посылки Как я вообще представляю себе это дело: 1. arduino получает посылку и после сборки строки кидает ее в ParseData(InputData); 2. Парсинг начинается с разбора первого байта и в зависимости от его значения остатки строки передаются в процедуру чтения или записи. 3. Далее, идет разбор оставшейся строки и все принятые данные раскидываются по своим переменным. Естественно, что для чтения параметров, нам нет необходимости слать лишние данные, а следовательно и пакет будет уже из 3-х байт.
0
|
|||
|
techpriest
634 / 213 / 57
Регистрация: 27.02.2014
Сообщений: 1,180
|
|||||||||||||||||||||||
| 12.01.2017, 10:45 | |||||||||||||||||||||||
Что касается парсинга. Вы должны изменять алгоритм парсинга в зависимости от принимаемых данных. ЕСЛИ первый байт - ЗАПИСЬ вызываем функцию, отвечающую за парсинг посылки записи. Извлекаем второй байт. Если у вас разные типы реле, то в вашей программе где-то так или иначе есть таблица, отвечающая за то, какой тип у номера реле такого-то. Получаем из этой таблицы информацию о типе реле. Проверяем, соответствует ли длина посылки заявленному типу. Если нет, генерируем ошибку. Передаем посылку функции, отвечающей за парсинг значений для данного типа реле. Это концептуально. Разумеется не обязательно использовать награмождение функций, ваша задача вполне решается с использованием if-else. Важно то, что мы используем данные из заголовка посылки, чтобы скоректировать процедуру ее разбора. ... Тонкий момент. Если вы используете символ 0X0D как разделитель, это значит, что в теле ваших посылкок он встречаться не должен. Добавлено через 11 минут Прошу прощения:
Добавлено через 4 минуты А еще строка не должна уничтожаться между вызовами loop, так что нужно или использовать глобальный объект, или не выходить из loop:
0
|
|||||||||||||||||||||||
|
365 / 348 / 74
Регистрация: 18.03.2015
Сообщений: 1,293
|
||||||
| 12.01.2017, 11:31 | ||||||
|
Как то все сложно. Если задача принять строку и разложить по переменным, не проще ли так:
Команда Serial.read(); читает байт и удаляет его из приемного буфера, поэтому, когда будет прочитан весь буфер, в нем ничего не останется и Serial.flush(); нечего будет делать.
0
|
||||||
|
3 / 3 / 1
Регистрация: 27.02.2014
Сообщений: 103
|
||
| 12.01.2017, 12:19 [ТС] | ||
|
0
|
||
|
1280 / 1185 / 175
Регистрация: 02.12.2013
Сообщений: 4,883
|
|
| 12.01.2017, 12:23 | |
|
0
|
|
|
3 / 3 / 1
Регистрация: 27.02.2014
Сообщений: 103
|
||||||||||||
| 12.01.2017, 15:25 [ТС] | ||||||||||||
|
Сейчас посидел, подумал, поломал голову и родил следующее:
Осталось распарсить и разложить по переменным, но дальше наверное проблем быть не должно. Добавлено через 4 минуты Там получается как: 1. Что хотим сделать 2. К какому реле относится. 3. Куча параметров. А если мне нужно прочитать данные, то: 1. Что хотим сделать 2. С какого реле нам параметры нужны. Вот и получается, что в любом варианте нужно парсить строку ![]() Добавлено через 2 часа 56 минут Вот ума не приложу что за прикол, может кто подскажет... Если я передаю в процедуру глобальную переменную, то изменяется массив. Отправляется - 01 01 05 01 7f 01 01 14 31 00 ce 0d Приходит уже - 01 01 05 01 7f 01 01 14 31 00 fb 0d А если я ничего в процедуру не передаю, а напрямую обращаюсь к глобальной переменной, то массив не меняется. Кстати, заметил еще что если в самой процедуре создать переменную и присвоить ей значение глобальной переменной, то массив сразу же меняется на 01 01 05 01 7f 01 01 14 31 00 fb 0d
0
|
||||||||||||
|
techpriest
634 / 213 / 57
Регистрация: 27.02.2014
Сообщений: 1,180
|
|
| 12.01.2017, 15:39 | |
|
... Да... Я вас немного обманул. Класс String для копирования использует функцию strcpy. Следовательно он некорректно копируется при работе с бинарными нулями. Что мы и видим.
Так что ValeryS таки прав. Проше всего пойти в реализацию функции и изменить ей конструктор копирования (Или, если точнее, функцию String & String::copy(const char *cstr, unsigned int length)) (Нафига ей в таком случае явное указание длины?)... Но с образовательной целью, может быть лучше отказаться от класса String и использовать массивы. Добавлено через 5 минут Самому себе я этот класс давным давно переделал и благополучно об этом забыл.
0
|
|
|
3 / 3 / 1
Регистрация: 27.02.2014
Сообщений: 103
|
|||||||
| 13.01.2017, 11:24 [ТС] | |||||||
![]() Добавлено через 19 часов 42 минуты Ну вот что получилось.
0
|
|||||||
|
Модератор
8978 / 6744 / 921
Регистрация: 14.02.2011
Сообщений: 23,852
|
||
| 13.01.2017, 12:54 | ||
|
структурирован, в случае чего легко добавить/убрать ветку
0
|
||
|
3 / 3 / 1
Регистрация: 27.02.2014
Сообщений: 103
|
|
| 14.01.2017, 15:37 [ТС] | |
|
Я тут подумал, подумал и пришел к следующему:
А что если записывать данные не в переменные, а в EEPROM и потом просто ресетить контроллер или вызывать функцию чтения параметров? Просто добавить в посылку перед каждым значением адрес в памяти и через "for" раскладывать. Как думаете, не лучше ли? Правда количество циклов записи ограничено...
0
|
|
|
techpriest
634 / 213 / 57
Регистрация: 27.02.2014
Сообщений: 1,180
|
|
| 14.01.2017, 23:18 | |
|
С тем же успехом можно и в коде программы без eeprom их записать.
0
|
|
|
3 / 3 / 1
Регистрация: 27.02.2014
Сообщений: 103
|
||
| 15.01.2017, 06:22 [ТС] | ||
![]() Я то говорил о том, чтобы настройки сразу писать в EEPROM при сохранении. Логика будет следующей: 1. Настройки пишутся напрямую в память 2. После записи настроек контроллер ресетится программно. Пока я придерживаюсь правила - сначала в переменные закинуть, а потом уже сохранить в память (кто знает сколько раз нужно будет в память запись производить пока все устроит по настройкам)
0
|
||
|
techpriest
634 / 213 / 57
Регистрация: 27.02.2014
Сообщений: 1,180
|
|
| 15.01.2017, 09:33 | |
|
А, ну это можно...
0
|
|
|
365 / 348 / 74
Регистрация: 18.03.2015
Сообщений: 1,293
|
|
| 15.01.2017, 13:20 | |
|
0
|
|
|
3 / 3 / 1
Регистрация: 27.02.2014
Сообщений: 103
|
||
| 15.01.2017, 13:32 [ТС] | ||
|
0
|
||
| 15.01.2017, 13:32 | |
|
Помогаю со студенческими работами здесь
20
Прием и отправка данных на COM-порт Прием данных через COM порт Прием данных через LPT-порт Прием данных через USB порт Передача и приём данных через COM-порт Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
||||
|
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта
Симптом:
После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
|
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
|
Новый ноутбук
volvo 07.12.2025
Всем привет.
По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне:
Ryzen 5 7533HS
64 Gb DDR5
1Tb NVMe
16" Full HD Display
Win11 Pro
|
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
|
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
|
|
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов
На странице:
https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/
нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
|
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов.
. . .
|
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
|
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
|
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут.
В век Веб все очень привыкли к дизайну Single-Page-Application .
Быстренько разберем подход "на фреймах".
Мы делаем одну. . .
|