Having built, as explained in a previous post a power switch controlled using an ESP8266 wireless module, it is now to develop the program running on the ESP8266. To recap, I am using an ESP8266-01 wireless module which has two GPIO pins (GPIO0 and GPIO2) and two UART pins (Tx and Rx).

  • GPIO2 will be used as an output to control the relay, active low.
  • GPIO0 will be used as an input to manually override the setting and activate the relay, active low.
  • Tx will be be used for debugging, to read the microcontroller events</li>

The ESP8266 is preloaded with some simple AT commands. There are many toolsets to program the module, but the easiest in my opinion is using the Arduino IDE, available on github. It supports all main functions and has a pretty good reference. Each time a new program is loaded on the microcontroller, the Arduino core is loaded as well, so it takes about a minute. To program the module, it needs to enter in bootloader mode, essentially to pull down GPIO0 before power up. To sum up:

Bootloader mode

  • GPIO2: high
  • GPIO0: low
  • RST: high
  • CH_PD: high

Normal mode

  • GPIO2: high
  • GPIO0: high
  • RST: high
  • CH_PD: high

The github page of the Arduino IDE for ESP8266 contains analytical instructions on how to install the toolset.

The developed program is a modification of the "WiFiWebServer" example with the following requirements:

  • Connect automatically on the network
  • Create a webserver that every device (client) can access.
    • By accessing "http://<ESP8266IP>/gpio/0", GPIO2 becomes low and the web server returns "ON"
    • By accessing "http://<ESP8266IP>/gpio/1", GPIO2 becomes high and the web server returns "OFF"
    • By accessing "http://<ESP8266IP>/gpio/status", the web server returns the status ("ON" or "OFF")
  • If GPIO0 is low, the ESP8266 enters manual mode, meaning it sets GPIO2 low, discarding any change from the web
  • If the network connection is lost, the ESP8266 attempts to reconnect
  • If the ESP8266 gets an IP from a DHCP server *.*.0.*, it disconnects and tries to reconnect.

This last behavior programmed is due to the repeater found in the house. If the main router becomes inoperable, then the repeater acts as a DHCP server providing IP address 192.168.0.*. When the router is active again, then the ESP8266 does not change address and it becomes unreachable. So, if this occurs, then the module reconnects only when the main router is present again.

#include "ESP8266WiFi.h"

const char* ssid = "SSID";
const char* password = "PASSWORD";

int val=1;
int flag=0;

// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(80);

void setup() {
WiFiBegin();

// Start the server
server.begin();
Serial.println("Server started");
}

void loop() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi lost, trying to reconnect");
setup();
}

if (digitalRead(0) == LOW && flag==0) {
val=0;
flag=1;
digitalWrite(2, val);
Serial.println("Manual");
delay(1);
return;
}

if (digitalRead(0) == HIGH && flag==1) {
flag=0;
val=1;
Serial.println("Auto");
delay(1);
return;
}

// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
return;
}

// Wait until the client sends some data
Serial.println("new client");
while(!client.available()){
delay(1);
}

// Read the first line of the request
String req = client.readStringUntil('\r');
Serial.println(req);
client.flush();

// Match the request
if (req.indexOf("/gpio/0") != -1)
val = 1;
else if (req.indexOf("/gpio/1") != -1)
val = 0;
else if (req.indexOf("/gpio/status") != -1)
Serial.println("getting status");
else {
Serial.println("invalid request");
client.stop();
return;
}

// Set GPIO2 according to the request
digitalWrite(2, val);

client.flush();

// Prepare the response
String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>;\r\n<html>\r\n";
s += (val)?"OFF":"ON";
s += "</html>\n";

// Send the response to the client
client.print(s);
delay(1);
Serial.println("Client disonnected");

// The client will actually be disconnected 
// when the function returns and 'client' object is detroyed
}

void WiFiBegin(){
pinMode(2, OUTPUT);
digitalWrite(2, val);
pinMode(0, INPUT);
Serial.begin(115200);
delay(10);

// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");

// Print the IP address
Serial.println(WiFi.localIP());
IPAddress IPadd = WiFi.localIP(); 
if (IPadd[2] == 0) {
Serial.println("Connected to repeater, disconnecting");
WiFi.disconnect();
}
}

The full project for the ESP8266 power switch can be found on my Github page.