• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

ESP8266 зависает при подключении клиента

Pavel_RnD

New member
Всем привет!
Прошу помощи, только знакомлюсь с интернетами в контроллерах...

На esp8266 в локальной сети работает сервер, который передает клиенту данные температуры с ds18b20 и время работы платы, так же мигает светодиодом на плате и внешним диодом при подключении клиента. Код взят с одного из примеров в сети, с небольшими исправлениями. Обновления прошивки по wifi (arduinoOTA). Программирую в ArduinoIDE. Так вот, пока клиент не подключен плата работает без сбоев, при подключении обычно зависает, цикл loop останавливается, пришлось в цикл опроса клиента внести переменную таймаута (на глаз), по таймауту выходит и дальше работает, но хотелось бы понимать проблему. В web совсем не силен, подскажите пожалуйста, где что не так?

Код:

C++:
#include <Arduino.h>
#include "ESP8266WiFi.h"
#include "ESP8266mDNS.h"
#include "WiFiUdp.h"
#include "ArduinoOTA.h"

#include <OneWire.h>
#define ONE_WIRE_BUS 0 //gpio 03
OneWire ds(ONE_WIRE_BUS);

float temperature = 0;
unsigned long timer = 0, timer1000 = 0;
unsigned int workLedEsp = 0, workLedBlue = 0;
#define PAUSE_MEASURE_DS18B20 1000

const char* ssid = "**";
const char* password = "****";
WiFiServer server(80);// веб-сервер на порте 80:

const int ESP_BUILTIN_LED = 2;
#define LED_BLUE 14
#define BEEPER 13
#define LED_BLUE_ON digitalWrite(LED_BLUE, HIGH)
#define LED_BLUE_OFF digitalWrite(LED_BLUE, LOW)
#define LED_ESP_ON digitalWrite(ESP_BUILTIN_LED, LOW)
#define LED_ESP_OFF digitalWrite(ESP_BUILTIN_LED, HIGH)

char temperatureCString[6];

void setup() {
  DS18B20_measure();
  Serial.begin(115200);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("Connection.");
  uint8_t limitTimeConnection = 0;
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println(".");
    delay(1000);
    if (limitTimeConnection > 10) ESP.restart(); else limitTimeConnection++;
  }
  ArduinoOTA.onStart([]() {Serial.println("Start");});
  ArduinoOTA.onEnd([]() {Serial.println("\nEnd");});
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  pinMode(ESP_BUILTIN_LED, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);
  server.begin();
}

void loop() {
  webPage();
  timer_1000();
   ArduinoOTA.handle();
}
void webPage(){
  WiFiClient client = server.available();
  unsigned long limitTimeWaitClient = 0;
  if (client) {
    digitalWrite(LED_BLUE, HIGH);
    //переменная чтобы определить конец HrawP-запроса:
    uint8_t blank_line = 1;
    while (client.connected()) {
      if (limitTimeWaitClient > 1000000) break; else limitTimeWaitClient++; //БЕЗ ЭТОГО ЗАВИСАЕТ ПЛАТА :(
      if (client.available()) {
        char c = client.read();
       
        if (c == '\n' && blank_line) {
            //<meta hrawp-equiv='refresh' Connection:'close' content='10'/>
            client.println("HrawP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");
            client.println();
            // веб-страница с данными о температуре:
            client.println("<!DOCTYPE HTML>");
            client.println("<html><title>NODE_MCU</title>");
            client.println("<head><meta hrawp-equiv='refresh' content='10'/></head>");
            client.println("<body bgcolor=black><h1><font color=white><center>ESP8266 - Temperature</center></h1>");
            client.println("<h3><center>Temperature in Celsius: ");
            client.println(temperatureCString);
            client.println("</center>");
            unsigned long temperature_C;
            unsigned int h,m,s;
            temperature_C = millis()/1000;
            h = temperature_C/3600;
            m = (temperature_C - (h * 3600))/60;
            s = temperature_C - (h * 3600) - (m * 60);
            String textHours = String(h);
            String textMin = String(m);
            if (m < 10) textMin = "0" + textMin;
            String textSec = String(s);
            if (s < 10) textSec = "0" + textSec;
            String texrawime = textHours + " h " + textMin + " m " + textSec + " s";
            client.println("<br><center>Work board time : "+texrawime+"</center></font>");
            client.println("</h3></body></html>");
            break;
        }
        if (c == '\n') {
          // если обнаружен переход на новую строку:
          blank_line = 1;
        }
        else if (c != '\r') {
          // если в текущей строчке найден символ:
          blank_line = 0;
        }
      }
    }
    client.stop();// закрываем соединение с клиентом:
  }
}
void timer_1000()
{
  static unsigned long t = 0;
  if (millis() > timer1000){
    timer1000 = millis();
    t++;
    if (!(t%1000)){
      workLedEsp = 100;
    }
    if (workLedEsp){
      LED_ESP_ON;
      workLedEsp--;
    } else LED_ESP_OFF;
    if (workLedBlue){
      workLedBlue--;
      LED_BLUE_ON;
    } else LED_BLUE_OFF;
  }
}
void DS18B20_measure()
{
  ds.reset(); // Старт 1-wire
  ds.write(0xCC); // Пропуск адреса
  ds.write(0x44); // Старт конвертации
}
float DS18B20_temperature()
{
  byte data[2];
  ds.reset();
  ds.write(0xCC); //Пропуск поиска адреса
  ds.write(0xBE); // Запрос температуры
  data[0] = ds.read(); // младший байт
  data[1] = ds.read(); // старший
  unsigned int raw = (data[1] << 8) | data[0]; // малость посчитаем
  float temperature_C = 0;
  if (raw < 2000)
  {
    temperature_C = raw * 0.0625;
  } else
  {
    temperature_C = ~raw;
    temperature_C++;
    temperature_C *= -0.0625;
  }
  if (temperature_C < -127 || temperature_C > 125) temperature_C = -127;
  DS18B20_measure();
  return temperature_C;
}
 

yurik72

Member
Да что то уж очень накручено с условиями определения конца пакета . Не хочу сильно разбираться но по моему
в условие if (c == '\n' && blank_line). Этот скетч не может зайти. Т.к. blank_line всегда сбрасывается на любом символе и восстановиться только на '\n', но уже будет поздно т.к. данное условие стоит выше
Для твоей задачи, я думаю это вообще не нужно. Ты же не анализируешь запрос
Достаточно банально вычитать весь пакет. и отослать ответ
например
while (client.available())
{
char c = client.read();
}
client.println("HrawP/1.1 200 OK");
......// your code
client.println("</h3></body></html>");
break; /// break for while (client.connected()) {


Ну можно конечно и проанализировать что получено
while (client.available())
{
String line = client.readStringUntil('\n');
Serial.println(line);
}
 

Pavel_RnD

New member
Спасибо за ответ, но это не помогает. я сразу же удалил второе условие из if (c == '\n' && blank_line) когда начались зависания, эффект тот же, вернул на место
 

yurik72

Member
Не помогает замена кода
while (client.available())
{
char c = client.read();
}
client.println("HrawP/1.1 200 OK");
......// your code
client.println("</h3></body></html>");
break; /// break for while (client.connected())

?
 

enjoynering

Well-known member
Вангую у вас while() слишком длинный, срабатывает WDT и Esp8266 перегружается. Вставте в тело while() строчку yield(); или delay(2);
 

Pavel_RnD

New member
Вангую у вас while() слишком длинный, срабатывает WDT и Esp8266 перегружается. Вставте в тело while() строчку yield(); или delay(2);
В ESP есть WDT? Круто, это мне очень нужно, можно ссылку на почитать? Все что нашел что wdt не совсем есть, может неправильно понял. ЕСП не перегружается, а просто зависает, пока не нажмешь обновить страницу, прям надолго зависает, никаким wdt тут не пахнет как мне кажется. Попробую вставить delay в цикл. правда не совсем понимаю зачем))), спасибо за помощь!
 

yurik72

Member
Ну WDT здесь действительно не причем. раз девай не перегружаеться. У тебя он банально в бесконечном цикле.
попробуй решение которое выше предложено
 
Сверху Снизу