|
IoT Switch: From top: 5V relay PCB, Level Translator PCB and ESP-12E |
As mentioned in an
earlier post, lighting up a LED is very similar to controlling a relay. In place of the relay, we use a relay PCB with an optically-isolated input. I bought mine for RM9.99 from
here.
|
5V opto-isolated Relay PCB |
Since the ESP8266 ESP-12E is a 5V device, we need to translate its output to 5V. I am usually inclined to use a 1.8V zener diode like the
TZS4678-GS08, costing some RM1.14. However an
Arduino-type 4-channel level converter is only RM1.35.
|
4-Channel Logic Level Converter |
Unlike the resistor network or the zener diode method, this is an active circuit and uses the MOSFET
BSS138:
There is a full explanation on the schematic
here.
The wiring is quite straightforward:
ESP-12E Level Converter 2-Channel Relay
3.3V LV HV 5V
GND GND GND GND
D6 LV1 HV1 IN1
D7 LV2 HV2 IN2
|
Top wiring to ESP-12E, bottom wiring to 5V Relay PCB |
The program, a Lua 'sketch' for the Arduino IDE, is much the same as the last post, tweaked a little to add a second channel. The only fiddle here is if we used D5, it seems to interfere with the programming of the ESP-12E via its USB serial port. If you do use D5, simply disconnect the level translator from the ESP-12E before you program it.
/*
* This sketch demonstrates how to set up a simple HTTP-like server.
* The server will set a GPIO pin depending on the request
* http://server_ip:8080/gpio/0 will set the GPIO2 low,
* http://server_ip:8080/gpio/1 will set the GPIO2 high
* server_ip is the IP address of the ESP8266 module, will be
* printed to Serial when the module is connected.
static const uint8_t D0 = 16;
static const uint8_t D1 = 5;
static const uint8_t D2 = 4;
static const uint8_t D3 = 0;
static const uint8_t D4 = 2;
static const uint8_t D5 = 14;
static const uint8_t D6 = 12;
static const uint8_t D7 = 13;
static const uint8_t D8 = 15;
static const uint8_t D9 = 3;
static const uint8_t D10 = 1;
*/
#include <ESP8266WiFi.h>
const char* ssid = "YourAcessPoint";
const char* password = "YourSecretPassword";
// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(8080);
void setup() {
Serial.begin(115200);
delay(10);
// prepare GPIO
pinMode(D6, OUTPUT);
pinMode(D7, OUTPUT);
digitalWrite(D6, HIGH);
digitalWrite(D7, HIGH);
Serial.println("Relays off");
// Connect to WiFi network
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");
// Start the server
server.begin();
Serial.println("Server started");
// Print the IP address
Serial.println(WiFi.localIP());
}
int val = 1;
int val2 = 1;
void loop() {
// 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
String s = "";
// Prepare the response
Serial.print("Input string is ");
Serial.println(req);
if (req.indexOf("/D6/0") != -1) {
val = 0;
s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nD6 is now ";
s += (val)?"high":"low";
s += "</html>\n";
}
else if (req.indexOf("/D6/1") != -1) {
val = 1;
s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nD6 is now ";
s += (val)?"high":"low";
s += "</html>\n";
}
else if (req.indexOf("/D7/0") != -1) {
val2 = 0;
s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nD7 is now ";
s += (val2)?"high":"low";
s += "</html>\n";
}
else if (req.indexOf("/D7/1") != -1) {
val2 = 1;
s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nD7 is now ";
s += (val2)?"high":"low";
s += "</html>\n";
}
else if (req.indexOf("/index.html") != -1) {
s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nHello, world.</html>\n";
}
else if (req.indexOf("/favicon.ico") != -1) {
Serial.println("End of command");
client.stop();
}
else {
s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>\r\nInvalid request: ";
s += req;
s += "</html>\n";
Serial.println("invalid request");
Serial.println(req);
client.print(s);
delay(10);
client.stop();
return;
}
// Set GPIO2 according to the request
if (val == 0)
digitalWrite(D6, LOW);
if (val == 1)
digitalWrite(D6, HIGH);
if (val2 == 0)
digitalWrite(D7, LOW);
if (val2 == 1)
digitalWrite(D7, HIGH);
client.flush();
// 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 destroyed
}
As before, you turn on the first relay using:
http://yourIPaddress/D6/0
And off using:
http://yourIPaddress/D6/1
The commands for the second relay are:
http://yourIPaddress/D7/0
http://yourIPaddress/D7/1
The total cost of the parts was something like RM21.90 + RM9.99 + RM1.35 or RM33.24, not counting the 5V power supply and the various bits of wires and connectors.
|
Sonoff ITEAD |
There you have it: your DIY IoT switch actually sets you back some RM2.40. But as we shall see later, the Sonoff, among others, has some serious security problems, like the
Krack exploit. Rolling our own IoT relay switch is the first step to
taking control of our IoT security, rather than relying on the vendors' updates, both of the firmware and the accompanying app.