Скорость виртуального COM порта для Arduino Nano с CH341
- Войдите на сайт для отправки комментариев
Втр, 02/10/2018 - 23:44
void setup() { // put your setup code here, to run once: Serial.begin(1000000); // Устанвливаем высокую скорость } unsigned long t0; unsigned long t1; String s = "This is test String 123"; String s2 = "This is test String2"; String sCmd = ""; char c; void loop() { // put your main code here, to run repeatedly: // Прием - ответная передача. Режим минимальной обработки if(Serial.available() > 1) // Если есть символы { t0 = micros(); sCmd = Serial.readStringUntil('\xa'); // Принимаем строку t1 = micros(); Serial.print("Recevice time:"); Serial.println(t1 - t0); t0 = micros(); Serial.print(sCmd + "\xa"); // Передаем обратно Serial.flush(); // Ждем окончания передачи t1 = micros(); Serial.print("Send time:"); Serial.println(t1 - t0); } }
Здравствуйте! Начал работать с ардуино недавно. Сейчас использую Arduino Nano с китайской микросхемой преобразователя COM-USB CH341. При этом пытаюсь использовать для обмена между программой на компьютере и программой в плате виртуальный COM порт на задаваемой скорости до 2000000 бод. Но скорость обмена с программой на компьютере все равно не превышает 18 кбайт в секунду. Вывожу время одной операции при посылке данных через функцию Serial.println и при приеме данных через Serial.ReadStringUntil. Программа приведена выше. Вот ее результаты для одного символа и для группы символов:
Извините, вопрос не задал. Хотел спросить, что я делаю неправильно? Почему скорость обмена так далека от теоретической для данной заданной скорости в 1000000 бод или 2000000 бод?
А Вы уверены, что COM-порт Ардуины способен работать на скоростях порядка 1-2 Мбит?
Почему скорость обмена так далека от теоретической для данной заданной скорости в 1000000 бод или 2000000 бод?
По моим подсчётам, "Send time:158" соответствует не 18 кбайт в секунду, а примерно 58 - то есть, почти 600000 бод.
Нормальный результат для ардуины, я считаю. А если хочется полной теоретически возможной скорости - это наверно уже осциллографом смотреть, и выяснять где именно возикают паузы.
Вполне может быть, виноватым окажется даже не ардуино, а компьютер. Во всяком случае, я бы для начала проверил скорость передачи/приёма компом при работе "на себя", т.е. через просто замкнутые контакты RX и TX, без всякой ардуины, вообще.
Спасибо за ответы! Но понимаете, осциллограф здесь поможет разве что для внешнего порта. А я работаю через USB то есть порт то виртуальный. И к скорости посылки у меня нет претензий, проблема как раз в скорости приема от компьютера. И пожалуй Вы правы, скорее всего это компьютер. Но почему виртуальный порт компьютера через USB не может обеспечить скорость непонятно... Еще раз спасибо ! Вопрос как проверить максимальную скорость виртуального COM порта через USB на компьютере ???
осциллограф здесь поможет разве что для внешнего порта. А я работаю через USB то есть порт то виртуальный
Но всё равно, смысл эксперимента понятен - исключить влияние микроконтроллера, и узнать на какой скорости работает сам компьютер.
Насколько я понимаю, для этого нужно подать на ардуино сигнал RESET (постоянно), чтобы контроллер "отпустил" ноги RX/TX, и потом просто соединить эти RX и TX перемычкой.
Я не утверждал, что виноват именно комп - просто, если уж искать причину, так надо проверить всё что можно.
А Вы уверены, что COM-порт Ардуины способен работать на скоростях порядка 1-2 Мбит?
Несколько лет назад работало, проверял 921600 реалтермом (Realterm).
По крайней мере данные передавались и не терялись.....
А на самом деле дело еще печальнее. Я попробовал слать сообщения не из серии байт а из одного байта и мерять время пересылки в программе на компьютере. Скорость получилась вообще ужасной... около 2 кбайт в секунду. Тут точно, или я что - то не так делаю, или китайская ардуино нано не может больше. То есть что 1 байт что 16 передавать за раз скорость меняется не пропорционально.... Интересно, а можно как то два компьютера соединить через виртуальный ком порт по USB или лучше по Eithernet попробовать?
А на самом деле дело еще печальнее. Я попробовал слать сообщения не из серии байт а из одного байта и мерять время пересылки в программе на компьютере. Скорость получилась вообще ужасной... около 2 кбайт в секунду. То есть что 1 байт что 16 передавать за раз скорость меняется не пропорционально....
Вы прям Америку открыли :) Практически не существует протоколов, где передача 1 байта будет происходить с той же скоростью, как и серии. Да, кстати, это не только к байтам относится :) - передача одного ли яблока, ящика или тонны яблок из Петербурга в Казань тоже занимает примерно одинаковое время, вовсе не пропорциональное количеству :)
Аналогия понятна?
А на самом деле дело еще печальнее. Я попробовал слать сообщения не из серии байт а из одного байта и мерять время пересылки в программе на компьютере. Скорость получилась вообще ужасной... около 2 кбайт в секунду. То есть что 1 байт что 16 передавать за раз скорость меняется не пропорционально....
Вы прям Америку открыли :) Практически не существует протоколов, где передача 1 байта будет происходить с той же скоростью, как и серии. Да, кстати, это не только к байтам относится :) - передача одного ли яблока, ящика или тонны яблок из Петербурга в Казань тоже занимает примерно одинаковое время, вовсе не пропорциональное количеству :)
Аналогия понятна?
На совсем, по идее пересылка одного байта должна быть побыстрее ))) Мягко говоря. Иначе при чем тут 1 мегабит заявленной скрости? Вопрос только в том что реально тормозит так сильно, ардуино или же виртуальный порт на компьютере. И тогда вопрос почему порция данных пересылается не пропорционально медленее одного данного ??? Это что, логика такая у виртуального COM порта ?? А что ж тогда делать если надо слать короткие сообщения но часто???
вопрос почему порция данных пересылается не пропорционально медленее одного данного ??? Это что, логика такая у виртуального COM порта ?? А что ж тогда делать если надо слать короткие сообщения но часто???
Какие однако вы наивные вопросы задаете... не программист что ли?
Куча коротких сообщений ВСЕГДА передается значительно медленнее, чем одно длинное суммарной длины. В любом протоколе есть "накладные расходы" - заголовки пакетов, служебная информация. Вы думаете, что передали 1 байт, а компьютер для этого отправил в линию еще пятьдесят. И так ДЛЯ КАЖДОГО пакета, независмо от длины. В итоге для 1 байта передается 51, для 16-ти - 67, а для тысячи - 1050. И в каком случае удельная скорость передачи Ваших байтов оказывается выше, как вы думаете?
Те мегабиты скорости, о которых вы говорите - никогда не достигнутся на коротких сообщениях. Это аксиома.
Странно, что вообще приходится обьяснять такие очевидные вещи. Если не верите - проделайте эксперимент - сравните время, за которое копируется 1 файл размером 50-100мегабайт, и 500 файлов такого же суммарного обьема. Маленькие файлы можете найти в директории Windows\Fonts
Ну не будем показывать друг на друга пальцем и обвинять в том что кто - то из нас непрофессионал. )) Меня мой опыт устравивает))) Я понимаю что в драйвере порта есть буферы. И что драйвер не посылает байт немедленно(хотя по идее надо бы было предусмотреть такой режим). Сам писал такие драйверы. Но вот не совсем понятно почему такие дикие накладные расходы ? Вы всерьез верите что для того чтобы отправить в линию один байт необходимо готовиться к этому едва ли не миллисекунду? Я помню мы замеряли время реакции драйвера ядра для NT 4 на DeviceIoControl. Ну там ито было быстреен))) А именно такое время у меня получается для посылки одного байта в одну сторону.
ATMEGA328 Baud Rate Error = 0% at 2,4k, 250k, 0,5M, 1M
Извините, а что означает эта статистика? Каков реальный трафик ?
Извините, а что означает эта статистика? Каков реальный трафик ?
это реальный трафик) (если условие идеал не 200 ft кабель)
Тогда подскажите, пожалуйста, а как Вы его замеряли? Какой программой? И если программа Ваша, то какую модель доступа к COM порту Вы использовали ? Я использую асинхронную по событиям. Моя плата Arduino Nano с китайским чипом CH341 для преобразования COM - Serial. Если слать длинную последовательность байт скорость как будто выше если по одному байту скорость ужасная. Я грешить уже стал на то что виртуальный COM порт реализован через протокол USB и видимо драйвер связывает трафик COM порта с какой - то низкоприоритетной конечной точкой USB. Но не уверен в своих предположениях. Если не трудно поделитесь информацией как Вы замеряли скорость?
Учитывайте, что Винда - не RTOS. Если сам процесс уже начавшейся пересылки и будет привязан к заданной частоте, то его начало (синхронизация) не обязано произойти в тот момент, когда вы даете команду send().
персонально чип CH340G, чипконтроллер плата uno от китай, софт putty & TerminalPro. USB cabel 5.9 ft.
strarbit, так по даташиту у 340-й до 2Mbps обещанная скорость... Или нет?
персонально чип CH340G, чипконтроллер плата uno от китай, софт putty & TerminalPro. USB cabel 5.9 ft.
Извините за дотошность, эти программы как меряют трафик? Просто у меня в контроллере программная петля - получил строку послал обратно. Какая программа должна быть в контроллере для измерения скорости?
Учитывайте, что Винда - не RTOS. Если сам процесс уже начавшейся пересылки и будет привязан к заданной частоте, то его начало (синхронизация) не обязано произойти в тот момент, когда вы даете команду send().
Спасибо! Замечание справедливое. Просто мне казалось что если порт занят мной эксклюзивно и протокол нижнего уровня usb то протоколы не должны давать таких диких задержек. Я боюсь что проблема в драйвере порта.
Тем более что есть оказывается программы, которые дают заявленные скорости
Просто мне казалось что если порт занят мной эксклюзивно и протокол нижнего уровня usb то протоколы не должны давать таких диких задержек. Я боюсь что проблема в драйвере порта.
Исключать проблем драйвера нельзя, конечно. Однако, монопольный режим говорит нам только о том, что в данный порт никто более не может писать, но это не гарантирует ему обслуживание с более высоким приоритетом.
К тому же, насколько я помню, USB - не point-to-point шина, по двум ее проводам может передаваться траффик нескольких конкурирующих устройств.
Так что подводных камней тут множество. Но я, к сожалению, не могу сообразить, как устроить чистое тестирование.
Просто мне казалось что если порт занят мной эксклюзивно и протокол нижнего уровня usb то протоколы не должны давать таких диких задержек. Я боюсь что проблема в драйвере порта.
Исключать проблем драйвера нельзя, конечно. Однако, монопольный режим говорит нам только о том, что в данный порт никто более не может писать, но это не гарантирует ему обслуживание с более высоким приоритетом.
К тому же, насколько я помню, USB - не point-to-point шина, по двум ее проводам может передаваться траффик нескольких конкурирующих устройств.
Так что подводных камней тут множество. Но я, к сожалению, не могу сообразить, как устроить чистое тестирование.
Согласен, вопрос непростой! Увы я как раз боюсь что на уровне usb выделена конечная точка с низким приоритетом. Но я постарался исключить весь другой траффик на данном usb хабе. Скачаю наверное putty&Terminal Pro и попробую как рекомендуется выше померять.
strarbit, так по даташиту у 340-й до 2Mbps обещанная скорость... Или нет?
даташит 2Mbps, передатчик ошибка меньше чем 0,3%, приемник < 2%. В реально кабель USB 5pin 5,9 ошибка нет. (любовь ftdi, max)
strarbit, так по даташиту у 340-й до 2Mbps обещанная скорость... Или нет?
даташит 2Mbps, передатчик ошибка меньше чем 0,3%, приемник < 2%. В реально кабель USB 5pin 5,9 ошибка нет. (любовь ftdi, max)
Извините, я наверное тупой, но из вашего скриншота непонятно как меняется реальный траффик. Подскажите пожалуйста, как с помощью этого терминала или putty померять реальную скорость приема и передачи строки в плату с CH341?
Полагаю, что здесь мы видим простой эхо-тест на Custom speed. Если обратно (Recieve field) он приходит непобитым, то следует вывод - канал без ошибок работает на заданной скорости. Т.е. тут инструментальных измерений нет.
Полагаю, что здесь мы видим простой эхо-тест на Custom speed. Если обратно (Recieve field) он приходит непобитым, то следует вывод - канал без ошибок работает на заданной скорости. Т.е. тут инструментальных измерений нет.
Ну из этого как раз совсем не следует что реальный траффик при коротких сообщениях будет на заявленной скорости. Посмотрел исходники putty, ничего принципиально нового они не используют при обмене с COM портом в Windows. Похоже все же это драйвер порта.
В таком случае, для начала, необходимо принять общую методику измерений. Как минимум - оговорить от какой и до какой точки, а так же при каком характере траффика требуется измерение пропускной способности канала.
Я не думаю, что производитель чипа в даташите указал скорость исходя из промеров через винду. Ногами чип может дергать так, чтобы обеспечить частоту для передачи на скорости в 2Mbps, ошибок не делает при этом - значит так вендор и написал в документации. Считаю, что, в принципе, примененный strarbit метод оценки возможной скорости релевантен для вышеуказанных вводных условий при условии совершения минимума телодвижений.
В таком случае, для начала, необходимо принять общую методику измерений. Как минимум - оговорить от какой и до какой точки, а так же при каком характере траффика требуется измерение пропускной способности канала.
Я не думаю, что производитель чипа в даташите указал скорость исходя из промеров через винду. Ногами чип может дергать так, чтобы обеспечить частоту для передачи на скорости в 2Mbps, ошибок не делает при этом - значит так вендор и написал в документации. Считаю, что, в принципе, примененный strarbit метод оценки возможной скорости релевантен для вышеуказанных вводных условий при условии совершения минимума телодвижений.
Согласен. Для длинных сообщений я получал 33 килобайта в секунду. Скорее всего один символ передается в линию с заданной скоростью. Все остальное сделано так как удобно было для usb протокола при буферизации данных и не слишком быстрой реакции драйвера на очередной запрос.
Скрин видно время приема байты 123456789+0Dh+0Ah от чипконтроллер, скорость 2Mbps. Пауза или задержка и ошибка приема нет
Буфер размер на приемник и передатчик указывавет OS.
Скрин видно время приема байты 123456789+0Dh+0Ah от чипконтроллер, скорость 2Mbps. Пауза или задержка и ошибка приема нет
Буфер размер на приемник и передатчик указывавет OS.
Я смотрел код putty. Там даже проще чем я делаю для приема байтов. Скрин говорит о том что выставлена скорость 2 мегабода. А о реальном времени приема строки ничего не говорится. Точнее нет информации о разнице между временем посылки и временем приема в микросекундах. Есть лишь информация что при данной выставленной скорости ошибок нет. Определяющим здесь является реальное время за которое строка передана принята на другой стороне и получена в программе. А оно боюсь будет существенно выше чем для 2 мегабод. Или покажите мне на скрине красным кружком в Paint где реальное время передачи строки. Я видимо туплю и чего - то не понимаю.
OS windows не система реальное время. На скрин реально нет разницы между временем приема 12 байт, стого прием быстрый, пауза нет. на скрин время от компьютера - часы, минуты, секунды, миллисекунды, также в низ статус бар счетчик принятых байт RX. В Recieve ошибки байтов нет.
OS windows не система реальное время. На скрин реально нет разницы между временем приема 12 байт, стого прием быстрый, пауза нет. на скрин время от компьютера - часы, минуты, секунды, миллисекунды, также в низ статус бар счетчик принятых байт RX. В Recieve ошибки байтов нет.
Я Вас понял. Попробую тот же тест сделать дома для платы nano
Я провел тест терминала. В программе на плате я вставил цикл который 10 раз повторяет строку символов, посланную с терминала. В каждой итерации цикла была вставлена задержка в 500 микросекунд. По идее если бы терминал честно принимал строки с задержкой то он бы отобразил в поле миллисекунды разное время на каждую вторую запись. А он отобрази все ответы с одним временем. То есть терминал буферизирует ответы от платы и выводит их одним пакетом. Причем еще и с паузой.
Я провел тест терминала. В программе на плате я вставил цикл который 10 раз повторяет строку символов, посланную с терминала. В каждой итерации цикла была вставлена задержка в 500 микросекунд. По идее если бы терминал честно принимал строки с задержкой то он бы отобразил в поле миллисекунды разное время на каждую вторую запись. А он отобрази все ответы с одним временем. То есть терминал буферизирует ответы от платы и выводит их одним пакетом. Причем еще и с паузой.
Пример скетч и скрин разные. Все ответы с одинаковым временем, с того вы приказали это делать. Пауза это также приказ от вас. Программа не может быть виновата, честно выполнила приказ от вас.
Я провел тест терминала. В программе на плате я вставил цикл который 10 раз повторяет строку символов, посланную с терминала. В каждой итерации цикла была вставлена задержка в 500 микросекунд. По идее если бы терминал честно принимал строки с задержкой то он бы отобразил в поле миллисекунды разное время на каждую вторую запись. А он отобрази все ответы с одним временем. То есть терминал буферизирует ответы от платы и выводит их одним пакетом. Причем еще и с паузой.
Пример скетч и скрин разные. Все ответы с одинаковым временем, с того вы приказали это делать. Пауза это также приказ от вас. Программа не может быть виновата, честно выполнила приказ от вас.
Ну хорошо, если я неправильно настроил терминал, тогда подскажите как правильно провести тест, если в скетче именно такая вот программа когда каждый ответ задерживается на 500 микросекунд. Как это отобразить в терминале правильно ?
Я провел тест терминала. В программе на плате я вставил цикл который 10 раз повторяет строку символов, посланную с терминала. В каждой итерации цикла была вставлена задержка в 500 микросекунд. По идее если бы терминал честно принимал строки с задержкой то он бы отобразил в поле миллисекунды разное время на каждую вторую запись. А он отобрази все ответы с одним временем. То есть терминал буферизирует ответы от платы и выводит их одним пакетом. Причем еще и с паузой.
Пример скетч и скрин разные. Все ответы с одинаковым временем, с того вы приказали это делать. Пауза это также приказ от вас. Программа не может быть виновата, честно выполнила приказ от вас.
Ну хорошо, если я неправильно настроил терминал, тогда подскажите как правильно провести тест, если в скетче именно такая вот программа когда каждый ответ задерживается на 500 микросекунд. Как это отобразить в терминале правильно ?
Я с октября занимаюсь разработкой в Ардуино программы - измерения давления на двух датчиках. Реально меня интересовало время цикла измерений, а не когда результаты придут в компьтер через компорт. Поэтому я сначала поисследовал работу таймера в Ардуино и увидел, что разброс срабатывания достигает десятков микросекунд (+-12). Стало быть, прерывания также срабатывают "когда хотят".
Но для задачи это было некритично. Необходимо время измерения раз в 1-2 милисекунды. Самое интересное получается, если замерять время прохождения цикла LOOP с выдачей результатов и "молча" просто измеряя время цикла. Ведь от этого зависит когда ты измеришь свои АЦП. Так что, мне кажется за это надо "биться", а не как срабатывает непонятно когда выдающий накопленные данных буфер Serial.
Для замеров я написал тест (меня еще интересовало согласование двух датчиков). Кого интересует - есть диаграмма - две минуты Ардуино закидывает в монитор строки: 1 датчик, 2 датчик, номер цикла и длительность от начала опыта. Раброс времени цикла от 240 до 1200 микросекунд. Главное же то, что длительность между измерениями находится в пределах одной-двух милисекунд, не смотря на "отправку пакетов буфером Serial" когда ему хочется. Вот текст теста:
график времен прохождения цикла в течении 2 минут(не сумел вставить картинку) опишу так:
2 минуты измерений - рост времени цикла до 1 милисекунды за 1 секунду, потом неравномерно нарастает время цикла до 1.2 милисек к концу второй минуты измерений - дальше не измерял.
Вывод на Ардуино не удастся отследить изменения через компорт быстрее 1 милисек много данных. Поможет отслеживание в течение 10 сек через кольцевой буфер небольшого количества данных.
Например, мне удалось 10 сек наблюдать эти два датчика со временем цикла менее 700 микросекунд, обеспечивая по этой схеме 2 милисекундные измерения и выдавая 1 измерение из КБ за цикл, помогая (сглаживая время буфера) Serial равномернее "опорожняться". Если я неправ в чем - интересно услышать спокойное другое мнение.
арифметика в дополнительном коде устроена так, что А-Б - всегда дает правильный результат, даже если А - "перешагнуло" рубеж переполнения.
То есть :
В строке 9 уменьшаемое перешагнуло рубеж переполнения 32-разрядных чисел.
Для не-программиста не знать этого - простительно, просто исправьте, смешно выглядит.
Спасибо.
Так ведь тоже получается - зависит от того, что мы ловим.
Я, действительно, больше постановками и доработками за знатоками занимаюсь.
Главное получить ожидаемый результат.
Здесь я хотел сказать, что иногда важно проследить как идут измерения,
а вывести очень быстро не получится в компорт много данных и, главное,
измерения не удастся вовремя сделать.
Люблю молодых, считающих себя программистами. Спасибо еще раз за арифметику.
я сначала поисследовал работу таймера в Ардуино и увидел, что разброс срабатывания достигает десятков микросекунд (+-12). Стало быть, прерывания также срабатывают "когда хотят".
По какой методике разброст измеряли?
Какие прерывания имеются ввиду?
Не совсем понятно - за что именно надо биться?
Вы можете описать, что, конкретно, вам требуется для решения вашей задачи? Делать измерения с фиксированным интервалом в 2 мс?
Vladimir Shamov, долго пытался вникнуть в Ваш код и не слишком преуспел в этом.
Во-первых, масса ненужных глобальных переменных. Помимо прочего, они еще и затрудняют анализ текста программы.
Далее: по поводу 1 абзаца сообщения №38: не очень понятно, что и как Вы измеряли, но сильно подозреваю, что измеряли совсем не то, что хотели, либо сделали неверные выводы (по всей видимости, в этом абазаце Вы описываете результаты какого-то другого скетча, а не того, что приведен в сообщении).
Текст в остальных абзацах не прояснил того, что и как Вы пытаетесь сделать.
Запустил Вашу программу: она, судя по всему, аккуратно вываливает в порт нечто. Из анализа последних десятков строк этого нечто можно сделать выводы:
1. Вывод на печать происходит каждую итерацию цикла. Без пропусков.
2. Интервал времени между измереними порядка 2 мс.
3. Длина выводимой строки порядка 22 символов.
4. Из сравнения скорости порта 115200, а также пп. 1, 2 и 3 можно заключить, что длительность итерации определяется временем передачи по последовательному порту.
Но из приведенного совершенно непонятно:
- что именно Вы хотели измерить,
- с какой целью ставили эти эксперименты.
Если была цель уложиться в 2 мс, то Вы ее не просто не достигли, а явно и не пытались достичь. Тогда что?
Vladimir Shamov, долго пытался вникнуть в Ваш код и не слишком преуспел в этом.
Сергей! Коллега не спрашивал ничего, а пытался умничать. Типа глаза открывал на то, что у него не получилось отправлять в сериал со скоростью, нужной ему для измерений.
Жаль расстраивать коллегу тем, что отправлять можно со скоростью 1 Mbps и двоичные данные - по два байта на измерение, как раз по 10 мкс на байт плюс паузы. ;)))))))))))
Влад, мне кажется, достаточно отправлять по 3 байта на два измерения. А может, и меньше.
Влад, мне кажется, достаточно отправлять по 3 байта на два измерения. А может, и меньше.
для скорости АВРовского АЦП это уже почти безразлично... если мы не станем повторять подвиги А........, с раскруткой АЦП на 100500 дофиГерц. ;))))
для скорости АВРовского АЦП это уже почти безразлично... если мы не станем повторять подвиги А........, с раскруткой АЦП на 100500 дофиГерц. ;))))