Скорость передачи чисел через COM-порт (Arduino Uno)

hotubey
Offline
Зарегистрирован: 04.02.2019

Я новичек, купил себе плату с 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 Кбит/с !!!

Это что за такое, кто может объяснить феномен? Может, надо как-то по-другому делать?

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Как ты передавал, как принимал, как измерял, всё это знаешь только ты, а потому только ты и можешь ответить на свой вопрос.

Logik
Offline
Зарегистрирован: 05.08.2014

Феномен прост - ошибка в понимании называется, скорость 115200 и есть 100Кбит с учетом старта, стопа и возможно контрольного. 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Logik, ты не потрудился дочитать пост ТС до конца, а потому в твоём ответе, как всегда, никакой логики :(

Logik
Offline
Зарегистрирован: 05.08.2014

А в твоих вобще смысла нет, инфы ноль, подесаульщина одна ;)

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Ой, тока не надо, пжалста! Ну, поторопился ответить не дочитав, пукнул чуток в лужу, чё теперь холивар-то раздувать? Уймись, и впредь читай внимательно.

PANYTA
PANYTA аватар
Offline
Зарегистрирован: 27.01.2019

А как мерил скорость. Чем?

hotubey
Offline
Зарегистрирован: 04.02.2019
 
ПЕРЕДАВАЛ Я ТАК:
 
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 Кбит/сек.

 

 
Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Не, так не пойдёт. Внимательно читаем правила, и вставляем код как положено.

Logik
Offline
Зарегистрирован: 05.08.2014

hotubey пишет:

 
ПЕРЕДАВАЛ Я ТАК:
 

Плохо там все. И n=2 и double и синусы всякие не так быстро считаются.

hotubey
Offline
Зарегистрирован: 04.02.2019

Синусы тут не при чем, если передавать константу, а синусы закомментировать, скорость не изменится. При  n = 1 - то же самое; пробовал передавать по многу байт, например, n = 512 - скорость только падает.

Logik
Offline
Зарегистрирован: 05.08.2014

Поставте n в пару десятков, отпарвку массива с константами, прежде чем делать отправку - проверте что есть свободное место в буфере и луп не держать в вечном цикле там четотипа    

for (;;) {
        loop();
        if (serialEventRun) serialEventRun();
    }
И будет счасте.

Logik
Offline
Зарегистрирован: 05.08.2014

Коментировать не только синус надо бы, все с double не быстрое.

hotubey
Offline
Зарегистрирован: 04.02.2019

Спасибо! Надо же, все дело оказалось таки в синусе! Раньше я как-то не так смотрел, что ли... В общем, меня подвела уверенность высокоуровневого программиста в том, что "всякие там функции" не требуют существенного времени...

И что любопытно: если все-таки считать синус, то в случае double скорость получается 39,8 Кбит/с, а в случае float - 40,6 Кбит/с. А ведь я где-то читал, что в ардуине double - это то же, что и float, как же так? 

Вдогонку: а как проверять заполненность буфера, не подскажете?

Logik
Offline
Зарегистрирован: 05.08.2014

Вопрос не так уж и прост. Даже по описанию  http://arduino.ru/Reference/Serial/Flush видно что есть варианты. А вобще все ответы на все вопросы  - здесь ..\arduino-хххх\hardware\arduino\avr\cores\arduino\ и в даташите на контроллер.

Logik
Offline
Зарегистрирован: 05.08.2014

Logik пишет:

Вопрос не так уж и прост. Даже по описанию  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); - наверно оно.

Самоцитатнулся ,не ту кнопку тыцнул!

hotubey
Offline
Зарегистрирован: 04.02.2019

Не могу понять, как пойти по этим Вашим относительным ссылкам :):):)

Logik
Offline
Зарегистрирован: 05.08.2014

А это у Вас на диске, где ардуино инсталена.

hotubey
Offline
Зарегистрирован: 04.02.2019

Logik пишет:

А это у Вас на диске, где ардуино инсталена.

Спа-си-бо.