MeGa WiFi RobotDyn передача из Serial в Serial3

nkYellOw
Offline
Зарегистрирован: 23.11.2015

Добрый день! Нужна ваша помощь.

У меня логика такая: Есп берет из интернета данные,разбирает их и формирует строку вида : значение]значение2]значение3] и после этого, передает в сериал для меги, а мега уже разбирает эту строку и раздает задания на датчики. Значений может быть до 20 штук.

Вот строка которая формируется на есп:

a1]b18]c6]d55]e65]f0]g25]h28]i21]k24]l2019]m1]n16]o14]p36]r15]s18]t6]j18]q6]u0]v-63]w48680]

Влезает только вот это: 

a1]b18]c6]d55]e65]f0]g25]h28]i21]k24]l2019]m1]n16]o14]p36]r15]s

63 символа.

Если выводить в сериал на есп, то выводится вся строка, все ок.

Предположение: Режется потому что, пока идет рид сериала на меге, есп посылает в сериал уже новую строку и старая обрубается... Хз как решить данную проблему =( Нужно что то вроде этого:

Пока мега делает рид сериал3, есп не может отслылать ничего в сериал...

Есп отсылает в сериал раз в 10 секунд, как бы делей достаточно большой... =(

код рида на меге:

String inString = "";

  while (Serial3.available()) {
    // Чтение данных из порта Serial3
    char inChar = Serial3.read();
    // Вывод прочитанных данных в порт Serial
    Serial.write(inChar);
    // Поиск команды в полученных данных (команда должна быть в квадратных скобках)
    inString += inChar;  
  }

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

  Serial.print("a");
  Serial.print(Arduino_active);
  Serial.print("]");

  Serial.print("b");
  Serial.print(properties.start);
  Serial.print("]");

  Serial.print("c");
  Serial.print(properties.stop);
  Serial.print("]");

 

nkYellOw
Offline
Зарегистрирован: 23.11.2015

код отправки идет принтами не "на" есп а "с" есп на сериал меги. Сорри за ошибку =)

__Alexander
Offline
Зарегистрирован: 24.10.2012

эт скорее потому что буфер приема на 64 байта. надо ковырять файлы serial и увеличивать

MaksVV
Offline
Зарегистрирован: 06.08.2015

Или организовать обмен не заполняя весь буфер

nkYellOw
Offline
Зарегистрирован: 23.11.2015

каким образом если есть 20-30 значений и их нужно все передать?

nkYellOw
Offline
Зарегистрирован: 23.11.2015

Да, скорее всего вы правы! Буду читать в эту сторону, спасибо!

b707
Онлайн
Зарегистрирован: 26.05.2017

nkYellOw пишет:

каким образом если есть 20-30 значений и их нужно все передать?

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

nkYellOw
Offline
Зарегистрирован: 23.11.2015

Пока не нашел другого способа, сделаю так что бы двигаться дальше, но обязательно вернусь к этому вопросу что бы сделать "по человечески"

Перешел по C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\HardwareSerial.h

там нашел строки 

SERIAL_TX_BUFFER_SIZE 64

SERIAL_RX_BUFFER_SIZE 64

 

Поменял на 128, загрузил скетч на мегу+есп и все заработало. Спасибо

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

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

 

nkYellOw
Offline
Зарегистрирован: 23.11.2015

Завтра попробую в двоичном виде! Спасибо

b707
Онлайн
Зарегистрирован: 26.05.2017

А вообще - абсолютно ничто не мешает вам разбить данные на несколько посылок...

Если вы за раз можете унести 4 коробки, а надо перетащить восемь - вы ж не ростите себе дополнительные руки, а просто перетаскиваете груз за два захода :)

nkYellOw
Offline
Зарегистрирован: 23.11.2015

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

Я отправляю пакет данных и жду несколько секунд и отправляю второй пакет? Просто Синхронизации между мегой и есп никакой нет, надеятся на везение - тоже не правильно.

По вашей логике это должно быть? так? :

ЕСП отправляет 1 пакет.

Мега при завершении обработки первого пакета отправляет обратно ответ и ЕСП посылает второй пакет? 

 

nkYellOw
Offline
Зарегистрирован: 23.11.2015

b707 полностью с вами согласен! Логику я понял, а программно как мне понять что первая партия доставлена и пора вторую доставлять?)

И спасибо за совет =)

nkYellOw
Offline
Зарегистрирован: 23.11.2015

поставил delay(2000);

после каждых 5 значений. Всего 17 значений и 3 делея. 

Вернул в хедере сериала со 128 до 64, вроде работает. Но не уверен что я правильно понял b707 о пакетных передачах =(

Поправьте меня если я не прав =)

b707
Онлайн
Зарегистрирован: 26.05.2017

nkYellOw пишет:

b707 полностью с вами согласен! Логику я понял, а программно как мне понять что первая партия доставлена и пора вторую доставлять?)

а сейчас вы разве как-то заботитесь о том, дошло ли ваше сообщение? - или если один пакет данных потеряется, ничего страшного не произойдет? :) - если да - то в чем разница с таким вариантом?

Вообще, конечно, часто можно (и даже нужно) работать с подтверждением. Необходимость этого определяется тем, насколько критична доставка данных.

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

 

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

nkYellOw пишет:

каким образом если есть 20-30 значений и их нужно все передать?

Передавайте несколькими порциями.

MaksVV
Offline
Зарегистрирован: 06.08.2015

выложите весь код рида на меге. Сдается мне там задержка какая то есть. Потому что при этом коде 

String inString = "";

  while (Serial3.available()) {
    // Чтение данных из порта Serial3
    char inChar = Serial3.read();
    // Вывод прочитанных данных в порт Serial
    Serial.write(inChar);
    // Поиск команды в полученных данных (команда должна быть в квадратных скобках)
    inString += inChar;  
  }

при появлении данных в буфере УАРТа они сразу должны оттуда вычитываться и буфер не будет успевать заполняться. 

А если присутствует delay. и во время него от есп поступают данные, мега просто ждёт, буфер соответственно никто не вычитывает и он спокойно до конца заполняется. Поэтому строка не лезет полностью.

ПС. а лучше оба кода полностью. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

andriano пишет:

nkYellOw пишет:

каким образом если есть 20-30 значений и их нужно все передать?

Передавайте несколькими порциями.

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

nkYellOw
Offline
Зарегистрирован: 23.11.2015

на стороне меги стоит делай (500)

он считывает моментально. Проблема вся в том чтто строка передается одним махом, а места нет. Если поставить в хедере на запись и чтение вместо 64  - 128 то все работает просто отлично!!!

Второй вариант - передавать несколькими порциями, я поделил на 3 порции по 7 значений и работает все отлично!!

MaksVV
Offline
Зарегистрирован: 06.08.2015

nkYellOw пишет:
на стороне меги стоит делай (500)....

он считывает моментально. 

друг, а как вы думаете сколько времени займёт передача на этом канале 64 байт со скоростью 9600? это будет заметно меньше 500мс. 

А считывает он конечно моментально, только вот это происходит, когда ваша программа на меге доберётся до цикла while. Но уже поздно, буфер то заполнился до конца.   Ведь приём данных в буфер Serial не зависит от вашей программы, он на прерывании на сколько я знаю, поэтому когда вы простаиваете в delay, буфер спокойно и полностью заполняется. 

nkYellOw пишет:
Проблема вся в том чтто строка передается одним махом, а места нет.

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

nkYellOw
Offline
Зарегистрирован: 23.11.2015

у меня стоит скорость 115200 с обеих сторон и со стороны меги пока нет ничего кроме проверки Serial.available() каждые 500мсек. Может конечно, я не так понимаю работу изнутри как вы! Я еще поковыряю код, т.к. день ушел только на то что бы это заработало, теперь осталось "прилизать" =)

спасибо большое за помощь!

MaksVV
Offline
Зарегистрирован: 06.08.2015

nkYellOw пишет:

у меня стоит скорость 115200 с обеих сторон и со стороны меги пока нет ничего кроме проверки Serial.available() каждые 500мсек. Может конечно, я не так понимаю работу изнутри как вы! Я еще поковыряю код, т.к. день ушел только на то что бы это заработало, теперь осталось "прилизать" =)

спасибо большое за помощь!

каждые 500 мсек с помощью delay? Блин я же вроде выше понятно объяснил почему у вас такой косяк. Сделайте свой delay через millis() без delay и все будет в порядке даже с 64кб буфером. 

nkYellOw
Offline
Зарегистрирован: 23.11.2015

теперь понятно)))))) попробую и отпишу! Спасибо!!!

MaksVV
Offline
Зарегистрирован: 06.08.2015

единственное нужно хотябы delay(2) в цикле while добавить, а то будет другая крайность - слишком быстрое чтение из буфера и будет вылетать из цикла while , дробя тем самым строку.  Т.е. примерно так: 


String inString = "";

uint32_t prev = 0;

void setup() {
  Serial.begin  (115200);
  Serial3.begin (115200);
             }

void loop() {
   
   // незнаю зачем вам был нужен этот delay(500)
   // я просто буду чистить строку 
   if (millis()-prev>500) {
        inString = "";  // чистим строку 
    prev = millis();
    }

  while (Serial3.available()) {
    // Чтение данных из порта Serial3
    char inChar = Serial3.read();
    delay (2);                   
    // Вывод прочитанных данных в порт Serial
    Serial.write(inChar);
    // Поиск команды в полученных данных (команда должна быть в квадратных скобках)
    inString += inChar;  
  }

}

 

nkYellOw
Offline
Зарегистрирован: 23.11.2015

убрал delay и millis() вообще. Действительно. Зачем он нужен, сам не понимаю =(

поставил в while delay(2);

в общем, так же работает как и раньше. Завтра буду выкладывать код тогда сюда, видимо все проблемы в нем =(

Либо в платную часть напишу, за деньги сделать. А то я походу совсем баран =(

MaksVV
Offline
Зарегистрирован: 06.08.2015

уберите delay (2), на скорости 115200 он вреден. Он нужен когда 9600. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

также на передатчике рекомендую ввести маркер конца строки ,получив который на приёмнике , делать необходимые манипуляции со строкой inString , затем очищать её  и выходить из цикла while.  

передатчик

uint32_t prev = 0; 

void setup() { Serial.begin (115200);}

void loop() {

if (millis() - prev > 10000){

// тут уж я для короткого примера всё в цикл фор запихал, типа передаём 30 параметров
 for (int i = 0; i<30; i++){
  Serial.print("a");
  Serial.print(i);
  Serial.print("]");
  if (i==29) Serial.println(); // в конце строки передаем маркер конца строки (перевод строки)
                           }
  
 prev = millis();
                            }

}

приёмник 

String inString = "";



void setup() {
  Serial.begin  (115200);
  Serial3.begin (115200);
             }

void loop() {
   
  
 while (Serial3.available()) {
    // Чтение данных из порта Serial3
    char inChar = Serial3.read();
    // Вывод прочитанных данных в порт Serial
    Serial.write(inChar);
    // Поиск команды в полученных данных (команда должна быть в квадратных скобках)
    inString += inChar;  
   
    if (inChar=='\n') {  //если получили маркер конца строки
      
      // тут чё-нибудь делаем с нашей строкой
      
      inString = ""; return; }  //далее чистим её и выходим      
  }

}

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

А еще можно соеденить ЕСП с мегой дополниетльной линией готовности. И передавать данные только тогда, когда мега готова их принять.

nkYellOw
Offline
Зарегистрирован: 23.11.2015

MaksVV пишет:

также на передатчике рекомендую ввести маркер конца строки ,получив который на приёмнике , делать необходимые манипуляции со строкой inString , затем очищать её  и выходить из цикла while.  

передатчик

uint32_t prev = 0; 

void setup() { Serial.begin (115200);}

void loop() {

if (millis() - prev > 10000){

// тут уж я для короткого примера всё в цикл фор запихал, типа передаём 30 параметров
 for (int i = 0; i<30; i++){
  Serial.print("a");
  Serial.print(i);
  Serial.print("]");
  if (i==29) Serial.println(); // в конце строки передаем маркер конца строки (перевод строки)
                           }
  
 prev = millis();
                            }

}

приёмник 

String inString = "";



void setup() {
  Serial.begin  (115200);
  Serial3.begin (115200);
             }

void loop() {
   
  
 while (Serial3.available()) {
    // Чтение данных из порта Serial3
    char inChar = Serial3.read();
    // Вывод прочитанных данных в порт Serial
    Serial.write(inChar);
    // Поиск команды в полученных данных (команда должна быть в квадратных скобках)
    inString += inChar;  
   
    if (inChar=='\n') {  //если получили маркер конца строки
      
      // тут чё-нибудь делаем с нашей строкой
      
      inString = ""; return; }  //далее чистим её и выходим      
  }

}

 

ПОМОГЛО!!!! Спасибо тебе огромнейшее!!! Работает отлично. На передатчике данные передаются одним пакетом а на приемнике разбираются когда получает конец строки. Супер!!!!!

millis() работает лучше/легче/стабильнее чем delay? 

nkYellOw
Offline
Зарегистрирован: 23.11.2015

asam пишет:

А еще можно соеденить ЕСП с мегой дополниетльной линией готовности. И передавать данные только тогда, когда мега готова их принять.

Честно не понимаю о чем вы говорите. Можно попродробнее что это за линия такая?

Думаю мне это тоже будет интересно т.к. Сериал имеет таймаут а у меня в лупе кроме чтения сериала будет еще раздача заданий для датчиков и запись данных на сервер в интернете и боюсь что опять будут теряться данные т.к. время будет уходить на интернет отправку а в этому время сериал будет либо перезаполняться либо еще что нибудь...

MaksVV
Offline
Зарегистрирован: 06.08.2015

nkYellOw пишет:
millis() работает лучше/легче/стабильнее чем delay?

просто во время delay программа останавливается и больше делать нчего не может, а когда вы делаете периодические действия через millis(), программа дальше спокойно крутится и может выполнять другие операции. 

nkYellOw
Offline
Зарегистрирован: 23.11.2015

MaksVV пишет:

nkYellOw пишет:
millis() работает лучше/легче/стабильнее чем delay?

просто во время delay программа останавливается и больше делать нчего не может, а когда вы делаете периодические действия через millis(), программа дальше спокойно крутится и может выполнять другие операции. 

Понял, спасибо!

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

nkYellOw пишет:

asam пишет:
А еще можно соеденить ЕСП с мегой дополниетльной линией готовности. И передавать данные только тогда, когда мега готова их принять.

Честно не понимаю о чем вы говорите. Можно попродробнее что это за линия такая?

Ну, в общем, можно сделать аналог CTS сигнала RS232. Соединяем свободный пин (цифровой вход) ЕСП со своббодным пином Ардуино (цифровой выход).  Назовем его CTS. Когда Ардуино готово считывать данные из сериал, переводит CTS в HIGH (в стандарте RS232 наоборот, ну это не важно). ЕСП перед тем как передавать данные проверяет CTS если он LOW, то или ждет или идет чего другое делать. Если CTS HIGH, то начинает передачу порциями, проверяя CTS после каждой партии. Если он оказался LOW передачу тормозим.

Ардуино же, после того как приняла нужную информацию, ставит CTS в LOW и идет делать свои дела, зная что ничего ей передавать не будут, пока она CTS опять в HIGH не поставит. 

nkYellOw
Offline
Зарегистрирован: 23.11.2015

asam пишет:

nkYellOw пишет:

asam пишет:
А еще можно соеденить ЕСП с мегой дополниетльной линией готовности. И передавать данные только тогда, когда мега готова их принять.

Честно не понимаю о чем вы говорите. Можно попродробнее что это за линия такая?

Ну, в общем, можно сделать аналог CTS сигнала RS232. Соединяем свободный пин (цифровой вход) ЕСП со своббодным пином Ардуино (цифровой выход).  Назовем его CTS. Когда Ардуино готово считывать данные из сериал, переводит CTS в HIGH (в стандарте RS232 наоборот, ну это не важно). ЕСП перед тем как передавать данные проверяет CTS если он LOW, то или ждет или идет чего другое делать. Если CTS HIGH, то начинает передачу порциями, проверяя CTS после каждой партии. Если он оказался LOW передачу тормозим.

Ардуино же, после того как приняла нужную информацию, ставит CTS в LOW и идет делать свои дела, зная что ничего ей передавать не будут, пока она CTS опять в HIGH не поставит. 

Интересная идея! Спасибо!