Веб-сервер ESP8266 не отвечает при запуске функции HTTP-запроса

esp8266 nodemcu stepper-motor esp8266webserver

Я пытаюсь создать что-то, что может управлять шаговым двигателем на основе информации о погоде из openweathermap. Я настроил веб-сервер ESP8266 для ручного управления движением двигателя с помощью кнопок и настроил структуру для взаимодействия с API openweathermap для получения нужной мне информации (пока печатаю их на серийный монитор для тестирования).

Однако, когда я объединил две вещи, они сломались. Текущий код позволяет мне отлично получать информацию о погоде, но я больше не могу подключиться к своему веб-серверу, работающему в режиме STA. Что-то в функции getWeather() мешает работе веб-сервера, потому что если я удалю getWeather() из своего цикла, веб-сервер заработает.

Есть идеи, что я делаю неправильно?

#include <SPI.h> 
#include <AccelStepper.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>  // библиотека веб-доступа по http
#include <ArduinoJson.h>        // библиотека декодирования JSON

// Определяем соединения шагового двигателя и тип интерфейса двигателя. Тип интерфейса двигателя должен быть установлен на 1 при использовании драйвера:
#define dirPin 5
#define stepPin 4
#define motorInterfaceType 1
bool motorStop;
bool motorCW;
bool motorCCW;

AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);

//Поместите свой SSID & Пароль
const char* ssid = "[ssid]";  // Введите SSID здесь
const char* password = "[password]";  //Введите пароль здесь

//Ключ API OpenWeatherMap
String apiKey= "[apikey]"; 

//Местоположение OpenWeatherMap
String location= "lat=37.30&lon=-121.91";
String unit= "metric";

const unsigned long postingInterval = 1000*60*60; // задержка между обновлениями в миллисекундах

WiFiClient client; 

ESP8266WebServer server(80);

// Установите свой статический IP-адрес
IPAddress local_IP(192, 168, 86, 248);
// Установите IP-адрес вашего шлюза
IPAddress gateway(192, 168, 86, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(192, 168, 86, 1);


void setup() {
  Serial.begin(9600);
  delay(100);
  
// Настраивает статический IP-адрес
if (!WiFi.config(local_IP, gateway, subnet,primaryDNS)) {
  Serial.println("STA Failed to configure");
}
  
  stepper.setMaxSpeed(1000);

  Serial.println("Connecting to ");
  Serial.println(ssid);
  
  //подключаемся к вашей локальной сети wi-fi
  WiFi.begin(ssid, password);
  
  //проверяем, подключен ли wi-fi к сети wi-fi
  while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.print(".");
  }
  //Выводим информацию о соединении
  Serial.println("");
  Serial.println("WiFi connected..!");

  server.on("/", handle_OnConnect);
  server.on("/cw_on", handle_CW_on);
  server.on("/cw_off", handle_CW_off);
  server.on("/ccw_on", handle_CCW_on);
  server.on("/ccw_off", handle_CCW_off);
  server.on("/mstop", handle_stop);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("HTTP server started");
}


void loop() {

  server.handleClient();
  if(motorStop)
  {stepper.setSpeed(0);}
  if(motorCW)
  {stepper.setSpeed(400);}
  if(motorCCW)
  {stepper.setSpeed(-400);}

  // Шаг мотора с постоянной скоростью, заданной setSpeed():
  stepper.runSpeed();
  
  getWeather();
}

void getWeather()
{    
  // если есть успешное соединение:
  if (client.connect("api.openweathermap.org", 80)) 
  {
    Serial.println("connected");
    // отправляем HTTP-запрос PUT:
    client.println("GET /data/2.5/onecall?" + location + "&exclude=current,minutely,hourly" +  "&appid=" + apiKey);
    client.println("Host: api.openweathermap.org");
    client.println("Connection: close");
    client.println();

    const size_t capacity = 8*JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(8) + 16*JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5) + 8*JSON_OBJECT_SIZE(6) + 8*JSON_OBJECT_SIZE(14) + 1810;
    DynamicJsonDocument doc(capacity);

    deserializeJson(doc, client);

    float lat = doc["lat"]; // 37,3
    float lon = doc["lon"]; // -121,91
    const char* timezone = doc["timezone"]; // "Америка/Лос-Анджелес"
    int timezone_offset = doc["timezone_offset"]; // -25200

    JsonArray daily = doc["daily"];

    // завтрашний прогноз (daily_1)
    JsonObject daily_1 = daily[1];
    long daily_1_dt = daily_1["dt"]; // 1596225600
    long daily_1_sunrise = daily_1["sunrise"]; // 1596201109
    long daily_1_sunset = daily_1["sunset"]; // 1596251761

    JsonObject daily_1_temp = daily_1["temp"];
    float daily_1_temp_day = daily_1_temp["day"]; // 306,61
    float daily_1_temp_min = daily_1_temp["min"]; // 288,67
    float daily_1_temp_max = daily_1_temp["max"]; // 306,61
    float daily_1_temp_night = daily_1_temp["night"]; // 288,67
    float daily_1_temp_eve = daily_1_temp["eve"]; // 295,94
    float daily_1_temp_morn = daily_1_temp["morn"]; // 293,26

    JsonObject daily_1_feels_like = daily_1["feels_like"];
    int daily_1_feels_like_day = daily_1_feels_like["day"]; // 303.31
    float daily_1_feels_like_night = daily_1_feels_like["night"]; // 287,59
    float daily_1_feels_like_eve = daily_1_feels_like["eve"]; // 293,77
    float daily_1_feels_like_morn = daily_1_feels_like["morn"]; // 292,42

    int daily_1_pressure = daily_1["pressure"]; // 1015
    int daily_1_humidity = daily_1["humidity"]; // 17
    float daily_1_dew_point = daily_1["dew_point"]; // 278,68
    float daily_1_wind_speed = daily_1["wind_speed"]; // 3.12
    int daily_1_wind_deg = daily_1["wind_deg"]; // 318

    JsonObject daily_1_weather_0 = daily_1["weather"][0];
    int daily_1_weather_0_id = daily_1_weather_0["id"]; // 800
    const char* daily_1_weather_0_main = daily_1_weather_0["main"]; // "Очистить"
    const char* daily_1_weather_0_description = daily_1_weather_0["description"]; // "чистое небо"
    const char* daily_1_weather_0_icon = daily_1_weather_0["icon"]; // "01d"

    int daily_1_clouds = daily_1["clouds"]; // 0
    int daily_1_pop = daily_1["pop"]; // 0
    float daily_1_uvi = daily_1["uvi"]; // 9.53

    // распечатать информацию о погоде
    Serial.print("Tomorrow's Forecast");
    Serial.print("Temperature: ");
    Serial.println(daily_1_feels_like_day);
    Serial.print("Weather: ");
    Serial.println(daily_1_weather_0_main);
    delay (postingInterval);
  } 
  else 
  {
    // если не удалось установить соединение:
    Serial.println("connection failed");
    delay (postingInterval);
  }
}

void handle_OnConnect() {
  motorStop = HIGH;
  motorCW = LOW;
  motorCCW = LOW;
  Serial.println("Motor: Stopped");
  server.send(200, "text/html", SendHTML(motorStop, motorCW, motorCCW)); 
}

void handle_CW_on() {
  motorStop = LOW;
  motorCW = HIGH;
  motorCCW = LOW;
  Serial.println("Motor: Running Clock-wise");
  server.send(200, "text/html", SendHTML(motorStop, motorCW, motorCCW)); 
}

void handle_CW_off() {
  motorStop = HIGH;
  motorCW = LOW;
  motorCCW = LOW;
  Serial.println("Motor: Stopped");
  server.send(200, "text/html", SendHTML(motorStop, motorCW, motorCCW)); 
}

void handle_CCW_on() {
  motorStop = LOW;
  motorCW = LOW;
  motorCCW = HIGH;
  Serial.println("Motor: Motor: Running Counter Clock-wise");
  server.send(200, "text/html", SendHTML(motorStop, motorCW, motorCCW)); 
}

void handle_CCW_off() {
  motorStop = HIGH;
  motorCW = LOW;
  motorCCW = LOW;
  Serial.println("Motor: Stopped");
  server.send(200, "text/html", SendHTML(motorStop, motorCW, motorCCW)); 
}

void handle_stop() {
  motorStop = HIGH;
  motorCW = LOW;
  motorCCW = LOW;
  Serial.println("Motor: Stopped");
  server.send(200, "text/html", SendHTML(motorStop, motorCW, motorCCW)); 
}

void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}


String SendHTML(uint8_t mstop,uint8_t cw, uint8_t ccw){
  String ptr = "<!DOCTYPE html> <html>\n";
  ptr +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  ptr +="<title>LED Control</title>\n";
  ptr +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n";
  ptr +=".button {display: block;width: 80px;background-color: #1abc9c;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n";
  ptr +=".button-cw {background-color: #1abc9c;}\n";
  ptr +=".button-cw:active {background-color: #16a085;}\n";
  ptr +=".button-ccw {background-color: #34495e;}\n";
  ptr +=".button-ccw:active {background-color: #2c3e50;}\n";
  ptr +=".button-mstop {background-color: #34495e;}\n";
  ptr +=".button-mstop:active {background-color: #2c3e50;}\n";
  ptr +="p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
  ptr +="</style>\n";
  ptr +="</head>\n";
  ptr +="<body>\n";
  ptr +="<h1>Weather Station</h1>\n";
  ptr +="<h3>Runs either direction continuously</h3>\n";
  
   if(cw)
  {ptr +="<p>Motor running Clock-wise</p><a class=\"button button-off\" href=\"/cw_off\">Stop</a>\n";}
  else
  {ptr +="<p>Motor not running Clock-wise</p><a class=\"button button-on\" href=\"/cw_on\">Run</a>\n";}

  if(ccw)
  {ptr +="<p>Motor running Counter Clock-wise</p><a class=\"button button-off\" href=\"/ccw_off\">Stop</a>\n";}
  else
  {ptr +="<p>Motor not running Counter Clock-wise</p><a class=\"button button-on\" href=\"/ccw_on\">Run</a>\n";}

  
  ptr +="</body>\n";
  ptr +="</html>\n";
  return ptr;
}

, 👍0


1 ответ


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

1

В конце getWeather() вы вызываете delay(postingInterval);

Для

postingInterval установлено значение 60*60*1000... один час. Это означает, что getWeather() не вернется в течение одного часа, и в течение этого времени ничего в loop() не будет обрабатываться, включая веб-сервер.

Вам нужно удалить этот вызов delay() и переписать свой цикл, чтобы проверить, прошло ли миллисекунды postingInterval, и вызывать только getWeather() если они есть.

,

Спасибо, это работает! Однако теперь появилась новая проблема. Я использую millis() в своем цикле для вызова getWeather(). Однако «интервал» повлияет на работу степпера. Предполагается, что stepper.runSpeed() заставляет степпер работать непрерывно в заданном направлении; но теперь степпер будет останавливаться на «интервале»., @user2201584

Отлично, рад, что помог. Новая проблема звучит как хорошая вещь, чтобы опубликовать ее как новый вопрос; тогда вы привлечете внимание многих людей, которые могут ответить на него и не увидеть его здесь в качестве комментария :), @romkey

Сделаю. Благодарю вас!, @user2201584