Проблема с чтением из SoftwareSerial
- Войдите на сайт для отправки комментариев
Добрый день, уважаемые форумчане.
Занялся сборкой устройства для дистанционного управления обогревателем в гараже. Для реализации использую клон Arduino Nano на 168 микросхеме, связь обеспечивает модуль Neoway M590, далее нагрузкой управляет реле. Данные отправляю на сервер народного мониторинга, откуда отправляю и команду на включение или выключение нагревателя.
С контролем температуры реализовать передачу данных на narodmon труда не составило, в интернете полно примеров реализации. А вот с тем, чтобы встретить команду от сервера возникла проблема.
Для работы с модулем в него надо в определенной последовательности вбить последовательность строк для подготовки модуля для передачи данных по GPRS. Далее необходимо отправить данные для сервера, это тоже определенная последовательность, содержащая индивидуальный номер прибора, показания с датчиков и два символа завершения передачи ##. После чего с сервера мы получаем ОК, или команду управления вместо ОК.
Когда я вручную ввожу данные используя такую конструкцию в скетче:
void bypass(){ //передает ответы модема напрямую в serial
if (gsm.available())
Serial.write(gsm.read());
if (Serial.available())
gsm.write(Serial.read())
}
То после того, как я передаю данные на сервер, то всегда получаю команду управления от сервера в виде:
+TCPRECV:0,Х#ИМЯ_КОМАНДЫ", где X - длина имени команды
Однако когда я записываю свои действия следующим образом:
void gprssend(){
DHT11.read(DHT11PIN); // читаем данные с градусника
char val[61];
snprintf(val, sizeof(val), "#ХХХХХХХХХХХХХХХХ#akotb\n#H1DHT11#%d\n#T1DHT11#%d\n#V1VCC10#%d\n##",
DHT11.humidity, DHT11.temperature, 5);
gsm.println("AT+TCPCLOSE=0"); // закрываем соединение, на всякий случай
while(1){ // в цикле соединяемся с сервером народмон
gsm.println("AT+TCPSETUP=0,185.245.187.136,8283");
delay(2500);
if (gsm.find("+TCPSETUP:0,OK")) break; // если соединились, выходим из цикла
Serial.println("tcp_err");
// если нет, проверяем соединины ли с интернетом
gsm.flush();
gsm.println("at+xiic?");
delay(100);
if (gsm.find("0.0.0.0")){
gprsconnect(); // если нет, то подключаемся
delay(2000);
}
}
// отправляем 60 байт
gsm.println("at+tcpsend=0,60");
delay(100);
Serial.available();
gsm.println(val);
//delay(2500);
Serial.println("sendOK");
if (gsm.find("+TCPRECV:0,7,#warm1")){ Serial.println("WARM1"); W1 = !W1;}
else if (gsm.find("+TCPRECV:0,7,#warm2")){ Serial.println("WARM2"); W2 = !W2;}
else if (gsm.find("+TCPRECV:0,6,#ref1")) TIME = 5;
else if (gsm.find("+TCPRECV:0,6,#ref2")) TIME = 30;
}
digitalWrite(IN1, W1);
digitalWrite(IN2, W2);
Serial.println(TIME);
Serial.println(W1);
Serial.println(W2);
gsm.println("AT+TCPCLOSE=0"); // закрываем соединение
Serial.print("!!!");
}
То по какой-то причине ардуинка в упор не видит команды от сервера. К примеру при ручной передаче я четко вижу, что сервер передал "+TCPRECV:0,7,#warm1", однако когда я пишу if (gsm.find("+TCPRECV:0,7,#warm1")){ Serial.println("WARM1"); W1 = !W1;}, то ничего не происходит, как будто такая строка в порт не заходит.
Я пробовал укоротить проводник между модулем и ардуиной до 1см, не помогло. Пробовал вместо "+TCPRECV:0,7,#warm1" писать только первый элемент строки "+", в этом случае срабатывало, однако оно срабатывало даже если команду с народмона я не направлял. Пробовал уменьшать длину команды, пробовал изменять имя команды на числовое значение, не помогло.
Добрый день.
Спасибо за совет. Возможно вы подскажете как можно определить пришла в порт искомая строка или нет?
Самый простой способ - выводить все, что приходит, в консоль и там проверять глазками.
Вы невнимательно читали первое сообщение в теме.
Первое сообщение в теме читать внимательно опасно для здоровья глаз
Первое сообщение в теме читать внимательно опасно для здоровья глаз
Я понимаю что оформление следует поправить, но на этом форуме править сообщения нельзя, или я не нашел как это делать
Да, в общем-то, у меня нет такой обязанности внимательно читать все сообщения. Если бы Вы хотели, чтобы на что-то было обращено особое внимание, вполне можно было на этом акцентировать.
Также я не обязан помнить все темы с начала до последнего сообщения. Поэтому я могу отвечать буквально на заданный вопрос, не сверяясь с тем, что было написано ранее. А следить за темой - это уже обязанность ТС. В частности, формулировать новые вопросы так, чтобы они содержали достаточную информацию, не надеясь, что отвечающий вспомнит, что было в начале обсуждения.
Ну и еще одно замечание: IMHO 168 содержит слишком мало памяти, чтобы полноценно работать со строками. Поэтому было бы целесообразно сначала отладить весь скетч на Меге, и только потом пытаться упихать его в 168.
PS. И - да, требовать внимательного прочтения от так оформленного текста IMHO выходит за рамки разумного.
AKOTb - выложите код, во-первых, по правилам форума. Во-вторых - целиком. В нынешнем обрывке мне совершенно непонятно, откуда берется функция gsm.find(). gsm - это экземпляр класса SoftwareSerial, у которого, насколько мне известно, нет метода find()
ТС - и в принципе. Заставьте программу работать без сети, а уж потом добавьте сеть.
Проблему решил установив в конце строки передачи данных символ перевода каретки. Теперь возник вопрос оптимизации кода.
Для 168 микросхемы сообщение об объеме занимаемой скетчем программы выглядит так:
#include <SoftwareSerial.h> #include <dht11.h> #define DHT11PIN 11 // пин DHT11 boolean W1 = true; boolean W2 = true; float LT = 0; int TIME = 30; int IN1 = 4; SoftwareSerial gsm(8, 7); // RX, TX dht11 DHT11; void gprsconnect() { gsm.println("AT+CGATT?"); // подключаем GPRS while(!gsm.find("+CGATT: 1")){ Serial.print(". "); delay(100); } Serial.print(4); // GPRS OK gsm.println("AT+XISP=0"); // выбираем TCP/IP протокол while(!gsm.find("OK")){ Serial.print(". "); delay(100); } Serial.println(); Serial.println(5); //TCP OK gsm.println("AT+CGDCONT=1,\"IP\",\"internet.beeline.ru\""); // регистрируемся в сети GPRS while(!gsm.find("OK")){ Serial.print(". "); delay(100); } Serial.println(); Serial.println(6); //"REG OK" gsm.println("AT+XGAUTH=1,1,\"beeline\",\"beeline\""); //авторизация while(!gsm.find("OK")){ Serial.print(". "); delay(100); gsm.println("AT+XGAUTH=1,1,\"beeline\",\"beeline\""); } Serial.println(); Serial.println(7); // "AUT OK" gsm.println("AT+XISP=0"); // включаем РРР delay(100); gsm.println("at+xiic=1"); delay(100); do{ // проверяем выдали ли нам IP gsm.println("at+xiic?"); Serial.print("."); delay(300); } while(gsm.find("0.0.0.0")); gsm.println("AT+XIIC=1"); //Установка PPP-соединения while(!gsm.find("OK")){ Serial.print(". "); delay(100); } Serial.println(); Serial.println(8); // "PPP OK" } void gprssend(){ DHT11.read(DHT11PIN); // читаем данные с градусника char val[61]; snprintf(val, sizeof(val), "#ХХХХХХХХХХ#akotb\n#H1DHT11#%d\n#T1DHT11#%d\n#V1VCC10#%d\n##", DHT11.humidity, DHT11.temperature, 5); gsm.println("AT+TCPCLOSE=0"); // закрываем соединение, на всякий случай while(1){ // в цикле соединяемся с сервером народмон gsm.println("AT+TCPSETUP=0,185.245.187.136,8283"); delay(2500); if (gsm.find("+TCPSETUP:0,OK")) break; // если соединились, выходим из цикла Serial.println(9); //"tcp_err" // если нет, проверяем соединины ли с интернетом gsm.flush(); gsm.println("at+xiic?"); delay(100); if (gsm.find("0.0.0.0")){ gprsconnect(); // если нет, то подключаемся delay(2000); } } // отправляем 47 байт gsm.println("at+tcpsend=0,60"); delay(100); gsm.println(val); gsm.println("/n"); delay(250); Serial.println(10); if (gsm.find("+TCPRECV:0,7,#warm1")){Serial.println(881); W1 = !W1;} digitalWrite(IN1, W1); gsm.println("AT+TCPCLOSE=0"); // закрываем соединение Serial.println(999); } void setup(){ pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); digitalWrite(IN1, HIGH); digitalWrite(IN2, HIGH); Serial.begin(9600); gsm.begin(9600); /// незабываем указать скорость работы UART модема while(!gsm.find("+PBREADY")){ // при включении ждем отклик от модема Serial.print(". "); } gsm.println("ATE0"); Serial.println(); Serial.println(1); // MODEM READY Serial.println(2); //OPERATOR SEARCH while(!gsm.find("+COPS: 0,0,\"Beeline\"")){ // ждем когда найдется оператор gsm.println("AT+COPS?"); Serial.print(". "); delay(500); } Serial.println(); Serial.println("3"); //BEELINE gprsconnect(); gprssend(); } void loop() { if (gsm.find("RING")) gprssend(); if ((millis() - LT) > (TIME*60000)) { gprssend(); LT = millis(); } }АКОТ, похоже вы не мастер отвечать на вопросы. Так откуда все-таки берется метод gsm.find() ?
А на тему оптимизации - начните с применения макроса F() - с вашими строчками должны выиграть байтов двести оперативки
Ну для экономии ОЗУ можно воспользоваться макросом F() к текстовым строкам.
АКОТ, похоже вы не мастер отвечать на вопросы. Так откуда все-таки берется метод gsm.find() ?
стандартный метод, я ничего не изобретал, вот у гайвера про него нашел информацию
https://alexgyver.ru/lessons/serial/
Serial.find(target), Serial.find(target, length)
за совет спасибо. Буду изучать
Ух как это круто!
126if((millis() - LT) > (TIME*60000))127{128gprssend();129LT = millis();130}Здесь путаница с типами.
LT у вас зачем то float. После 60000 надо дописать UL т.е. 60000UL
LT у вас зачем то float. После 60000 надо дописать UL т.е. 60000UL
Спасибо, исправил.
Посоветуйте по примененной мною конструкции:
if (gsm.find("+TCPRECV:0,7,#warm1")){Serial.println(F("WARM1")); W1 = !W1;} else if (gsm.find("+TCPRECV:0,7,#warm2")){Serial.print(F("WARM2")); W2 = !W2;} else if (gsm.find("+TCPRECV:0,6,#ref1")){Serial.print(F("TCPRCV_REF1")); TIME = 5;}Мне кажется, что она не рациональная, когда я хочу найти строку "+TCPRECV:0,6,#ref1", то никогда её не нахожу, так как она стоит далеко. Я полагаю, что тут оптимальнее было бы записывать в строку то, что находится между +TCPRECV:0 и концом строки, и уже в дальнейшем работать с этим. Но как это записать не знаю пока. Можно конечно просто попробовать String = gsm.read(), ну туда может и пустая запись попасть. Буду думать.
Посоветуйте по примененной мною конструкции:
if (gsm.find("+TCPRECV:0,7,#warm1")){Serial.println(F("WARM1")); W1 = !W1;} else if (gsm.find("+TCPRECV:0,7,#warm2")){Serial.print(F("WARM2")); W2 = !W2;} else if (gsm.find("+TCPRECV:0,6,#ref1")){Serial.print(F("TCPRCV_REF1")); TIME = 5;}Мне кажется, что она не рациональная, когда я хочу найти строку "+TCPRECV:0,6,#ref1", то никогда её не нахожу, так как она стоит далеко.
Абсолютно верно вам кажется, использовать find таким образом нельзя. Эта функция ищет строку во входных данных Сериал, то есть читает приходящие в порт символы и сравнивает их со строкой в первом if(). Функция работает до тех пор, пока не найдет строку или данные в Сериал не кончатся. Только после этого программа перейдет к условию во втором if(), однако не будет искать вторую строчку в уже принятых данных, а будет ждать новых. Таким образом, если в Сериал приходит только одна строка из трех - строки во втором и последующих elseif() не будут найдены никогда.
да, в вашем случае правильнее СНАЧАЛА принять данные, сохранить куда-то, а уже потом в этих данных искать нужные строки. Символы "+TCPRECV:0", однаковые во всех строках - можно использовать как маркер для определения, что именно сохранять
Посоветуйте по примененной мною конструкции:
if (gsm.find("+TCPRECV:0,7,#warm1")){Serial.println(F("WARM1")); W1 = !W1;}На днях здесь было обсуждение по похожей теме. http://arduino.ru/forum/programmirovanie/nuzhna-pomoshch-s-uart#comment-589960 Без изменений вам не подходит, но как пример посмотрите.
стандартный метод, я ничего не изобретал, вот у гайвера про него нашел информацию
https://alexgyver.ru/lessons/serial/
Serial.find(target), Serial.find(target, length)
Upd:
Посоветуйте по примененной мною конструкции:
if (gsm.find("+TCPRECV:0,7,#warm1")){Serial.println(F("WARM1")); W1 = !W1;} else if (gsm.find("+TCPRECV:0,7,#warm2")){Serial.print(F("WARM2")); W2 = !W2;} else if (gsm.find("+TCPRECV:0,6,#ref1")){Serial.print(F("TCPRCV_REF1")); TIME = 5;}Мне кажется, что она не рациональная, когда я хочу найти строку "+TCPRECV:0,6,#ref1", то никогда её не нахожу, так как она стоит далеко.
Всем спасибо, с Вашими советами удалось реализовать стабильную работу.
Написал следующую функцию, которую вызываю сразу после передачи данных с датчиков температуры
void SSRead() { while(1){ while (gsm.available() > 0) { // ПОКА есть что то на вход strData += (char)gsm.read(); // забиваем строку принятыми данными recievedFlag = true; // поднять флаг что получили данные delay(2); } if (recievedFlag) { // если данные получены if (strData.substring(11,20) == "0,7,#warm") { if (strData.substring(20,21).toInt() == 1) { W1 = !W1; Serial.println(F("WARM1")); } else { W2 = !W2; Serial.println(F("WARM2")); } strData = ""; recievedFlag = false; break; } else if (strData.substring(15,19) == "#ref") { Serial.print(F("TCPRCV_REF1")); TIME = strData.substring(19,21).toInt(); strData = ""; recievedFlag = false; break; } else if (strData.substring(11,17) == "0,3,OK"){Serial.println(F("Нет новых команд")); Serial.println(strData.substring(0,17)); strData = ""; recievedFlag = false; break;} else if (strData.substring(12,18) == "0,Link"){strData = ""; recievedFlag = false; break;} strData = ""; // очистить recievedFlag = false; // опустить флаг } } }Благодаря такому способу реализации, я могу считать с отправленной команды данные, к примеру ранее я создавал команду ref1 чтобы обновление данных шло раз в 5 минут, а команду ref2 ,чтобы раз в 30 минут. Теперь же я реализовал чтение числа после ref, и стало гораздо удобнее. Также вызов нагревателя я организовал одним If, возможно это не имело смысла, ещё подумаю над этим.
Рассмотрел также ситуацию, когда вместо команды придёт абракадабра, программа нормально на это реагирует, и игнорирует такие запросы. Сейчас ещё реализую обратную связь, чтобы быть уверенным, что нагреватель включен/выключен, и думаю это победа.
Всем спасибо)
победой можно считать избавление от String (что еще более важно для атмеги 168) и неблокирующее чтение из Serial без delay и while
здесь более подходящая для ТС тема и код. Почитайте внимательно ту тему сначла
да макрос F() еще недоиспользован )
Макрос F как оказалось с операторами сравнения работает нестабильно. Через раз, а иногда и вовсе не срабатывает. Вынужденная мера убрать макросы Эф из while и if.
По вопросу избавления от string спасибо за совет. Как посетит вдохновение, обязательно займусь усовершенствованием кода. Тут другая задача появилась. В течении длительного теста что-то в связке ардуина+модем стало зависать. Вот думаю над организацией какого-то аналога watchdog'а. Хотя возможно стоит внимательнее почитать в мониторе порта, что там а это время происходит. Сложность в том что проблема вылезла пока что единожды, а плавающие ошибки ловить сложнее всего.
Нестабильно может работать программа. Но тогда - все вопросы к программисту.
Нестабильно? Возможно, вы имели ввиду, что макросы могут иметь скрытые эффекты?
Нестабильно может работать программа. Но тогда - все вопросы к программисту.
Безусловно моей компетенции в этом вопросе недостаточно, но по своим наблюдениям заметил, что при введении в скетч этой конструкции появляются проблемы, убрал, стало лучше.
Всю ночь тестировал на стабильность устройство, пока работает.
Нестабильно? Возможно, вы имели ввиду, что макросы могут иметь скрытые эффекты?
Да, я пока не набрал опыта в использовании этой новой для меня конструкции, но первое впечатление оказалось неоднозначным, памяти сэкономил здорово, но встретился с некоторыми особенностями
...но по своим наблюдениям заметил, что при введении в скетч этой конструкции появляются проблемы, убрал, стало лучше.
Почему-то начинающие программисты винят в неустойчивости работы программы что угодно: компилятор, макросы, библиотеки, но никогда не себя любимого.
Написал следующую функцию, которую вызываю сразу после передачи данных с датчиков температуры
void SSRead() { while(1){ while (gsm.available() > 0) { // ПОКА есть что то на вход strData += (char)gsm.read();К вопросу о стабильности. Замечания ниже возможно не критичны в вашем случае, но в общем случае могут пригодится.
strData лучше объявить внутри функции SSRead(). Тогда будет меньше вероятность утечки памяти. См. http://arduino.ru/forum/programmirovanie/etyudy-dlya-nachinayushchikh-pamyat-3-dinamicheskie-i-avtomaticheskie-peremen параграфы про String
При заполнении strData желательно ограничить (контролировать) ее длину.
дак задача может это вовсе и не другая. String-и любят пожирать ресурсы МК, особенно у начинающих юзеров, не умеющих эти трусы готовить. И уж тем более это актуально для атмеги 168. А когда заканчивается ОЗУ, чудеса бывают самые разные и естественно их сложно локализовать и отловить. Так что я не зря вам даже ссылку с примером дал. тот пример поправить под ваши нужды было не трудно, ну как хотите
#include <SoftwareSerial.h> SoftwareSerial gsm(8, 7); // RX, TX #define BUF_SIZE 60 // размер буфера парсилки char currStr[BUF_SIZE+3]; // буфер парсилки #define MAX_CHAR_COMMAND 10 // максимальное количество символов в команде enum {OK , WARM , REF , LINK, COMMAND_QUANTITY}; //пишем список команд const char comm[][MAX_CHAR_COMMAND] = {"0,3,OK", "warm", "ref", "Link"}; // массив строк команд (очередность должна совпадать со списком выше) const char strBegin[] = "+TCPRECV"; // с чего должна начинаться строка от модема #define VAR_QUANTITY 2 // здесь задаём максимальное количество переменных после команды // (числа писать через пробел после команды, например, warm 2 пропарсится val[0]==2 // а также пробел между числами, например Link 20 567 пропарсится: val[0]==20, а val[1]==567 char *sTr[VAR_QUANTITY+1]; // это нужно для парсинга bool W1=0, W2=0; // ваши вэ int TIME = 30; // ваши тайм //------------------------------функция исполнения полученной команды void runCommand(byte command) { int val[VAR_QUANTITY]; // переменные, в которые парсим значения из поступившей строки Serial.print (comm[command]); // распечатаем поступившую команду в отладку //парсим переменные for (int i = 1; i<=VAR_QUANTITY; i++ ) { sTr[i]=strchr(sTr[i-1], ' ')+1; val[i-1]= atoi (sTr[i]); } // делаем нужные действия на соответствующие команды: if (command==WARM){Serial.println(val[0]); if (val[0]==1) W1=!W1; else if (val[0]==2) W2=!W2; } else if (command==REF) {Serial.print (F(" TIME = ")); Serial.println(val[0]); TIME = val[0];} else if (command==LINK){Serial.println(val[0]); Serial.println(val[1]);} else if (command==OK) {Serial.println(F(" NO new commands"));} } //------------------------функция чтения информации от модема void Modem_read() { if (!gsm.available()) return; // если данных нет игнорируем эту функцию char currSymb[2] = {0}; // символьный кэш currSymb[0] = gsm.read(); // читаем очередной символ static bool stringEnd = 0; // флаг переполнения буфера if (currSymb[0] == '\r' || stringEnd == 1) // если полностью получили строку - парсим: { bool commCorrect = 0; // флаг найдена ли нужная команда // парсим все команды: for (int i=0; i<COMMAND_QUANTITY; i++) { if (strstr(currStr, strBegin)>0){ // если строка началась с +TCPRECV, парсим if ((sTr[0] =strstr(currStr, comm[i]))>0) {runCommand (i); commCorrect = 1; break;}} } if (!commCorrect)Serial.println ("Command is not correct!"); // поругаемся, если нет такой команды currStr[0] = 0; stringEnd = 0; // в конце парсинга нулим буфер } // если не конец строки, то прибавляем очередной байт к буферу : else if ( currSymb[0] != '\n') strcat (currStr,currSymb); // если буфер закончился , то режем строку на этом месте: if (strlen(currStr)>=BUF_SIZE) {stringEnd = 1;} } //-------------------------------- void setup() { Serial.begin(9600); gsm.begin(9600); } void loop() { Modem_read(); // функция чтения из UART // тут остальной код }Макс, вот тебе в копилку: есть такая штука для хранения строк, называется PROGMEM. И всякие к ней функции имеются в avr lib: https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html#ga... -очень полезные.
прогмем то я пользуюсь когда надо, но все равно пасиб, посмотрю
Спасибо, ребят! Вот реально приятно, когда людям не безразличен твой проект. Протестирую обновление, обязательно отпишусь!
типа так?
#include <SoftwareSerial.h> SoftwareSerial gsm(8, 7); // RX, TX #define BUF_SIZE 60 // размер буфера парсилки char currStr[BUF_SIZE+3]; // буфер парсилки #define MAX_CHAR_COMMAND 10 // максимальное количество символов в команде enum {OK , WARM , REF , LINK, COMMAND_QUANTITY}; //пишем список команд const char comm[][MAX_CHAR_COMMAND]PROGMEM = {"0,3,OK", "warm", "ref", "Link"}; // массив строк команд (очередность должна совпадать со списком выше) const char strBegin[] PROGMEM = "+TCPRECV"; // с чего должна начинаться строка от модема #define VAR_QUANTITY 2 // здесь задаём максимальное количество переменных после команды // (числа писать через пробел после команды, например, warm 2 пропарсится val[0]==2 // а также пробел между числами, например Link 20 567 пропарсится: val[0]==20, а val[1]==567 char *sTr[VAR_QUANTITY+1]; // это нужно для парсинга bool W1=0, W2=0; // ваши вэ int TIME = 30; // ваши тайм //------------------------------функция исполнения полученной команды void runCommand(byte command) { int val[VAR_QUANTITY]; // переменные, в которые парсим значения из поступившей строки char buff[MAX_CHAR_COMMAND+1] = {0}; strcpy_P(buff,(const char*)comm[command]); Serial.print (buff); // распечатаем поступившую команду в отладку //парсим переменные for (int i = 1; i<=VAR_QUANTITY; i++ ) { sTr[i]=strchr(sTr[i-1], ' ')+1; val[i-1]= atoi (sTr[i]); } // делаем нужные действия на соответствующие команды: if (command==WARM){Serial.println(val[0]); if (val[0]==1) W1=!W1; else if (val[0]==2) W2=!W2; } else if (command==REF) {Serial.print (F(" TIME = ")); Serial.println(val[0]); TIME = val[0];} else if (command==LINK){Serial.println(val[0]); Serial.println(val[1]);} else if (command==OK) {Serial.println(F(" NO new commands"));} } //------------------------функция чтения информации от модема void Modem_read() { if (!gsm.available()) return; // если данных нет игнорируем эту функцию char currSymb[2] = {0}; // символьный кэш currSymb[0] = gsm.read(); // читаем очередной символ static bool stringEnd = 0; // флаг переполнения буфера if (currSymb[0] == '\r' || stringEnd == 1) // если полностью получили строку - парсим: { bool commCorrect = 0; // флаг найдена ли нужная команда // парсим все команды: for (int i=0; i<COMMAND_QUANTITY; i++) { if (strstr_P(currStr, (const char*)strBegin)>0){ // если строка началась с +TCPRECV, парсим if ((sTr[0] =strstr_P(currStr, (const char*)comm[i]))>0) {runCommand (i); commCorrect = 1; break;}} } if (!commCorrect)Serial.println ("Command is not correct!"); // поругаемся, если нет такой команды currStr[0] = 0; stringEnd = 0; // в конце парсинга нулим буфер } // если не конец строки, то прибавляем очередной байт к буферу : else if ( currSymb[0] != '\n') strcat (currStr,currSymb); // если буфер закончился , то режем строку на этом месте: if (strlen(currStr)>=BUF_SIZE) {stringEnd = 1;} } //-------------------------------- void setup() { Serial.begin(9600); gsm.begin(9600); } void loop() { Modem_read(); // функция чтения из UART // тут остальной код }