Ардуина долго принимает (или обрабатывает?) данные из serial

wenom86
Offline
Зарегистрирован: 04.11.2012

Здравствуйте. В ардуину из монитора порта на скорости 115200 отправляется строка вида: a200,200,200,200,100,100,100,100,100,100,100,100,100 где:

а- символ начала передачи, значения - значения канала управления, запятые - это разделители каналов.

После нажатия кнопки "отправить" и зажигания светодиодов на ардуине проходит 5-7 секунд. Не могу понять-почему так происходит.



#include <Servo.h>
  
 int Kn1 = 4; //канал кнопки 1 подключен к 4 пину
 int Kn2 = 7; //...
 int Kn3 = 8;
 int Kn4 = 9;
 int Kn7 = 10;
 int Kn8 = 12;
 int Kn9 = 13;
 // int Kn11 = ...; //не хватило пинов
 // int Kn12 = ...; //не хватило пинов
 
 
 int KanA, KanB, KanC, KanD, KanE, KanF, KanJ, KanH, KanI, KanG, KanK, KanL, KanM;
 Servo M1; //мотор 1 (горизонтального перемешения) подключен к 3 пину
 Servo M2; //мотор 2 (горизонтального перемешения) подключен к 5 пину
 Servo M3; //мотор 3 (вертикального перемешения) подключен к 6 пину
 Servo M4; //мотор 4 (вертикального перемешения) подключен к 11 пину
  
 void setup()
 {
   Serial.begin(115200);
   M1.attach(3);
   M2.attach(5);
   M3.attach(6);
   M4.attach(11);
   
   pinMode(2, OUTPUT);
   pinMode(4, OUTPUT);
   pinMode(7, OUTPUT);
   pinMode(8, OUTPUT);
   pinMode(9, OUTPUT);
   pinMode(10, OUTPUT);
   pinMode(12, OUTPUT);
   pinMode(13, OUTPUT);
 }
  
  
 void loop()
 {
     while (Serial.read() != 'a'); //начало передачи данных с символа "а" и далее каждый канал через запятую. (значения от -255 до 255)
     KanA = Serial.parseInt();
     KanB = Serial.parseInt();
     KanC = Serial.parseInt();
     KanD = Serial.parseInt(); 
     KanE = Serial.parseInt();
     KanF = Serial.parseInt();
     KanJ = Serial.parseInt();
     KanH = Serial.parseInt();
     KanI = Serial.parseInt();
     KanG = Serial.parseInt();
     KanK = Serial.parseInt();
     KanL = Serial.parseInt();
     KanM = Serial.parseInt();

    
// + Канал А (двигатель 1)
     KanA=map(Serial.parseInt(), -255, 255, 20,160);
     M1.write(KanA);
// + Канал B (двигатель 2)
     KanB=map(Serial.parseInt(), -255, 255, 20,160);
     M2.write(KanB);
// + Канал C (двигатель 3)
     KanC=map(Serial.parseInt(), -255, 255, 20,160);
     M3.write(KanC);
// + Канал D (двигатель 4)
     KanD=map(Serial.parseInt(), -255, 255, 20,160);
     M4.write(KanD);
     
// Канал E (соответствует кнопке 1 на пульте- фикс)  
// Канал F (соответствует кнопке 2 на пульте- фикс)  
// Канал J (соответствует кнопке 3 на пульте- фикс) 
// Канал H (соответствует кнопке 4 на пульте- фикс) 


// + Канал I (соответствует кнопке 7 на пульте)
if (KanI > 0)  {digitalWrite(Kn7, HIGH);}
else  {digitalWrite(Kn7,LOW);}  
//Канал G (соответствует кнопке 8 на пульте) 
if (KanG > 0)  {digitalWrite(Kn8, HIGH);}
else  {digitalWrite(Kn8,LOW);} 
//Канал K (соответствует кнопке 9 на пульте)
if (KanK > 0)
     {digitalWrite(Kn9, HIGH);}
else
     {digitalWrite(Kn9,LOW);}
     
     
// Канал L (соответствует кнопке 11 на пульте)
// Канал M (соответствует кнопке 12 на пульте)


 }

 

 

 

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013
// + Канал А (двигатель 1)
58	     KanA=map(Serial.parseInt(), -255, 255, 20,160);
59	     M1.write(KanA);
60	// + Канал B (двигатель 2)
61	     KanB=map(Serial.parseInt(), -255, 255, 20,160);
62	     M2.write(KanB);
63	// + Канал C (двигатель 3)
64	     KanC=map(Serial.parseInt(), -255, 255, 20,160);
65	     M3.write(KanC);
66	// + Канал D (двигатель 4)
67	     KanD=map(Serial.parseInt(), -255, 255, 20,160);
68	     M4.write(KanD);

зачем в map опять с порта считываете данные, если у вас выше уже все считано

м/б надо было так сделать


    M1.write(map(KanA, -255, 255, 20,160));

 

leshak
Offline
Зарегистрирован: 29.09.2011

wenom86 пишет:

После нажатия кнопки "отправить" и зажигания светодиодов на ардуине проходит 5-7 секунд. Не могу понять-почему так происходит.

А если после последней сотки поставить,скажем, запятую? Отправить строку

a200,200,200,200,100,100,100,100,100,100,100,100,100,

Есть задержка? (после внесения  поправки предложенной Michal)

leshak
Offline
Зарегистрирован: 29.09.2011

А еще, после своих parseInt, можете добавить 

Serial.print(millis());
Serial.println(": Command parsed");

Что-бы разделить "мухи и котлеты". Узнать где дуплеж происходит, на приемке данных или на исполнении команды.

maksim
Offline
Зарегистрирован: 12.02.2012

При вызове parseInt() задержка ожидания последующего символа по умолчанию 1 секунда, функцией setTimeout() можно изменить эту задержку, в вашем случае при скорости 115200 достаточно 1-2 мс.
Просто добавьте в 
setup() строку:

void setup()
 {
   Serial.begin(115200);
   Serial.setTimeout(2);
   ......

и будет вам счастье.

leshak
Offline
Зарегистрирован: 29.09.2011

maksim пишет:

При вызове parseInt() задержка ожидания последующего символа по умолчанию 1 секунда, функцией setTimeout() можно изменить эту задержку, в вашем случае при скорости 115200 достаточно 1-2 мс.

timeOut можно и не трогать (он как раз, может не лишним оказатся, хотя-бы для своевременного обнаружения проблем). Вы предлагаете уменьшить timeOut но ведь он не на ровном месте возник. При норме - он вообще не должен срабатывать (и не важно в какой интервал он выставлен).

1. parseInt() - должен вызваться именно столько раз сколько данных послали (поправка от Michal)
2. После последней цифры желательней терминатор, означачющий что "передача закончена". Это может быть "добавить запятую" (для проверки этой версии я предложил) или просто в терминали выставить "line ending"

setTimeout() в данном случае будет лечением больного зуба с помощью обезболивающих. Вроде "помогло", но воспаление осталось. Оно может пролечить проблему "последней цифры", но зато скроет проблемы лишних вызовов (и всех подобных ошибок). Причем скроет подло - будут выскакивать нули, "не те цифры", непонятно откуда берующиеся.

Не говоря уже про то, что timeOut-ты - это, все-таки, блокировка скетча. Которые обычно - не желательны.

Вообщем не нужно timeOut-ты, нужно причину лечить: не делать лишних вызовов и после последней цифры, тем или иным способом послыать что-то не цифвровое.

 

maksim
Offline
Зарегистрирован: 12.02.2012

Может 5 - 7 секунд это и есть тот самый Timeout в 1 секунду (во времени все по разному ориентируются) и если конец строки это цифра - то вот вам и таймаут. Поставить запятую в конце решение конечно же лучше.

leshak
Offline
Зарегистрирован: 29.09.2011

maksim пишет:

Может 5 - 7 секунд это и есть тот самый Timeout в 1 секунду (во времени все по разному ориентируются) и если конец строки это цифра - то вот вам и таймаут. Поставить запятую в конце решение конечно же лучше.

Ну "Запятую" - это чисто проверить догадку. Красивей, все-таки просто слать \r\n

А имеет у нас - четыре лишних parseInt(), плюс конец строки. - 5-ть таймаутов не нужных. Каждый по секунде - ну вот она. Наша искомая задержка ровно  в 5-ть сек :)  (или 4-ре секунды, если проблемы конца строки нет, и Line-ending все-таки включен)
А сделали бы Serial.setTimeout(2); - задержку не заметили бы. Копать причины - не начали. А ломали себе голову, почему в KanA,KanB,KanC попадает число 90, что-бы мы не посылали.
wenom86
Offline
Зарегистрирован: 04.11.2012

После исправления кода на:

1    M1.write(map(KanA, -255, 255, 20,160));

стало работать мгновенно. Больше никакие манипуляции делать не пришлось.  Большое спасибо.