Считывание последовательных данных

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Хочу считать девять байт от стороннего устройства. Частота передачи 25 КГц (такт 40 мкС).  Устройство генерит по нажатию на кнопку последовательную передачу 9 байт. Прога опрашивает порт и после приема стартового бита, после задержки заполняет буфер полученными данными. Байт должен быть заполнен числом 01010101 (55H). Получается совсем другая картинка. 

int  TX=17;  //передача 
int  RX=14;  //прием
int  i;      //переменная цикла
int  j;      //переменная цикла
unsigned long time0;
unsigned long time1;
unsigned long time2;
unsigned long time3;
unsigned long time4;

byte  B[9]={0,0,0,0,0,0,0,0,0};    //

//
void setup(void) {
  pinMode(TX, OUTPUT);
  pinMode(RX, INPUT);
  Serial.begin(9600);
}
 
void loop() {
     Serial.println("Wait press ");
    Serial.println()

 while  (digitalRead(RX)!= HIGH) {};//ожидание стартового бита
 time0 = micros();
 delayMicroseconds(8);//задержка от фронта стартового бита
 time1 = micros();
       delayMicroseconds(40);//задержка для попадания в следующий слот
 time2 = micros(); 

 
 for  (i=0;i<9;i++){                     //заполнение буфера
   for (j=0;j<7;j++)
     {if  (digitalRead(RX)== HIGH){
       bitWrite(B[i], j,1);
     }
     else  {bitWrite(B[i], j,0);
               }
     delayMicroseconds(40);
     }
  }
Serial.print("time1="); Serial.println(time1-time0,DEC); // вывод показаний таймера для проверки времени выполнения команды
 Serial.print("time2="); Serial.println(time2-time1,DEC);
for  (i=0;i<9;i++){
Serial.print("B");Serial.print(i,DEC);Serial.print("=");Serial.print(B[i],BIN);Serial.println();// вывод значений полученных байт
}
 delay(1000);
     Serial.println("Was signale");
    Serial.println();
 //
 
}

Получается совсем другая картинка.

Wait press

 

time1=12

time2=40

B0=10011

B1=1001001

B2=100100

B3=110010

B4=1011011

B5=1101101

B6=10110

B7=0

B8=0

Was signale

 

Wait press

 

time1=8

time2=48

B0=10010

B1=1001001

B2=100100

B3=110110

B4=1011011

B5=1101101

B6=10110

B7=0

B8=0

Was signale

 

Wait press

 

time1=12

time2=40

B0=1011011

B1=1101101

B2=110110

B3=10010

B4=1001001

B5=100101

B6=10110

B7=0

B8=0

Was signale

 

Wait press

Что делать? Писать на АСМе обработчик? 

ptr
Offline
Зарегистрирован: 28.05.2016
  uint32_t time_start, time_end;

  time_start=micros();
  for  (i=0;i<9;i++){                     //заполнение буфера
    for (j=0;j<7;j++)
      {if  (digitalRead(RX)== HIGH){
        bitWrite(B[i], j,1);
      }
      else  {bitWrite(B[i], j,0);
               }
      time_end=micros();
      delayMicroseconds(40-(time_end-time_start));
      time_start=time_end;
      }
  }

 

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Спасибо за отклик!

Но не помогло.  в распечатке содержимого буфера, в первом байте В1=11, в остальных - нули. Попробывал учитывать задержку в самом цикле.  Буфер стал наполняться содержимым, но не тем. Уменьшил количество считываемых байт, 

 
int  TX=17;  //передача 
int  RX=14;  //прием 
int  i;      //
int  j;      //
uint32_t time_start, time_end;
 
unsigned long time0;
unsigned long time1;
unsigned long time2;
unsigned long time3;
unsigned long time4;
 
 
 
byte  B[9]={0,0,0,0,0,0,0,0,0};    //
 
//
void setup(void) {
  pinMode(TX, OUTPUT); 
  pinMode(RX, INPUT); 
  Serial.begin(9600);
}
 
void loop() {
     Serial.println("Wait press ");
    Serial.println();
   
 while  (digitalRead(RX)!= HIGH) {};
// time0 = micros();
 delayMicroseconds(20);
 //time1 = micros();
  //     delayMicroseconds(36);
 time_start = micros();  
 
 for  (i=0;i<5;i++){
   for (j=0;j<7;j++)
     { time_start = micros(); 
       if  (digitalRead(RX)== HIGH){
       bitWrite(B[i], j,1);
     }
     else  {bitWrite(B[i], j,0);
               }
  time_end=micros();
     delayMicroseconds(40-(time_end-time_start));
time_start=time_end;
     }
  }
//Serial.print("time_start="); Serial.println(time_start,DEC); 
// Serial.print("time_end="); Serial.println(time_end-time_start,DEC); 
 
for  (i=0;i<9;i++){
Serial.print("B");Serial.print(i,DEC);Serial.print("=");Serial.print(B[i],BIN);Serial.println();
}
// delay(1000); 
 //    Serial.println("Was signale");
 //   Serial.println();
 
  
}
 
получил на мониторе
 
 
Wait press 
 
B0=1001101
B1=1001101
B2=1001101
B3=1001100
B4=1001001
B5=0
B6=0
B7=0
B8=0
Wait press 
 
B0=1101101
B1=1101100
B2=1100100
B3=1001100
B4=1001100
B5=0
B6=0
B7=0
B8=0
Wait press 
 
B0=1001101
B1=1001100
B2=1101100
B3=1001100
B4=1001101
B5=0
B6=0
B7=0
B8=0
Wait press 
 
Неужели однотипные команды выплняются за различное время? Использую Ардуино Уно3
 
 
wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

История - ледянящая кровь!!! ;)

---

По делу: Я прошу обратить внимание на то, как устроена передача в аналогичных ситуациях профессионально, Например УАРТ. там есть стартовый бит, стоповый и длина посылки не более 8 бит. Именно для того, чтобы не потерять синхронизацию.

Вы собираетесь принять 9*8=72 бита без контроля синхронизации, полагаясь лишь на веру в то, что 40 мкс на процессре - такие же, как и на приборе.

Удивительная доверчивость! Вас в юности цыгане на "погадаю" не разводили? -Шутка... если что.

 

Без синхроимпульсов есть один проверенный десятилетиями метод - избыточность частоты.

Делается так: Вы пишите в буфер с частотой в 3-4 раза выше необходимой. По окончания приема разбирате буфер приема. 3-4 единицы подряд - "1", больше - уже вторая единица пошла и так далее. Много 1 или много 0 подряд все равно могут вызвать ошибку "бит-фрейма" Но уже сложнее.

Подробнее разжевывать не стану. Вроде все понятно. Чем выше частота, тем легче точнее можно определить бит-фрейм. В идеале писать по прерыванию таймера. Тогда Вы будете точно уверены в частоте семплов. Делаете таймер1 на 5, например, мкс. Это 80 тактов. Каждый раз по достижении 80 у вас вызывется прерывание, в нем Вы читаете бит порта и пишите его в бит буфера. Таймер сам продолжит отсчет. Важно, чтобы за 80 тактов вы успели записать бит в буфер. На это время стоит остановить таймер0, который миллис считает. Не хватает времени? - сделайте на 10 мкс.

Попробуйте написать это самостоятельно, ничего, кроме основ програмирования и знания аглицкого, для чтения даташита, Вам не понадобится.

-----

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

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Устройство я делаю сам, так что то, что оно будет передавать и как будет передавать - это зависит от моей хотелки. Можно подумать по УСАРТ...

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Тогда передавайте, как в SPI, с синхрой. Для этого есть примитивы в Ардуино: shiftIn() и shiftOut(). И никаких проблемм не будет.

----------------

добавлю: если сами делаете, но хотите провода экономить - смотрите на 1-wire. Есть в сети много вариантов софтовой реализации. Там смысл в том, что приемник сам синхронизирует передачу: я опускаю линию на короткое время и поднимаю снова и жду, что сделает передатчик - опустит линию или нет. Очень легко реализовать.

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Передача данных по 485. Конечно можно извратится и по принципу одноволновых, но уж это совсем... 

Если написать обработчик на АСМе? Как передать в основную прогу то, что получит обработчик? 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Для связки Ардуино и 485 все уже 100500 раз написано. Зачем Вы велосипедостроением стали заниматься?  То есть, если стали, то Вам, вероятно, нужно. Просто Вы не пояснили - зачем?

А про асм - читайте про ассемблерный код внутри gcc. Это горазно правильнее, чем отдельно писать, тогда компилятор свободно интегрирует С-шный код и ассемблерный, с точки зрения распределения регистров и много чего еще. Прямо в поиске вбиваете "avr-gcc asm" - и читаете все подряд, пока не постигните дзен.

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Поясняю. :)

Связать 485 и любой МК- нет проблем. Электрических, так сказать. Как обрабатывать данные , которые приходят на порт МК? Приходят побитно от любого девайса. К примеру -  от моего. Сейчас я выставил на передачу для тестировки процесса передачи следующую последовательность: стартовый бит, далее сколько то байт (это уже не так важно) младшим битом вперед. По идее, заполнив побитно буфер приемника, будет отображаться содержимое принятого байта- 55Н. А этого не происходит. Моя железяка генерирует железно - смена бит происходит через 40 мкс. Не такая уж и большая скорость передачи. Значит, неграматно пишу обработчик. Или принципиально невозможно решить эту задачу данным способом. Сейчас обдумываю применение UART.  Можно ли его использовать на других портах, к примеру. и как им пользоваться. Как всегда на первой стадии - почти ничего не понятно.

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Спасибо за наколку avr-gcc asm - стало понятно, как сформулировать критерии поиска. 

ptr
Offline
Зарегистрирован: 28.05.2016

Визуально, у Вас скорость передачи в два раза выше. То есть вы передете бит не за 40мкс, а за 20.

Раз у Вас стартовый бит высокого уровня то можно первый байт использовать для синхронизации. Он должен быть всегда 01010101b. Примерно так:

uint32_t time_start, time_end, period;
uint8_t last_level;

period=last_level=0;
for (j=0;j<8;j++)
{
  while  (digitalRead(RX)==last_level);
  if ( i )
  {
    time_end=micros();
    period+=time_end-time_start;
    time_start=time_end;
  } else {
    time_start=micros();
  }
  last_level~=last_level;
}
period/=8;
delayMicroseconds(period/2-4);
time_start=micros();

  for  (i=0;i<8;i++){                     //заполнение буфера
    for (j=0;j<7;j++)
      {if  (digitalRead(RX)== HIGH){
        bitWrite(B[i], j,1);
      }
      else  {bitWrite(B[i], j,0);
               }
      time_end=micros();
      delayMicroseconds(period-(time_end-time_start));
      time_start=time_end;
      }
  }

 

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

На скорую руку, конечно, можно по УАРТу передать/принять, пока не напишу свой обработчик.

nik182
Offline
Зарегистрирован: 04.05.2015

Я чисто для понимания процесса. Зачем свой обработчик? Если для собственного развития то совет - посмотрите как реализован software serial. Уже реализовано несколькими способами то что вы хотите. И работает. Если для запутывания иностранных шпионов .... Люди уже много раз наступили на грабли передачи информации между устройствами. Придумали много разных шин и способов обеспечить помехозащищённость. Надо ли изобретать велосипед?

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Ну , мало ли у кого какие тараканы! Мне вообще то нужен результат. Сейчас как раз юзаю эту библу-. К сожалению (скоро перезжаю) приходится делать некоторые операции (буквально) на коленке. Типа, пихать в программатор чип. Прохождение некоторых операций приходится отслеживать косвенно, типа, запрограммировал девайс, а что там с него идет... Только косвенно. Ну да ладно, разберемся. 

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Да! Что бы небыло лишних поводов тыкнуть палкой! Сейчас выходной сигнал стандартизировал под передачу по нормальному - 1 высокий, 0 - низкий.

 

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Перепрограммировал девайс. По умолчанию UART работает в режиме 8N1. А как это проверить? Ардуина девайс видит, но данные идут с искажениями - видимо частоты плавают. Чуть попозже выложим результаты. А как режим 8N1 поменять - нигде указаний не  нашел. В описании библиотек сказано, что режим этот задается по умолчанию. Полазил по форумам - тот же результат.

nik182
Offline
Зарегистрирован: 04.05.2015

USART Control and Status Register n C – UCSRnC

Bits 5:4 – UPMn1:0: Parity Mode

Bit 3 – USBSn: Stop Bit Select

Bit 2:1 – UCSZn1:0: Character Size

В любом даташите AVR! Только для Вас! Любая мода на выбор.

Ни разу не наблюдал ошибок нормально настроенного UART. Если плывёт частота, просто надо снизить скорость. Всегда можно подобрать режим где ошибок нет.

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

nik182 пишет:

Ни разу не наблюдал ошибок нормально настроенного UART. Если плывёт частота, просто надо снизить скорость.

А вот я недавно наблюдал. По стандарту скорость должна быть 31250. И снижать ее, естественно, нельзя. Да и невозможно. Удалось избавиться от ошибок при установки частоты в 31500.

Да, кстати, частота там вместо расчетной 440 Гц выдавалась 437 Гц. Видать такой кварц (или керамика).

nik182 пишет:

Всегда можно подобрать режим где ошибок нет.

Вот с этим соглашусь. Правда, я нескольколько вечеров бился, пока догадался, что нужно поварьировать скорость.

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Конечно согласен!  Тоже прикидываю, насколько можно упасть в скорости обмена, что бы не совсем заморачиваться с абсолютной синхронизацией (время сдачи поджимает). Спасибо за строчку "USART Control and Status Register n C – UCSRnC". Я то спрашивал, есть ли настройки типа mySerial.begin(19200, XXX), где ХХХ - установка режима обмена. Во всяком случае, в описании библиотеки, приводится именно такая конструкция.  Сегодня прикину, насколько выгоднее понизить скорость что бы избежать большого рассогласования. В том смысле, что учту "гуляние" частот девайсов. В даташитах есть указание - рассогласование в битрейтах(аж поморщился) - не более 1,5%. Понижение битрейта равносильно повышению частоты ЗГ девайсов, так что процент рассогласования будет неизменно падать.

 

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

"  В любом наборе исходных данных самая надежная величина,  не требующая никакой проверки, является ошибочной." . Сменил кварц, поставил  в два раза больший по частоте.  Все работает, скорость обмена установил 38400.  Как говорится, спасибо, за поддержку! Бум теперь организовывать обмен по УАРТу. 

ptr
Offline
Зарегистрирован: 28.05.2016

Я же приводил выше самосинхронизирующийся код

nik182
Offline
Зарегистрирован: 04.05.2015

Я недавно строил программый сериал на tiny25. Для подбора констант задержки запускал в цикле изменение и вывод величины текущей задержки. Прикольно было наблюдать как постепенно исчезают ошибки передачи а потом опять появляются до полной потери информации. Без ошибок принималось +-10% на 19200.    

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Вообще то я железячник, поэтому и смотрю на некоторые тексты программ с некоторым недоверием. Для меня важен  железный результат, чтобы девайсы работали без излишних костылей, программных или железячных. Ну невозможно объять сразу все и все помнить! Особенно когда бегаешь по форумам и натыкаешься на одни и те же ссылки, на одни и теже неясночти.  Вот к примеру, Stream.readBytesUntil(character, buffer, length) Все вроде бы ясно. Но не все length - типа int. Значит ли это, что можно принимать одним пакетом 65536 байта? Я так понимаю, что пересылка идет сплошным потоком, без разделительных старт/стопных бит?

ptr
Offline
Зарегистрирован: 28.05.2016

Во-первых, если int, то все же 32767 максимум. Во-вторых, если размер буфера (объем оперативой памяти) позволяют, то можно и гигабайты одним вызовом функции в буфер прочитать.

Любая передача данных - это всегда стек протоколов. Начиная с протоколов физического уровня (токовая петля, фазовая модуляция, частотная модуляция, отсутствие модуляции и т.п.) и бесконечное количество протоколов более высокого уровня. Причем последние могут еще и инкапсулироваться друг в друга. Например, если физический уровень позволяет нам передавать и принимать байты, то ничто, кроме недостатка ресурсов МК, не мешает нам развернуть на этот уровень PPP/IP/TCP/HTTP/SSL/IP/TCP/HTTP/SSL и так до бесконечности.

Сильно ли Вы задумываетесь, когда читаете эту страницу, о том, какие протоколы физического и нижнего логического уровня были использованы для доставки содержимого этой страницы к Вам на компьютер и для отображения ее на мониторе?

Аналогично и для класса Stream. Метод readBytesUntil может быть перегружен и унаследован множество раз. И с какого уровня стека протоколов он берет данные, зависит от конкретного объекта, который Вы создали и его свойств. Причем сам объект, в случе инкапсуляции протоколов, может даже не знать ничего о том, на каком уровне в стеке протоколов оказался тот протокол, которым он воспользовался.

 

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

У меня железка - работает, как оконечное устройтсво, типа кнопочки и лампочки. В этом девайсе, нет ни ОС, нет вычурных построений. Девайс работает железно- по железной логике, которую прошиваю на программаторе.  Стыкуется с Ардуиной, на котором собран другой девайс. Физически состыковать два девайса - не сложная задача. Ардуина должна принимать пакет данных в 10 байт. Стартовый бит, потом 10 байт инфы и стоповый бит. Ардуина должна посылать следуюшую последовательность сигналов - стартовый бит, затем 6 байт инфы, стоповый бит. ВОзможно ли это сделать с помощью Stream.readBytes(buffer, length)? В описании методов, потоков практически на всех форумах одни и теже слова. Ситуация, которую описал Лем с Йоном Тихим. когда он попытался узнать, что такое сепуление.

Или процесс заполнения буфера в УАРТ происходит СТРОГО по 8бит? С обрамлением старт/стоповых бит?

LastHopeMan
Offline
Зарегистрирован: 19.09.2016

А вы уже обратили внимание, что в коде для перехода к следующему биту используется delay? Не удивляйтесь, что даже при малых объемах у вас будет вся линейка съезжать. 

40 мкс вы подождали, дальше какая-то инструкция. Она тоже кушает время. В итоге вы подождали по факту больше, чем надо. Как решить? Ну вы можете читать таймер, а не пропускать время. В цикле читаете таймер и сравниваете его с расчетным, по которому вы ожидаете бит.

Вы и сами можете прикинуть: если ваш МК допутим 16 мегагерц, то он выполнит до 16 инструкций за 1 мкс. Учитывая то, что МК у вас скорее всего восьмибитный, то это еще больше усугубляет положение по точности ожиданий.

 

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

ptr
Offline
Зарегистрирован: 28.05.2016

CotDaVinchi пишет:

ВОзможно ли это сделать с помощью Stream.readBytes(buffer, length)?

Все возможно, перегрузив имеющийся класс своей реализацией нужных методов. Но новичкам я это не советую, так как перегрузка классов требует хорошего понимания не только того, что Вы делаете, а и того, что в преспективе Вам потребуется получить. Поэтому рекомедую обойтись вообще без объектно-ориентированного программирования. Для начала просто реализовав нужный Вам функционал в рамках C. А когда и если будет необходимость - оформите уже в виде класса на C++.

ptr
Offline
Зарегистрирован: 28.05.2016

LastHopeMan пишет:

40 мкс вы подождали, дальше какая-то инструкция. Она тоже кушает время.

Я уже написал ему выше код, в котором данная проблема решена.

LastHopeMan
Offline
Зарегистрирован: 19.09.2016

ptr пишет:

LastHopeMan пишет:

40 мкс вы подождали, дальше какая-то инструкция. Она тоже кушает время.

Я уже написал ему выше код, в котором данная проблема решена.

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

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

LastHopeMan пишет:

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

Именно учел. Я - железячник. Фронты импульсов не завалены ибо формируются неким amd485, с обоих концов физической передачи. Ошибки передачи контролируются CRC8 (да, девайс восьмибитный, как было написано выше).

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Собственно связал два девайса: Ардуино Уно Р3 и свое устройство, выровнил все задержки. 

Скетч посылает на девайс байт, девайс полсекунды его держит и отправляет на Ардуино. В принципе, это и требовалось на этом этапе проектирования/изготовления - обеспечить устойчивую связь. 


#include <SoftwareSerial.h>

int  RX=17;  //А3 зеленый
int  TX=14;  //А0 салатный
byte      i;      
byte incomingByte = 0;   // для хранения полученного байта
SoftwareSerial mySerial(RX,TX);

//
void setup(void) {
  pinMode(TX, OUTPUT); 
  pinMode(RX, INPUT); 
  Serial.begin(9600);
mySerial.begin(38400); //такт 26 мкС
}

void loop() {
  i=i+1;  
      mySerial.write(i);
        Serial.print("I trans:    ");Serial.print(i, BIN);Serial.print(" H=");Serial.println(i,HEX);
  delay(500);

 while (mySerial.available()){  //если есть доступные данные
        // считываем байт
    

        incomingByte = mySerial.read();        // отсылаем то, что получили
        Serial.print("I received: ");
        Serial.print(incomingByte, BIN);Serial.print(" H=");
       Serial.println(incomingByte, HEX);
       delay(1000);
   mySerial.flush();//чистим буфер

}
} 
  

На монитор отправляется для сравнения то, что я посылаю в девайс и то, что девайс отправляет обратно. Вопрос следующий. При первом включении или при сбросе на Ардуине прием первого полученног байта отображается неправильно. 

При включении монитора:

I trans:               1 H=1
I received: 101111 H=2F
I trans:      10 H=2
I received: 10 H=2
I trans:      11 H=3
I received: 11 H=3
I trans:      100 H=4
I received: 100 H=4
I trans:      101 H=5
I received: 101 H=5
 
При сбросе Ардуино.
 
I trans:      111101 H=3D
I received: 111101 H=3D
I trans:      111110 H=3E
I received: 111110 H=3E
I trans:      111111 H=3F
I trans:               1 H=1
I received: 101111 H=2F
I trans:      10 H=2
I received: 10 H=2
I trans:      11 H=3
I received: 11 H=3
 
Почему это происходит?

 

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

byte incomingByte = i;

// while (mySerial.available()){ 

// mySerial.flush();

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

И? инициализируем byte incomingByte = i;  , убираем проверку заполнености буфера? 

При первом обращении к УАРТу mySerial.read(); считывает содержимое буфера. Вместо ожидаемого содержимого H=1, там находится H=2F. С чем это связано? Настройки УАРТа все по умолчанию, в последующих циклах передачи/ прием все отображается ожидаемо. 

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

CotDaVinchi пишет:

И? инициализируем byte incomingByte = i;  , убираем проверку заполнености буфера? 

При первом обращении к УАРТу mySerial.read(); считывает содержимое буфера. Вместо ожидаемого содержимого H=1, там находится H=2F. С чем это связано? Настройки УАРТа все по умолчанию, в последующих циклах передачи/ прием все отображается ожидаемо. 

byte incomingByte = i; // это должно быть очевидно

убираем проверку заполнености буфера?// зачем тебе проверять наличие в приёмном буфере чего-то, если ты перед этим отправил что-то в сериал - очевидно же, что в буфере что-то будет всегда.

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Буфера на передачу и прием - разные. Это отдельные регистры- устройства. Причем, независимо от реализации микро или процессорной платформы. Именно поэтому:

  • available() – функция возвращает количество байт, принятых микроконтроллером в специальный буфер и доступных для считывания в программу. Буфер может хранить до 64 байт.
  • read() – считывает один байт из буфера последовательного соединения. При этом считанный байт из буфера уходит. Байты из буфера считываются в той последовательности, в которой они поступили в порт.
  • write(val) – записывает один (или несколько) байт в последовательный порт.

"byte incomingByte = i; // это должно быть очевидно" - очевидно только сокращение исходного кода, что в данном конкретном случае не так важно. 

При первом обращении к УАРТу mySerial.read(); считывает содержимое буфера входных данных(если уж становиться на позицию буквоедства). Вместо ожидаемого содержимого H=1, там находится H=2F. - так почему этакое происходит?

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

CotDaVinchi пишет:

Буфера на передачу и прием - разные. Это отдельные регистры- устройства. Причем, независимо от реализации микро или процессорной платформы. Именно поэтому...

ты сделал byte incomingByte = i; прежде чем здесь играть в Капитан Очевидность? - мне лично пофиг, зачем ты тупишь, но если ты не станешь сотрудничать, останешься наедине со своими глюками.

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016
#include <SoftwareSerial.h>

int  RX=17;  //А3 зеленый
int  TX=14;  //А0 салатный
byte      i;      
byte incomingByte = i;   // для хранения полученного байта
SoftwareSerial mySerial(RX,TX);

//
void setup(void) {
  pinMode(TX, OUTPUT); 
  pinMode(RX, INPUT); 
  Serial.begin(9600);
mySerial.begin(38400); //такт 26 мкС
}

void loop() {


  i=i+1;  
      mySerial.write(i);
        Serial.print("I trans:    ");Serial.print(i, BIN);Serial.print(" H=");Serial.println(i,HEX);
  delay(500);

// while (mySerial.available()){  //если есть доступные данные
        // считываем байт
    

        incomingByte = mySerial.read();        // получаем , что отослали
        Serial.print("I received: ");
        Serial.print(incomingByte, BIN);Serial.print(" H=");
       Serial.println(incomingByte, HEX);
       delay(1000);
 //   mySerial.flush();//чистим буфер

//}
} 

И получаем... кто возьмет билетов пачку....

I trans:    1 H=1
I received: 1101111 H=6F
I trans:    10 H=2
I received: 10 H=2
I trans:    11 H=3
I received: 11 H=3
I trans:    100 H=4
I received: 100 H=4
I trans:    101 H=5
I received: 101 H=5
I trans:    110 H=6
I received: 110 H=6
I trans:    111 H=7
I received: 111 H=7
I trans:    1000 H=8
 

Ещё какие тыкалки будут? 

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

CotDaVinchi пишет:

Ещё какие тыкалки будут? 

добавь в сетап:

void setup(void) {
Serial.print("mySerial.available?:    ");
Serial.write(mySerial.read());
Serial.println("");
}

 

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016
mySerial.available?:    ÿ
I trans:    1 H=1
I received: 11111111 H=FF
I trans:    10 H=2
I received: 10 H=2
I trans:    11 H=3
I received: 11 H=3
I trans:    100 H=4
CotDaVinchi
Offline
Зарегистрирован: 12.05.2016
"И тут же они услыхали откуда-то сверху стальное гнусавое гоготание:
– Где-то здесь Трурль… я чую Трурля…"
 
Не парься. придется самому разбираться, почему буферина приемный не чистится автоматом при вызове.
Клапауций 234
Offline
Зарегистрирован: 24.10.2016

CotDaVinchi пишет:

почему буферина приемный не чистится автоматом при вызове.

не при вызове не чистится, а при инициализации там уже что-то есть.

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Спасибо, учтем. Эффект интересный, но пока неопасный.

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Уха-ха!  Это Ардуино в первый раз посылает в девайс что то, что лежит в буфере при включении или при ресете! Девайс, как железяка, отсылает то, что получил.  Как почистить выходной буфер, после первой инициализации?

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

CotDaVinchi пишет:

Уха-ха!  Это Ардуино в первый раз посылает в девайс что то, что лежит в буфере при включении или при ресете! Девайс, как железяка, отсылает то, что получил.  Как почистить выходной буфер, после первой инициализации?

прекращай тупить - проверяй этим:


#include <SoftwareSerial.h>

int  RX=17;  //А3 зеленый
int  TX=14;  //А0 салатный
SoftwareSerial mySerial(RX,TX);

// void setup(void) { // нах здесь void?
void setup() {
// pinMode(TX, OUTPUT); // нах ты сюда что-то пишешь, а затем удивляешься, что там что-то есть?
// pinMode(RX, INPUT); // нах ты сюда что-то пишешь, а затем удивляешься, что там что-то есть?
// Serial.begin(9600); // нах такая скорость?
  Serial.begin(38400);
mySerial.begin(38400); //такт 26 мкС
while (mySerial.available()){Serial.write(mySerial.read());} // здесь должно быть пусто!!!
}

void loop() {}

 

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016
#include <SoftwareSerial.h>

int  RX=17;  //А3 зеленый
int  TX=14;  //А0 салатный
int  m;
byte      i;      
byte iByte = 0;   // для хранения полученного байта
unsigned long time0;
unsigned long time1;
unsigned long time2;
SoftwareSerial mySerial(RX,TX);

//
void setup(void) {
  pinMode(TX, OUTPUT); 
  pinMode(RX, INPUT); 
  Serial.begin(9600);
mySerial.begin(38400); //такт 26 мкС
 //     mySerial.write(i);
while (mySerial.available()){Serial.write(mySerial.read());} // здесь должно быть пусто!!!

}

void loop() {

    for (i=1;i<7;i++){
      mySerial.write(i);
        Serial.print("I trans:    ");Serial.print(i, BIN);Serial.print(" H=");Serial.println(i,HEX);
  delayMicroseconds(50);
    }
 delay(500);
 
 
 
   
   // while (mySerial.available()){  //если есть доступные данные считываем байт
     m=mySerial.available();
   
     for (i=0;i<11;i++){
         iByte = mySerial.read();        // получаем , что отослали
 // Serial.print("time="); Serial.println(time1-time0,DEC); // вывод показаний таймера для проверки времени выполнения команды
  Serial.print("M =");Serial.print(m, DEC);Serial.print(" "); 
  Serial.print("I =");Serial.print(i, DEC);Serial.print(" ");
        Serial.print("I received: ");
        Serial.print(iByte, BIN);Serial.print(" H=");
       Serial.println(iByte, HEX);

 //      delay(1000);
  //  mySerial.flush();//чистим буфер
 
 
 
 
 //}
  delayMicroseconds(50);

}
    delay(5000);
} 
  
 Ухаха!

Программа работает следующим образом. На девайс посылаются  1 .. 6. Получаем 11 байт от девайса. В девайсе первоначально байты заполнены от 11 до ВВ. Девайс принимает байты , записывает их себе в буфер и посылает в Ардуину.

Получаем на мониторе...

I trans:    1 H=1
I trans:    10 H=2
I trans:    11 H=3
I trans:    100 H=4
I trans:    101 H=5
I trans:    110 H=6
M =11 I =0 I received: 1011111 H=5F
M =11 I =1 I received: 11110000 H=F0
M =11 I =2 I received: 10 H=2
M =11 I =3 I received: 11 H=3
M =11 I =4 I received: 100 H=4
M =11 I =5 I received: 101 H=5
M =11 I =6 I received: 1110111 H=77
M =11 I =7 I received: 10001000 H=88
M =11 I =8 I received: 10011001 H=99
M =11 I =9 I received: 10101010 H=AA
M =11 I =10 I received: 10111011 H=BB
I trans:    1 H=1
I trans:    10 H=2
I trans:    11 H=3
I trans:    100 H=4
I trans:    101 H=5
I trans:    110 H=6
M =11 I =0 I received: 1 H=1
M =11 I =1 I received: 10 H=2
M =11 I =2 I received: 11 H=3
M =11 I =3 I received: 100 H=4
M =11 I =4 I received: 101 H=5
M =11 I =5 I received: 110 H=6
M =11 I =6 I received: 1110111 H=77
M =11 I =7 I received: 10001000 H=88
M =11 I =8 I received: 10011001 H=99
M =11 I =9 I received: 10101010 H=AA
M =11 I =10 I received: 10111011 H=BB
 

 

 

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

А это без словечка их четырех букавок (void)

I trans:    1 H=1
I trans:    10 H=2
I trans:    11 H=3
I trans:    100 H=4
I trans:    101 H=5
I trans:    110 H=6
M =11 I =0 I received: 1011111 H=5F
M =11 I =1 I received: 11110000 H=F0
M =11 I =2 I received: 10 H=2
M =11 I =3 I received: 11 H=3
M =11 I =4 I received: 100 H=4
M =11 I =5 I received: 101 H=5
M =11 I =6 I received: 1110111 H=77
M =11 I =7 I received: 10001000 H=88
M =11 I =8 I received: 10011001 H=99
M =11 I =9 I received: 10101010 H=AA
M =11 I =10 I received: 10111011 H=BB
I trans:    1 H=1
I trans:    10 H=2
I trans:    11 H=3
I trans:    100 H=4
I trans:    101 H=5
I trans:    110 H=6
M =11 I =0 I received: 1 H=1
M =11 I =1 I received: 10 H=2
M =11 I =2 I received: 11 H=3
M =11 I =3 I received: 100 H=4
M =11 I =4 I received: 101 H=5
M =11 I =5 I received: 110 H=6
M =11 I =6 I received: 1110111 H=77
M =11 I =7 I received: 10001000 H=88
M =11 I =8 I received: 10011001 H=99
M =11 I =9 I received: 10101010 H=AA
M =11 I =10 I received: 10111011 H=BB
 

 

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

#include <SoftwareSerial.h>

int  RX=17;  //А3 зеленый
int  TX=14;  //А0 салатный
int  m;
byte      i;      
byte iByte = 0;   // для хранения полученного байта
unsigned long time0;
unsigned long time1;
unsigned long time2;
SoftwareSerial mySerial(RX,TX);

//
// void setup(void) { // я же просил не тупить!!!
void setup() {
  // pinMode(TX, OUTPUT); // я же просил не тупить!!!
  // pinMode(RX, INPUT); // я же просил не тупить!!!
  // Serial.begin(9600);  // я же просил не тупить!!!
  Serial.begin(38400);
mySerial.begin(38400); //такт 26 мкС
 //     mySerial.write(i);
while (mySerial.available()){Serial.write(mySerial.read());} // здесь должно быть пусто!!!

}

void loop() {}

 

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

SoftwareSerial mySerial(10, 11); // RX, TX

https://www.arduino.cc/en/Tutorial/SoftwareSerialExample

Ещё есть какие нибудь мнения ?

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

CotDaVinchi пишет:

SoftwareSerial mySerial(10, 11); // RX, TX

https://www.arduino.cc/en/Tutorial/SoftwareSerialExample

Ещё есть какие нибудь мнения ?

есть мнение, что ты кретин

15   pinMode(TX, OUTPUT);
16   pinMode(RX, INPUT);

 

Клапауций 234
Offline
Зарегистрирован: 24.10.2016

while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

и, это ты не делаешь - нужно ждать, пока не расдуплится сериал

CotDaVinchi
Offline
Зарегистрирован: 12.05.2016

Может быть, остряк. ТХ - передающий пин. Тип - ВЫХОД, RX- приемный пин. Тип - ВХОД. Хоть убейся ап стену. Короче - не знаешь, не пищи и не пиши. При твоем раскладе - обмен вааще работать не будет.