Поиск нужной строки при работе с Com портом
- Войдите на сайт для отправки комментариев
Пнд, 13/12/2021 - 01:44
Всем привет, работаю с GSM модулем SIM800L немного хочу доработать управляющую программу, чтобы была внешняя индикация его готовности (к примеру светодиодом) к работе.
Известно что запускается модуль командами в моем случае:
| C++Выделить код | ||
|
||
Если, после загрузки программы в МК смотреть в com порт то выдает он примерно вот такие значения:
AT
ОК
AT+CLIP=1
ОК
AT+CMGF=1
ОК
Это означает что модуль готов и можно работать с ним.
Я хочу дописать программу так что если в выведенных значениях есть "ОК" то идет нужное мне действие...
Есть какой оператор который ищет в выведенных значениях в порт нужные данные ?
Есть какой оператор который ищет в выведенных значениях в порт нужные данные ?
нет.
Надо сначала собрать из порта строчку символ за символом, а уже потом в этой строке искать, например функциями strstr() strtok() ( вариантов поиска много)
Есть какой оператор который ищет в выведенных значениях в порт нужные данные ?
Такая "встроенная" возможность есть, но не всегда ее удобно использовать, т.к. если ничего не найдет, будет ждать время заданное в setTimeout() и блокировать выполнение остальной программы. А если данные идут постоянно, но не содержат искомого, то будет блокировать пока идут данные т.к. Timeout сбрасывается при чтении каждого очередного символа. И оно только ищет и отбрасывает просмотренные данные.
Serial.find(target, length)
https://www.arduino.cc/reference/en/language/functions/communication/serial/find/
Такая "встроенная" возможность есть, но не всегда ее удобно использовать
Serial.find(target, length)
это не "возможность", а сплошная профанация, не надо такое новичкам советовать
Вот такой функцией пользуюсь. Аналог find() , но не блокирует скетч.
byte isMarker (const char * marker){ // "OK\r\n" len=4 static byte index = 0; byte len = 0; len = strlen(marker); while(esp8266.available()){ byte c = esp8266.read (); if(index < len){ if(c == marker[index]) index++; // else{ //не маркер index = 0; if(c == marker[index]) index++; //возможно снова начало маркера } } if(index == len){ index = 0; return 1; } } return 0; }Вызывается так же
if(isMarker("OK")){ //что-то делаем }Есть какой оператор который ищет в выведенных значениях в порт нужные данные ?
нет.
Надо сначала собрать из порта строчку символ за символом, а уже потом в этой строке искать, например функциями strstr() strtok() ( вариантов поиска много)
По хорошему надо не накапливать в строке, тем более, если заранее неизвестно, какой длины может быть строка, а разбирать сразу - по приходу очередного символа.
Есть какой оператор который ищет в выведенных значениях в порт нужные данные ?
Такая "встроенная" возможность есть, но не всегда ее удобно использовать, т.к. если ничего не найдет, будет ждать время заданное в setTimeout() и блокировать выполнение остальной программы. А если данные идут постоянно, но не содержат искомого, то будет блокировать пока идут данные т.к. Timeout сбрасывается при чтении каждого очередного символа. И оно только ищет и отбрасывает просмотренные данные.
Serial.find(target, length)
https://www.arduino.cc/reference/en/language/functions/communication/serial/find/
Понял, но эта часть должна выполняться void setup() так что по идеи блокировать выполнение основной программы не должно
Вот такой функцией пользуюсь. Аналог find() , но не блокирует скетч.
Спасибо буду пробовать
Пробовал через Serial.find(target, length) она ищет нужное значение или строку, но когда вручную вводишь его через терминал, если же вывод значений в послед порт указан в коде, то не может найти нужного .
Если через
if(isMarker("")так вообще такого оператора нет, может дополнительные библиотеки нужно подключать.Если через
if(isMarker("")так вообще такого оператора нет, может дополнительные библиотеки нужно подключать.пипец.... Вы язык Си знаете вообще? Вам исходный код "этого оператора" в сообщении #4 зачем дали, как вы думаете?
Если через
if(isMarker("")так вообще такого оператора нет, может дополнительные библиотеки нужно подключать.Понимаю... Даже скетч не буду просить показать. Могу дать пример работы с АТ командами с ESP8266 запрос-ответ без блокировки скетча и с таймаутом. Надо?
[/quote]
Понимаю... Даже скетч не буду просить показать. Могу дать пример работы с АТ командами с ESP8266 запрос-ответ без блокировки скетча и с таймаутом. Надо?
[/quote]
Хорошо, давайте
SIM800 у меня нет под рукой, а ESP8266 подключена к меге. Для нее и будет пример.
При включении ESP ждет 5 сек и подключается к точке доступа на смартфоне. Если ESP не отвечает на команды, то происходит аппаратная перезагрузка модуля. Если точка доступа отключена, ESP пытается подключиться каждые 15 сек. После подключения к точке доступа, больше ничего не происходит- это просто пример. Все это происходит в фоновом режиме. Подредактируйте под свои задачи.
#define DEBUG 1 //закомментировать эту строку, если не нужна отладка #ifdef DEBUG #define DEBUG_BEGIN(x) Serial.begin(x) #define DEBUG_PRINT(x) Serial.print(x) #define DEBUG_PRINTLN(x) Serial.println(x) #else #define DEBUG_BEGIN(x) #define DEBUG_PRINT(x) #define DEBUG_PRINTLN(x) #endif #define PIN_HARDRESET_ESP 7 uint32_t currMillis, startTimeOut, timeDelayEspMs, timeOutMs; enum {RESET_START, RESET_END, POWER_ON,//команда, ответ AT_TEST, AT_TEST_REPLY, // AT, OK AT_CWMODE, AT_CWMODE_REPLY, //AT+CWMODE=1, OK CONNECT_TO_WIFI, CONNECT_TO_WIFI_REPLY,//"AT+CWJAP=\"Redmi Note 9\",\"123456789\" , OK STOP_ESP }; byte automataStatesEsp = POWER_ON; void setup() { Serial1.begin(115200); DEBUG_BEGIN(115200); digitalWrite(PIN_HARDRESET_ESP, HIGH); } void loop() { currMillis = millis(); runAutomataEsp(); } ////////////////////////////////////////////////////////// void runAutomataEsp() { switch (automataStatesEsp) { case RESET_START: // digitalWrite(PIN_HARDRESET_ESP, LOW); pinMode(PIN_HARDRESET_ESP, OUTPUT); setTimeOutForNextStep(200, RESET_END); DEBUG_PRINTLN(F("RESET_START")); break; case RESET_END: if (isTimeOutElapsed()) { pinMode(PIN_HARDRESET_ESP, INPUT); digitalWrite(PIN_HARDRESET_ESP, HIGH); automataStatesEsp = POWER_ON; DEBUG_PRINTLN(F("RESET_END")); } break; case POWER_ON: //после подачи питания ждем 5 сек и отправляем команду "АТ" setTimeOutForNextStep(5000, AT_TEST); DEBUG_PRINTLN(F("POWER_ON")); break; case AT_TEST: if(isTimeOutElapsed()) { clearInputBuff(); Serial1.println(F("AT")); //После команды "АТ" устанавливаем таймаут=1 сек и переходим на след.шаг setTimeOutForNextStep(1000, AT_TEST_REPLY); DEBUG_PRINTLN(F("AT_TEST")); } break; case AT_TEST_REPLY: if(isTimeOutElapsed()){//если ESP не отвечает, то перезагружаем automataStatesEsp = RESET_START; //без задержки на следующий шаг } else if (Serial1.available() > 0 && isMarker("OK")){ setTimeOutForNextStep(200, AT_CWMODE); DEBUG_PRINTLN(F("AT_TEST_REPLY")); } break; case AT_CWMODE: if (isTimeOutElapsed()) { clearInputBuff(); Serial1.println(F("AT+CWMODE=1")); setTimeOutForNextStep(500, AT_CWMODE_REPLY); DEBUG_PRINTLN(F("AT_CWMODE=1")); } break; case AT_CWMODE_REPLY: if(isTimeOutElapsed()) setTimeOutForNextStep(200, AT_TEST); else if(Serial1.available() > 0 && isMarker("OK")) { setTimeOutForNextStep(300, CONNECT_TO_WIFI); DEBUG_PRINTLN(F("AT_CWMODE_REPLY_OK")); } break; case CONNECT_TO_WIFI: if (isTimeOutElapsed()) { clearInputBuff(); Serial1.println(F("AT+CWJAP=\"Redmi Note 9\",\"don198753\"")); setTimeOutForNextStep(15000, CONNECT_TO_WIFI_REPLY); DEBUG_PRINTLN(F("AT+CWJAP=\"Redmi Note 9\",\"don198753\"")); } break; case CONNECT_TO_WIFI_REPLY: if(isTimeOutElapsed()) setTimeOutForNextStep(100, AT_TEST); else if (Serial1.available() > 0 && isMarker("OK")) { automataStatesEsp = STOP_ESP; DEBUG_PRINTLN(F("CONNECT_TO_WIFI_OK")); } break; default: automataStatesEsp = STOP_ESP; } } // Очищаем приемный буфер. (для данного примера буфер можно не чистить) void clearInputBuff(){ while (Serial.available() > 0) { Serial.read(); } } //================== byte isMarker (const char * marker){ static byte index = 0; byte len = 0; len = strlen(marker); while(Serial1.available()){ byte c = Serial1.read (); if(index < len){ if(c == marker[index]) index++; else{ //не маркер index = 0; if(c == marker[index]) index++; //возможно снова начало маркера } } if(index == len){ index = 0; return 1; } } return 0; } //=========================== void setTimeOutForNextStep(word ms, byte nextStep){ setTimeOut(ms); automataStatesEsp = nextStep; } //====================== inline void setTimeOut(uint32_t ms) { startTimeOut = millis(); timeOutMs = ms; } //================== inline void stopTimeOut() { timeOutMs = 0xFFFFFFFF; } //================== таймер для таимаута bool isTimeOutElapsed() { if (currMillis - startTimeOut > timeOutMs) { stopTimeOut(); return 1; } return 0; }Спасибо!