Ответы AT команды (понимание порядка выполнения кода на Arduino)

Я посылаю AT-команды на ESP8266 из Arduino Uno/Nano (ATmega328) и пытаюсь проанализировать конец полученных строк в ответ, чтобы определить, как ESP отреагировал и был ли он успешным (и готов ли он к получению другой команды). еще). Мне известно, что разбор ответов AT-команд уже обсуждался здесь: Получить AT-ответ команд

Но у меня есть конкретная проблема, которая там не освещена, и которая может быть интересна другим людям здесь...

Сначала вызывается функция, которая отправляет AT-команду в ESP для подключения к ThingSpeak (серверу регистрации данных). Это работает нормально в ручном режиме, а также подключается при попытке разобрать ответ, но он анализирует только первую строку, которая возвращается. Например, ожидаемый вывод в последовательном мониторе будет:

c
AT+CIPSTART="TCP","api.thingspeak.com",80
CONNECT

OK
Connected to ThingSpeak!

куда c это просто командный символ, который я печатаю, чтобы инициировать соединение.

Фактический ответ, однако, заключается в следующем:

c
AT+CIPSTART="TCP","api.thingspeak.com",80
Cannot connect to ThingSpeak!


CONNECT

OK

Это означает, что функция синтаксического анализа завершается до того, как она получает ответ... Как показано в приведенном ниже коде, в настоящее время указан 10-секундный тайм-аут. Даже с 20-секундным таймаутом происходит то же самое, несмотря на тот факт, что при выполнении вручную ответ приходит примерно за одну секунду.

Просто чтобы проверить функцию разбора, я попытался найти "80" и он вернул истину, так как он находится в конце первой строки ответа. Ищет ли он "OK" или же "OK\r\n" результат тот же, он возвращает ложь, а затем остальная часть ответа получена.

Вот код:

boolean waitForResponse(String target, unsigned long timeout)
{
  unsigned long startTime = millis();
  String responseBuffer;
  char charIn;

  //keep checking for ESP response until timeout expires
  while ((millis() - startTime) < timeout)
  {
    if (ESP.available())
    {
      responseBuffer += ESP.read();
    }
  }
  Serial.println(responseBuffer);
  if (responseBuffer.endsWith(target))
  {
    return true;
  } else {
    return false;
  }
}

void openCxn()
{
  ESP.print("AT+CIPSTART=\"TCP\",\"api.thingspeak.com\",80");
  delay(500);
  if (waitForResponse("80",10000L))
  {
    Serial.println("Connected to ThingSpeak!");
  } else {
    Serial.println("Cannot connect to ThingSpeak!");
  }
}

Любая идея, почему он возвращается до получения полного ответа (в течение периода ожидания)? Это как-то связано с endsWith() функционировать?

Следовательно, у вас есть какие-либо идеи о том, как заставить его анализировать весь ответ, а не только первую строку?

Повторюсь, меня интересует только конец ответа (например, "OK" или же "OK\r\n").

2 ответа

Решение

Любая идея, почему он возвращается до получения полного ответа (в течение периода ожидания)?

Да, ваша главная проблема заключается в следующем

if (ESP.available())

Это заставляет функцию waitForResponse возвращаться всякий раз, когда UART (или какой-либо другой буфер последовательного ввода-вывода) пуст - это не то, что вам нужно. То, что вы хотите, это читать с последовательного порта, пока вы не получили строку, оканчивающуюся на "\r\n",

Это как-то связано с функцией endWith()?

Да, это дополнительная проблема в сочетании с ESP.available потому что вы пытаетесь сопоставить конец строки ответа от модема с тем, что происходит случайное прерывание данных в последовательном пути. Если вам очень повезло, это будет на линии границ, но, скорее всего, нет, и вы не должны полагаться на это.

Это общая проблема протокола, известная как кадрирование, которая применяется к любому виду асинхронной последовательной связи. Для модемной связи обрамляющие символы \r а также \n,

Сделайте себе одолжение и осуществите readline функция, которая читает один за другим символ, пока предыдущий символ не был \r и текущий символ \n и затем верните все, что прочитано до сих пор.

Затем используйте эту функцию исключительно 1 для чтения данных ответа модема. Это относится как к промежуточным кодам результатов, таким как CONNECT а также коды конечного результата (например, OK так далее). "Разбор" строк ответа может быть таким простым, как

if (responseLine.equals("CONNECT\r\n")) ...

или же

if (isFinalResultCode(responseLine)) ...

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


1 Единственное исключение - при анализе данных ответа AT+CMGS.

Ваше if через некоторое время действительно неверно, потому что вы, возможно, прочитали больше материала назад, и, таким образом, вы не заканчиваете целевую строку, даже если все в порядке.

Вы должны просто проверить, заканчивается ли responseBuffer на target и вернуть true только тогда, когда вы получите новый Char в цикле while, а не после. После истечения времени ожидания просто верните false.

Другие вопросы по тегам