Форум программистов, компьютерный форум, киберфорум
КИП, датчики
Войти
Регистрация
Восстановить пароль
 
0 / 0 / 0
Регистрация: 23.05.2014
Сообщений: 70
1

Прием массива в ComPort. Как можно увеличить скорость?

22.04.2021, 16:37. Показов 454. Ответов 7
Метки нет (Все метки)

Всех приветствую!
Есть нужда принимать и отображать данные из массива 100-150 байт с частотой 25...50 Гц. На данный момент удалось достигнуть максимальной частоты 30 Гц, а хотелось бы 50 (хотелось бы 100 Гц, но уже наверное перфекционизм)))).
Вот код:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
           Thread.Sleep(30);//Pause = 30 mSec
 
            if ((serialPort1.BytesToRead > 0)&(serialPort1.IsOpen))
            {
                rxidx = serialPort1.BytesToRead;//индекс приемного буфера byte rssi[]
                try
                    { serialPort1.Read(rssi, 0, rxidx);}
                    catch (Exception ex)
                    { MessageBox.Show(ex.Message); }            
                  serialPort1.DiscardInBuffer();
                }
            Invalidate(new Rectangle(15, 70, 550, 400)); //Перерисовка
        }
Фактически на скорость влияет всего один параметр - время приостановки потока. К своему стыду, не смог разобраться какой именно поток тормозится - поток, в котором происходит прием данных или поток, в котором происходит отрисовка?

P.S. Убедительная просьба: все соображения о моем интеллекте, об уровне знаний и просто упражнения в остроумии здесь не публиковать . Если непосредственно по теме сказать нечего, но очень хочется вставить шпильку, уколоть или показать свое превосходство - пишите пожалуйста в личку. Спасибо.

Добавлено через 6 минут
Забыл написать: приём/передача осуществляется через виртуальный COM-port (FT232) на скорости 115200 Baud.

Добавлено через 1 час 50 минут
Если я правильно понимаю, то считывание данных происходит асинхронно, т.е. не привязано ни к каким событиям, кроме SerialPort.DataReceived. На практике вроде бы так и выходит - как только я открываю порт кнопкой "OPEN", так сразу же начинается отрисовка и она тут же прекращается пир закрытии порта кнопкой "CLOSE".
Тогда для чего требуется тормозить поток? 20-30 милисекунд для окончания приёма пакета или время на завершение обработки предыдущего? Вроде как прослеживается аналогия с обработчиком прерываний в микроконтроллерах - событие вызывает процедуру-обработчик, которая исполняется вне зависимости от основного цикла. Значит, если предположить эту аналогию, то задержка потока нужна для окончания приема посылки от микроконтроллера. Может тогда стоит создать(или использовать существующее) событие, которое возникает по некой метке - EOF(конец передачи) или \n(конец строки)?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.04.2021, 16:37
Ответы с готовыми решениями:

Приём большого массива данных через COMport
Есть МК, по команде с компьютера он в ответ отправляет 32772 байт. Вопрос, как лучше принимать...

Как можно увеличить скорость подсчета строк в таблице
Доброй ночи. Есть таблица на 9500000 строк как можно увеличить скорость подсчета строк в таблице...

Как увеличить скорость прорисовки массива вершин?
Имеется пара вертексных массивов, применяю простой код для прорисовки: ......... float...

Можно ли увеличить скорость ответа БД
Привет всем у меня возник такой вопрос как можно увеличить скорость ответа бд, иногда когда долго...

7
фрилансер
2197 / 1664 / 410
Регистрация: 11.10.2019
Сообщений: 4,865
22.04.2021, 17:08 2
Цитата Сообщение от mpetrovich Посмотреть сообщение
Thread.Sleep(30);
вот один тормоз я точно вижу. Зачем он тут?

Добавлено через 1 минуту
логичнее сделать так - если serialPort1.Read ничего не прочитало, сделать sleep(1)

Добавлено через 58 секунд
надеюсь, sp_DataReceived - это всё в отдельном потоке ?

Добавлено через 2 минуты
схема должна быть такая:

в отдельном потоке в бесконечном цикле тупо вычитывается весь трафик из порта, данные анализируются, осмысленные пакеты складываются в синхронизированную очередь

другой поток разгребает эту очередь и рисует текущее состояние на картинке
0
0 / 0 / 0
Регистрация: 23.05.2014
Сообщений: 70
22.04.2021, 17:39  [ТС] 3
Цитата Сообщение от Алексей1153 Посмотреть сообщение
вот один тормоз я точно вижу. Зачем он тут?
Да я, собственно, тоже не понимаю. но без него рисует произвольные куски массива.
Цитата Сообщение от Алексей1153 Посмотреть сообщение
логичнее сделать так - если serialPort1.Read ничего не прочитало, сделать sleep(1)
Так у меня пока нет данных, ничего и не происходит: if((serialPort1.BytesToRead > 0)&(serialPort1.IsOpen)), тогда и производятся действия, а на нет и действий нет.)))
Цитата Сообщение от Алексей1153 Посмотреть сообщение
надеюсь, sp_DataReceived - это всё в отдельном потоке ?
Что Вы имеете в виду? Создан ли поток для обработчика?
Цитата Сообщение от Алексей1153 Посмотреть сообщение
схема должна быть такая:
в отдельном потоке в бесконечном цикле тупо вычитывается весь трафик из порта, данные анализируются, осмысленные пакеты складываются в синхронизированную очередь
другой поток разгребает эту очередь и рисует текущее состояние на картинке
По-моему трафик из порта вычитывается в любом случае весь, поскольку сначала rxidx = serialPort1.BytesToRead;
а потом serialPort1.Read(rssi, 0, rxidx);
Если не затруднит, набросайте примерный код для Вашего варианта.

Добавлено через 11 минут
Цитата Сообщение от Алексей1153 Посмотреть сообщение
логичнее сделать так - если serialPort1.Read ничего не прочитало, сделать sleep(1)
Само событие sp_DataReceived возникает при приёме в буфер порта данных(я, во всяком случае, так понимаю это событие). Сто байт пришло, сто раз выскочило событие. Аналогом может служить запрос на прерывание по окончания приёма в буфер UART микроконтроллера, по которому выставляется соответствующий флаг в регистре состояния. Или я неверно понимаю?
0
фрилансер
2197 / 1664 / 410
Регистрация: 11.10.2019
Сообщений: 4,865
22.04.2021, 18:11 4
mpetrovich, пример накидать не могу, я шарп не знаю.

Если sp_DataReceived - это обработчик события, то слип там точно не нужен. Почему не работает без него - нужно разбираться. Наверное, потому что Invalidate должен вызываться внутри if (то есть - при наличии новых данных)
0
0 / 0 / 0
Регистрация: 23.05.2014
Сообщений: 70
23.04.2021, 12:49  [ТС] 5
Цитата Сообщение от Алексей1153 Посмотреть сообщение
схема должна быть такая:
в отдельном потоке в бесконечном цикле тупо вычитывается весь трафик из порта, данные анализируются, осмысленные пакеты складываются в синхронизированную очередь
другой поток разгребает эту очередь и рисует текущее состояние на картинке
Попробовал воспользоваться процедурой, предложенной Вами. Честно сказать, не ожидал, что получится))) Однако же, получилось! Код вот такой:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            while ((e.EventType != SerialData.Eof) | (rxidx < 100))
                 {
                    if (serialPort1.IsOpen)
                    {
                        try
                        { rssi[rxidx++] = (byte)serialPort1.ReadByte(); }
                        catch (Exception ex)
                        { MessageBox.Show(ex.Message); }
                    }
                }
 
            Invalidate(new Rectangle(15, 70, 550, 400));
            serialPort1.DiscardInBuffer();
        }
С частотой 50 Гц принимает и отображает, быстрее не успевает передаться вся посылка в 100 байт и оттого начинает рисовать кусками. Похоже мне удалось реализовать предельную скорость отображения при связи на 115200 Baud.
Единственное, что досаждает теперь - это исключения типа "истекло время ожидания...", возникающие при закрытии порта без закрытия формы. Но это терпимо)))
0
фрилансер
2197 / 1664 / 410
Регистрация: 11.10.2019
Сообщений: 4,865
23.04.2021, 13:00 6
mpetrovich, молодец, что разобрался )

Цитата Сообщение от mpetrovich Посмотреть сообщение
Invalidate(new Rectangle(15, 70, 550, 400));
тут: я, конечно, понимаю, что есть GC, всё такое, но всё же лучше создать Rectangle как поле класса или глобальную переменную, чтобы не дёргать постоянно кучу. Всёж-таки данный участок кода будет выполняться очень часто

Добавлено через 1 минуту
Цитата Сообщение от mpetrovich Посмотреть сообщение
while ((e.EventType != SerialData.Eof) | (rxidx < 100))
а в шарпе булево ИЛИ это одна палка или таки две?

Добавлено через 1 минуту
Цитата Сообщение от mpetrovich Посмотреть сообщение
"истекло время ожидания...", возникающие при закрытии порта
сделай break, если порт закрыт
0
0 / 0 / 0
Регистрация: 23.05.2014
Сообщений: 70
23.04.2021, 16:58  [ТС] 7
Цитата Сообщение от Алексей1153 Посмотреть сообщение
лучше создать Rectangle как поле класса или глобальную переменную
Rectangle вроде как структура. В методе Invalidate(new Rectangle(15, 70, 550, 400)); она вроде используется как переменная, по-моему.
Цитата Сообщение от Алексей1153 Посмотреть сообщение
а в шарпе булево ИЛИ это одна палка или таки две?
Я тоже удивлялся, но работает
Цитата Сообщение от Алексей1153 Посмотреть сообщение
сделай break, если порт закрыт
Сделал, стало маленько пореже выскакивать исключение. Но совсем не ушла эта фигня.

Добавлено через 1 час 50 минут
При остановке передачи с микроконтроллера, возникает исключение: "Операция ввода/вывода была прервана из-за завершения потока команд или по запросу приложения". Что это означает, я не смог пока разобраться.
0
11 / 9 / 4
Регистрация: 26.06.2020
Сообщений: 34
25.04.2021, 13:01 8
mpetrovich.
Сразу извинюсь, за банальный совет.
Попробуйте логическим анализатором посмотреть, что происходит на шине UART.
100 байт на скорости 115200 будут передаваться примерно 10 mS.
А с начало надо послать, как я понимаю, команду которая то же какое то время будет передаваться.
Затем команда будет обработана в устройстве, на это нужно время, затем устройство сформирует ответ и начнет передавать посылку сообщения (может непрерывно, а может будет прерываться).
Так вы сможете выяснить, какое максимальное кол-во запросов + ответов вы сможете реализовать за определенное время (вы обозначили за секунду).
Может цифра к которой вы стремитесь вообще не достижима.
По программе не подскажу, так как "Си шарп" не знаю, знаю только "Делфи" и "Си"
Могу сказать, что для получения максимальной скорости нужно использовать асинхронный режим работы UART.
Статей для реализации на "Делфи" или "Си Билдере" достаточно.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.04.2021, 13:01

Заказываю контрольные, курсовые, дипломные работы и диссертации здесь.

Можно ли увеличить скорость парсинга в HtmlAgilityPack?
Привет всем, я написал код для парсинга одного сайт, код рабочий, но срабатывает довольно долго(от...

Максимальная скорость беспроводного соединения: 54 Мбит/с - можно ли увеличить ее?
Здравствуйте.У меня старый wi-fi роутер. У него Макс. скорость беспроводного соединения: 54 Мбит/с....

Можно ли увеличить скорость на мамке Shuttle AB52 USB1.1 до USB2.0?
Добрый вечер!Скажите пожалуйста можно ли как нибудь увеличить скорость на мамке Shuttle AB52 USB1.1...

Увеличить скорость перебора элементов массива
Всем привет! Пишу тут первый раз, так что, не ругайте за возможные косяки. Дело вот в чем:...

Как можно увеличить размер массива на 1, чтобы добавилась еще одна строка снизу
дан двумерный массив, где i - индекс столбца, j - индекс строки. Как можно увеличить размер массива...

Как увеличить скорость Wi-Fi?
Добрый день, прошу совета. Провайдер - мгтс, тариф разгони вай-фай, 150 мбит/с, новый роутер (без...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.