ESP8266 在简单的 http 请求后崩溃

问题描述 投票:0回答:2

我正在使用 NodeMCU V3 模块。每当我尝试向服务器发出 http 请求时,模块就会崩溃。

这是代码:

void setup() {
    WiFi.begin("wifi-name", "wifi-password");  

    while (WiFi.status() != WL_CONNECTED) {  //Wait for the WiFI to connect }
}
void loop() {
   HTTPClient http; 
   WiFiClient client;

   http.begin( client, "server-address" );  

   int httpCode = http.GET();  
   String payload = http.getString();  //Get the response payload

   Serial.println(httpCode);   //Print HTTP return code
   Serial.println(payload);    //Print request response payload

   http.end();  //Close connection

   delay( 1000 );
}

这是结果,如串行监视器中所示:

200
["JSON response from the server"]

Exception (28):
epc1=0x40212e82 epc2=0x00000000 epc3=0x00000000 excvaddr=0x000001b6 depc=0x00000000

>>>stack>>>

ctx: cont
sp: 3ffffc90 end: 3fffffc0 offset: 01a0
3ffffe30:  00000000 4bc6a7f0 0000333f 3ffee5f8  
3ffffe40:  00000000 00000000 4bc6a7f0 00000000  
[...] 
3fffffb0:  feefeffe feefeffe 3ffe84e8 40100c41  
<<<stack<<<

奇怪的是,它正确地从服务器检索到响应,但大约一秒钟后,它向串行监视器吐出异常并重置。起初我以为这可能是因为我同时运行 ESP8266WebServer,但即使我运行我在互联网上找到的最基本的示例,它仍然崩溃。我尝试在 Arduino IDE 而不是 PlatformIO 上编译相同的代码,甚至使用不同的 NodeMCU,但无济于事。

编辑:再玩一会儿后,似乎将延迟设置为至少 10 秒会使 NodeMCU 在 3 个请求后崩溃,而不是在第一个请求后崩溃。难道是几次请求之后内存就溢出了?我是否遗漏了让 ESP8266 为新请求做好准备的关键部分?

esp8266 nodemcu arduino-c++
2个回答
14
投票

无需在

loop()
中一遍又一遍地重新创建 WiFi 和 HTTP 客户端。您可以在全局范围内声明一次它们。这是这个简单草图的稳定版本:

#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESPHTTPClient.h>

HTTPClient http; 
WiFiClient client;

void setup() {
  Serial.begin(115200);
  Serial.println();
  WiFi.begin("****", "****");  

  Serial.print("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("done.");
}

void loop() {
  http.begin(client, "http://httpbin.org/get"); // <1KB payload
//  http.begin(client, "http://www.geekstips.com/esp8266-arduino-tutorial-iot-code-example/"); // 30KB payload

  int httpCode = http.GET();  
  String payload = http.getString();  //Get the response payload

  Serial.println(httpCode);   //Print HTTP return code
  Serial.println(payload);    //Print request response payload

  http.end();  //Close connection

  Serial.printf("Free heap: %d\n", ESP.getFreeHeap());
  delay(1000);
}

随着时间的推移,报告的空闲堆非常稳定。 请记下我在注释行中添加的用于测试的第二个 URL。

http.getString()
很方便,对于小型资源效果很好,但会产生意想不到的结果,即对于较大资源会产生错误的结果 - 您只能看到打印到控制台的一小部分正文。

对于较大的有效负载,您应该直接使用低级 WiFiClient 并逐行或逐字符读取/解析响应。请参阅 https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/client-examples.html 上的文档获取模板。

void loop()
{
  WiFiClient client;

  Serial.printf("\n[Connecting to %s ... ", host);
  if (client.connect(host, 80))
  {
    Serial.println("connected]");

    Serial.println("[Sending a request]");
    client.print(String("GET /") + " HTTP/1.1\r\n" +
                 "Host: " + host + "\r\n" +
                 "Connection: close\r\n" +
                 "\r\n"
                );

    Serial.println("[Response:]");
    while (client.connected() || client.available())
    {
      if (client.available())
      {
        String line = client.readStringUntil('\n');
        Serial.println(line);
      }
    }
    client.stop();
    Serial.println("\n[Disconnected]");
  }
  else
  {
    Serial.println("connection failed!]");
    client.stop();
  }
  delay(5000);
}

0
投票

就我而言,定义客户的顺序很重要。 当

HTTPClient
客户端在
WiFiClient
之前定义时,我遇到了同样的问题。

更改订单后,一切开始正常工作。

WiFiClient wifi_client;  // 1st (before HTTPClient)
HTTPClient http_client;  // 2nd

(...)
© www.soinside.com 2019 - 2024. All rights reserved.