0

I am trying to build something that can control a stepper motor based on weather information from openweathermap. I've set up a ESP8266 webserver to manually control motor movement with buttons and I have set up the structure to talk to openweathermap API to get the information I want (printing them to serial monitor for now for testing).

However, when I combined the 2 things break. The current code allows me to get weather perfectly but I can no longer connect to my web server running in STA mode. Something in the getWeather() function is messing with the web server because if I remove getWeather() from my loop the web server works.

Any idea what I am doing wrong here?

#include <SPI.h> 
#include <AccelStepper.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>  // http web access library
#include <ArduinoJson.h>        // JSON decoding library

// Define stepper motor connections and motor interface type. Motor interface type must be set to 1 when using a driver:
#define dirPin 5
#define stepPin 4
#define motorInterfaceType 1
bool motorStop;
bool motorCW;
bool motorCCW;

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

//Put your SSID & Password
const char* ssid = "[ssid]";  // Enter SSID here
const char* password = "[password]";  //Enter Password here

//OpenWeatherMap API key
String apiKey= "[apikey]"; 

//OpenWeatherMap location
String location= "lat=37.30&lon=-121.91";
String unit= "metric";

const unsigned long postingInterval = 1000*60*60; // delay between updates, in milliseconds

WiFiClient client; 

ESP8266WebServer server(80);

// Set your Static IP address
IPAddress local_IP(192, 168, 86, 248);
// Set your Gateway IP address
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);
  
// Configures static IP address
if (!WiFi.config(local_IP, gateway, subnet,primaryDNS)) {
  Serial.println("STA Failed to configure");
}
  
  stepper.setMaxSpeed(1000);

  Serial.println("Connecting to ");
  Serial.println(ssid);
  
  //connect to your local wi-fi network
  WiFi.begin(ssid, password);
  
  //check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.print(".");
  }
  //Print out connection info
  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);}

  // Step the motor with a constant speed as set by setSpeed():
  stepper.runSpeed();
  
  getWeather();
}

void getWeather()
{    
  // if there's a successful connection:
  if (client.connect("api.openweathermap.org", 80)) 
  {
    Serial.println("connected");
    // send the HTTP PUT request:
    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"]; // "America/Los_Angeles"
    int timezone_offset = doc["timezone_offset"]; // -25200

    JsonArray daily = doc["daily"];

    // tomorrow's forecast (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"]; // "Clear"
    const char* daily_1_weather_0_description = daily_1_weather_0["description"]; // "clear sky"
    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

    // print out weather information
    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 
  {
    // if you couldn't make a connection:
    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;
}

1 Answer 1

1

At the end of getWeather() you call delay(postingInterval);

postingInterval is set to 60*60*1000 ... one hour. That means getWeather() won't return for one hour and nothing else in loop() will be processed during that time, including the web server.

You need to remove that delay() call and rewrite your loop to check if postingInterval milliseconds have passed and only call getWeather() if they have.

3
  • 1
    Thanks this works! However now there is a new problem. I am using millis() in my loop to call getWeather(). However the interval will affect how stepper runs. stepper.runSpeed() is suppose to get stepper to run continuously at the set direction; but now the stepper would pause at interval. Jul 21 at 19:21
  • Great, happy that helped. The new problem sounds like a good thing to post as a new question; then you'll get the attention of a lot of people who might answer it and not see it here as a comment :)
    – romkey
    Jul 21 at 19:25
  • 1
    Will do. Thank you! Jul 21 at 19:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.