Hello, this is my first project written in the Arduino IDE. The hardware is a NodeMCU ESP8266 board and what I believe to be a knockoff version of the SEEED Relay Shield v3.0. I based most of the code off examples I have found online, but the issue I am having, is this: I need the "drain" button to only stay open for 5 seconds after being triggered. The code below does work, however I have hit a snag which I am not sure how to solve. The while loop runs perfectly and closes the valve after the required time. However, if the web client is left active in a web browser, as soon as the loop finishes, the browser refreshes and send the button command again. This repeats until I manually force the browser to stop or simply close the tab.
If anyone can help me find a way to get this loop to only run once after the web browser button is pushed, it would be sincerely appreciated. Thank you for taking the time to look over my code.
Sincerely,
Jason
#include <ESP8266WiFi.h>
#include "secret.h"
char ssid[] = SECRET_SSID;
char password[] = SECRET_PASS;
// Set your Static IP address
IPAddress local_IP(192, 168, 1, 123);
// Set your Gateway IP address
IPAddress gateway(192, 168, 1, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8); //optional
IPAddress secondaryDNS(8, 8, 4, 4); //optional
WiFiServer server(80);
//Variable to store HTTP request
String header;
//Auxilliary variable so store the current output state
String compressorState = "off";
String drainState = "closed";
String airSupply1State = "off";
String airSupply2State = "off";
// Assign output variables to GPIO pins
const int compressor = 16; // GPIO16
const int drain = 5; //GPIO05
const int airSupply1 = 4; //GPIO4
const int airSupply2 = 0; //GPIO0
//Current Time
unsigned long currentTime = millis();
//Previous time
unsigned long previousTime = 0;
//Define timeout time in milliseconds
const long timeoutTime = 2000;
//drain timer
static unsigned long drainTime = 0;
static unsigned long drainTimeState = LOW;
void setup() {
Serial.begin(115200);
delay(10);
pinMode(compressor, OUTPUT);
pinMode(drain, OUTPUT);
pinMode(airSupply1, OUTPUT);
pinMode(airSupply2, OUTPUT);
digitalWrite(compressor, LOW);
digitalWrite(drain, LOW);
digitalWrite(airSupply1, LOW);
digitalWrite(airSupply2, LOW);
//configure static ip
if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
Serial.println("STA Failed to configure");
}
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.print("Use this URL to connect: ");
Serial.print("http://");
Serial.print(WiFi.localIP());
Serial.println("/");
}
void loop() {
WiFiClient client = server.available(); //listen for clients
if (client) { //If a client connects,
Serial.println("New Client."); //print message to serial port
String currentLine = ""; //create string to hold date from client
currentTime = millis();
previousTime = currentTime;
while (client.connected() && currentTime - previousTime <= timeoutTime) { //loop while client is connected
currentTime = millis();
if (client.available()) { //if there is a byte to read from client,
char c = client.read(); //read the byte, then
Serial.write(c); //print in serial monitor
header += c;
if (c == '\n') { //if the byte is a newline character
//if the current line is blank, you get two newline characters in a row.
//that is the end of the client HTTP request, so send the response:
if (currentLine.length() == 0) {
//HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
//and a content-type so the client knows what is comming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println("Connection: close");
client.println();
//turn the GPIOs on and off
if (header.indexOf("GET /16/on") >= 0) {
Serial.println("GPIO 16 on");
compressorState = "on";
digitalWrite(compressor, HIGH);
} else if (header.indexOf("GET /16/off") >= 0) {
Serial.println("GPIO 16 off");
compressorState = "off";
digitalWrite(compressor, LOW);
} else if (header.indexOf("GET /5/on") >= 0) {
Serial.println("GPIO 05 on for 5 seconds");
drainState = "open";
drainTimeState = HIGH;
digitalWrite(drain, HIGH);
drainTime = millis();
while (drainTimeState == HIGH) {
Serial.println(millis() - drainTime);
if (millis() - drainTime > 5000)
{
digitalWrite(drain, LOW);
Serial.println("GPIO 05 off");
drainState = "closed";
drainTimeState = LOW;
break;
}
}
} else if (header.indexOf("GET /5/off") >= 0) {
Serial.println("GPIO 05 off");
drainState = "closed";
digitalWrite(drain, LOW);
} else if (header.indexOf("GET /4/on") >= 0) {
Serial.println("GPIO 4 on");
airSupply1State = "on";
digitalWrite(airSupply1, HIGH);
} else if (header.indexOf("GET /4/off") >= 0) {
Serial.println("GPIO 4 off");
airSupply1State = "off";
digitalWrite(airSupply1, LOW);
} else if (header.indexOf("GET /0/on") >= 0) {
Serial.println("GPIO 0 on");
airSupply2State = "on";
digitalWrite(airSupply2, HIGH);
} else if (header.indexOf("GET /0/off") >= 0) {
Serial.println("GPIO 0 off");
airSupply2State = "off";
digitalWrite(airSupply2, LOW);
}
// Display the HTML web page
client.println("<!DOCTYPE html><html>");
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
client.println("<link rel=\"icon\" href=\"data:,\">");
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2 {background-color: #77878A;}</style></head>");
// Web Page Heading
client.println("<body><h1>ESP8266 Web Server</h1>");
// Display current state, and ON/OFF buttons for GPIO 16
client.println("<p>Compressor Status " + compressorState + "</p>");
// If the compressorState is off, it displays the ON button
if (compressorState == "off") {
client.println("<p><a href=\"/16/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/16/off\"><button class=\"button button2\">OFF</button></a></p>");
}
// Display current state, and open/close buttons for GPIO 5
client.println("<p>Drain Valve Status " + drainState + "</p>");
// If the drain is closed, it displays the OPEN button
if (drainState == "closed") {
client.println("<p><a href=\"/5/on\"><button class=\"button\">OPEN</button></a></p>");
} else {
client.println("<p><a href=\"/5/off\"><button class=\"button button2\">CLOSE</button></a></p>");
}
// Display current state, and ON/OFF buttons for GPIO 4
client.println("<p>Air Supply 1 Status " + airSupply1State + "</p>");
// If the airSupply1State is off, it displays the ON button
if (airSupply1State == "off") {
client.println("<p><a href=\"/4/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/4/off\"><button class=\"button button2\">OFF</button></a></p>");
}
// Display current state, and open/close buttons for GPIO 0
client.println("<p>Air Supply 2 Status " + airSupply2State + "</p>");
// If airSupply2State is off, it displays the ON button
if (airSupply2State == "off") {
client.println("<p><a href=\"/0/on\"><button class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a href=\"/0/off\"><button class=\"button button2\">OFF</button></a></p>");
}
client.println("</body></html>");
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} else { //if you got a newline, then clear the current line
currentLine = "";
}
} else if (c != '\r') { //if you get anything but a carriage return character,
currentLine += c; //add it to the end of the currentLine
}
}
}
//Clear the header variable
header = "";
//Close the connection
client.stop();
Serial.println("Client disconnected.");
Serial.println("");
}
}