SerialPort из Windows в Arduino. Ограничения по количеству байт

lvtky
Offline
Зарегистрирован: 10.04.2019

Добрый день.

Совсем новичок, поэтому прошу сориентировать по проблеме.

Передаю в Ардуино UNO с компа (C#) данные в SerialPort. Примерно 300 байт.

Получается передать всю строку целиком только если передавать побайтно с задержкой на компе в 10мс

Так ведь не должно быть?

 

Варианты передавать буфером по 8, 32, 64 байта с задержками между каждым буфером привели только к худшим результатам по времени.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Там приемный буфер 64 байта. Передающий, впрочем, такой же

lvtky
Offline
Зарегистрирован: 10.04.2019

Я думал об этом. Попробовал передавать разбивая по 32 байта - все равно целиком не принимает, даже если ставить задержку 100мс

sadman41
Offline
Зарегистрирован: 19.10.2016

Значит приёмник тормозит.

lvtky
Offline
Зарегистрирован: 10.04.2019

sadman41 пишет:

Значит приёмник тормозит.

 

На приемнике ничего, кроме чтения компорта - нет...

 

void serialEvent() {

    char inChar;
    

    while (Serial.available() && (inChar = (char)Serial.read()) != -1 ) {
        Serial.println("New char: " + String(inChar));
    }
}

 

При побайтной передаче с компа при задержке 10мс - работает (что быстрее, чем задержка 100мс при 8 байтной передача)
 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Вывсеврети. 

sadman41
Offline
Зарегистрирован: 19.10.2016

Что за жуткая конструкция... Или available > 0 проверяйте или read с -1 сравнивайте. Лучше первое, потому как сравнение написано так себе, как мне кажется.

loop() пустой или набит чем-то? Прерывания активированы?

lvtky
Offline
Зарегистрирован: 10.04.2019

sadman41 пишет:

Что за жуткая конструкция... Или available > 0 проверяйте или read с -1 сравнивайте. Лучше первое, потому как сравнение написано так себе, как мне кажется.

loop() пустой или набит чем-то? Прерывания активированы?

Спасибо за рекомендацию, два сравнения в while друг другу вроде не мешают, но ваш вариант красивее.

 

loop  пустой, прерывания не активированы.

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Дебаггера у меня в голове нет, поэтому сразу оценить по условию последствия затрудняюсь.

Однако: read() возвращает int и только в этом случае его стоит сравнивать с -1 и, вообще, с >= 0. У вас же он сначала приводится к char, а только потом сравнивается. Т.е. тут можно поиметь проблем.

Вообще - я бы не стал в этот serialEvent соваться, а прямо в setup() сделал бы 

byte cnt=0x00;

while(1) { 
  if (Serial.available() > 0) {
     char c=Serial.read();
     cnt++;
      ....
     // Извращения со String
  
     if (cnt > 63) {
       // мигаем лампой, пишем на LCD или ещё чего
        cnt = 0x00;
     }
  } 
}

 

lvtky
Offline
Зарегистрирован: 10.04.2019

sadman41 пишет:

Дебаггера у меня в голове нет, поэтому сразу оценить по условию последствия затрудняюсь.

Однако: read() возвращает int и только в этом случае его стоит сравнивать с -1 и, вообще, с >= 0. У вас же он сначала приводится к char, а только потом сравнивается. Т.е. тут можно поиметь проблем.

Вообще - я бы не стал в этот serialEvent соваться, а прямо в setup() сделал бы 

byte cnt=0x00;

while(1) { 
  if (Serial.available() > 0) {
     char c=Serial.read();
     cnt++;
      ....
     // Извращения со String
  
     if (cnt > 63) {
       // мигаем лампой, пишем на LCD или ещё чего
        cnt = 0x00;
     }
  } 
}

 

Ваш пример на буфер com порта никак не реагирует, а только на количество прочтенных байт, а он уже в этом месте, даже если ЧИТАТЬ побайтно - принимает не все 300 на него отправленные.

Вот хотелось бы понять, почему в serialEvent лучше не соваться и какие там ограничения?

Нигде нормально на этот вопрос, который бы мою проблему описал, я ответа не нашел.

В setup засунуть не могу, так как проект предполагает частый обменмежду компом и ардуиной, без перезагрузки.

sadman41
Offline
Зарегистрирован: 19.10.2016

1) Как вы определили, что он принимает не все?
2) serialEvent() вызывается между вызовами loop(). Так что особого смысла в написании фрагментов кода именно там я не вижу;
3) Проблемы, как таковой, не существует. Если МК успевает выгребать из буфера Serial байты, то хоть мегабайт в него лей;
4) В setup() стоит поместить чисто для теста для получения максимальной скорости на уровне Wiring.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:
для получения максимальной скорости на уровне Wiring.
Особливо вот с таокй конструкцией - ""New char: " + String(inChar)"

sadman41
Offline
Зарегистрирован: 19.10.2016

Вам виднее, я стрингом не пользуюсь. Хотя, в принципе, да: обратный принт - потенциальный тормоз. И чем длиннее строка - тем больше шансов на потерю входных данных.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Он не просто потенциальный, когда его буфер забивается, он тупо ждет его освобождения, внутри Serial.write(), в блокирующем режиме, заметьте.

Алексей.
Алексей. аватар
Offline
Зарегистрирован: 02.02.2018

Для уны собрал из примеров ArduinoISP и загрузил дудкой

Using Port                    : /dev/ttyUSB0
Using Programmer              : arduino
Overriding Baud Rate          : 115200

Почти четыре с половиной колобайта за 0.74 сек

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file "/tmp/arduino_build_873943/ArduinoISP.ino.hex"
avrdude: writing flash (4402 bytes):

Writing | ################################################## | 100% 0.74s

avrdude: 4402 bytes of flash written
avrdude: verifying flash memory against /tmp/arduino_build_873943/ArduinoISP.ino.hex:
avrdude: load data flash data from input file /tmp/arduino_build_873943/ArduinoISP.ino.hex:
avrdude: input file /tmp/arduino_build_873943/ArduinoISP.ino.hex contains 4402 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.58s

avrdude: verifying ...
avrdude: 4402 bytes of flash verified

Что то не так, но с какой стороны не так, мож. C# ?

lvtky
Offline
Зарегистрирован: 10.04.2019

sadman41 пишет:

1) Как вы определили, что он принимает не все?
2) serialEvent() вызывается между вызовами loop(). Так что особого смысла в написании фрагментов кода именно там я не вижу;
3) Проблемы, как таковой, не существует. Если МК успевает выгребать из буфера Serial байты, то хоть мегабайт в него лей;
4) В setup() стоит поместить чисто для теста для получения максимальной скорости на уровне Wiring.

 

 

Исходный код проекта, конечно не такой. Я передаю буфер, его ардуиной закачиваю, заполняю структуру данных, потом выгружаю ее в порт обратно на комп и смотрю. Структура пришедших данных была не полной. Стал ковырять и вам уже написал отладочный фрагмент. При этом, если грузить побайтно с задержкой на компе после каждого байта в 10мс - все норм. Я понимаю, что так не должно быть, но в чем дело понять не могу.

С компа гружу стандартным .net SerialPort.Write

Параметры настройки порта, естесственно, одинаковые с ардуино. В исходном варианте ничего в порт не пишу, пока все не приму...

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

lvtky пишет:

...но в чем дело понять не могу.

Перечитайте сообщения №11, 12 и 13.

lvtky
Offline
Зарегистрирован: 10.04.2019

andriano пишет:

lvtky пишет:

...но в чем дело понять не могу.

Перечитайте сообщения №11, 12 и 13.

 

в исходном варианте обратного принта нет. Данные приходят не все

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

А код в сообщении №4 не Вы писали?

Для этого источник проблем - указан.

А каких ошибок Вы насажали в том коде, который постеснялись привести, никто не знает.

 

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

Onkel
Offline
Зарегистрирован: 22.02.2016

lvtky пишет:

Добрый день.....Варианты передавать буфером по 8, 32, 64 байта с задержками между каждым буфером привели только к худшим результатам по времени.

То, что худшие- странно. Протоколы, передающие данные по 8 байт работают так, что за годы бывают единичные сбои. Я бы предложил передавать по 8 байт, используя первый (или два первых) байта как старт и последний как контрольную сумму. У меня неделями работает без одного сбоя, я годами не экспериментировал. Можно для верности продублировать. Вот к примеру протокол ADNet - два 0xFF, адрес, данные четыре байта, контрольная сумма. Если к.с. не бьется - данные не учитываем. А то Вы может быть научитесь принимать , а потом перейдете к реальным программам и опять все поплывает. Можете какой-либо известный протокол вроде MODBus попробовать. Народ не зря напридумывал.

lvtky
Offline
Зарегистрирован: 10.04.2019

Onkel пишет:

lvtky пишет:

Добрый день.....Варианты передавать буфером по 8, 32, 64 байта с задержками между каждым буфером привели только к худшим результатам по времени.

То, что худшие- странно. Протоколы, передающие данные по 8 байт работают так, что за годы бывают единичные сбои. Я бы предложил передавать по 8 байт, используя первый (или два первых) байта как старт и последний как контрольную сумму. У меня неделями работает без одного сбоя, я годами не экспериментировал. Можно для верности продублировать. Вот к примеру протокол ADNet - два 0xFF, адрес, данные четыре байта, контрольная сумма. Если к.с. не бьется - данные не учитываем. А то Вы может быть научитесь принимать , а потом перейдете к реальным программам и опять все поплывает. Можете какой-либо известный протокол вроде MODBus попробовать. Народ не зря напридумывал.

 

Ок. Спасибо. Почитаю.

 

lvtky
Offline
Зарегистрирован: 10.04.2019

А может быть такой эффект из-за VisualMicro (trial version) в связке с VisualStudio 2017?

Я пролил прогу через стандартный IDE и все заработало нормально. (Тест делал на своих примерах)

В любом случае - спасибо всем, учту ваши рекомендации. Если есть идеи про причины связанные с VisualMicro - напишите.