我正在开发一个项目,我在其中使用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多个字符响应:
目的是通过&#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;结束之前打印响应。范围。我还要把输出的照片放在一边:
总之,问题是:SoftwareSerial有64字节缓冲区,可以增加到256字节,当我增加它时,程序能够打印256个字符,但是,在我的第一个代码中,我发送了AT命令手动,它可以处理整个响应,尽管它的64字节缓冲区,并能够将其打印到串行监视器。在第二个中,我无法处理并将整个响应存储到char数组中。
我希望我能解释一下我的问题并指出我在我的过程中的具体细节。
你建议我做什么。处理这个大响应并将其放入字符数组时,我该怎么办?我怎样才能处理ESP8266ex上的整体响应&#39;缓冲区最初由Arduino RX引脚通过SoftwareSerial类读取,其中函数read()具有64字节数组,可以增加到256但不能再增加?
答案 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主体,并丢弃其他所有东西,这意味着找到数据的缓冲区很小,实际存储主体的缓冲区可能要大得多。