本文介绍了AT 命令响应(理解 Arduino 上代码执行的顺序)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从 ESP8266 发送 AT 命令://arduino.cc/en/Main/ArduinoBoardUno" rel="nofollow noreferrer">Arduino Uno/Nano (ATmega328) 并尝试解析收到的字符串的结尾以建立 ESP 的反应和它是否成功(以及它是否准备好接收另一个命令).我知道这里之前已经讨论了解析 AT 命令响应:

I'm sending AT commands to an ESP8266 from an Arduino Uno/Nano (ATmega328) and attempting to parse the end of the strings received in response to establish how the ESP reacted and whether it was successful (and whether it's ready to receive another command yet). I'm aware that parsing AT command responses has been discussed before here:

获取 AT 命令响应

但我有一个特定问题没有在那里涵盖,这里的其他人可能也感兴趣......

But I have a specific issue not covered there that might also be of interest to other people on here...

首先,调用一个函数将 AT 命令发送到 ESP 以连接到 ThingSpeak(数据记录服务器).这在手动模式下工作正常,并且在尝试解析响应时也会连接,它只解析返回的第一行.例如,串行监视器中的预期输出为:

First, a function is called which sends the AT command to the ESP to connect to ThingSpeak (datalogging server). This works fine in manual mode and also connects when trying to parse the response, but it only parses the first line that comes back. For example, the expected output in the serial monitor would be:

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

OK
Connected to ThingSpeak!

其中 c 只是我输入的用于启动连接的命令字符.

Where c is just the command character I type to initiate the connection.

然而,实际响应如下:

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


CONNECT

OK

这意味着解析函数在收到响应之前就结束了……如下代码所示,当前指定了 10 秒超时.即使有 20 秒的超时,同样的事情也会发生,尽管手动执行时,响应会在大约一秒内到达.

This means that the parsing function is ending before it receives the response... As shown in the code below, there is a 10 second timeout currently specified. Even with a 20 second timeout, the same thing happens, despite the fact that when executed manually, the response arrives in around one second.

只是为了测试解析函数,我尝试搜索 "80" 并且它返回 true,因为它位于响应的第一行的末尾.无论搜索 "OK" 还是 "OK\r\n" 结果都是一样的,它返回 false,然后接收其余的响应.

Just to test the parsing function, I tried searching for "80" and it returned true as this is found at the end of the first line of the response. Whether it searches for "OK" or "OK\r\n" the result is the same, it returns false and THEN the rest of the response is received.

代码如下:

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() 函数有关?

Why does it return before the full response is received (well within the timeout period)? Is it something to do with the endsWith() function?

因此,您对如何让它解析整个响应而不是仅仅解析第一行有什么想法吗?

Consequently, do you have any ideas of how to make it parse the entire response instead of just the first line?

重申一下,我只对响应的结尾感兴趣(例如 OK"OK\r\n").

To reiterate, I am only interested in the end of the response (e.g. "OK" or "OK\r\n").

推荐答案

是的,您的主要问题如下

Yes, your main problem is the following

if (ESP.available())

这使得 waitForResponse 函数在 UART(或其他一些串行 IO 缓冲区)为空时返回 - 这不是您想要的.您想要的是从串行端口读取,直到您收到一条以 "\r\n" 结尾的行.

This makes the waitForResponse function return whenever the UART (or some other serial IO buffer) is empty - which is not what you want. What you want is to read from the serial port until you have received a line terminated with "\r\n".

是否与endsWith()函数有关?

是的,这是一个与 ESP.available 结合的附加问题,因为您试图将来自调制解调器的响应行的末尾与串行路径中发生的随机数据截断相匹配.如果您非常幸运,这将是在线边界,但很可能不是,您不应该依赖它.

Yes, that is an additional problem combined with ESP.available because you are attempting to match the end of a response line from the modem with what ever random data chopping occurs in the serial path. If you are extremely lucky this will be on line boundaries, but most likely not and you should not rely on that.

这是一个称为成帧的通用协议问题,适用于任何类型异步串行通信.对于调制解调器通信,帧字符是 \r\n.

This is a general protocol problem known as framing that applies to any kind of asynchronous serial communication. For modem communications the framing characters are \r and \n.

帮自己一个忙,实现一个readline函数,一个一个字符读取,直到前一个字符是\r,当前字符是\n 然后返回它到目前为止读取的所有内容.

Do yourself a favour and implement a readline function that reads one by one character until it the previous character was \r and the current character is \n and then return everything it read so far.

然后专门使用该函数 来读取调制解调器响应数据.这适用于中间结果代码(如CONNECT)以及最终结果代码(例如OK 等).解析"响应行就可以像

Then use that function exclusively for reading modem response data. This applies both to Intermediate result codes like CONNECT as well as Final result codes (e.g. OK etc)."Parsing" the response lines can then be as simple as

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

if (isFinalResultCode(responseLine)) ...

正如我在之前所说的,处理调制解调器输出的唯一正确方法是将输出分成完整的行并一次迭代一整行.

唯一的例外是解析 AT+CMGS 响应数据时.

The only exception is when parsing AT+CMGS response data.

这篇关于AT 命令响应(理解 Arduino 上代码执行的顺序)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 12:38