ESP8266 всегда сбрасывается после 65 секунд работы

У меня есть простой код, в котором ESP8266 запрашивает базу данных MySQL о фактическом состоянии светодиода (будь то 1 или 0), и когда в БД есть 1, ESP8266 включает светодиод... Но моя проблема после 65-66 секунд работы сервера все равно сбрасывает... Программа делает то, что должна, но через 65-66 секунд перезагружается и пытается переподключиться к wifi

---- РЕДАКТИРОВАТЬ -----

После некоторых экспериментов с кодом я обнаружил, что не имеет значения время выполнения, но количество циклов цикла... Каждый раз, независимо от задержки или скорости обработки, происходит сбой после 48 циклов....

код .ino

// Загрузить библиотеку Wi-Fi
#include <ESP8266WiFi.h>
#include <WiFiClient.h> 
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>

// Замените учетными данными вашей сети
const char* ssid     = "XXXX";
const char* password = "XXXX";
const char* host = "http://www.XXXX.XX/arduino_PHP/post_data.php";

// Установить номер порта веб-сервера на 80
WiFiServer server(80);
HTTPClient http; 

// Переменная для хранения HTTP-запроса
String header;

// Вспомогательные переменные для хранения текущего состояния вывода
String output5State = "off";
String output4State = "off";

// Назначаем выходные переменные контактам GPIO
const int output5 = 5;
const int output4 = 4;
byte green, red= 0;

void setup() {
 Serial.begin(115200);
 // Инициализировать выходные переменные как выходы
  WiFi.mode(WIFI_OFF);        // Предотвращает проблему повторного подключения (слишком долгое подключение)
  WiFi.mode(WIFI_STA);        //Эта строка скрывает просмотр ESP как точки доступа Wi-Fi
 delay(1000);
 pinMode(output5, OUTPUT);
 pinMode(output4, OUTPUT);
 // Установить выходы на НИЗКИЙ уровень
 digitalWrite(output5, LOW);
 digitalWrite(output4, LOW);

 // Подключаемся к сети Wi-Fi с SSID и паролем
 Serial.print("Connecting to ");
 Serial.println(ssid);
 WiFi.begin(ssid, password);
 while (WiFi.status() != WL_CONNECTED) {
   delay(500);
   Serial.print(".");
 }
 // Выводим локальный IP-адрес и запускаем веб-сервер
 Serial.println("");
 Serial.println("WiFi connected.");
 Serial.println("IP address: ");
 Serial.println(WiFi.localIP());
 server.begin();
}

void loop(){
delay(500);
DB_state("Green",green);
DB_state("Red",red);
delay(500);
}

void DB_state(String component,int state){
 String postData =("component=" + String(component) + "&state=" + String(state));
 Serial.println(postData);
  http.begin("http://www.XXXX.XX/arduino_PHP/DB_state.php");
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");
 http.POST(postData);   //Отправить запрос
 String payload = http.getString();    //Получить полезную нагрузку ответа
 Serial.println(payload);
 http.end();  //Закрыть соединение
 state_LED(payload,component);
 }

void state_LED(String str, String led){ 
 int x; 
   if (led== "Green") {
     x = 4;}
   else if (led== "Red") {
      x = 5;}
   if (str == "State: 1") {
     digitalWrite(x, HIGH);}
   else if (str == "State: 0") {
     digitalWrite(x, LOW);}
 }
 

Отладка стека ESP8266

Exception 28: LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads
PC: 0x4020744a: ClientContext::state() const at C:\Users\XXXX\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\libraries\ESP8266WiFi\src/include/ClientContext.h line 364
EXCVADDR: 0x00000184

Decoding stack results
0x40203f10: HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\XXXX\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266/HardwareSerial.h line 164
0x40203f1c: HardwareSerial::write(unsigned char const*, unsigned int) at C:\Users\XXXX\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266/HardwareSerial.h line 165
0x40207512: HTTPClient::connected() at C:\Users\XXXX\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\libraries\ESP8266HTTPClient\src\ESP8266HTTPClient.cpp line 475
0x40202d24: HTTPClient::disconnect(bool) at C:\Users\XXXX\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\libraries\ESP8266HTTPClient\src\ESP8266HTTPClient.cpp line 434
0x40203ac8: HTTPClient::end() at C:\Users\XXXX\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\libraries\ESP8266HTTPClient\src\ESP8266HTTPClient.cpp line 425
0x402012ba: DB_State(String, int) at C:\Users\XXXX\Documents\Arduino\ESP8266_php_DB_control/ESP8266_php_DB_control.ino line 87
0x40201334: loop() at C:\Users\XXXX\Documents\Arduino\ESP8266_php_DB_control/ESP8266_php_DB_control.ino line 73
0x40100175: esp_schedule() at C:\Users\XXXX\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\core_esp8266_main.cpp line 125
0x40205628: loop_wrapper() at C:\Users\XXXX\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266\core_esp8266_main.cpp line 197

Спасибо за любой совет

, 👍3

Обсуждение

Таким образом, это может быть проблема с памятью, такая как утечка или проблема с распределением ресурсов., @the busybee

Я так и думал, но как это исправить?, @Sahasrar

Прежде чем вы сможете исправить это, вам нужно его идентифицировать. Прочтите документацию по WiFiServer и HTTPClient, используйте свои навыки поиска в Интернете для подробного сообщения об ошибке «исключение 28» и так далее. Проверьте свои выводы и предположения с помощью тестовых программ; например, дважды вызовите http.POST() в DB_state() и подсчитайте количество циклов., @the busybee

сначала я бы перестал использовать String, @Juraj

Почему? И как вы его заменяете?, @Sahasrar

@Juraj pozdravujem slovenského brata v programovaní :D :D :D, @Sahasrar


1 ответ


Лучший ответ:

1

Не знаю как, но наконец-то я нашел работающее решение... Я добавил HTTPClient http; поверх функции, и все работает...

void DB_state(String component,int state){
HTTPClient http; // ЭТО ДОБАВЛЕНО
 String postData =("component=" + String(component) + "&state=" + String(state));
 Serial.println(postData);
  http.begin("http://www.XXXX.XX/arduino_PHP/DB_state.php");
  http.addHeader("Content-Type", "application/x-www-form-urlencoded");
 http.POST(postData);   //Отправить запрос
 String payload = http.getString();    //Получить полезную нагрузку ответа
 Serial.println(payload);
 http.end();  //Закрыть соединение
 state_LED(payload,component);
 }

Кто-нибудь может объяснить мне, как это возможно? Потому что я не совсем понимаю эту процедуру.

,

Теперь вы каждый раз создаете и уничтожаете объект HTTPClient в этой области, как [указывает C++](https://en.cppreference.com/w/cpp/language/storage_duration#Storage_duration). Предположительно глобальная утечка какого-то ресурса, но я могу только строить догадки на этот счет., @nanofarad

Извините, я не понимаю. Не могли бы вы быть проще?, @Sahasrar

Я не могу разбить это дальше в пространстве, предоставленном мне комментарием. Я предлагаю взять учебник по C++, который охватывает объекты, конструкторы, деструкторы и т. д., который предоставит эту информацию в более понятном виде. Но в основном вместо того, чтобы иметь один HTTPClient на время жизни программы, вы создаете новый HTTPClient и очищаете его после каждого запроса. Это интуитивно понятно, но я недостаточно знаю внутренности HTTPClient, чтобы понять, почему это происходит. в конечном итоге сбой, если вы повторно используете один и тот же экземпляр снова и снова., @nanofarad

https://github.com/esp8266/Arduino/issues/7613#issuecomment-700782051, @Juraj