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
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.
-
1Thanks this works! However now there is a new problem. I am using
millis()
in my loop to callgetWeather()
. However theinterval
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 atinterval
.user2201584– user22015842022年07月21日 19:21:42 +00:00Commented Jul 21, 2022 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– romkey2022年07月21日 19:25:48 +00:00Commented Jul 21, 2022 at 19:25
-
1Will do. Thank you!user2201584– user22015842022年07月21日 19:26:15 +00:00Commented Jul 21, 2022 at 19:26
Explore related questions
See similar questions with these tags.