Flashing ESP8266 with NodeMCU (Windows, Linux, Arduino and Raspberry Pi)

How to flash NodeMCU on ESP8266 boards via serial port or Arduino

Each time when I’m unable to find a coherent guide on a single page within three pages of Google search, I’m creating an article like this. Flashing ESP8266 is easy if you know what you are doing already and you have the research done already. The ESP8266 flash guide supposes to make it easy regardless. In short, the aim of this piece is to end up on one of first three pages of Google. I will be using the ESP8266-01, but the guide should be relevant to all the ESP8266 boards.

ESP8266 Flash Guide

There are few ways to flash your ESP8266 board depending on the tools you might have at your disposal. Please don’t jump to the selected method just yet. There are few things I’d like to address, that will apply to each section.

Issue no 1

Always double-check the jumper cables. You may discover a good guide online, but when your cables are messed up, it’s not going to help you. I have made this mistake before. I was sure 100% all the cables are connected correctly, just to be proven wrong few moments later. Always double-check the jumper cables, if the flash is not successful check the cables! I think I stressed it enough now.

Issue no 2

ESP8266 is a 3.3V board. Unless it comes as a dev board with power regulator or similar, make sure to use a correct power supply. While we are talking electricity, the current must be sufficient to flash the board successfully. 500mA supply is recommended. USB 2.0 port should be enough to deliver it.

Support NotEnoughTech


Start with the software, mostly because download will take you few moments, this will give you some time to hook up the jumper cables correctly. You will need several programs. Once the firmware is flashed, you will use only one.

Software requirements:

Hardware Hookup

Get serial port adapter  (FTD1232) if possible, you can also use Arduino Uno to flash the firmware.

Take a closer look at your serial port adapter. There are 2 ways to connect your ESP8266, but before you do this make sure your adapter is not running at 5V. Mine has a bridge which selects the 3.3V and 5V. You want to make sure that ESP8266 is running on 3.3V.

Another thing to note is the DTR pin. The FTD1232 has that pin available, other adapters may not.

ESP8266 FTD1232 DTR FTD1232 no DTR Arduino Uno
Tx Rx Rx Tx
Rx Tx Tx Rx
GPIO 16/RST GND (don’t connect) GND (don’t connect) GND (don’t connect)

Don’t use external power, it can mess up the flash process. Connect cables as per the table above. For GPIO16/RST – reset pin use female-male cable and leave it hanging from the ESP8266. You will need it to touch the GND pin to reset the ESP.

If you have more than 2 ESP8266 consider making an adapter, reconnecting the cables each time is annoying. I have a nice build log here.

If you are using the Arduino as the serial adapter you have to also connect the RESET pin on Arduino Uno to the GND. This will put the microcontroller into the adapter mode.

Lastly, check the cables again. It’s easy to get something wrong.


I will show you how to erase the flash, which could be the issue of all your troubles.It’s a good point to start and not many sources mention this step. If you are on Windows, you need Python 2.7 installed and the pyserial library (links above). If you are on Linux or a Raspberry Pi, things are little easier for you – just:

git clone https://github.com/espressif/esptool.git
cd esptool

The easiest way to get the ESP8266 into the flash mode is:

  1. Pull down the GPIO 0 (connect it to GND or DTR, DTR may not work with esptool)
  2. Start the flash (press Flash button or execute the cmd command)
  3. Reset the ESP8266 by pulling down the GPIO16/RST pin  (touch any of the GND pins with a male end)

Open the folder with esptool and bring up the cmd (right click +shift > Open command window here). Check what port has been assigned to your FDT1232 by bringing up a device manager.

If you are on Linux or Raspberry Pi use:

$ dmesg | grep tty

This should give you a device port name:


Run the command (python.exe path + esptool.py –port [your com port here] erase_flash)

>>c:\Python27\python esptool.py --port COM5 erase_flash

Execute the line and then immediately reset the ESP. You should see this:

If you on the Linux or Raspberry Pi, you can continue with the esptool, if you are using Windows you can now switch to the NodeMCU flasher tool.

I’ll continue with the esptool as we are one command away from the firmware flash:

>>c:\Python27\python esptool.py --port COM5 write_flash -fm dio -fs 8m 0x00000 C:\node1.bin

The command is built in the following way: (path to python) esptool.py — port [your com port] write_flash -fm [mode: dio for 4MB+, qio for <4Mb]) -fs (flash size 8Mb in my case) 0x00000 (path to bin file)

As before, execute the command and reset the ESP8266 by shorting the GPIO16/RST pin to GND.

If you are using Windows and NodeMCU flash tool the procedure is similar:

Then press flash and reset the ESP8266 by shorting the GPIO16/RST to GND:

The flash will take few moments and you will see the progress:

Once the flash is complete you are ready to upload your lua files. This is where the ESPlorer comes in handy. Disconnect the GPIO 0, we don’t need it any more. Set the baud rate to 115200 open the COM port and reset the ESP8266 by shorting the GPIO16/RST and GND. Your screen should look like this:

Congratulations. You are nearly done! While this is not a lua script tutorial I will provide you with a init script. Init is the file that loads on boot. It should contain the vital set up of your script. Avoid entering entire project into the init file, get the init file to set up your environment, connect to network and launch the needed scripts. It’s a good idea to create a wait in the init file in case you made a mistake. This way you will have few seconds to flash new init file even if your ESP8266 ends with a bootloop.

function startup()
    if file.open("init.lua") == nil then
        print("init.lua deleted or renamed")
signalPin = 3
gpio.mode(signalPin, gpio.OUTPUT)
gpio.write(signalPin, gpio.LOW)
print("Connecting to WiFi access point...")
wifi.sta.config("YOUR_SSID", "YOUR_PASSWORD")
-- wifi.sta.connect() not necessary because config() uses auto-connect=true by default
tmr.alarm(1, 1000, 1, function()
    if wifi.sta.getip() == nil then
        print("Waiting for IP address...")
        print("WiFi connection established, IP address: " .. wifi.sta.getip())
        print("You have 10 seconds to abort")
        tmr.alarm(0, 10000, 0, startup)

Support NotEnoughTech
A lot of time and effort goes into keeping NotEnoughTech alive! If my work helped you out, consider buying me a coffee or check out exclusive rewards available to Patreon supporters.