Introduction: Flash ESP-01 (ESP8266) Without USB-to-serial Adapter Using Raspberry Pi

This Instructable guides you on how to start programming your ESP8266 microcontroller on an ESP-01 WIFI module. All you need to get started (besides the ESP-01 module, of course) is

  • Raspberry Pi
  • Jumper wires
  • 10K resistor

I wanted to refurbish an old bedside lamp into modern Alexa controlled LED night lamp. Nothing fancy just turning it on/off using voice command. I ordered the simplest ESP-01 WIFI module, relay and wire with LEDs online, and totally forgot to order USB-to-serial adapter to program ESP8266 microcontroller. But since I had a Raspberry Pi and both the Raspberry Pi and the ESP-01 board had UART pins, I figured I could use my RPi to program ESP8266 without the adapter.

Step 1: Configure Rapberry Pi

I used Raspberry Pi 3 Model B+, however, instructions should work on other versions, especially on model B.

So, first things first - we need to enable UART on Pi.

Go RPi configuration settings. In terminal window run

$ sudo raspi-config

Go to 5 Interfacing Options, then selectP6 Serial. You then prompted Would you like a login shell to be accessible over serial? selectsince we don't want to use UART to run the Pi headless, but to communicate with other devices, hence on the following screen when asked Would you like the serial port hardware to be enabled? select . Restart the Pi as prompted. UART should now be enabled for Serial Communication on RX and TX pin of Raspberry Pi 3. Note: after this there should appear a new entry enable_uart=1 at the end of /boot/config.txt.

Step 2: Connect ESP-01 to Raspberry Pi

Now we get down to wiring everything together.

Firstly, identify on your RPi 3.3V powerand GND (ground) pins to power ESP8266 microcontroller, TXD (transmit) and RXD (receive) pins to communicate, and two general purpose pins to operate ESP8266 (pins that can be set either high or low). Look up pin arrangement on pinout.xyz or type in terminal:

$ pinout

Secondly identify necessary pins on ESP-01. But in the beginning we need to have understanding of the ESP-01 pins. I found a number of helpful resources available on the internet to assist you in that regard. This one is being the shortest, while this one gives so much better explanation. In short: There are 8 pins, we are going to need 7 of them, namely VCC power and GND (ground) pins for power, TXD and RXD pins for communication, and RST (reset), CH_PD (Chip Power Down, sometimes labeled CH_EN or chip enable) and GPIO0 to operate the module. Usually ESP8266 operates in a regular mode, but when uploading a code to ESP8266 it heeds to be in a flash mode. For regular or normal operation mode the module needs to be connected to power (obviously), but also the pin CH_PD has to be connected to VCC via a 10K (this value varies in different recourses, I found values down to 3K) pull-up resistor at boot. on the other side, to enter flashing or programming mode you need to ground GPIO0 pin at boot. To prevent unrestricted current flow via GPIO0 when grounded it is recommended to connect GPIO0 to ground via some low resistance resistor 300Ω - 470Ω (more on this here). The RST pin as the name suggests resets (or restarts) the MCU. During normal operation it may be connected to VCC via a 10K pull-up resistor, but should be grounded to reset the microcontroller. While it is always possible to use physical buttons to ground RST and GPIO0 pins (or even manually join wires to simulate a button), it is much more pleasing experience to use Raspberry Pi pins to set voltage high and low on the module's RST and GPIO0 pins. Also there is no need in 10K and 470Ω resistors then.

Now being aware of the ESP-01 pins peculiarities, we can start connecting everything together. You may use the following table as a reference along with the drawing above:

ESP-01 < - > Raspberry Pi

  • VCC (3.3V) < - > pin #1 (3.3V)
  • GND < - > pin #6 (GND)
  • TXD < - > pin #10 (RXD / BCM 15)
  • RXD < - > pin #8 (TXD / BCM 14)
  • CH_PD < - 10K resistor - > pin #1 (3.3V)
  • RST < - > pin #3 (BCM 2)
  • GPIO 0 < - > pin #5 (BMC 5)

Connect VCC pin the last. The instance you connected VCC pin your Wi-Fi module will turn on. Use screen or minicom to check if RPi and ESP8266 can communicate using UART (note: you may need to install screen or minicom first, as they are not seem to be installed on Raspbian by default).

Using screen run:

$ sudo screen /dev/serial0 115200

Using minicom run:

$ sudo minicom -b 115200 -o -D /dev/serial0<br>

Note: many online resources suggest connecting to ESP8266 on /dev/ttyAMA0, but this does not work of RPi 3 or later (including zero W) as per RPi documentation. Connect via /dev/serial0 instead or /dev/ttyS0.

After you entered screen or minicom, use AT commands to communicate with ESP8266. Type in AT, then press Enter and then press Ctrl+J to send command. You should get OK in response. List of available AT commands can be found on espressiff.com or just here.

Ones the devices are physically connected and talk to each other we can get down to programming the RPi GPIO pins and, finally, the ESP8266 itself.

Step 3: Software Setup (Python to Operate and Arduino IDE to Program)

PART 1. Using python to switch ESP8266 modes

As mentioned above it is convenient to use RPI's GPIO pins to switch operation modes of ESP8266. I wrote two basic python codes that put ESP8266 into regular or programming mode.

  • Regular mode: To put the microcontroller in to regular operation mode we just need to power it and connect CH_PD via pull-up resistor to VCC, but to switch the MCU from programming to normal mode we need to reset it (think restart). To do that on RPi we are going to briefly pull down the RPi's GPIO connected to RST pin on ESP-01 (by default the RPi pin I used for resetting is set to HIGH). How briefly? For me that is a speculative question. You can try different time intervals, but I found that 200 - 500 ms work just fine. Write in comments if you've got a better idea. Save your code as reset.py.
#!/usr/bin/python

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD) # sets GPIO identification by physical pin numbers
resetPin = 3 # identify RPi physical pin connected to ESP8266 RST pin

GPIO.setup(resetPin, GPIO.OUT) # set reset pin as output

GPIO.output(resetPin, GPIO.LOW) # drop voltage on RST pin
time.sleep(.2) # wait for .2 s
GPIO.output(resetPin, GPIO.HIGH) # restore voltage on RST pin

GPIO.cleanup() # reset pins on RPI to prevent future runtime warnings
  • Programming mode: To put the MCU into programming mode we need to power the ESP8266 with GPIO0 grounded, or alternatively reset it and ground GPIO0 while booting (again exact duration of the voltage drops is not quite known to me, so don't be strictly guided by used values). Save code as flash.py or download below. The succession of actions is the following:
    • pull down RST pin
    • pull down GPIO0 pin
    • pull up RST pin
    • pull up GPIO0 pin
#!/usr/bin/python

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD) # sets GPIO identification by physical pin numbers
resetPin = 3 # identify RPi physical pin connected to ESP8266 RST pin
flashPin = 5 # identify RPi physical pin connected to ESP8266 GPIO0 pin

GPIO.setup(resetPin, GPIO.OUT) # set reset pin as output
GPIO.setup(flashPin, GPIO.OUT) # set flash pin as output

GPIO.output(resetPin, GPIO.LOW) # drop voltage on RST pin
time.sleep(.2) # need for this waiting is speculative
GPIO.output(flashPin, GPIO.LOW) # drop voltage on GPIO0
time.sleep(.2) # need for this waiting is speculative
GPIO.output(resetPin, GPIO.HIGH) # start booting ESP8266
time.sleep(.5) # wait for ESP8266 to boot
GPIO.ouput(flashPin.GPIO.HIGH) # restore voltage on

GPIO pinGPIO.cleanup() # reset pins on RPI to prevent future runtime warnings

In terminal change permissions:

$ sudo chmod +x flash.py
$ sudo chmod +x reset.py

From now on whenever you need to enter programming mode run in terminal:

$ python <path to your file>/flash.py

after uploading code to enter normal operation mode run:

$ python <path to your file>/reset.py

At this point you may also want to update ESP8266 firmware. There are many online tutorials on how to do that, so I will not be going into details on how to do that.

PART 2. Setting up Arduino IDE

if you already have Arduino IDE installed, you still may want to skim through the section making sure your IDE is ready for ESP8266.

On Rapberry Pi you can use Arduino IDE to program your ESP8266. There are two ways to install the IDE on RPi:

  • via command line from repositories using apt-get install
  • download and install manually from arduino.cc.

I strongly suggest going the latter path. The IDE version from repositories seems to be obsolete and you will most certainly have to do more before you are ready to start programming ESP8266. To avoid the hassle, go to Arduino.cc download page and download Linux ARM version. Next uncompress and install: If the name of the downloaded file looks something like this arduino-X.Y.Z-linuxarm.tar.xz, in the download folder run:

$ tar -xvf arduino-X.Y.Z-linuxarm.tar.xz

This should uncompress the file to arduino-X.Y.Z folder. Run:

$ sudo ./arduino-X.Y.Z/install.sh

This should install the IDE. After the installation is complete, start the IDE.

  • From the Arduino IDE go to File > Preferences. Look for “Additional Board Manager URLs” at the bottom of the preferences window. Enter http://arduino.esp8266.com/stable/package_esp8266com_index.json into the “Additional Board Manager URLs” field, click the “OK” button.
  • Go to Tools > Board: XXX > Boards Manager. In the window use search or scroll down, select the ESP8266 board menu and click install. Wait for the installation to complete and close the window.
  • Again go to Tools > Board: XXX and look for ESP8266 boards. Choose Generic ESP8266 Module.

Now IDE is ready to program ESP8266. Type in or paste desired code into IDE window and save it. Click Upload. From terminal run flash.py, this should put your board into programming mode. Wait a few minutes for the IDE to finish compiling and uploading (note: ESP-01 typically comes with 2 LEDs, the blue LED will flash while the code is being uploaded) and run reset.py. Now your ESP-01 board is ready to perform duties.