Arduino ESP8266 Softwareserial没有足够的缓冲区大小来获取HTTP请求

时间:2016-07-14 10:39:37

标签: c arduino esp8266

我正在开发一个项目,我在其中使用arduino uno和ESP8266ex作为wifi模块。电线的连接:

Arduino 5V - > 3.3V稳压器 - > ESP:CH_PD(带有10k电阻)和VCC Arduino GND - > 3.3V稳压器 - > ESP:GND和RST(复位通过按钮和电阻连接)Arduino RX - > ESP TX Arduino TX - >分压器(2k 1k电阻器) - > ESP RX 5uF电容器 - >电压调节器可防止ESP自行复位。

现在让我解释一下我遇到的问题。我有两个代码,我使用ESP8266作为arduino uno的wifi模块。在我的第一个程序中,我手动发送命令:

#define ard_rx_esp_tx 2
#define ard_tx_esp_rx 3

#include <SoftwareSerial.h>

SoftwareSerial ESPserial(ard_rx_esp_tx, ard_tx_esp_rx); // RX | TX

void setup()
{
  int i = 0;
  Serial.begin(9600);     // communication with the host computer
  while (!Serial);

  // Start the software serial for communication with the ESP8266
  ESPserial.begin(9600);
  Serial.println("");
  Serial.println(F("Remember to to set Both NL & CR in the serial monitor."));
  Serial.println(F("Ready"));
  Serial.println(F(""));
  Serial.println(F("start"));
  delay(1000);
}
void loop()
{

  if ( ESPserial.available() )   {
    char c = ESPserial.read();
    Serial.print(c);
  }

  if ( Serial.available() )    {
    ESPserial.write( Serial.read() );
  }
}

我成功打开了与服务器的TCP连接,发送了一个长(超过600个字符)的GET请求,并通过SoftwareSerial read()函数处理所有长响应,并将它们全部打印到串行监视器。简而言之,此代码可以处理服务器的600多个字符响应:

enter image description here

目的是通过&#34; SoftwareSerial.print()&#34;发送这些AT命令。并将整个响应放在一个字符数组中来解析其API-KEY。到目前为止我为此编写的代码:

#define ard_rx_esp_tx 2
#define ard_tx_esp_rx 3
char response[625];
#include <SoftwareSerial.h>
SoftwareSerial ESPserial(ard_rx_esp_tx, ard_tx_esp_rx); // RX | TX
int i;

void setup() 
{

    Serial.begin(9600);     // communication with the host computer
    while (!Serial);

    // Start the software serial for communication with the ESP8266
    ESPserial.begin(9600);  

    Serial.println("");
    Serial.println(F("Remember to to set Both NL & CR in the serial monitor."));
    Serial.println(F("Ready"));
    Serial.println(F(""));
    Serial.println(F("start"));
    delay(1000);

    ESPserial.println("AT+CIPSTART=\"TCP\",\"domainname\",80");
    delay(5000);

    i = 0;
    while ( ESPserial.available() ) {
      response[i] = ESPserial.read();
      i++;
    }
    response[i++] = '\0';
    Serial.println(response);
    for (i = 0; i < 625; i++) {
      response[i] = '\0';
    }

    ESPserial.println("AT+CIPSEND=107");
    delay(5000);

    i = 0;
    while ( ESPserial.available() ) {
      response[i] = ESPserial.read();
      i++;
    }
    response[i++] = '\0';
    Serial.println(response);
    for (i = 0; i < 625; i++) {
      response[i] = '\0';
    }

    ESPserial.println("GET request to the server which has length 107 as indicated");
    delay(5000);

    i = 0;
    while ( ESPserial.available() ) {
      response[i] = ESPserial.read();
      i++;
    }
    response[i++] = '\0';
    Serial.println(response);
    for (i = 0; i < 625; i++) {
      response[i] = '\0';
    }
}
void loop() {
  // put your main code here, to run repeatedly:

}

在&#34; setup()&#34;结束之前打印响应。范围。我还要把输出的照片放在一边:

enter image description here

总之,问题是:SoftwareSerial有64字节缓冲区,可以增加到256字节,当我增加它时,程序能够打印256个字符,但是,在我的第一个代码中,我发送了AT命令手动,它可以处理整个响应,尽管它的64字节缓冲区,并能够将其打印到串行监视器。在第二个中,我无法处理并将整个响应存储到char数组中。

我希望我能解释一下我的问题并指出我在我的过程中的具体细节。

你建议我做什么。处理这个大响应并将其放入字符数组时,我该怎么办?我怎样才能处理ESP8266ex上的整体响应&#39;缓冲区最初由Arduino RX引脚通过SoftwareSerial类读取,其中函数read()具有64字节数组,可以增加到256但不能再增加?

1 个答案:

答案 0 :(得分:4)

所以,问题在于时间问题。您知道软件序列的缓冲区大小有限制(对于任何硬件UART也是如此),这是256字节,波特率为9600位/秒。

由于有一个起始位,8个数据位和一个停止位(假设你在这里使用9600 8N1,因为它是最常见的),你将每隔(1/9600)* 10秒接收一个数据字节,或1.04毫秒。因此,要接收256个字节,它应该需要大约266毫秒。这意味着在266毫秒之后,您的缓冲区将完全填满,之后您收到的任何内容都将开始删除以前接收的数据。

问题的关键在于 - 您正在向ESP发送命令以从服务器接收数据,然后进入休眠状态5秒,这意味着什么都没有从缓冲区中提取数据,因此它包裹起来,导致数据丢失。串行缓冲区的要点不是保存您将在单个点接收的整个数据集,而是保持它足够长,直到您可以读出它,这就是为什么它们通常非常小。

您需要做的是发送命令,让您的Arduino立即运行代码,以便尽可能快地从缓冲区中检索数据,直到找到预期的结束或超时。

像这样基本的东西会让你前进:

char espBuffer[1024] = {0};
int readCount = 0;
long startTime = millis();

ESPserial.println("AT+CIPSTART=\"TCP\",\"domainname\",80");

while (millis() - startTime < 5000) { // Run for at least 5 seconds 
  // Check to make sure we don't exceed espBuffer's boundaries
  if (ESPserial.available() > readCount + sizeof espBuffer - 1) 
    break;
  readCount += ESPserial.readBytes(espBuffer + readCount, ESPserial.available());
}

Serial.println(espBuffer);

现在,您希望修改此代码,以便在收到所需的所有数据时结束。此外,这个简单的设置限制了响应的最大大小1023字节,这也没有太大帮助。理想情况下,你会继续阅读,直到找到HTTP主体,并丢弃其他所有东西,这意味着找到数据的缓冲区很小,实际存储主体的缓冲区可能要大得多。