2016-07-14 66 views
1

我正在一個項目中使用arduino uno和ESP8266ex作爲wifi模塊。電線連接:Arduino ESP8266 Softwareserial HTTP獲取請求沒有足夠的緩衝區大小

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閱讀:在我的第一個程序我的手發出的命令()函數並將它們全部打印到串行監視器。總之,這個代碼能夠處理這是一個服務器的600 +炭響應:

enter image description here

目的是發送這些AT經由「SoftwareSerial.print()」命令,並把在字符整個響應數組來解析它的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: 

} 

它在「setup()」作用域的末尾打印響應。讓我也把輸出的照片:

enter image description here

總之,問題是:SoftwareSerial具有64字節的緩衝區,可提高到256個字節,當我增加它的程序能夠打印然而,這次是256個字符,然而,在我的第一個手動發送AT命令的代碼中,它可以處理整個響應,儘管它具有64字節的緩衝區,並且可以將它打印到串行監視器。在第二個我無法處理和存儲整個響應到一個字符數組。

我希望我能解釋我的問題,並指出我在我的過程中的具體細節。

你建議我做什麼。在處理這個大響應並將其放入字符數組中時,我能做些什麼?我該如何處理整個響應,它始終保留在ESP8266ex'緩衝區中,並且通過SoftwareSerial類讀取Arduino RX引腳,其中函數read()具有64字節數組,並且可以增加到256但不再增加?

回答

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主體,然後放棄其他所有內容,這意味着查找數據的緩衝區很小,實際存儲主體的緩衝區可能更大。

+0

謝謝你的好解釋 – 4JaoDeka