从 OpenWeatherMap 获取数据时,ESP8266 在正常运行一段时间后重置 [英] ESP8266 resets after some time of normal running while getting data from OpenWeatherMap

查看:29
本文介绍了从 OpenWeatherMap 获取数据时,ESP8266 在正常运行一段时间后重置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,如果有什么没有很好的解释,请见谅;这是我第一次在 Stack Overflow 上寻求帮助.我有一个 ESP8266 连接到 DHT11 温度/湿度传感器和一个 ILI9341 TFT-LCD 屏幕,以显示我从 NTP 服务器和 OpenWeatherMap 收到的数据.我注意到在正常运行一段时间后它只是由于我认为内存不足(由 OpenWeatherMap 引起)而重置.我尝试检查它在重置时给出的错误,它与 ESP8266 的恐慌"模式有关,尽管我从未设法获得它吐出的内容的副本.

First of all, sorry if anything isn't well explained; this is my first time asking for help on Stack Overflow. I have an ESP8266 connected to a DHT11 temp/humidity sensor and an ILI9341 TFT-LCD screen to display the data I receive from the NTP server and OpenWeatherMap. I noticed that after a while of normal running it just resets due to what I believe is a shortage of memory (caused by OpenWeatherMap). I tried inspecting the error it gives when it resets and it has something to do with a "Panic" mode of the ESP8266's, although I never managed to get a copy of what it spits out.

我问这个问题是因为我打算添加一个天气预报部分,但是当我尝试添加获取预测数据所需的代码片段时,它每次打开时都会立即崩溃.

I'm asking this question because I'm planning to add a weather forecast section, but when I tried to add the piece of code needed to get the forecast data, it just crashed right off the bat everytime it turned on.

这里是供您检查的代码,以防 Json 部分出现任何问题,我认为这是造成此问题的罪魁祸首,因为我是使用 ArduinoJson 库的新手,尽管我对此有所了解

Down here is the code for you to inspect, in case anything is wrong with the Json part, which I believe is the culprit for this, as I'm new to working with the ArduinoJson library, although I got my head around it.

#include <DHT.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ILI9341esp.h>
#include <ESP8266WiFi.h>
#include <time.h>
#include <Adafruit_GFX.h>
#include <ArduinoJson.h>

#define TFT_MISO D6
//#define TFT_LED 3.3V (change to IO pin if you want the screen to be toggled on/off)
#define TFT_SCK D5
#define TFT_MOSI D7
#define TFT_DC D2
#define TFT_RESET D3
#define TFT_CS D8
#define DHTPIN D1
#define DHTTYPE DHT11
#define WIFI_SSID "MY_SSID"
#define WIFI_PASS "MY_PASS"
#define TX_LED D0

WiFiClient client;
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
DHT dht(DHTPIN, DHTTYPE);

int wifitries = 0;
int timezone = 2 * 3600; //when time changes change this from 2 to 1
int dst = 0;
float t = 0.0;
float h = 0.0;
const long interval = 15000;
int elapsed_t = 0;
String APIKEY = "someapikey";
String CityID = "somecityid";
char servername[] = "api.openweathermap.org";
String result;
String weatherDescription = "";
String weatherDesc;
String weatherID;
int Temperature;
int Humidity;
char* tem = "  ";
char* hum = "  ";
char* temp = "  ";
char* humi = "  ";

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(TX_LED, OUTPUT);
  digitalWrite(TX_LED, HIGH);
  digitalWrite(LED_BUILTIN, HIGH);

  Serial.begin(115200);
  tft.begin();
  configTime(timezone, dst, "pool.ntp.org", "it.pool.ntp.org");
  dht.begin();

  WiFi.disconnect();
  delay (3000);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  Serial.println();
  Serial.println ("Connecting to TP-LINK_DD1E61");

  tft.setRotation(3);
  tft.fillScreen(ILI9341_BLACK);
  tft.setTextSize(2);
  tft.println("Connecting to ");
  tft.println("TP-LINK_DD1E61");
  while ((!(WiFi.status() == WL_CONNECTED))) {
    Serial.print(".");
    wifitries++;
    tft.setTextSize(1);
    tft.print(".");
    delay(300);
  }
  if (wifitries = 15) {
    wifitries = 0;
    WiFi.disconnect();
    delay (3000);
    WiFi.begin(WIFI_SSID, WIFI_PASS);
    while ((!(WiFi.status() == WL_CONNECTED))) {
      Serial.print(".");
      wifitries++;
      tft.setTextSize(1);
      tft.print(".");
      delay(300);
    }
  }
  if (WiFi.status() == WL_CONNECTED) {
    tft.setTextSize(2);
    tft.println();
    tft.println("Connected to ");
    tft.println("TP-LINK_DD1E61");
    delay(500);
    tft.fillScreen(ILI9341_BLACK);
  }

  while (!time(nullptr)) {
    Serial.print("*");
    delay(300);
  }

  tft.drawLine(0, 18, 320, 18, ILI9341_WHITE);
  tft.setTextSize(2);
  tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK);
  tft.setCursor(0, 135);
  tft.print("TEMPO");
  tft.setCursor(20, 25);
  tft.println("TEMPERATURA");
  tft.println();
  tft.println();
  tft.setCursor(215, 25);
  tft.println("UMIDITA'");
  tft.setTextSize(1);
  tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);
  tft.setCursor(0, 52);
  tft.print("INTERNO");
  tft.setCursor(0, 87);
  tft.print("ESTERNO");

  delay(1000);
  DHT_read();
  getWeatherData();
  displayConditions(Temperature, Humidity, weatherDescription);
}

void DHT_read() {
  float newT = dht.readTemperature();
  if (isnan(newT)) {
    Serial.println("Failed to read from DHT sensor!");
    tft.setTextSize(2);
    tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
    tft.setCursor(109, 43);
    tft.print("!");
  }
  else {
    int t = newT;

    if (t >= 10) {
      char* temp = "  ";
      sprintf(temp, "%02d", t);
    }
    else {
      char* temp = "  ";
      sprintf(temp, "%01d", t);
      tft.setTextColor(ILI9341_BLACK);
      tft.setTextSize(2);
      tft.setCursor(79, 43);
      tft.print("0");
    }

    Serial.print("Temperature: ");
    Serial.print(temp);
    Serial.println();
    tft.setTextSize(2);
    tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
    tft.setCursor(67, 43);
    tft.print(temp);
    tft.setCursor(92, 40);
    tft.setTextSize(1);
    tft.print("o");
    tft.setCursor(99, 43);
    tft.setTextSize(2);
    tft.print("C");
    tft.setTextColor(ILI9341_BLACK);
    tft.setCursor(109, 43);
    tft.print("!");
  }
  float newH = dht.readHumidity();
  if (isnan(newH)) {
    Serial.println("Failed to read from DHT sensor!");
    tft.setTextSize(2);
    tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
    tft.setCursor(287, 43);
    tft.print("!");
  }
  else {
    int h = newH;

    if (h >= 10 && h <= 99) {
      char* humi = "  ";
      sprintf(humi, "%02d", h);
      tft.setTextColor(ILI9341_BLACK);
      tft.setTextSize(2);
      tft.setCursor(261, 43);
      tft.print("0");
    }
    else if (h = 100) {
      char* humi = "  ";
      sprintf(humi, "%03d", h);
    }
    else {
      char* humi = "  ";
      sprintf(humi, "%01d", h);
      tft.setTextColor(ILI9341_BLACK);
      tft.setTextSize(2);
      tft.setCursor(261, 43);
      tft.print("0");
    }

    Serial.print("Humidity: ");
    Serial.print(humi);
    Serial.println();
    tft.setTextSize(2);
    tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
    tft.setCursor(237, 43);
    tft.print(humi);
    tft.setCursor(277, 43);
    tft.print("%");
    tft.setTextColor(ILI9341_BLACK);
    tft.setCursor(287, 43);
    tft.print("!");
  }
}

void screen() {
  time_t now = time(nullptr);
  struct tm* p_tm = localtime(&now);

  char* day = "  ";
  sprintf(day, "%02d", p_tm->tm_mday);

  tft.setCursor(192, 0);
  tft.setTextSize(2);
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
  tft.print(day);

  tft.setCursor(217, 0);
  tft.print("/");

  char* month = "  ";
  sprintf(month, "%02d", p_tm->tm_mon + 1);

  tft.setCursor(231, 0);
  tft.setTextSize(2);
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
  tft.print(month);

  tft.setCursor(256, 0);
  tft.print("/");

  char* year = "    ";
  sprintf(year, "%04d", p_tm->tm_year + 1900);

  tft.setCursor(268, 0);
  tft.setTextSize(2);
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
  tft.print(year);

  char* hour = "  ";
  sprintf(hour, "%02d", p_tm->tm_hour);

  tft.setCursor(0, 0);
  tft.setTextSize(2);
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
  tft.print(hour);

  tft.setCursor(22, 0);
  tft.print(":");

  char* minute = "  ";
  sprintf(minute, "%02d", p_tm->tm_min);

  tft.setCursor(34, 0);
  tft.setTextSize(2);
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
  tft.print(hour);



}

void getWeatherData() {
  if (client.connect(servername, 80))
  { //starts client connection, checks for connection
    client.println("GET /data/2.5/weather?id=" + CityID + "&units=metric&APPID=" + APIKEY + "&lang=it");
    client.println("Host: api.openweathermap.org");
    client.println("User-Agent: ArduinoWiFi/1.1");
    client.println("Connection: close");
    client.println();
  }
  else {
    Serial.println("connection failed");        //error message if no client connect
    Serial.println();
    tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
    tft.setCursor(0, 220);
    tft.print("CONNESSIONE FALLITA");
  }

  while (client.connected() && !client.available())
    delay(1);                                          //waits for data
  while (client.connected() || client.available())
  { //connected or data available
    char c = client.read();                     //gets byte from ethernet buffer
    result = result + c;
  }

  client.stop();                                      //stop client
  result.replace('[', ' ');
  result.replace(']', ' ');
  Serial.print(result);
  Serial.println();
  char jsonArray [result.length() + 1];
  result.toCharArray(jsonArray, sizeof(jsonArray));
  jsonArray[result.length() + 1] = '\0';
  DynamicJsonBuffer json_buf(3584); //was 4096
  JsonObject &root = json_buf.parseObject(jsonArray); //

  if (!root.success())
  {
    Serial.println("parseObject() failed");
    tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
    tft.setCursor(109, 78);
    tft.print("!");
    tft.setCursor(287, 78);
    tft.print("!");

  }
  else {
    tft.setTextColor(ILI9341_BLACK);
    tft.setCursor(109, 78);
    tft.print("!");
    tft.setCursor(287, 78);
    tft.print("!");
  }

  float temperature = root["main"]["temp"];
  float humidity = root["main"]["humidity"];
  String weather = root["weather"]["main"];
  String description = root["weather"]["description"];
  String id = root["weather"]["id"];
  weatherDescription = description;
  Temperature = temperature;
  Humidity = humidity;
  weatherID = id;

  result = "";  //to clean memory and keep it from running out of space
}

void displayConditions(int Temperature, int Humidity, String weatherDescription) {
  tft.setTextSize(2);
  tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);

  if (Temperature >= 10) {
    char* tem = "  ";
    sprintf(tem, "%02d", Temperature);
  }
  else {
    char* tem = "  ";
    sprintf(tem, "%01d", Temperature);
    tft.setTextColor(ILI9341_BLACK);
    tft.setTextSize(2);
    tft.setCursor(79, 78);
    tft.print("0");
  }

  tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
  tft.setCursor(67, 78);
  tft.print(tem);
  tft.setCursor(92, 75);
  tft.setTextSize(1);
  tft.print("o");
  tft.setCursor(99, 78);
  tft.setTextSize(2);
  tft.print("C");

  if (Humidity >= 10 && Humidity <= 99) {
    char* hum = "  ";
    sprintf(hum, "%02d", Humidity);
    tft.setTextColor(ILI9341_BLACK);
    tft.setTextSize(2);
    tft.setCursor(261, 78);
    tft.print("0");
  }
  else if (Humidity = 100) {
    char* hum = "  ";
    sprintf(hum, "%03d", Humidity);
  }
  else {
    char* hum = "  ";
    sprintf(hum, "%01d", Humidity);
    tft.setTextColor(ILI9341_BLACK);
    tft.setTextSize(2);
    tft.setCursor(261, 78);
    tft.print("0");
  }

  tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
  tft.setCursor(237, 78);
  tft.print(hum);
  tft.setCursor(277, 78);
  tft.print("%");

  if (weatherDesc != weatherDescription) {
    weatherDesc = weatherDescription;
    tft.fillRect(0, 150, 320, 240, ILI9341_BLACK);
    tft.setCursor(0, 150);
    tft.print(weatherDescription);
  }
  else {
    tft.setCursor(0, 150);
    tft.print(weatherDescription);
  }
}


void loop() {
  screen();
  if (millis() > elapsed_t + interval) {
    elapsed_t = millis();
    getWeatherData();
    DHT_read();
    displayConditions(Temperature, Humidity, weatherDescription);
    Serial.print("Free heap: ");
    Serial.print(ESP.getFreeHeap());
    Serial.println();
  }
  if (ESP.getFreeHeap() < 1000) {
    ESP.reset();
  }
}

EDIT 这是我从运行代码中得到的负载:

EDIT This is the payload I get from running the code:

        {"coord":{"lon":longitude,"lat":latitude},
        "weather": {"id":800,"main":"Clear","description":"cielo sereno","icon":"01d"} ,"base":"stations",
    "main":{"temp":16.56,"feels_like":13.87,"temp_min":13.33,"temp_max":20,"pressure":1022,"humidity":38},
    "visibility":10000,
    "wind":{"speed":1.5,"deg":80},
    "clouds":{"all":0},"dt":1586590775,
"sys":{"type":1,"id":6776,"country":"IT","sunrise":1586579815,"sunset":1586627707},
    "timezone":7200,"id":city_id,"name":"city_name","cod":city_code}

推荐答案

首先,你为DynamicJsonBuffer json_buf(3584)做了相当多的过度分配,根据发回的payload从您使用的 API 来看,json_buf 只需要不到 800 个字节,因此 DynamicJsonBuffer json_buf(800) 就足够了.您可以使用 ArduinoJson Assistant 来计算通过将 json 有效负载复制并粘贴到输入中所需的缓冲区大小页面上的框.

First of all, you do over-allocated quite a bit for the DynamicJsonBuffer json_buf(3584), according to the payload send back from the API you used, the json_buf would only need less than 800 bytes, so DynamicJsonBuffer json_buf(800) would be more than sufficient. You can use ArduinoJson Assistant to calculate the buffer size required by copying and pasting the json payload into the input box on the page.

然而,过大的 ArduinoJson 缓冲区并不是您面临的堆碎片的罪魁祸首.String 类导致堆碎片的问题之一来自 String 连接,这就是您的情况.字符串连接使 Arduino 用户能够像在 JavaScript 或 Pyhton 中一样将两个字符串放在一起,String temp = "Temperature=" + String(temperature)+"Celsius".但是,即使您只想要最后一个,该语句也会生成 5 个堆分配(而不是 4 个).

Over-size ArduinoJson buffer however is not the cultprit for the heap fragmentation that you are facing. One of the problem that String class caused heap fragmentation come from String concatenation, and this is what happen to your case. String concatenation gives Arduino users the capability of put two strings together like in JavaScript or Pyhton, String temp = "Temperature=" + String(temperature)+" Celsius". However, this statement along generates 5 heap allocations (not 4) even though you only want the final one.

在您的代码中,您声明了一个全局变量 result 并且您正在您的函数中进行字符串连接.

In your code, you declare a global variable result and you are doing String concatenation in your function.

String result;

// later in your function

void getWeatherData() {

  // at part of your function

  while (client.connected() || client.available())
  { //connected or data available
    char c = client.read();                //gets byte from ethernet buffer
    result = result + c;
  }

  // at end of your function  

  result = "";  //to clean memory and keep it from running out of space
}

当你做串联时,你的全局变量result的原始分配可能不再有足够的空间给串联的变量,所以它创建一个临时堆并做串联,然后最终把结果返回到堆上为 result 新分配的内存,在堆上为原始 result 变量留下一个洞.最糟糕的是,while 循环的每次迭代都会发生这种情况.这就是为什么即使一些堆分配在函数结束时被释放,也没有必要可以重用(想想一块上面有很多洞的奶酪).

When you do concatenation, the original allocation for your global variable result may no longer have enough space for the concatenated variable, so it create a temporary heap and do the concatenation, and then eventually put the result back to a newly allocated memory for result on the heap, leaving a hole at the heap for the original result variable. What make this worst is that this is happening for each iteration of the while loop. This is why even some of the heap allocations get free-up at the end of function, it does not necessary will be re-usable (think of a piece of cheese with a lot of holes on it).

顺便说一句,你的代码:

BTW, your code:

result = "";  //to clean memory and keep it from running out of space

从来没有真正释放内存分配.这是另一个常见的误解.

never really free up the memory allocation. This is another common misunderstanding.

话虽如此,如果您知道发生了什么以及如何使用它,String 类并不总是邪恶的.您的问题的快速解决方法之一(因为我没有时间为您优化代码)是在函数中本地使用它,并且不要将全局变量用于 String result;.我做了一个快速测试,通过删除全局变量 result 并在 getWeatherData() 函数中声明为丢弃"局部变量,空闲堆内存稳定了,不再导致崩溃.当你在函数中使用 String 类时,它不会在整个堆空间中留下一个洞,而是在函数结束时释放出来.

Having said that, String class is not always the evil if you know what's going on and how to use it. One of the quick fix for your problem (as I don't have time to optimise the code for you) is to use it locally within the function and do not use the global variable for the String result;. I did a quick test, by removing the global variable result and declare as a "throw-away" local variable within the getWeatherData() function, the free heap memory stabilised and no longer caused crash. When you use String class within a function, it does not leave a hole in the overall heap space, but get free up at the end of the function.

// String result; //comment the global variable out

void getWeatherData() {

  String result;    //declare it as a local variable

  while (client.connected() || client.available())
  { //connected or data available
    char c = client.read();           //gets byte from ethernet buffer
    result = result + c;
  }

  //result = "";  //this is not necessary and does not free up heap
}

长期修复 - 不要使用 String 类

为了更好的修复,不要在 while 循环中使用字符串连接.这里是没有使用String类的版本,为了消除不必要的全局变量做了很多清理(也对一些重复的代码进行了一些重构).

Long term fix - Don't use String class

For a better fix, do not use String concatenation within the while loop. Here is the version without using String class, and quite a bit clean up for eliminating the unnecessary global variables (also some re-factoring some of the repetitive codes).

#include <Arduino.h>
#include <DHT.h>
#include <ESP8266WiFi.h>
#include <time.h>
#include <ArduinoJson.h>
#include <Adafruit_Sensor.h>
// #include <Adafruit_ILI9341esp.h>
// #include <Adafruit_GFX.h>

#define TFT_MISO D6
//#define TFT_LED 3.3V (change to IO pin if you want the screen to be toggled on/off)
#define TFT_SCK D5
#define TFT_MOSI D7
#define TFT_DC D2
#define TFT_RESET D3
#define TFT_CS D8

#define DHTPIN D1
#define DHTTYPE DHT11

#define WIFI_SSID "wifi-ssid"
#define WIFI_PASS "wifi-password"
#define TX_LED D0

WiFiClient client;
// Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
DHT dht(DHTPIN, DHTTYPE);

int timezone = 2 * 3600; //when time changes change this from 2 to 1
int dst = 0;

const unsigned long interval = 15000;
unsigned long elapsed_t = 0;

const char APIKEY[] = "open-weather-api-key";  //replace with actual api-key
const char CityID[] = "cityID";  //replace with actual city ID
char servername[] = "api.openweathermap.org";

void displayConditions(int Temperature, int Humidity, char *weatherDescription) {
  // tft.setTextSize(2);
  // tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);

  char tem[3] = {0};
  if (Temperature >= 10) {
    sprintf(tem, "%02d", Temperature);
  }
  else {
    sprintf(tem, "%01d", Temperature);
    // tft.setTextColor(ILI9341_BLACK);
    // tft.setTextSize(2);
    // tft.setCursor(79, 78);
    // tft.print("0");
  }

  // tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
  // tft.setCursor(67, 78);
  // tft.print(tem);
  // tft.setCursor(92, 75);
  // tft.setTextSize(1);
  // tft.print("o");
  // tft.setCursor(99, 78);
  // tft.setTextSize(2);
  // tft.print("C");

  char hum[4] = {0};
  if (Humidity >= 10 && Humidity <= 99) {
    sprintf(hum, "%02d", Humidity);
    // tft.setTextColor(ILI9341_BLACK);
    // tft.setTextSize(2);
    // tft.setCursor(261, 78);
    // tft.print("0");
  }
  else if (Humidity == 100) {
    sprintf(hum, "%03d", Humidity);
  }
  else {
    sprintf(hum, "%01d", Humidity);
    // tft.setTextColor(ILI9341_BLACK);
    // tft.setTextSize(2);
    // tft.setCursor(261, 78);
    // tft.print("0");
  }

  // tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
  // tft.setCursor(237, 78);
  // tft.print(hum);
  // tft.setCursor(277, 78);
  // tft.print("%");

  static char weatherDesc[10];
  if (strcmp(weatherDesc, weatherDescription) != 0) {
    strcpy(weatherDesc, weatherDescription);
    // tft.fillRect(0, 150, 320, 240, ILI9341_BLACK);
    // tft.setCursor(0, 150);
    // tft.print(weatherDescription);
  }
  else {
    // tft.setCursor(0, 150);
    // tft.print(weatherDescription);
  }
}

void DHT_read() {

  float newT = dht.readTemperature();
  float newH = dht.readTemperature();
  if (isnan(newT) || isnan(newH)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    // tft.setTextSize(2);
    // tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
    // tft.setCursor(109, 43);
    // tft.print("!");
    // tft.setCursor(287, 43);
    // tft.print("!");
    return;
  }
  char condition[] = "";
  displayConditions((int)newT, (int)newH, condition);
}

void screen() {
  char timeNow[20];
  time_t now = time(nullptr);
  struct tm* p_tm = localtime(&now);

  strftime(timeNow, 20, "%H:%M  %d:%m:%Y", p_tm);
  Serial.println(timeNow);
  // tft.setCursor(0, 0);
  // tft.setTextSize(2);
  // tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
  // tft.print(timeNow);
}

void getWeatherData() {

  if (client.connect(servername, 80))
  { //starts client connection, checks for connection
    char buff[110];
    char getString[] = "GET /data/2.5/weather?id=%s&units=metric&APPID=%s&lang=it";
    sprintf(buff, getString, CityID, APIKEY);
    client.println(buff);
    client.println(F("Host: api.openweathermap.org"));
    client.println(F("User-Agent: ArduinoWiFi/1.1"));
    client.println(F("Connection: close"));
    client.println();
  }
  else {
    Serial.println(F("connection failed"));        //error message if no client connect
    Serial.println();
    // tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
    // tft.setCursor(0, 220);
    // tft.print(F("CONNESSIONE FALLITA"));
    return;
  }

  while (client.connected() && !client.available())
    delay(1);                                          //waits for data

  char result[800];
  int i = 0;
  while (client.connected() || client.available())
  { //connected or data available
    result[i++] = (char)client.read();
  }

  client.stop();                                      //stop client
  result[strlen(result) + 1] = '\0';
  Serial.println(result);

  DynamicJsonBuffer json_buf(800); //was 4096
  JsonObject &root = json_buf.parseObject(result); //

  if (!root.success())
  {
    Serial.println(F("parseObject() failed"));
    // tft.setTextColor(ILI9341_RED, ILI9341_BLACK);
    // tft.setCursor(109, 78);
    // tft.print("!");
    // tft.setCursor(287, 78);
    // tft.print("!");
    return;
  }

  // tft.setTextColor(ILI9341_BLACK);
  // tft.setCursor(109, 78);
  // tft.print("!");
  // tft.setCursor(287, 78);
  // tft.print("!");

  char weatherDescription[10] = {0};
  strcpy(weatherDescription, (const char*)root["weather"][0]["main"]);
  weatherDescription[strlen(weatherDescription) + 1] = '\0';

  int temperature = (int)root["main"]["temp"];
  int humidity = (int)root["main"]["humidity"];
  int weatherID = root["weather"][0]["id"];    //this was not used anywhere in the program

  displayConditions(temperature, humidity, weatherDescription);
}



void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(TX_LED, OUTPUT);
  digitalWrite(TX_LED, HIGH);
  digitalWrite(LED_BUILTIN, HIGH);

  Serial.begin(115200);
  // tft.begin();
  // dht.begin();

  WiFi.begin(WIFI_SSID, WIFI_PASS);
  Serial.println (F("Connecting to TP-LINK_DD1E61"));

  // tft.setRotation(3);
  // tft.fillScreen(ILI9341_BLACK);
  // tft.setTextSize(2);
  // tft.println(F("Connecting to "));
  // tft.println(F("TP-LINK_DD1E61"));
  while (WiFi.status() != WL_CONNECTED) {
   Serial.print(".");
   // tft.setTextSize(1);
   // tft.print(".");
   delay(300);
  }

  // query the ntp should be only after the establish of wifi connection
  configTime(timezone, dst, "pool.ntp.org", "it.pool.ntp.org");
  while (!time(nullptr)) {
   Serial.print("*");
   delay(300);
  }

  Serial.println(F("Connceted"));
  // tft.setTextSize(2);
  // tft.println();
  // tft.println(F("Connected to "));
  // tft.println(F("TP-LINK_DD1E61"));
  // delay(500);
  // tft.fillScreen(ILI9341_BLACK);

  // tft.drawLine(0, 18, 320, 18, ILI9341_WHITE);
  // tft.setTextSize(2);
  // tft.setTextColor(ILI9341_YELLOW, ILI9341_BLACK);
  // tft.setCursor(0, 135);
  // tft.print("TEMPO");
  // tft.setCursor(20, 25);
  // tft.println(F("TEMPERATURA"));
  // tft.println();
  // tft.println();
  // tft.setCursor(215, 25);
  // tft.println(F("UMIDITA'"));
  // tft.setTextSize(1);
  // tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);
  // tft.setCursor(0, 52);
  // tft.print(F("INTERNO"));
  // tft.setCursor(0, 87);
  // tft.print(F("ESTERNO"));

}

void loop() {
  screen();
  if (millis() > elapsed_t + interval) {
    elapsed_t = millis();
    getWeatherData();
    DHT_read();
    // displayConditions(Temperature, Humidity, weatherDescription);
    Serial.print("Free heap: ");
    Serial.print(ESP.getFreeHeap());
    Serial.println();
  }
  delay(1000);  // only update the time once per second
 }

您可以了解更多关于The EvilsArduino 字符串"的更多细节.我希望我的例子能帮助你了解如何管理内存和避免使用 String 类.

You can learn more about "The Evils of Arduino Strings" in more details. I hope my example will help you to learn something on how to manage the memory and avoid of using String class.

这篇关于从 OpenWeatherMap 获取数据时,ESP8266 在正常运行一段时间后重置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆