# ESP8266 driving relay and reading button

I want to have an ESP8266 (ESP-01S), which has only GPIO0 and GPIO2 exposed, drive a relay (via an NPN Transistor on GPIO2) and read a button (GPIO0).

The circuit diagram is as follows:

The problem is that as soon as I connect the red line, it looks like there is not enough power delivered by the PSU.

Even without the relay, it looks like the LM1117-3,3 is going into thermal shutdown after a couple of minutes.

The problem with the ESP8266 is that GPIO0 must be HIGH and GPIO2 must be HIGH when it powers on, to get it to boot successfully. It works perfectly for the first couple of minutes though, so I know the code works fine.

What am I doing wrong? Should I up both the resistor to 10K from the 3K3 that I have now?

Just in case, here is the source code:

// Relay control using the ESP8266 WiFi chip

// Import required libraries
#include <ESP8266WiFi.h>

// WiFi parameters
const char* ssid = "SSID";

//Room Name
const String RoomName = "Room 1";

//Response from Client
String request = "";

// The port to listen for incoming TCP connections
#define LISTEN_PORT           80

// set pin numbers:
const int buttonPin = 0;    // the number of the pushbutton pin
const int relayPin = 2;      // the number of the LED pin

int relayState = LOW;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output     flickers

// Create an instance of the server
WiFiServer server(LISTEN_PORT);
WiFiClient client;

void setup(void)
{
// Start Serial
Serial.begin(115200);
delay(10);
Serial.println();
Serial.println();
Serial.println();
Serial.println();

pinMode(buttonPin, INPUT);
pinMode(relayPin, OUTPUT);

// set initial LED state
digitalWrite(relayPin, relayState);

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

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

Serial.println("You can connect to this Switch at this URL:");
Serial.print("http://");
Serial.print(WiFi.localIP());
Serial.println("/");

}

void loop() {
request = "";

// Handle REST calls
WiFiClient client = server.available();
if (client) {
Serial.println("User connected.");
while(!client.available()){
delay(1);
}
Serial.println(request);
client.flush();
}

//process the request
if (request.indexOf("/LED=ON") != -1) {
relayState = HIGH;
}
if (request.indexOf("/LED=OFF") != -1) {
relayState = LOW;
}

// read the state of the switch into a local variable:

// If the switch changed, due to noise or pressing:
// reset the debouncing timer
lastDebounceTime = millis();
}

if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:

// if the button state has changed:

// only toggle the LED if the new button state is HIGH
if (buttonState == HIGH) {
relayState = !relayState;
}
}
}

digitalWrite(relayPin, relayState);

// save the reading.  Next time through the loop,
// it'll be the lastButtonState:

if (client) {
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html; charset=UTF-8");
client.println("");
client.print(RoomName);
client.print(": Gineer.Home.SmartSwicth</title><style>body
{background-color: black;color: white;text-align: center;}#switchSlider     {display: inline-block;left: 28px;position: relative;border: 4px solid     gray;width: 40px;height: 120px;vertical-align: central;}#switchToggle {display:     inline-block;left: -30px;position: relative;border: 4px solid     gray;width: 60px;height: 20px;vertical-align: central;}#switchSlider.off     {background-color: silver;}#switchToggle.off {top: -20px;background-color:     silver;}#switchSlider.on {background-color: yellow;}#switchToggle.on {top:     -80px;background-color: yellow;}</style></head><body><h1>");
client.print(RoomName);
client.print("</h1><a href=\"/LED=");
if(relayState == HIGH)
{
client.print("OFF");
}
else
{
client.print("ON");
}
client.print("\" border=\"0\"><div class=\"");
if(relayState == HIGH)
{
client.print("on");
}
else
{
client.print("Off");
}
client.print("\" id=\"switchSlider\"></div><div class=\"");
if(relayState == HIGH)
{
client.print("on");
}
else
{
client.print("Off");
}
client.println("\" id=\"switchToggle\"></div></a><br /><br />Brought to you by <a     href=\"http://www.gineer.co.za/\">Gineer R&D</a></body></html>");
Serial.println("htmlsent");
}
}


Update
Okay, so the following circuit solves the booting problem, but the LM1117-3,3 overheats and shuts down.

Update
I've added 3K3 resistors inline with both the chip_enable and reset lines. It seems to work fine now, for a couple of minutes, then the ESP8266 seems to shut down and then only the LM1117-3,3 seems to get very hot quite quickly. Is this some kind of sleep mode/Should I add more delays in my loop so it runs slower? Surely not?

• Try putting a 3k3 resistor at the GPIO2 output. – hcabral Sep 3 '16 at 20:04
• adding 3K3 between base and GPIO2 results in the ESP8266 not booting successfully – Gineer Sep 3 '16 at 21:22

Remove 3k3 from V+

Replace connection GPIO2 to base with 470Ω to 1kΩ.

GPIO has low impedance driver (~25Ω) so (3.3-0.7)/25 = up to 100mA ! into base ! n.g. This is why a series R about 10x the relay coil resistance is used.

Include Red line emitter to ground.

• That's what I originally had. I tried it again, but the ESP8266 does not boot unless GPIO2 is high at power-up. – Gineer Sep 3 '16 at 21:02

It seems the circuit in my first update was the correct version. The only additional bits I have in my circuit over and above the diagram above is the 2 addition 3K3 resistors between Vcc and Reset and Chip Enable.

The overheating issue seems to have been the output capacitor on the LM1117-3,3 being the wrong way around.

Thanks to all the input though, it got me thinking in the right direction.

Here is the final working version:

• Something I should add here is that this circuit seems to be a little unstable in the off state (I.E. when the light is off, which in my case is when the relay is energised, so that the LED is on). I assumed the Bypass diode would be enough for the inductive load, but in future versions I would add an opto coupler in place of the transistor. (Haven't tried it yet though) – Gineer Nov 6 '17 at 7:40
• The instability here was observed in that the device would become unresponsive after some time. The solution to this was not an electrical fault but rather in my source code. This device is working perfectly for some months now. – Gineer Feb 22 '18 at 4:27