I am trying to use a on-off switch with the ESP8266 to change whether GPI02 is HIGH or LOW. I am using GPIO3 as input. My circuit looks like this:

enter image description here

The red area to the right is a relay, I wasn't sure how to make it work in fritzing but I am sure that it is wired correctly, it just has a signal, +, and -, pin. The more important stuff is happening with the ESP8266. First, here is the code:

  This a simple example of the aREST Library for the ESP8266 WiFi chip.
  This example illustrate the cloud part of aREST that makes the board accessible from anywhere
  See the README file for more details.

  Written in 2015 by Marco Schwartz under a GPL license.

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

// Clients
WiFiClient espClient;
PubSubClient client(espClient);

// Create aREST instance
aREST rest = aREST(client);

// Unique ID to identify the device for cloud.arest.io
char* device_id = "ew1zard";

// WiFi parameters
const char* ssid = "MaisonBlanche";
const char* password = "7932gLBw";

// Functions
void callback(char* topic, byte* payload, unsigned int length);

void setup(void)
  // Set input / output pin
  pinMode(3, INPUT);
  pinMode(2, OUTPUT);
  //pinMode(2, OUTPUT);
  //digitalWrite(3, 0);

  // Start Serial

  // Set callback

  // Give name & ID to the device (ID should be 6 characters long)

  // Connect to WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
  Serial.println("WiFi connected");

  // Set output topic
  char* out_topic = rest.get_topic();

void loop() {

  // Connect to the cloud

  int read3 = digitalRead(3);
  Serial.println(read3 + " input");
  digitalWrite(2, read3);


// Handles message arrived on subscribed topic(s)
void callback(char* topic, byte* payload, unsigned int length) {

  Serial.println("request from interwebs");
  rest.handle_callback(client, topic, payload, length);


The output of the Serial.println is always input (there is no HIGH or LOW or 1 or 0, or whatever it should be, before the input. I have verified that the switch is working. In the on position it is sending 3.3v to GPIO3 (I have measured it with my multimeter) and still the input never changes. In the off position it sends 0v and the ESP8266 just acts as if there is nothing to read it seems. Since I am using this with aREST and you can set the mode of pins through that, I thought maybe I had to set the pinMode with the aREST request cloud.arest.io/xxxxx/mode/3/i and it verifies with a JSON response that the pin is being set to input, but still no reading. Do I not have the ESP8266 wired correctly for this? Maybe I need some pull-ups/pull downs or I can't use the pins in the configuration I am using them? One other thing, when I set the input pin with aREST, it turns on the relay (sending something through GPIO2 for some reason). If I don't set the input with aREST the relay stays off.

UPDATE I tried with this code to rule out that it might be aREST:

void setup() {
  // put your setup code here, to run once:
  pinMode(3, INPUT);
  pinMode(2, OUTPUT);

  // Start Serial

void loop() {
  // put your main code here, to run repeatedly:
  int read3 = digitalRead(3);
  Serial.println(" input");
  digitalWrite(2, read3);

It always outputs 0 input, the ESP8266 seems to be ignoring that input pin.

UPDATE I am now trying with GPIO0 as input. I have the switch wired to ground, and it leads to GPIO0. When I turn it on, GPIO0 reads 1 (on), then I use the switch and it turns the relay off correctly, then I try and turn it on again, and nothing happens, GPIO0 continues to be read at 0. So I can't use the switch past the initial off.

3 Answers 3


The expression read3 + " input" performs pointer arithmetic, i.e. you either add 0 or 1 to the start adress of " input", so you get either " input" or "input". Does the leading space disappear when pressing the button?

To correct your code you can print the number separately:

Serial.println(" input");

You should get rid of the rest and pub-sub code. You can add this later after having solved the problem with the button.

Also note that GPIO03 uses the same pin as RX. The docs state the following:

Serial uses UART0, which is mapped to pins GPIO1 (TX) and GPIO3 (RX).

So it should work after disabling Serial and after providing a pull down resistor. The resistor is needed to prevent having a floating input.

  • Comments are not for extended discussion; this conversation has been moved to chat.
    – Majenko
    Oct 3, 2017 at 21:06

The issue occurs when you try to use the RX port (3) and you also define Serial.begin. This is double dipping. You can only use the RX/TX as a single unit of digital or serial communication.


There are certain pins that output a 3.3V signal when the ESP8266 boots. This may be problematic if you have relays or other peripherals connected to those GPIOs. The following GPIOs output a HIGH signal on boot: GPIO1, GPIO3, GPIO9, GPIO10. GPIO3: pin must high at BOOT and is pulled up to that position. I have no idea what will happen if low at that point. Since I2C I/O modules are cheep I use them and do not worry about the rest of the pins. Not the cheapest but keeps me out of trouble. It makes my life a bit easier as well as I pull up the I2C lines to the 3.3V and connect the PCF8574 to 5 Volts. No problem as the SCL and SCI are by definition Open Drain or Open Collector (Bipolar parts). This made my first try with a LCSD work first shot. I tried the 3.3V and it would not work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.