Анализ переменной типа String в loop

arduino.rnd
Offline
Зарегистрирован: 12.09.2018

Добрый день форум!

Помогите понять особенность языка Arduino. Ниже следующий скейтч отправляет устройству по протоколу UART команду, запрос напряжения питания, устройство возвращает ответ на каждый запрос. Я пытаюсь анализировать этот ответ с помощью процедуры ckeck(), в этом момент происходит нечто, что мне не понятно.

Суть процедуры check(): полученный по uart ответ устройства анализируется на предмет количества символов и наличию служебных символов, с выводом результата в serial.

В зависимости от нахождения процедуры (строка 46 или строка 48) внутри .available() я получаю разные результаты и странное зависание программы. В случае строки 46, идет два корректных результата и зависание, в случае строки 48 не корректный 1 вывод, 2 вывод корректный и зависание (см рисунок выделен красным). Без этой процедуры ответы устройства корретные и постоянные (тест более суток) без зависаний.

Я же ожидаю что каждый ответ устройства должен быть проанализирован check() и выведена раскладка этого ответа с соотв заменой символов.

В конечном счете мне необходимо выводить информацию на 16 символьный экран после обработки ответа (фильтр не нужной информации).

 

#include <AltSoftSerial.h>
#include <LiquidCrystal_I2C.h>

AltSoftSerial altSerial;
LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей

void setup() {
  Serial.begin(19200);
  Serial.println("AltSoftSerial Test Begin");
  altSerial.begin(19200);
  //altSerial.println("Hello World");
}

String check(String line) {
// разложить строку line на символы, указать служебные символы строк
// синтаксис check(имя_переменной_для_анализа);
// вывод в терминал

   String symbol_line ="empty";
   int j= line.length();
    for (int i=0; i<=j ; i++) {
      symbol_line=line.charAt(i);
      if (symbol_line=="\n") {symbol_line="<n>";} //new line LF
      if (symbol_line=="\r") {symbol_line="<r>";} //carridge return CR
      if (symbol_line=="\t") {symbol_line="<t>";} //tab
      if (symbol_line=="\0") {symbol_line="<0>";} //end string
      if (symbol_line==" ")  {symbol_line="<s>";} //space
      Serial.print(symbol_line);}  
    Serial.println("\nsymbols count line = " + String(j));            
}

String c;

void loop() {

  altSerial.println("at+cbc");
  if (Serial.available()) {
    c = Serial.readString();
    altSerial.println(c);
  }
  delay(10);
 
  if (altSerial.available()) {
    c = altSerial.readString();
    Serial.println(c);
 //   check(c);
  }
   check(c);
  //Serial.println("loop "+c);
 
}

 

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

Ну, так это не пишется.

1. Вы читаете что пришло в строке 44. А кто Вам сказал, что пришло уже всё, а не часть только?

2. Если Вы отлаживаете связь с прибором - выбросьте нахрен ВСЁ, что к этой связи не относится - ВСЁ. Т.е. строки 2,5,37-41 - нахрен. Они не имеют отношения к связи с прибором, а значит сейчас не нужны.

3. Убирайте постоянное повторени в loop - переносите чтение в setup - не будут засоряться мозги повторениями

4. В строке 14 - что у Вас делает самая первая String, если в функции нет ни одного return?

5. В строке 14 - зачем Вы создаёте новую копию параметра, Вы что меняете его там - нет, таз зачем Вы его по значению передаёте?

Давайте, переделывайте, а там поговорим.

arduino.rnd
Offline
Зарегистрирован: 12.09.2018

ЕвгенийП, спасибо за ваш ответ.

Я только учусь :-). 

1. Особенность устройства, его документация, отправив туда команду она возвращает ответ определнного формата с окончанием \0

2. Можно отбросить, но они нужны в будущем, я не уверен но они алгоритмически не оказывают влияния на тело программы, например возможность записи в serial позволет мне отправить команды устройству руками, это полезно при разработке.

3. В этом основная сложность, однкратно устройство работать может, многократно могут быть не штатные ситуации именно в loop необходимо отправлять и получать состояние устройства.

4. 5. Большое спасибо, изменив строку 14, на void check  программа заработала, так как и задумывалось. Сложно мне сказать зачем, читая документацию и примеры я решил использовать такую конструкцию т.к. она более универсальна, т.е. небольшие косметические изменения позволят мне возвращать различные состояния процедуры по мере дальнейшей разработки, документация не указывает обязательность возврата или я не увидел этого, из-за не опытности я не обратил на это внимание, ещё раз спасибо за подсказку, проблема решена. Если вы ткнете в документ который пояснит что происходит при отсуствии возврата, буду признателен.

Спасибо ещё раз!

 

 

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

arduino.rnd пишет:

1. Особенность устройства, его документация, отправив туда команду она возвращает ответ определнного формата с окончанием \0

Так вот и я ж про тоже. метод readString ждёт либо '\0', либо истечения таймаута. Если таймаут истекает, то он возвращает то, что успел получить. Поэтому никаких гарантий, что Вы получили строку целиком у Вас при таком чтении нет.

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

arduino.rnd пишет:

2. Можно отбросить, но они нужны в будущем, я не уверен но они алгоритмически не оказывают влияния на тело программы, например возможность записи в serial позволет мне отправить команды устройству руками, это полезно при разработке.

В будущем будет будущее. Пока же Вы отлаживаете связь с прибором и всё, что не относится к связи должно быть убрано. Всегда так поступайте - не валите всё в одну кучую Иначе будете ловить непонятки и не будете знать за что хвататься и что глючит. Убирайте. Как отладите связь с прибором - вставите.

arduino.rnd пишет:

3. В этом основная сложность, однкратно устройство работать может, многократно могут быть не штатные ситуации именно в loop необходимо отправлять и получать состояние устройства.

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

arduino.rnd пишет:

4. 5. Большое спасибо, изменив строку 14, на void check  

Но Вы, как я понял, по-прежнему передаёте параметр по значению - зачем? У Вас лишняя память? Вообще, зачем создавать новую копию строки при каждом вызове check?