ESP8266 Digital Read/Write failed

Hello community,

I am trying to build a project with my ESP8266 and actually even if I try to just blink a LED in D2 or D8 pin nothing happens. Notice that I first connect to my wifi network because i want to do some stuff over my network. The next step is to read a value from a sensor or write. So I thought ok, whats the simplest thing to do? Blink a LED. Oups its not working. Anyone has any idea why not working?

thank you in advance! :slight_smile:

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

const char* ssid = "Cronos";
const char* password = "*******";

const char* host = "myhost";
const int httpsPort = myport;

// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char* fingerprint = "CF 05 98 89 CA FF 8E D8 5E 5C E0 C2 E4 F7 E6 C3 C7 50 DD 5C";

void setup() {
  pinMode(2, OUTPUT);
  Serial.begin(115200);
  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");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // Use WiFiClientSecure class to create TLS connection
  WiFiClientSecure client;
  Serial.print("connecting to ");
  Serial.println(host);
  if (!client.connect(host, httpsPort)) {
    Serial.println("connection failed");
    return;
  }
/*
  if (client.verify(fingerprint, host)) {
    Serial.println("certificate matches");
  } else {
    Serial.println("certificate doesn't match");
  }
*/
  String url = "/";
  Serial.print("requesting URL: ");
  Serial.println(url);

  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "User-Agent: BuildFailureDetectorESP8266\r\n" +
               "Connection: close\r\n\r\n");

  Serial.println("request sent");
  while (client.connected()) {
    String line = client.readStringUntil('\n');
    if (line == "\r") {
      Serial.println("headers received");
      break;
    }
  }
  
  String line = client.readStringUntil('\n');
  if (line.startsWith("{\"state\":\"success\"")) {
    Serial.println("esp8266/Arduino CI successfull!");
  } else {
    Serial.println("esp8266/Arduino CI has failed");
  }
  Serial.println("reply was:");
  Serial.println("==========");
  Serial.println(line);
  Serial.println("==========");
  Serial.println("closing connection");
}

void loop() {
  Serial.println("Main loop...");
  digitalWrite(2, HIGH);
  delay(1000);
  digitalWrite(2, LOW);
  delay(1000);
}

Instead of using 2, use D2 as the pin "name" (D2 is actually GPIO4)

See this pinout

Thank you. Can I use GPIO pins 1, 3 for bluetooth connection?

I am using something like SoftwareSerial mySerial(D9,D10); but i am not sure if my definition is correct.

D1 and D3 are hardware Tx0 and Rx0 so if you BT module uses a serial interface (some do but some are SPI) then that will work without software serial, once you disconnect your USB cable from the PC

Pin numbers in Arduino correspond directly to the ESP8266 GPIO pin numbers. pinMode, digitalRead, and digitalWrite functions work as usual, so to read GPIO2, call digitalRead(2).but the labels on your board do not match GPIO numbers as said above...Pin mapping are defined here for the different variants. For example for a nodeMCU you would go look up this file .../variants/nodemcu/pins_arduino.h and you can see the following mapping between labels and GPIO

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;

So use the D[color=blue]#[/color] pin names to match what you see on your boards as labels.

Here You go for more info and reference documentation

Are you using this SoftwareSerial library??

They have this method

bool SoftwareSerial::isValidGPIOpin(int pin) {
   return (pin >= 0 && pin <= 5) || (pin >= 12 && pin <= MAX_PIN);
}

called when you instantiate an object on both Tx and Rx. So you can see which GPIO are good to go with.

Depending on your needs You might consider first using hardware Serial. See the doc above where they mention

Serial

Serial object works much the same way as on a regular Arduino. Apart from hardware FIFO (128 bytes for TX and RX) HardwareSerial has additional 256-byte TX and RX buffers. Both transmit and receive is interrupt-driven. Write and read functions only block the sketch execution when the respective FIFO/buffers are full/empty.

Serial uses UART0, which is mapped to pins GPIO1 (TX) and GPIO3 (RX). Serial may be remapped to GPIO15 (TX) and GPIO13 (RX) by calling Serial.swap() after Serial.begin. Calling swap again maps UART0 back to GPIO1 and GPIO3.

Serial1 uses UART1, TX pin is GPIO2. UART1 can not be used to receive data because normally it's RX pin is occupied for flash chip connection. To use Serial1, call Serial1.begin(baudrate).

If Serial1 is not used and Serial is not swapped - TX for UART0 can be mapped to GPIO2 instead by calling Serial.set_tx(2) after Serial.begin or directly with Serial.begin(baud, config, mode, 2).

By default the diagnostic output from WiFi libraries is disabled when you call Serial.begin. To enable debug output again, call Serial.setDebugOutput(true). To redirect debug output to Serial1 instead, call Serial1.setDebugOutput(true).

You also need to use Serial.setDebugOutput(true) to enable output from printf() function.

Both Serial and Serial1 objects support 5, 6, 7, 8 data bits, odd (O), even (E), and no (N) parity, and 1 or 2 stop bits. To set the desired mode, call Serial.begin(baudrate, SERIAL_8N1), Serial.begin(baudrate, SERIAL_6E2), etc.

A new method has been implemented on both Serial and Serial1 to get current baud rate setting. To get the current baud rate, call Serial.baudRate(), Serial1.baudRate(). Return a int of current speed. For example

// Set Baud rate to 57600

Serial.begin(57600);

// Get current baud rate
int br = Serial.baudRate();

// Will print "Serial is 57600 bps"
Serial.printf("Serial is %d bps", br);



I've done this also for official ESP8266 Software Serial library, see this pull request.
Note that this implementation is only for ESP8266 based boards, and will not works with other Arduino boards.

Thank you for all that documentation that you wrote. I really appreciate your help. Yes I am using SoftwareSerial. Actually I used it in arduino Uno. My code was something like

SoftwareSerial(0, 1);

which means that now in ESP8266 I will directly digitalRead() from pins 9 and 10 right? 9 and 10 are the GPIO pins for TX0 Rx0

Well I hope you read it...

On a uno SoftwareSerial(0, 1); is totally ridiculous (sorry :slight_smile: ) because 0 and 1 are the pins for the hardware Serial port, so no need to use software Serial, just use the Serial instance directly. Same applies to the ESP, if you use hardware Serial, then don't bother with software serial... and hardware Serial is way more robust

I see. When we have a hardware serial port we just use it. Softwareserial lib is to overwrite this and use for example 5 and 6 digital pins as serial communication.

So all i have to do is, define at setup() function

  bthSerial.begin(115200);

and then at the loop() write sth like

byte mybyte = bthSerial.read();

it seems that i am missing something and i feel like I do noob questions but i am confused. :confused: I would like to read from the hardware serial pins GPIO9 and GPIO10. The default ones.

If your Bluetooth is connected to the hardware pins, then no need for software serial at all - the object driving those pins in serial mode is called Serial so you just do Serial.begin(xxxx); in the setup() and use Serial to speak to you BT module. (Serial.available(), Serial.read(),....) --> see Arduino Serial

Indeed if you take other pins, then they don't have (usually) an hardware Serial capability attached and then the software serial library is useful. But best is to start using the hardware one

In order to correctly use a serial port, read and practice with Robin's Serial basics tutorial

I already have a Serial communication for my debuging monitor. That is why I defined a bthSerial.begin(XXXX); This is wrong? I have opened 10 tutorials about that and I am really confused about the RIGHT WAY.

Can you please take a look at my code?

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>

#include <string.h>
#include <stdio.h>

//SoftwareSerial mySerial(D9,D10);

String Data = "";
String password1 = "";
String ssid1 = "";

char inChar;

int READINGSTATUS = -1;

char str[80] = "This is - www.tutorialspoint.com - website";
const char s[2] = ":";
char *token;

   
const char* ssid = "s";
const char* password = "";

const char* host = ".com";
const int httpsPort = 02;

// Use web browser to view and copy
// SHA1 fingerprint of the certificate
const char* fingerprint = "CF 05 98 89 CA FF 8E D8 5E 5C E0 C2 E4 F7 E6 C3 C7 50 DD 5C";

void parseInput() {
  int i=0;
  for(i=0; i<Data.length(); i++) {
    str[i] = Data[i];
  }
  
  token = strtok(str, s);
  password1 = token;
  
  while( token != NULL ) {
    Serial.println(token );
  
    token = strtok(NULL, s);
    ssid1 = token;
    break;
  }
  Serial.println("");
  Serial.print("SSID: ");
  Serial.println(ssid1);
  Serial.print("PASSWORD: ");
  Serial.println(password1);
  Serial.println("Serial input was read sucesfully.");   
}

void setup() {
  Serial.begin(115200);
  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");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // Use WiFiClientSecure class to create TLS connection
  WiFiClientSecure client;
  Serial.print("connecting to ");
  Serial.println(host);
  if (!client.connect(host, httpsPort)) {
    Serial.println("connection failed");
    return;
  }
/*
  if (client.verify(fingerprint, host)) {
    Serial.println("certificate matches");
  } else {
    Serial.println("certificate doesn't match");
  }
*/
  String url = "/";
  Serial.print("requesting URL: ");
  Serial.println(url);

  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "User-Agent: BuildFailureDetectorESP8266\r\n" +
               "Connection: close\r\n\r\n");

  Serial.println("request sent");
  while (client.connected()) {
    String line = client.readStringUntil('\n');
    if (line == "\r") {
      Serial.println("headers received");
      break;
    }
  }
  
  String line = client.readStringUntil('\n');
  if (line.startsWith("{\"state\":\"success\"")) {
    Serial.println("esp8266/Arduino CI successfull!");
  } else {
    Serial.println("esp8266/Arduino CI has failed");
  }
  Serial.println("reply was:");
  Serial.println("==========");
  Serial.println(line);
  Serial.println("==========");
  Serial.println("closing connection");
}

void loop() {
    if (Serial.available() > 0) {
      char myc = Serial.read();
      Serial.print(myc);
      Serial.print(" ");
    }
    /*  
       
    inChar = mySerial.read();
      if(inChar == '<') {
        READINGSTATUS = 1;
        inChar = mySerial.read();
      }else if (inChar == '>') {
        READINGSTATUS = 0;
      }

      if (READINGSTATUS == 1) {
        Data.concat(inChar);
      }
    }
    
    if( READINGSTATUS == 0) {
      parseInput();
      READINGSTATUS = -1;
    }
    */
    delay(50);
}

I already have a Serial communication for my debuging monitor. That is why I defined a bthSerial.begin(XXXX);

(why do you want to use BT when you have wifi capability? but that's another story)

OK then you need Sowftare Serial indeed. install the library i pointed at above (the one for ESP8266), include that library in your code and instantiate a SowftareSerial object using the right pins. then you can discuss with that instance just like you would do with a Serial Port - same APIs. best not to push too fast the baud rate and keep data rates reasonable as otherwise you'll run in troubles (the ESP needs also time to maintain the wifi stack)

I use BTH for authorization/security purposes due to the range of the technology. Ok then, the only thing left is to define the pins. Since I want to use the default TX/RX pins I must start a SoftwareSerial(D9, D10). Am I correct?

Double check which Dx match to for real GPIO and based on information provided above you should be in good position to see it that makes sense

GPIO1 -> TXD0 is index No 10
GPIO3 -> RXD0 is index No 9

I have triple checked that. So I code

SoftwareSerial(D9, D10);

but it is not working. I have also checked with 9600 or 115200 baud rate. Any ideasJ-M-L?

 SoftwareSerial([color=red]D9[/color], [color=blue]D10[/color]);
static const uint8_t [color=red]D9[/color]   = 3;
static const uint8_t [color=blue]D10[/color]  = 1;

So you are mapping to GPIO 1 and 3

Now as mentioned above you know that Serial uses UART0, which is mapped to pins GPIO1 (TX) and GPIO3 (RX).

So you are doing again the declaration of Software Serial on the Hardware Serial Pins, which you use for Serial.print etc.... so it can't work...

--> long story short, you need to pick other pins for your Software Serial. as mentioned above the GPIO available for this are checked in the code

bool SoftwareSerial::isValidGPIOpin(int pin) {
   return (pin >= 0 && pin <= 5) || (pin >= 12 && pin <= MAX_PIN);
}

--> that means GPIO 0 to 5 or GPIO 12 to MAX_PIN (depends on how many pins are mapped to your board)

I gave you above the mapping between GPIO and D# notation

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;

so you have all the info needed to pick pins that are

  • Valid for Software Serial
  • Not clashing with the Hardware Serial
  • Not used by your sensors

makes sense?
Think a bit about it....

thank you for your help. I solved it :wink: have a nice night.

Fantastic - have fun!!