Getting Started with the ESP8266 and Arduino

The ESP8266 is a low cost serial wifi SOC device. It comes with an AT firmware for interacting with a host or MCU but it’s also a MCU with GPIO capabilities, and can run software. These are available from US suppliers from around $8 and around $3 (shipped) from China, but expect a few weeks or longer for delivery. Previously, wifi boards for use with Arduino would cost upwards of $30 or more!

Update: Since I wrote this post there are some better alternatives to use the esp8266 with Arduino. The NodeMCU board has breadboard friendly pinout and best of all can be programmed from the Arduino IDE. It even supports OTA firmware updates!

To communicate with the ESP8266 I’m using a 3.3V FTDI board and the Arduino IDE Serial console. At first I tried the 115200 baud rate and “Carriage Return” but didn’t get an OK. Then I selected 9600 for baud rate, and both NL & CR and sent an AT command and got back OK. What I found is many of the guides I found refer to the older firmware that defaults to 115K baud rate. Mine came with a newer AT firmware (which I updated, see below).

To get started, wire up the esp8266 to a 3.3V FTDI board.

Now run some AT commands

To change the baud rate use the AT+CIOBAUD command (older firmware)


If it responds with an ERROR, try AT+IPR


Remember to change the Arduino IDE baud rate.


[ Version:]

Firmware version


Act as station and access point


List networks


Join a network. This may take a few seconds


See if we got an ip address


Be a server (seems that it can’t be client and server at same time)


Listen on port


Note: On a power reset or restart, the esp8266 retains the access point configuration (CWJAP) but CMUX and CIPSERVER must be applied again.

Now from a host terminal, telnet to the device and send a message

telnet 1111

“Link” is sent when a client connects. Then the message follows


Note the size of 7, which includes the CR + LF characters.

To send a message back to telnet client we need to add 2 chars to the length for the CR + LF

> hi

Almost all the resources I found while searching for help reference the v0.9.2.2 AT Firmware.bin, yet it is no longer available for download on the site ( I found it here and there are some other obscure references to it as well. Later releases have multiple bin files in the “at” folder. The readme describes the address to load the bin files, where as for version it’s just a single file.

At some point later I started seeing some gibberish on restarts.

[ Version:]


The esp8266 pins are not 5V tolerant, so I’m using a logic level shifting board to interface with the Arduino. The logic level converter (LLC) board I purchased off ebay seems to be a clone of the Sparkfun LLC. The TX is bidirectional but the RX is directional and *only* works from high side to low side. So, accordingly I wired the ESP TX to the TX low pin and the ESP RX to the RX low pin. More info here

The logic level shifter is convenient to use on a breadboard but if you don’t have one or prefer a simpler solution, a voltage divider circuit can be substituted. I tested with three 1K resistors and it worked flawlessly at 9600 baud (Note: at higher rates it may not function as well). The ESP TX can safely be connected to the Arduino SoftSerial RX as the Arduino will register a 3.3V signal as HIGH.

Some guides show the CH_PD pin (Chip Enable) as not connected but my board would not respond to any command unless this pin was held at VCC.

Caveat: the esp8266 really should not be powered from the Arduino as the Arduino cannot supply quite enough oomph. Although it seemed to work as many others have found, it can fail in unexpected ways if the voltage drops. It’s recommended that the esp8266 be powered by an independent power supply, capable of providing ~300mA.

It’s possible to use other for SoftSerial but keep in mind that some digital pins are not supported by SoftSerial RX, as it requires interrupt support. I choose pin 8 for RX as it works for Leonardo and Atmega 328, but for Mega a different pin would need to be selected. SoftSerial TX can use any digital pin. For more information

On a succesful boot the ESP blue led flashes twice on power up then goes off until serial is received.

According to this diagram I have the ESP-01 version 2

Firmware update

There is no factory restore option with this firmware version, so the only recourse to get it to the initial state is reflashing. However I was unable to find the version of the firmware that came my device — google searches turn up nothing — so I used the firmware from espressif on github.

The official esp8266 firmware updating tool is a windows UI application but fortunately some awesome person wrote esptool, a command line tool for firmware updates. It is written in Python so should work on a variety of operating systems: Mac, Linux and Windows etc.

The esp wiki specifies the following connections for updating the firmware over UART. Of course this is in addition to Vcc, GND, TX and RX. All pins should be connected except RESET.

CH_PD → High. Enables the chip

GPIO0 → Low. Selects UART download boot mode

GPIO2 → High. Selects UART download boot mode

For more information refer to

Based on recommendations elsewhere, I have powered the device with an external 3.3V supply and only have the GND, TX and RX of FTDI connected. Oh, and make sure you don’t have the Arduino serial console open when using the esptool.

Get the tool from github

git clone

At this time the project was at commit



python install

Get the esp8266 AT firmware

git clone

Current commit


There are two options for the user1.bin: newer/user1.bin and v0.20/user1.bin; I arbitrarily chose the v0.20/user1.bin version, then later tried the newer version.

I flipped the power switch then started the command. At first I would get errors intermittently:

./ --port /dev/tty.usbserial-A4004Rim write_flash 0x00000 ../esp8266_at/bin/boot_v1.1.bin 0x01000 ../esp8266_at/bin/newest/user1.bin 0x7C000 ../esp8266_at/bin/esp_init_data_default.bin 0x7E000 ../esp8266_at/bin/blank.bin
Erasing flash…
Writing at 0x00000400… (100 %)
Erasing flash…
Writing at 0x00012c00… (33 %)
Traceback (most recent call last):
File “./”, line 536, in <module>
esp.flash_block(block, seq)
File “./”, line 195, in flash_block
struct.pack(‘<IIII’, len(data), seq, 0, 0)+data, ESPROM.checksum(data))[1] != “\0\0”:
File “./”, line 110, in command
raise Exception(‘Invalid response’)
Exception: Invalid response

I checked the pins were seated and tried a few more times and finally it worked. Another time I inadvertently left the Arduino IDE console open on the FTDI serial port. It would fail consistently with

serial.serialutil.SerialException: device reports readiness to read but returned no data (device disconnected or multiple access on port?)

Here’s the successful flash output

ceylon:esptool andrew$ ./ --port /dev/tty.usbserial-A4004Rim write_flash 0x00000 ../esp8266_at/bin/boot_v1.1.bin 0x01000 ../esp8266_at/bin/newest/user1.bin 0x7C000 ../esp8266_at/bin/esp_init_data_default.bin 0x7E000 ../esp8266_at/bin/blank.bin
Erasing flash…
Writing at 0x00000400… (100 %)
Erasing flash…
Writing at 0x00036c00… (100 %)
Erasing flash…
Writing at 0x0007c000… (100 %)
Erasing flash…
Writing at 0x0007ec00… (100 %)

Now unplug GPIO0 and GPIO2 to run AT commands.

Unlike the previous firmware, this firmware defaults to 115200, and expects \r\n.

ets Jan 8 2013,rst cause:4, boot mode☹3,7)
wdt reset
load 0x40100000, len 612, room 16
tail 4
chksum 0x12
load 0x3ffe8000, len 788, room 4
tail 0
chksum 0x50
load 0x3ffe8314, len 264, room 8
tail 0
chksum 0x4a
csum 0x4a
2nd boot version : 1.1
SPI Speed : 40MHz
SPI Mode : QIO
SPI Flash Size : 4Mbit
jump to run user1

Firmware version


I need a lower baud rate to use with SoftSerial on Arduino. I tried setting it to 9600 but got an error


After digging through I found the command has changed to AT+IPR.


But now if we run AT+RST again we non-ascii after the OK


Also tried flashing the “V0.20” version (esp8266_at/bin/V0.20/user1.bin) which seemed to work fine as well.

I attempted to try the Adafruit library but I did not work at all. I knew the bootmarker would not work since this firmware does not report “ready” @9600, but even without restart it would just timeout with errors.

Writing a Sketch

Update: I wrote an Arduino Library. It’s available at github

For my application I need to setup the esp8266 as a server to receive programming data. I really didn’t want to write the code to do this but I couldn’t find a solution anywhere. Interfacing with the esp8266 AT firmware programmatically is challenging since the command responses are not fixed length in many cases and some responses do not include a reliable delimiter to indicate when the response is complete.

The sketch looks for commands IPD (data), CONNECT, and CLOSE. Any other commands are ignored and actually reset the device. When an IPD arrives, the channel and data length are parsed, e.g


This command indicates the connection id is zero and the length is four. The IPD command always ends with CR,LF,O,K,CR,LF (5 characters), so it’s easy to parse by reading the data length characters plus five.

After parsing the data I return an ACK. First you tell the esp how many characters to send with the CIPSEND command.


This responds with


If “OK” is present in the response it is assumed to be successful.

if (strstr(cbuf, “OK”) == NULL) // error!

Then write the data to the client


The esp8266 retains the wifi connection config on a power cycle but it loses the config to act as a server. The reset procedure I use is

// close active connection
// stop server
// restart
// enable multiple connections (required for server mode)
// start listening

One issue I found is that while AT+CIPCLOSE=id triggers a input stream io error on the client, and I could reconnect after it completed, I would not receive data for a few minutes, although the socket writes where successful from the client point of view.


Next I wrote Java client to connect to the esp8266 and transfer data. I discovered a few quirks while developing the client. I found that if the data was sent by multiple calls to


(bytes are signed in Java), then multiple IPD commands would be received on the esp8266, even if flush was called after write calls.. To get around this behavior, I modified the code to instead call


I ran the client all night, continuously sending messages (of 32 bytes) after the ACK was received. I checked in the morning and it had sent over 256,000 messages with no errors, so not bad. The transmission rate was just a hair under 8 messages per second, so just under 256 bytes per second. This includes the Arduino process time and sending back an ACK, so the actual data speed is much higher.