Скорость передачи чисел через COM-порт (Arduino Uno)
- Войдите на сайт для отправки комментариев
Пт, 22/02/2019 - 10:41
Я новичек, купил себе плату с Uno R3 (16U2).
Решил проверить, как работает передача данных через COM-порт (на скорости 115200).
Написал в цикле: Serial.print(77); на принимающем компе замерил скорость приема данных, то есть скорость передачи. Получилось чуть меньше 100 Кбит/с, гут. Функция print передает числа символами, то есть 77 передается как '7' и '7' (2 байта), а число 777.7 - как '7', '7', '7', '.' и '7' (5 байт), что меня, конечно не устраивает.
Поэтому я, конечно, воспользовался функцией Serial.write(x, n). Отлично, теперь byte приходит как 1 байт. Замерил скорость... всего 40 Кбит/с !!!
Это что за такое, кто может объяснить феномен? Может, надо как-то по-другому делать?
Как ты передавал, как принимал, как измерял, всё это знаешь только ты, а потому только ты и можешь ответить на свой вопрос.
Феномен прост - ошибка в понимании называется, скорость 115200 и есть 100Кбит с учетом старта, стопа и возможно контрольного.
Logik, ты не потрудился дочитать пост ТС до конца, а потому в твоём ответе, как всегда, никакой логики :(
А в твоих вобще смысла нет, инфы ноль, подесаульщина одна ;)
Ой, тока не надо, пжалста! Ну, поторопился ответить не дочитав, пукнул чуток в лужу, чё теперь холивар-то раздувать? Уймись, и впредь читай внимательно.
А как мерил скорость. Чем?
void setup() { Serial.begin(115200); } void loop() { long int i, j, n; double pi = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128, fr, x; byte *y; fr = 20; n = 2; y = NULL; y = new byte[n]; i = 0; while(1) { memmove(y, &y[1], sizeof(y[0]) * (n - 1)); x = 128 + 128 * sin(2 * pi * fr * ((double)micros() / 1000000)); x = (x >= 256) ? (256 - 1) : x; x = (x < 0) ? 0 : x; y[n - 1] = (byte)x; if(i >= n - 1) { Serial.write(y, n); } i = (i < n - 1) ? (i + 1) : 0; } if(y) { delete y; y = NULL; } }bStart->Enabled = false; PortOk = false; CP = NULL; CP = new TIPCommPort(); Port = StrToInt(ePort->Text); if(!CP) return; if(CP->GetConnected()) CP->CloseCommPort(); // Если уже был включен CP->SetCommPort(Port); CP->SetBaudRate(115200); CP->SetParity(0); // Проверка на четность (0 - не используем эту проверку; если бы использовали, то надо еще указывать, ODD или EVEN; бит четности идет после значимых, перед стоп-битом) CP->SetStopBits(1); // Продолжительность стопового бита в тактах (обычно - 1 или 2, но может быть и нецелое число) CP->SetByteSize(8); // Количество значимых битов в байте (бывает 9) CP->OpenCommPort(); if(!CP->GetConnected()) { delete CP; return; } CP->ResetRB2(1000); // команда на сброс контроллеру COM-порта; CP->ResetRB2(1000) - вычитывание всего из COM-порта с той же целью (сброса) в течение 1000 мс PortOk = true; bStart->Enabled = true; // ----------------------------------------- int Size, tm, tmprev; float dt; BYTE buf[8192]; while(PortOk) { Application->ProcessMessages(); Size = PortOk ? CP->InputCount() : 0; if(Size < 4096) continue; // Чтобы не тратить время на чтение маленьких блоков Size = PortOk ? CP->ReadBlock(buf, (Size > 8192) ? 8192 : Size) : 0; tmprev = tm; tm = GetTickCount(); dt = (float)(tm - tmprev) / (8 * Size * 1000); } // ... ЗДЕСЬ dt - ВРЕМЯ ПЕРЕДАЧИ 1 БИТА. В СЛУЧАЕ ПЕРЕДАЧИ ФУНКЦИЕЙ Serial.write получается 2.56e-5, то есть 39 Кбит/сек.Не, так не пойдёт. Внимательно читаем правила, и вставляем код как положено.
Плохо там все. И n=2 и
doubleи синусы всякие не так быстро считаются.Синусы тут не при чем, если передавать константу, а синусы закомментировать, скорость не изменится. При n = 1 - то же самое; пробовал передавать по многу байт, например, n = 512 - скорость только падает.
Поставте n в пару десятков, отпарвку массива с константами, прежде чем делать отправку - проверте что есть свободное место в буфере и луп не держать в вечном цикле там четотипа
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
И будет счасте.
Коментировать не только синус надо бы, все с
doubleне быстрое.Спасибо! Надо же, все дело оказалось таки в синусе! Раньше я как-то не так смотрел, что ли... В общем, меня подвела уверенность высокоуровневого программиста в том, что "всякие там функции" не требуют существенного времени...
И что любопытно: если все-таки считать синус, то в случае double скорость получается 39,8 Кбит/с, а в случае float - 40,6 Кбит/с. А ведь я где-то читал, что в ардуине double - это то же, что и float, как же так?
Вдогонку: а как проверять заполненность буфера, не подскажете?
Вопрос не так уж и прост. Даже по описанию http://arduino.ru/Reference/Serial/Flush видно что есть варианты. А вобще все ответы на все вопросы - здесь ..\arduino-хххх\hardware\arduino\avr\cores\arduino\ и в даташите на контроллер.
Вопрос не так уж и прост. Даже по описанию http://arduino.ru/Reference/Serial/Flush видно что есть варианты. А вобще все ответы на все вопросы - здесь ..\arduino-хххх\hardware\arduino\avr\cores\arduino\ и в даташите на контроллер.
Вот открыл \arduino-1.8.3\hardware\arduino\avr\cores\arduino\HardwareSerial.h а там virtual int availableForWrite(void); - наверно оно.
Самоцитатнулся ,не ту кнопку тыцнул!
Не могу понять, как пойти по этим Вашим относительным ссылкам :):):)
А это у Вас на диске, где ардуино инсталена.
А это у Вас на диске, где ардуино инсталена.
Спа-си-бо.