ESP8266 Tutorial

ESP8266 on a carrier board.

The ESP8266 is a microcontroller WiFi module that allows you to connect to WiFi access points, or even create one. It is available as a tiny module or as a module on a carrier board. The one I chose is an ESP12, with a "large" white carrier board. The board is too wide for a breadboard, but if you connect two breadboards as shown, with a power strip between them, it will fit perfectly.

This tutorial concentrates on using WiFi endpoints in a client and server application on your existing WiFi network. Future tutorials will cover creating a new WiFi network using the ESP8266 as an access point.

What does it do?

The ESP8266 and its variants are designed to provide the average microcontroller with WiFi access. This can be in the form of a client, or user, or as an access point for other clients, or as both an access point and a client. It communicates with the microcontroller at 115kBaud, although it can be set to talk slower if need be. Because it is easier to use a board with two hardware serial ports, I chose the Teensy3.1 for this tutorial. If you don't have one, you could use the Arduino Due. If you choose to use a basic Arduino model, you'll have to make one serial port using a software serial driver, and you'll have to use level shifters on the input lines of the ESP8266, unless you use a 3.3V version.

What are some common problems?

  • First, the power supply. The WiFi module draws up to 270mA. I had a weak supply, which caused all of the commands that sent data over WiFi to fail. You can't use the 3.3V output of a typical Arduino to power it.
  • If you see the device connect to then disconnect from your wireless router, try the station DHCP settings. See the bottom of the page for how to fix that problem.
  • Commands end with CR+LF, not just a CR or LF. Make sure your terminal program is set up for CR+LF.

Building a Client/Server application

There are times when you may want a small IoT-like server hanging off of your wireless router for access by other devices. To do that you can create a server that listens on a TCP port and responds to specific messages. The interchange to do that looks something like this:

ClientServerComment
AT+CIPMUX=1Set the MUX on the server
OK
AT+CIPSERVER=1,80Start the server listening on chnl 1, port 80
OK
AT+CIPMUX=1Set the MUX on the client
OK
AT+CIPSTART=1,"TCP","10.0.1.97",80Make the client connect to the server
0,CONNECT0,CONNECTBoth connect
AT+CIPSEND=1,10Tell the client to send 10 characters
>0123456789Type in 10 characters
Recv 10 bytesClient received 10 characters (from you)
SEND OKSend worked
+IPD,0,10:0123456789Server received 10 characters from client
AT+CIPSEND=1,3Tell the server to send 3 characters to the client
>123Enter the three characters
Recv 3 bytesServer received from you
SEND OKServer sent to client
+IPD,0,3:123Client received 3 characters
AT+CIPCLOSE=1Tell client to close the connection
1,CLOSED0,CLOSEDClient and server both close

The responses are in light green. The ">" before the sent data is a prompt the ESP8266 throws out to indicate it is time to enter data. When you enter the last expected character, off it goes sending it. It doesn't wait for an enter key. The data is received on the other end in an "+IPD" packet that shows the mux channel, and the length of the data, followed by ":" and the data. Either end can issue the "AT+CIPCLOSE" command and the connection will be closed. If the client does not send something for a period exceeding the server timeout, the connection will be closed by the server.

The second command issued to the server is AT+CIPSERVER=1,80. The response is "OK". If it says anything else before the "OK", it probably didn't work. The same goes for the AT+CIPSTART=1,"TCP","10.0.1.97",80 command to the client. "OK" is good, anything else is bad. Generally speaking, if the server command didn't work, it wasn't preceeded by AT+CIPMUX=1. The same holds true for the client side. But make sure you are connected and have an IP address. AT+CIPSTA? tells you.

With this in mind, I built a TCP server that responds to the word "MAGIC". Connect digital pin 16 to the RESET pin on the ESP8266 carrier. Below the code is a list of serial commands for the client ESP8266. The code requires an Arduino or compatible with two or more hardware serial ports. I used a Teensy 3.1 from PJRC.

    
#define ESP_RESET 16

const char * mux = "AT+CIPMUX=1\r\n";
const char * server = "AT+CIPSERVER=1,80";
const char * resp_hdr = "AT+CIPSEND=0,";
const char * magic_resp = "xyzzy";
const char * cipsta = "AT+CIPSTA?\r\n";

void getIP()
{
  Serial1.print(cipsta);
  Serial.print(Serial1.readString());
}

int waitForOK()
{
  int tries = 3;
  String response;

  Serial1.setTimeout(1000);

  do
  {
    response = Serial1.readStringUntil('\n');

    if (response.startsWith("OK"))
      break;
  } while (--tries);
  return (tries > 0);
}

int waitForPrompt()
{
  int tries = 3;
  String response;

  Serial1.setTimeout(1000);

  do
  {
    response = Serial1.readStringUntil('>');

    if (response.endsWith(" "))
      break;
  } while (--tries);

  return (tries > 0);
}

int setupServer()
{
  String response;

  Serial1.print(mux);
  
  if (waitForOK())
  {
    delay(250);
    Serial1.print(server);
    Serial1.print("\r\n");
    
    if (waitForOK())
    {
      return 1;
    }
  }
  return 0;
}

void resetESP()
{
  String response;
  
  digitalWrite(ESP_RESET, LOW);
  delay(1);
  digitalWrite(ESP_RESET, HIGH);
  Serial1.setTimeout(5000);
  response = Serial1.readString();
}

void setup() {

  pinMode(ESP_RESET, OUTPUT);
  resetESP();

  // Setup computer to Teensy serial
  Serial.begin(115200);

  // Setup Teensy to ESP8266 serial
  Serial1.begin(115200);

  // Loop forever trying to start the server.
  while (!setupServer())
  {
    resetESP();
    delay(2500);
  }
  Serial.println("Server listening on port 80");
  getIP();
}

void loop() {
  String request = "";

  request = Serial1.readStringUntil('\n');

  if (request.length()) Serial.println(request);

  if (request.startsWith("0,CLOSED"))
  {
    while (!setupServer())
    {
      resetESP();
      delay(2500);
    }
  }
  if (request.startsWith("0,CONNECT"))
  {
    // Do client connect stuff here.
  }
  else if (request.startsWith("+IPD"))
  {
    if (request.endsWith("MAGIC"))
    {
      Serial1.print(resp_hdr);
      Serial1.print(strlen(magic_resp));
      Serial1.print("\r\n");
      if (waitForOK())
      {
        if (waitForPrompt())
        {
          Serial1.print(magic_resp);
        }
      }
    }
  }
}
    

When the server starts, which takes a few seconds, it prints the well known fact that it is listening on port 80, and then prints the results of the "AT+CIPSTA?" command, which is a pair of IP addresses and a netmask. The top IP address is the address of the server, assuming it successfully connected to the WiFi network. To connect with the server, the client must issue the following commands. The IP address is bogus, and should be replaced with your server's address.

    
AT+CIPMUX=1
AT+CIPSTART=1,"TCP","10.0.1.97",80
AT+CIPSEND=1,5
>MAGIC
    

If you hit enter after the word "MAGIC" you will trigger an error. Don't worry about that. It is not significant. The server will eventually respond with "xyzzy", a magical word. Use it with caution.

Notes:

All of this presupposes you have already connected to your WiFi router with both ESP8266 devices. If you have, they will automatically reconnect at power up. If you haven't connected them to the WiFi network yet, connect them to a 3.3V serial cable and 3.3V power supply and do this:

AT+CWLAP

The ESP will respond with a list of WiFi networks it can see. Then you would connect with the one you own, entering the network name (SSID) and the password. You can't enter apostrophes or a few other characters, so it would be a good time to shorten your SSID from "Bob's Ethernet Emporium" to simply "Bob". You'll know there is a problem if you get "Error" back. Of course, you won't know what the problem is because it sends the word "Error" for all errors.

AT+CWJAP="Bob","password"

The ESP will respond with something like "WIFI CONNECTED" and "WIFI GOT IP". If you then issue the "AT+RST" command, the ESP will reset, and should reconnect automatically with the router.

If, when you connect to your router, you get something like this:

    
AT+CWJAP="Bob","password"

WIFI CONNECTED
+CWJAP:1

FAIL
WIFI DISCONNECT
    

You have DHCP set wrong. The "WiFi Station" DHCP setting is funny. It is not asking "Should I use DHCP?" It is asking "Should I be a DHCP server?" So it looks backwards. To use DHCP to get an IP address, you need to disable DHCP by setting it to "1 - Disable".

AT+CWDHCP=1
Arduino Board Logo

 

Arduino-Board is the go-to source for information on many available Arduino and Arduino-like boards, tutorials and projects.

Help and Support

Arduino-Board

Stay updated

Sign up if you would like to receive our once monthly newsletter.