Анализ переменной типа String в loop
- Войдите на сайт для отправки комментариев
Добрый день форум!
Помогите понять особенность языка 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);
}
Ну, так это не пишется.
1. Вы читаете что пришло в строке 44. А кто Вам сказал, что пришло уже всё, а не часть только?
2. Если Вы отлаживаете связь с прибором - выбросьте нахрен ВСЁ, что к этой связи не относится - ВСЁ. Т.е. строки 2,5,37-41 - нахрен. Они не имеют отношения к связи с прибором, а значит сейчас не нужны.
3. Убирайте постоянное повторени в loop - переносите чтение в setup - не будут засоряться мозги повторениями
4. В строке 14 - что у Вас делает самая первая String, если в функции нет ни одного return?
5. В строке 14 - зачем Вы создаёте новую копию параметра, Вы что меняете его там - нет, таз зачем Вы его по значению передаёте?
Давайте, переделывайте, а там поговорим.
ЕвгенийП, спасибо за ваш ответ.
Я только учусь :-).
1. Особенность устройства, его документация, отправив туда команду она возвращает ответ определнного формата с окончанием \0
2. Можно отбросить, но они нужны в будущем, я не уверен но они алгоритмически не оказывают влияния на тело программы, например возможность записи в serial позволет мне отправить команды устройству руками, это полезно при разработке.
3. В этом основная сложность, однкратно устройство работать может, многократно могут быть не штатные ситуации именно в loop необходимо отправлять и получать состояние устройства.
4. 5. Большое спасибо, изменив строку 14, на void check программа заработала, так как и задумывалось. Сложно мне сказать зачем, читая документацию и примеры я решил использовать такую конструкцию т.к. она более универсальна, т.е. небольшие косметические изменения позволят мне возвращать различные состояния процедуры по мере дальнейшей разработки, документация не указывает обязательность возврата или я не увидел этого, из-за не опытности я не обратил на это внимание, ещё раз спасибо за подсказку, проблема решена. Если вы ткнете в документ который пояснит что происходит при отсуствии возврата, буду признателен.
Спасибо ещё раз!
1. Особенность устройства, его документация, отправив туда команду она возвращает ответ определнного формата с окончанием \0
Так вот и я ж про тоже. метод readString ждёт либо '\0', либо истечения таймаута. Если таймаут истекает, то он возвращает то, что успел получить. Поэтому никаких гарантий, что Вы получили строку целиком у Вас при таком чтении нет.
Чтение строки надо переделывать.
2. Можно отбросить, но они нужны в будущем, я не уверен но они алгоритмически не оказывают влияния на тело программы, например возможность записи в serial позволет мне отправить команды устройству руками, это полезно при разработке.
В будущем будет будущее. Пока же Вы отлаживаете связь с прибором и всё, что не относится к связи должно быть убрано. Всегда так поступайте - не валите всё в одну кучую Иначе будете ловить непонятки и не будете знать за что хвататься и что глючит. Убирайте. Как отладите связь с прибором - вставите.
3. В этом основная сложность, однкратно устройство работать может, многократно могут быть не штатные ситуации именно в loop необходимо отправлять и получать состояние устройства.
И опять. Пока оно у Вас и однократно толком не работает. Перенесите в сетап и отладьте однократную работу. Потом уже переходите к лупу. Снова, как и раньше - не валите всё в кучу, отлаживайте по частям. Сейчас, когда оно и однократно не работает, Вам эта многократность только создаёт многократные трудности - убирайте без разговоров. Не валите всё в одну кучу - так не разрабатывают.
4. 5. Большое спасибо, изменив строку 14, на void check
Но Вы, как я понял, по-прежнему передаёте параметр по значению - зачем? У Вас лишняя память? Вообще, зачем создавать новую копию строки при каждом вызове check?