I’m seeing a problem that the WiFi is pretty unstable.
My app is pretty simple, (using Webserver.h from the community library) based on specific HTTP GET requests it flips relays on a relay shield.
I received my core and relay shield almost a week ago, along with a second core for a friend of mine. Both cores are experiencing the problems that I am going to describe in detail. Also, in order to rule out outside causes, I have tested this on two completely different WiFi networks (different routers from different manufacturers) in different buildings.
Frequency:
Varies. In one day 1 occurrence per 2 hours was followed by 5 occurrences in one hour, and that was followed by 1 occurrence over the next hour.
Behavior:
The core stops responding to all requests (including http GETs and spark core firmware updates from the cloud), but the status light continues to breathe cyan. After anywhere from a few seconds to five minutes, the status light will begin flashing cyan for a variable amount of time and sometimes the status light will turn off completely (for up to 30 seconds). After this the status light begins breathing cyan again and is the core begins to respond normally.
Troubleshooting steps and results:
I wrote a small bit of code to ping the local gateway every 60 seconds and flip a relay if it failed. Upon the next occurrences of the problem, the relay did not flip when the core stopped responding, and did not do so until the status light began to breathe cyan.
Code is below, Any help is appreciated.
(I originally posted this in the “Cyan of death” thread as it is similar to a problem that someone else posted in that thread, but Zach asked me to post this in a new thread with my code)
// *** SOURCE INCLUDES ***
#include "HttpClient/HttpClient.h"
#include "WebServer/WebServer.h"
// *** DECLARE / INITIALIZE ***
// Begin: Declare/Initialize for relay shield
int RELAY1 = D0;
int RELAY2 = D1;
int RELAY3 = D2;
int RELAY4 = D3;
// End: Declare/Initialize for relay shield
// Begin: Declare/Initilaize for ping loop variables
int lastMinute;
int tenSecondResetWifi = 0;
// End: Declare/Initilaize for ping delay loop variable
// Begin: Declare/Initialize for WebServer, require WebServer.h
/* all URLs on this server will start with / because of how we
* define the PREFIX value. We also will listen on port 80, the
* standard HTTP service port */
#define PREFIX ""
WebServer webserver(PREFIX, 80);
// End: Declare/Initialize for WebServer
// Begin: Declare/initialize WebClient, requires WebClient.h
unsigned int nextTime = 0; // Next time to contact the server
HttpClient http;
// Headers currently need to be set at init, useful for API keys etc.
http_header_t headers[] = {
// { "Content-Type", "application/json" },
// { "Accept" , "application/json" },
{ "Accept" , "*/*"},
{ NULL, NULL } // NOTE: Always terminate headers will NULL
};
http_request_t request;
http_response_t response;
// End: Declare/initialize WebClient
// *** FUNCTIONS ***
// Begin: Functions for WebServer. require Webserver.h
// This command is the default, executed when only / is sent
void defaultCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) {
// Assemble HTML
P(message) =
"<html>"
"<head><title></title></head>"
"<style>"
" body { background: black; font-family: Ariel; color: #CCCCCC; }"
" a { color: #00CCCC; text-decoration: none; }"
"</style>"
"<body>"
"<h2>"
"<center>"
"<h1>III-Core-G</h1>"
"<a href=\"pulse.html\">pulse.html</a><br><br>"
"<a href=\"enabled.html\">enabled.html</a><br><br>"
"<a href=\"disabled.html\">disabled.html</a><br><br>"
"<a href=\"eventGhostStatus.html\">eventGhostStatus.html</a><br><br>"
"<a href=\"clearStatus.html\">clearStatus.html</a><br><br>"
"<a href=\"setRebootStatus.html\">setRebootStatus.html</a><br><br>"
"<a href=\"reportStatus.html\">reportStatus.html</a><br><br>"
"<br>"
"</center>"
"</h2>"
"</body>"
"</html>"
;
server.printP(message);
return;
}
// This command is executed when /clearRebootStatus.html is sent
void clearStatusCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) {
// If type isn't GET, stop
if (type == WebServer::HEAD) return;
else if (type == WebServer::POST) return;
// Go low on RELAY3
digitalWrite(RELAY3, LOW);
// Go low on RELAY4
digitalWrite(RELAY4, LOW);
// Go back to previous page
server.httpSeeOther("javascript:javascript:history.go(-1)");
return;
}
// This command is executed when /disabled.html is sent
void disabledCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) {
// If type isn't GET, stop
if (type == WebServer::HEAD) return;
else if (type == WebServer::POST) return;
// Go high on RELAY2
digitalWrite(RELAY2, HIGH);
// Go back to previous page
server.httpSeeOther("javascript:javascript:history.go(-1)");
return;
}
// This command is executed when /enabled.html is sent
void enabledCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) {
// If type isn't GET, stop
if (type == WebServer::HEAD) return;
else if (type == WebServer::POST) return;
// Go low on RELAY2
digitalWrite(RELAY2, LOW);
// Go back to previous page
server.httpSeeOther("javascript:javascript:history.go(-1)");
return;
}
// This command is executed when /eventGhostStatus.html is sent
void eventGhostStatusCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) {
// If type isn't GET, stop
if (type == WebServer::HEAD) return;
else if (type == WebServer::POST) return;
sendEventGhostStatus("index.html?III-Core-G-statusResponse");
// Go back to previous page
server.httpSeeOther("javascript:javascript:history.go(-1)");
return;
}
// This command is executed when /pulse.html is sent
void pulseCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) {
// If type isn't GET, stop
if (type == WebServer::HEAD) return;
else if (type == WebServer::POST) return;
// Go HIGH on RELAY1 for 500 ms, then back to LOW
digitalWrite(RELAY1, HIGH);
delay(500);
digitalWrite(RELAY1, LOW);
// Go back to previous page
server.httpSeeOther("javascript:javascript:history.go(-1)");
return;
}
// This command is executed when /reportStatus.html is sent
void reportStatusCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) {
// Assemble HTML
String myMessage =
"<!DOCTYPE html><html>"
" <head>"
" <title>III-Core-G</title>"
" <style>"
" body { background: black; font-family: Ariel; color: #CCCCCC; }"
" a { color: #00CCCC; text-decoration: none; }"
" </style>"
" </head>"
" <body>"
" <center><h1>III-Core-G Status</h1></center>"
" <h2>"
" Network: ";
myMessage += WiFi.SSID();
myMessage += "<BR> Strength: ";
myMessage += WiFi.RSSI() + " "
"<br> IP Address: ";
IPAddress myIP = WiFi.localIP();
myMessage += String(myIP[0]) + "." + String(myIP[1]) + "." + String(myIP[2]) + "." + String(myIP[3]);
myMessage += "<br> Subnet: ";
myIP = WiFi.subnetMask();
myMessage += String(myIP[0]) + "." + String(myIP[1]) + "." + String(myIP[2]) + "." + String(myIP[3]);
myMessage += "<br> Gateway: ";
myIP = WiFi.gatewayIP();
myMessage += String(myIP[0]) + "." + String(myIP[1]) + "." + String(myIP[2]) + "." + String(myIP[3]);
myMessage += " ";
// "<br> MAC: "
//WiFi.macAddress())"
myMessage += "<br><br> lastMinute: ";
myMessage += lastMinute;
myMessage += " </body>"
" </html>";
server.print(myMessage);
}
// This command is executed when /setRebootStatusCmd.html is sent
void setRebootStatusCmd(WebServer &server, WebServer::ConnectionType type, char *, bool) {
// If type isn't GET, stop
if (type == WebServer::HEAD) return;
else if (type == WebServer::POST) return;
// Go high on RELAY2
digitalWrite(RELAY4, HIGH);
// Go back to previous page
server.httpSeeOther("javascript:javascript:history.go(-1)");
return;
}
// End: Functions for WebServer. require Webserver.h
// Begin: Functions for Webclient
void sendEventGhostStatus(String path) {
request.hostname = "192.168.1.10";
request.port = 80;
request.path = path;
http.get(request, response, headers);
}
// End: Functions for Webclient
void setup() {
// Begin: Setup for relay shield
//Initilize the relay control pins as output
pinMode(RELAY1, OUTPUT);
pinMode(RELAY2, OUTPUT);
pinMode(RELAY3, OUTPUT);
pinMode(RELAY4, OUTPUT);
// Initialize all relays to an OFF state
digitalWrite(RELAY1, LOW);
digitalWrite(RELAY2, LOW);
digitalWrite(RELAY3, LOW);
digitalWrite(RELAY4, LOW);
// End: Setup for relay shield
// Begin: Setup for WebServer, requires WebServer.h
/* register our default command (activated with the request of
* http://x.x.x.x/cmd */
webserver.setDefaultCommand(&defaultCmd);
webserver.addCommand("clearStatus.html", &clearStatusCmd);
webserver.addCommand("disabled.html", &disabledCmd);
webserver.addCommand("enabled.html", &enabledCmd);
webserver.addCommand("eventGhostStatus.html", &eventGhostStatusCmd);
webserver.addCommand("pulse.html", &pulseCmd);
webserver.addCommand("reportStatus.html", &reportStatusCmd);
webserver.addCommand("setRebootStatus.html", &setRebootStatusCmd);
/* start the server to wait for connections */
webserver.begin();
// End: Setup for WebServer, requires WebServer.h
}
void loop() {
// Begin: Loop for WebServer, requires WebServer.h
// process incoming connections one at a time forever
webserver.processConnection();
// End: Loop for WebServer, requires WebServer.h
}