С com портом что не пойму

kholonkin
Offline
Зарегистрирован: 14.10.2013

Не уверен что в нужной ветке.

в общем с одной ардуины шлю в порт другой:

Serial.write(200);
 i++;
 k=i+100;
Serial.write(k);
 if (i==9){i=0;}
delay(3000);

На другой принимаю, и шлю в порт, то что принял на комп:

if (Serial.available()==2){
s[0]=Serial.read(); s[1]=Serial.read();
Serial.print(s[0]); Serial.print(s[1]); Serial.println("");
Serial.flush();
}

в мониторе порта наблюдаю:

200101
200102
200103
200104
200105
200106
200107
200108
200109
200101
200102
200103
200104
200106
200106
200107
200108
200109
200102
200102
200103
200104
200105
 
Скорость порта делал и 57600 и 2400, и вот таткие вот глюки вылазят, в какую сторону копнуть?
Из-за чего может подобное проявляться?
 

 

 

AS
Offline
Зарегистрирован: 12.03.2014

А можно побольше кода? может у вас 

Serial.print(s[0]); Serial.print(s[1]); Serial.println("");

прокручивается второй раз до того, как происходит Serial.flush();?

com
Offline
Зарегистрирован: 06.09.2013

вы думаете, что flush очищает входную очередь?

AS
Offline
Зарегистрирован: 12.03.2014

 

Serial.flush()
Ожидает окончания передачи исходящих данных (до версии Arduino 1.0 функция очищала буфер последовательного соединения).

 

Точно! у вас наверняка версия повыше 1.0?

kholonkin
Offline
Зарегистрирован: 14.10.2013

AS

это весь код, я пока разбираюсь с принципом работы. Я в этом вопросе пока чайник.. заварошный

Ардуина 1.5.5

а буфер входной как чиститься? Т.е. мы когда чтение делаем, он сам чистится?

 

 

AS
Offline
Зарегистрирован: 12.03.2014

я так понимаю, что пока новые данные в порт не запишутся, там сидят старые. Гуру подскажут?

может delay уменьшить? 

com
Offline
Зарегистрирован: 06.09.2013

и с типами записываемых и читаемых переменных неплохо бы разобраться

kholonkin
Offline
Зарегистрирован: 14.10.2013

Serial.flush() закоментировал, глюк остался

kholonkin
Offline
Зарегистрирован: 14.10.2013

com пишет:

и с типами записываемых и читаемых переменных неплохо бы разобраться

тип данныйх байт.

byte s[1]; 
int k;
byte i=0;
char ch;

 

com
Offline
Зарегистрирован: 06.09.2013

AS пишет:

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

старые будут сидеть не до тех пор, пока новые не запишутся, а пока старые не прочитаются. чтение read удаляет один байт из очереди. peek - нет

com
Offline
Зарегистрирован: 06.09.2013

kholonkin пишет:

Serial.flush() закоментировал, глюк остался

так flush при чтении вообще ничего не делает

kholonkin
Offline
Зарегистрирован: 14.10.2013

com пишет:

AS пишет:

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

старые будут сидеть не до тех пор, пока новые не запишутся, а пока старые не прочитаются. чтение read удаляет один байт из очереди. peek - нет

Т.е. вызовом функции чтения мы уменьшаем входну очередь на один байт. Т.е. Serial.available() уменьшается на 1. Я правильно понял?

com
Offline
Зарегистрирован: 06.09.2013

именно так прописано в основном законе :)

http://arduino.ru/Reference/Serial/Read

com
Offline
Зарегистрирован: 06.09.2013

к тому же  serial.available постоянно меняется. мы прверили

if (Serial.available()==2)

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

 
AS
Offline
Зарегистрирован: 12.03.2014

delay в посылаемых данных 3 секунды! буфер должен быть прочитан и очищен много раз, однако данные повторяются! Значит, что-то не так в датском королевстве :( 

kholonkin
Offline
Зарегистрирован: 14.10.2013

Данные я шлю раз в три секунды.

считывание контролирую в цикле контроллера, задержек нет ни каких, вроде должно робить.

хотя с другой стороны чипы ни как не синхронизированы.

Ничего пока не понимаю.

AS
Offline
Зарегистрирован: 12.03.2014

выкладывайте листинги полностью... может где-то еще ошибки?

kholonkin
Offline
Зарегистрирован: 14.10.2013

Дык это все листинги, это то, что в лупе лежит.

описание переменных я кидал, в сетупе сериал бегин, в общем то все.

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

А там что то не все алле выходит, вот я и озадачился.

com
Offline
Зарегистрирован: 06.09.2013

так, на всякий случай - int два байта

kholonkin
Offline
Зарегистрирован: 14.10.2013

com пишет:

так, на всякий случай - int два байта

ага, есть такое дело. 

завтра доберусь до макета, исправлю и проверю.

хотя глюк плавающий.....

 

kholonkin
Offline
Зарегистрирован: 14.10.2013

AS пишет:

delay в посылаемых данных 3 секунды! буфер должен быть прочитан и очищен много раз, однако данные повторяются! Значит, что-то не так в датском королевстве :( 

он не то чтоб повторяется, он как бы перескакивает через значение.

kholonkin
Offline
Зарегистрирован: 14.10.2013

com пишет:

именно так прописано в основном законе :)

http://arduino.ru/Reference/Serial/Read

там написано, что читает очередной доступный, т.е. какой, первый что поступил, или последний который поступил %) , остальное нужно додумать, если не в теме.

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

kholonkin пишет:

Дык это все листинги, это то, что в лупе лежит.

А вы все-таки дайте. Оба листинга. Целиком. Вы же можете ГАРАНТИРОВАТЬ что проблема не в том что осталась за кадром. Да и банально, представить себе картину когда "все в одном месте", гораздо легче чем когда в одном посте один кусочек, в другом объявление переменны, третье - на словах объяснено.

kholonkin
Offline
Зарегистрирован: 14.10.2013

завтра буду у компа с этим скетчем, выложу листинг

kholonkin
Offline
Зарегистрирован: 14.10.2013

Код.

byte s[1]; 
int k;
byte i=0;
char ch;

// инициализация 
void setup() {
  Serial.begin(1200);
  pinMode(9,OUTPUT);
  delay(100);
}

// рабочий цикл
void loop() {

////////////////////////////////////////////////////////////////////Приемник
//if (Serial.available()==2){
//s[0]=Serial.read(); s[1]=Serial.read();
//Serial.print(s[0]); Serial.print(s[1]); Serial.println("");
////Serial.flush();
//}
//if (s[1]==3){digitalWrite(9,1);} else{digitalWrite(9,0);} 
////////////////////////////////////////////////////////////////Передатчик
  Serial.write(200);
  //ch=char(i);
  k=i+100;
  Serial.write(k);
  i++;
  if (i>9){i=0;}
  delay(3000);

////////////////////////////////////////////////////////////////////////////////////////////////  
}

 

kholonkin
Offline
Зарегистрирован: 14.10.2013

тут выше делали замечание, что переменная k int, переделал на byte

та же хрень:

200100
200101
200102
200103
200104
200106
200106
200107
200108
200109
200100
200101
200103
200103
200104
200105
200106
200108
200108
200110
 
200110 - вообще не должно быть такого значения
 
dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

kholonkin, а аппаратно как организована связь этих ардуин?

kholonkin
Offline
Зарегистрирован: 14.10.2013

передатчик с Тх провод идет на Rx применика, с Тх приемника идет на порт компа

все это дела на макетке, источник питания общий.

 

AS
Offline
Зарегистрирован: 12.03.2014

а просто с одной ардуинки в комп передавать пробовали? без второй платы?

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

Эмц... вообщем-то можно и сразу два скетча пихать в один пост. Не обязательно их "смешивать в один" и коментировать...

Можно и как-то так:

Передатчик:

void setup(){
.....
}
void  loop(){
  // код передатчика
}

Приемник:

void setup(){
.....
}
void  loop(){
  // код приемника
}

Теперь "по сути..."

1. Теоретически int-товость переменной k мешать не должна... но лучше поменяйте на byte. Иначе каждый кто смотрит код, сразу получает "укол в мозг" и дальше высматривать мелочи уже трудно :)

2.  avaliable()==2 - это плохо. А если успело к этому моменту прилететь 3-байта? Все, никогда не сможем их прочитать? Лучше >1 использовать.... а еще лучше, вдруг были какие-то потери... и перым вы получили второй байт :)  Вообщем лучше иметь какой-то "маркер начала пакета". Подозреваю это "магическая цифра 200" и задумывалась таким маркером. Поэтому логика должна быть примерна такая: читаем любой 1-байт прилетевший по Serial. Если не равен 200 - игнорируем, а вот если равен.... тогда мы отмечаем что СЛЕДУЮЩИЙ будет данными. И читаем его уже как данные.

3. И главное, как вы думаете, сколько элементов у вас содержит массив s[]? Под какое количество байт вы выделили память?

AS
Offline
Зарегистрирован: 12.03.2014

leshak пишет:

2.  avaliable()==2 - это плохо. А если успело к этому моменту прилететь 3-байта? Все, никогда не сможем их прочитать? Лучше >1 использовать.... а еще лучше, вдруг были какие-то потери... и перым вы получили второй байт :)  Вообщем лучше иметь какой-то "маркер начала пакета". Подозреваю это "магическая цифра 200" и задумывалась таким маркером. Поэтому логика должна быть примерна такая: читаем любой 1-байт прилетевший по Serial. Если не равен 200 - игнорируем, а вот если равен.... тогда мы отмечаем что СЛЕДУЮЩИЙ будет данными. И читаем его уже как данные.

3. И главное, как вы думаете, сколько элементов у вас содержит массив s[]? Под какое количество байт вы выделили память?

Не может " к этому моменту" прилететь 3 байта. Как я уже писал, посыл раз в 3 секунды. Приемник за это время должен много раз прочесть и очистить буфер приемного порта. 

Как мы видим, любая полученная строка начинается на 200, поэтому, идея с "маркером" хоть и не плоха, но не сработает.

Третье. Массив s[1], как видно из листинга программы, содержит два элемента типа byte. 

Мне кажется, надо тестировать платы отдельно, подключая их к компу, выявить на какой половине ошибка, а потом уже ее вычленять.

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

AS пишет:

Третье. Массив s[1], как видно из листинга программы, содержит два элемента типа byte. 

Интерестно, а зачем же я тогда пытался обратить на это внимание? А мне из листинга видится что он содержит один элемент.

Кстати, компилятор тоже считает что один.

byte s[1];
void setup(){
  Serial.begin(57600);
  Serial.print("Array Size=");
  Serial.println(sizeof(s));
}

void loop(){
}

 

AS
Offline
Зарегистрирован: 12.03.2014
Доступ к элементам массива
Индексация массива начинается с 0. Это значит, что для массива с 10-тью элементами, индекс 9 будет последним:

int myArray[10]={9,3,2,4,3,2,7,8,9,11};
     // myArray[0]    первый элемент, содержит 9
     // myArray[9]    последний элемент, содержит 11
     // myArray[10]   это неверно возможно возвращение произвольного значения из области памяти не относящийся к массиву
Присваиваем значение э

http://arduino.ru/Reference/Array

А как же библия????

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Индексация с нуля, а размер массива считают  с единицы. Путают нас создатели СИ :))

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

>А как же библия????

То что вы процитировали, это раздел "доступ к элементам массива", а в разделе описывающий объявление массива - ничего не говорится про необходимость уменьшать.

Кстати, в том же разделе (доступ к элементам), есть такой пример объявления:

int myArray[10]={9,3,2,4,3,2,7,8,9,11};

Пересчитайте, каким количество элементов он инициализирован.

>Индексация с нуля, а размер массива считают  с единицы. Путают нас создатели СИ :))

За счет этого, удобней писать циклы, на один символ короче условие выхода. i<TOTAL, а не i<=TOTAL

Да и нет путаницы. Размер - это размер. Все интуитивно. s[2] - два элемента.

И с индексом, на самом деле нет путаницы. Просто нужно понять, что индекс, это не синоним слов "номер элемента", а синоним слова "смещение от начала". Тогда все становися на свои места и никакая "поправка на ветер не нужна". Что-бы получить первый элемент сместитится, нужно ... на 0 элементов. Что-бы получить второй нужно СМЕСТИТСЯ на 1, от начала.

А если начнете разбиратся с указателями, то... поймете что вообще супер-логично. Массивы это, на самом деле "синтаксический сахар" над указателями. Переменная-массив, это на самом деле, просто указатель на начало массива. А myAr[3], это "указатель на начало массива + смещение 3".

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

byte ar[3]={4,5,6}; // массив
byte* p;
void setup(){
  
  Serial.begin(57600);
  
  p=&ar[0]; // p указывает на адресс первого элемента ar[]
 
  Serial.println(*(p+1), DEC); //  выводим содержимое памяти, по адресу p плюс смещение 1
  Serial.println(ar[1],DEC); // ТОЖЕ САМОЕ, только короче.
  
  byte* p2=ar; // а можем и просто присвоить массив указателю, компилятор поймет что нужно взять "адрес", даже без явного указания  
  Serial.println(*(p2+1), DEC);  //  убеждаемся в этом

}

void loop(){
}

 

AS
Offline
Зарегистрирован: 12.03.2014

ну что же, ждем исправленный листинг и результат работы программы от kholonkin

kholonkin
Offline
Зарегистрирован: 14.10.2013

С массивом ясно, что дело темно..... завтра поправлю, опробую. Еще раз погляжу компом что шлется с передатчика.

Тогда мне ен понятно, как оно робит? Если в массиве всего 1 элемент.

 

kholonkin
Offline
Зарегистрирован: 14.10.2013

AS пишет:

Как мы видим, любая полученная строка начинается на 200, поэтому, идея с "маркером" хоть и не плоха, но не сработает.

Третье. Массив s[1], как видно из листинга программы, содержит два элемента типа byte. 

Почему не будут маркеры работать?

Удобный вариант объявления массоивов [0..1] все ясно и наглядно.

kholonkin
Offline
Зарегистрирован: 14.10.2013

ВОт еще, пробовал смотерть компом что передатчик шлет, у меня почему то монитор порта ардуины пишет пробелы, кода пользуюсь функцией записать. Когда пользуешь печать, то все видно.

Чую, что проблема в какой то фигне.......

kholonkin
Offline
Зарегистрирован: 14.10.2013

leshak пишет:

Эмц... вообщем-то можно и сразу два скетча пихать в один пост. Не обязательно их "смешивать в один" и коментировать...

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

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

kholonkin пишет:

Тогда мне ен понятно, как оно робит? Если в массиве всего 1 элемент.

Дык багово оно работает. Это вам не C#/Java, отвественность за проверки границ массива - сугубо на плечах програмера. А когда вышли за границы.... ну значит вы начали "портить" какой-то случайный участок памяти. Если он не используется другими частями кода - повезло, если повредили другие данные или код... ну что угодно имеете. От бреда в поведении, до зависания.

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

kholonkin пишет:

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

Ну значит вначале для себя разбейте, все-таки на два файла. Не нужно, одновременно, в одной тарелке, готовить оливье и замешивать цемент. Мухи отдельно, котлеты отдельно.

Бо "что-то не докоментили", что-то не до раскоментили.... один раз закоментили объявления переменной, второй раз решили оставить так как "да фиг с ним, все равно использование закоментили...". Вообщем сами себе усложняете воспроизводимость и однозначность. Когда "играешься с кодом".

kholonkin
Offline
Зарегистрирован: 14.10.2013

leshak пишет:

kholonkin пишет:

Тогда мне ен понятно, как оно робит? Если в массиве всего 1 элемент.

Дык багово оно работает. Это вам не C#/Java, отвественность за проверки границ массива - сугубо на плечах програмера. А когда вышли за границы.... ну значит вы начали "портить" какой-то случайный участок памяти. Если он не используется другими частями кода - повезло, если повредили другие данные или код... ну что угодно имеете. От бреда в поведении, до зависания.

В общем порядок с масивом навели, все причесали, ща робит как задумывалось.

AS
Offline
Зарегистрирован: 12.03.2014

о чем я и говорил: выкладывайте код целиком. Ну... хотя я на другое думал.

kholonkin
Offline
Зарегистрирован: 14.10.2013

AS пишет:

о чем я и говорил: выкладывайте код целиком. Ну... хотя я на другое думал.

на что?