|
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
|
||||||||||||||||
Почему пропадают/искажаются сообщения SerialPort?06.03.2025, 17:09. Показов 7647. Ответов 61
Метки serialport (Все метки)
Программа должна обмениваться данными с несколькими платами Arduino(сейчас подключаю 3 шт., планируется больше, но проблемы появляются и ни одной шт., и на двух…).
В тестовом режиме режиме я отправляю “99/0/0/0” – плата считывает это сообщение и отправляет обратно. В мониторе порта программы Arduino все работает четко и стабильно, без каких-либо сбоев (во всяком случае, мне не удалось такое обнаружить). Но вот когда подключаю написанную программу – начинаются проблемы: часто вместо отправленного сообщения программа получает не отображаемые символы, в кодировке Asc номера: 13, 10. Иногда программа вообще не получает никакого ответа. В программе использованы библиотеки:
0
|
||||||||||||||||
| 06.03.2025, 17:09 | |
|
Ответы с готовыми решениями:
61
Visual studio 2019. Элемент serialport, почему нет метода getportnames? Почему пропадают элементы в конструкторе формы? |
|
Модератор
1245 / 676 / 292
Регистрация: 10.11.2019
Сообщений: 1,406
|
|||||||||||
| 19.04.2025, 17:40 | |||||||||||
Сообщение было отмечено Yury Komar как решение
Решение
С кодировками действительно оказалась проблема - по умолчанию стоит ASCII и все русские символы
превращаются в знаки вопроса '?' Вот какой рабочий пример получился (на форме два TextBox, SerialPort,Timer)
Пересылку всех произвольных байт с кодами >=128 пока не проверял, может какие-то байты опять не работают.
1
|
|||||||||||
|
Модератор
1245 / 676 / 292
Регистрация: 10.11.2019
Сообщений: 1,406
|
||||||
| 20.04.2025, 13:14 | ||||||
|
Проверил, при использовании команд
Но тогда возникает вопрос: а как работать с нерусскими версиями Windows ? Или как правильно использовать .Write при передаче байт, а не текста ?
0
|
||||||
|
Модератор
1245 / 676 / 292
Регистрация: 10.11.2019
Сообщений: 1,406
|
||||||
| 08.08.2025, 17:38 | ||||||
|
Случайно нашёл ответ на этот вопрос. Достаточно написать:
1
|
||||||
|
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
|
||
| 16.08.2025, 08:33 [ТС] | ||
|
Отмечу тот момент, что время процедуры запрос-ответ, в данном варианте кода, у меня выдавал 105...115 мс (при скорости 250000, понятно что на эту величину влияет размер сообщения).
0
|
||
|
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
|
||||||
| 17.08.2025, 07:50 [ТС] | ||||||
|
К чему я в предыдущем посте привел цифры времени: привожу пример кода, к которому пришел я. Не утверждаю что в нем нет изъянов, и не претендую на исключительную правильность, при тех же исходных данных этот код дает затрату времени на оберацию порядка 40...65 мс:
0
|
||||||
| 17.08.2025, 11:54 | ||
|
Запись и чтение из порта без "арбитра", причём ещё и из разных потоков, теоретически ведёт к проблемам. Да и наличие Thread.Sleep и DoEvents как бы намекает на проблемы. Для стабильности принятия данных из порта нужно чтобы обратные вызовы были не блокирующими поток. Для реализации такого можно использовать SynchronizationContext и его метод Post. Метод _serialPort.WriteLine следует обернуть в методы "арбитра", который будет разруливать очерёдность работы с портом (чтение/запись по очереди) если протокол обмена запрос-ответ. Он же (арбитр) может следить за целостностью данных. Например, если ответ не принят полностью, то ожидать принятия данных и блокировать запись в порт. Как только данные получены полностью или не получены за установленный тайм-аут разрешать запись в порт. Если данные получены не полностью и истёк тайм-аут, то убивать "сломанный" пакет данных и поднимать соответствующий флаг. Не по теме: Работы не початый край.
1
|
||
|
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
|
|||
| 22.08.2025, 11:28 [ТС] | |||
|
0
|
|||
|
|
||
| 22.08.2025, 12:12 | ||
Send(), тогда будет гарантия выполнения задания и последующий код будет работать с реальными данными. Метод Post() асинхронный и после его вызова следующая строка выполняется сразу, не ожидая выполнения синхронизированного кода, а это чревато трудноуловимыми ошибками...Использование метода Send() не вешает основной поток, всё происходит как нужно при асинхронных операциях, но гарантировано даёт согласованность действий.
0
|
||
|
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
|
||||||
| 22.08.2025, 12:38 [ТС] | ||||||
|
Стоит еще обратить внимание на такой момент: приведенный вариант кода, с прежними исходными данными, дает скорость на одну оберацию 5...7 мс:
Добавлено через 24 минуты На данный момент у меня получается, что я разрушил все фундаменты, на которых собирался построит программу ![]() ![]() Предполагался следующий алгоритм действий для реализации: 1. Программа работает с динамическим количеством портов SerialPort, доступным при запуске программы и сообщившем ей уникальный идентификатор для общения. 2. Программа из файла Excel считывает таблицу адресов отправки сообщений. 3. Программа, в зависимости от адреса, общается с SerialPort в двух вариантах: в один порт отправляет сообщение и из него получает ответ. Второй вариант сообщения в 2 порта: 1 - подать сигнал; 2 - проверить получение сигнала и отправить соответствующее сообщение о результате в программу. 4. Наверное, нужен отдельный поток по обработке полученного результата и его выводе на форму и в Excel. Допускаю, что этот поток может отставать от процесса общения с портами... Как это всё разбросать по переменным/ классам/потокам/...? чтоб все работало стабильно и быстро?
0
|
||||||
|
Модератор
4372 / 3442 / 512
Регистрация: 27.01.2014
Сообщений: 6,266
|
|
| 22.08.2025, 14:40 | |
|
filat18, Я делал как-то прием всех сообщений (а это непрерывный поток) в отдельном потоке, этот поток тупо их собирал в очередь последовательно, а уже другой поток, при наличии в очереди тех самых сообщений, начинал эту очередь перебирал последовательно и обрабатывал.
Почему так делал? Потому, что скорость приема была быстрее, чем обработка данных с отрисовкой результатов. Разнича была примерно в одну секунду, и за эту секунду, без очереди принятых сообщений, часть данных просто терялась, пока обрабатывалось предыдущее, 2/3 сообщения пролетали мимо, и поэтому решил собирать ВСЁ и обрабатывать уже ВСЕ принятые ненапрямую из порта, а из очереди... Очень, на мой взгляд, удачное решение было для моего случая.
0
|
|
|
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
|
||
| 23.08.2025, 07:28 [ТС] | ||
|
Добавлено через 33 минуты У меня пока не складывается общая конфигурация алгоритма увязки коллекции портов с механизмом подключения события чтения? Если можно, добавьте пожалуйста максимум подробностей: на какой этапе и какие элементы должны появляться, и куда передаваться?
0
|
||
|
Модератор
4372 / 3442 / 512
Регистрация: 27.01.2014
Сообщений: 6,266
|
|
| 23.08.2025, 11:39 | |
|
filat18, Ну вот то, что вы сейчас делаете, тоесть по получению данных из порта - выполняете что-то (в подробности вашего кода не заглядывал, поэтому незнаю, что именно у вас там происходит) и после завершения выполнения процедуры, обрабатывающей принятые данные, снова слушаете порт и так далее по кругу...я так понимаю.
Так вот поставьте один поток непрерывно слушать порт, без остановок собирая приходящие сообщения в очередь (можно взять готовый класс в составе . NET "queue", а уже другой поток запускайте, ктороый будет поочереди в порядке получения брать каждое сообщение и обрабатывать (слать в другие порты или же пользователю показывать результат).
0
|
|
| 23.08.2025, 13:26 | ||
|
Как я вижу алгоритм оооочень приблизительно. 1. Создаётся поток чтения сом-порта. 2. В бесконечном цикле (естественно с проверкой CancellationToken или чего-то подобного) ведётся чтение порта, но только после запроса в порт. 3. После получения порции данных они либо сразу отправляются в потокобезопасную коллекцию, либо собираются во вспомогательной коллекции. Это нужно для контроля целостности данных. После получения полного ответа (для второго случая) он помещается в потокобезопасную коллекцию. И вот именно тут нужен неблокирующий вызов, т.к. коллекция может быть занята на чтение. 4. Далее поток переходит к ожиданию или отправке, если он уже есть, запроса в порт. Для организации очереди запросов, хранения ответов, арбитража запрос/ответ и контроля целостности данных нужен класс инкапсулирующий всю эту логику. Именно такой класс я имел ввиду называя его "арбитр" в сообщении выше. Тоже самое на пальцах: Мы поток работы с сом-портом. - ожидаем разрешающий сигнал (например от семафора) на чтение запроса из очереди запросов. - получив сигнал выгружаем запрос из очереди. При необходимости преобразуем его в пакет данных понятный устройству на линии сом-порта. - отправляем запрос в порт. - разрешаем чтение из порта просигналив соответствующим семафором. - метод чтения из порта блокирует отправку запросов в порт, например семафором. - в цикле читаем порт и складываем данные в переменную или свойство "арбитра". Одновременно с этим проверяем получение пакета данных и отсчитываем тайм-аут. - если пакет получен полностью завершаем чтение из порта при этом создаём разрешающий сигнал на чтение запроса из очереди запросов. Если истекает тайм-аут, а ответ не получен полностью, то генерируем либо исключение, либо событие об ошибке, а далее завершаем чтение точно также как в предыдущем предложении. При получении пакета данных он может быть преобразован в ответ "высокого уровня". Таким образом у нас есть два протокола: один низкоуровневый (на уровне сом-порта), другой высокоуровневый на уровне нашей программы. Причём стандартизируются как запросы так и ответы.
1
|
||
| 24.08.2025, 22:58 | |
|
Накидал пример "арбитра", в котором реализованы попеременная запись команд и приём данных. В примере два варианта обработки полученных данных. Первый через асинхронный вызов делегата, второй при помощи события (с блокировкой потока чтения). Второй вариант закомментирован. Оба варианта потокобезопасны.
В примере нет: - самих чтения и записи данных в порт (только имитация); - какой либо обработки команд и ответов (парсинг, контроль целостности и т.п.); - слежения за тайм-аутом ответа;
2
|
|
| 25.08.2025, 09:58 | |
|
Взглянув со свежей головой на код я думаю, что совершенно излишне я разделил чтение и запись по потокам. Так как протокол обмена "запрос-ответ", то процедуры записи и чтения можно запихнуть в один поток. То есть код можно значительно упростить и сократить.
0
|
|
|
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
|
||||||
| 29.08.2025, 13:12 [ТС] | ||||||
|
Чуть подправил, добавил строку закрытия порта:
0
|
||||||
|
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
|
|
| 29.08.2025, 13:45 [ТС] | |
|
И еще столкнулся с моментом когда процесс отправки стопорится (ни отправка, ни чтение не работают). Окно программы закрыть можно, но отдельный поток продолжает висеть... А в окне вывода пишет: "Программа "[12732] ProtokolBroker.exe" завершилась с кодом 4294967295 (0xffffffff)."
0
|
|
|
|
||
| 29.08.2025, 13:51 | ||
|
0
|
||
|
8 / 7 / 4
Регистрация: 03.12.2020
Сообщений: 342
|
|||||||
| 29.08.2025, 14:35 [ТС] | |||||||
0
|
|||||||
| 29.08.2025, 14:35 | |
|
Почему пропадают созданные ячейки таблицы? Serialport.write и serialport.basestream.write - в чем разница C# SerialPort Неполный прием сообщений Почему не приходит сообщение группе SignalR? Почему в отправляемом почтовом сообщении появляются вопросики? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Лето уходит
kumehtar 17.08.2026
|
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
|
Перемещение строк из ТЧ в другой документ с учетом текущего пробега
Maks 17.08.2026
Реализация из решения ниже выполнена на примере нетипового документа "Автозапчасти", с ТЧ "Шины".
За основу взят алгоритм отсюда: https:/ / www. cyberforum. ru/ blogs/ 359708/ 10838. html
Задача: . . .
|
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
|
|
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет:
1. Использовать системное время и дату,
2. Есть возможность вводить время и дату вручную.
3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
|
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber.
Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
|
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео:
https:/ / vkvideo. ru/ video-240781534_456239017
YouTube:
eY5-5PyI9NM
Текстовая версия
|
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать
Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
|