• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе 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 здесь действительно не причем. раз девай не перегружаеться. У тебя он банально в бесконечном цикле.
попробуй решение которое выше предложено
 
Сверху Снизу