Skip to main content
Background Image
  1. Blogs/

Programming a Non-Programmable ESP8266 Board

Table of Contents
See how I repurposed the ESP module from a more or less useless and limited commercial board for my own project.

If you are like me, you want RGB lights in everything. Be it your mouse, your keyboard, or heck even your room. Therefore, to fulfill this colorful need, I started working on a project to install the addressable WS2812B LEDs to the shelves in my room. The plan was simple: use an ESP8266-based board (specifically the Wemos D1 Mini) with WLED installed as the main controller, hook it up the LEDs and use the WLED Android App to control the LEDs.

A sneak peek of the finished project

If you are interested in making the project yourself, you can go through and follow the steps in my Instructable.

So as with any project, I hopped on the Delhi metro, arrived at the local market and bought all the required stuff including the LED Strip, Wemos D1 Mini board, an IRF540N n-channel MOSFET, some JST Connectors and screw terminals etc.

Anyways, back to the story. So, after getting all the stuff I returned home, connected the Wemos D1 Mini to my laptop, selected the correct port in Arduino IDE and uploaded the blink LED sketch to test the board. Aaaaand it didn’t work 🥲

Upon close inspection, I found some weird stuff going on with the board!! And with that came a realization…

Never Blindly Trust the Stuff You Buy
#

So here’s the problem: Whenever the board is connected, a serial port shows up in the Arduino IDE but no matter what, you cannot upload any code to it. Even dmesg shows that it is loading a driver for the FT232RL USB-to-UART Chip!

dmesg output when the Wemos D1 Mini board was connected. It shows that the Kernel is loading the drivers for the FT232RL USB-to-UART

Even the windows device manager does the same: assigns FT232 drivers for the device but the result is still the same. We can see the idVendor in the dmesg output as 0403 and a quick google search shows that this Vendor ID indeed belongs to FTDI (this is the company that manufactures the FT232RL chip). But here’s the catch:

If you read the Official Wemos Documentation for the D1 mini, it shows that the board uses CH340 as the USB-to-UART Converter not the FT232R! 😵‍💫

Sooooo, what the hell is happening here?

To find some answers I turned to the board specifically to see if it was actually using the FT232. And guess what? The name of the IC is erased off…🥲 Believe me when I say this does not end here. It gets better.

The Wemos D1 Mini board backside that shows the USB-to-UART chip with no name

I opened up the pinout of FT232R and the CH340 side by side, powered the board and started probing some pins with my multimeter to see which pinout it matches. Aaanddd…drum rolls please…it matches the pinout of the CH340 IC!! So, it is indeed CH340 but it acts like FT232R causing the OS to load the wrong drivers and resulting in the board not working.

So people, that’s why you should never completely trust the stuff you buy locally. As for me, I kept the board aside for further investigations and turned to next closest thing to an ESP-based board I had at the ready. This turned out to be the Bolt IOT Wifi Module which I had bought about 3 years back but never used once.

The Bolt IOT wifi module

If I had this, then why didn’t I go with it in the first place? Well, because although the WEMOS D1 Mini and Bolt IOT wifi module both use the same ESP-12E at its core, there is a big difference. While the Wemos D1 Mini is a developement board and can be programmed through USB for any application, the Bolt IOT Wifi Module is, in fact, a module. It comes pre-flashed with some code that allows you to program it through the Bolt IOT cloud platform (or app) or you can hook it up to an Arduino as a wifi module. The module itself does not have any USB-to-UART Converter on board. In my opinion, this feels like of a waste of capability of the ESP-12E module as it prevents standalone use of the board which I wanted in my case. So, let’s see how I worked my way around this.

The ESP-12E Bootloader Modes & How it gets Programmed
#

To understand how I used the Bolt IOT Wifi Module for this, we first need to understand the bootloader modes of the ESP-12E module. When we power up the ESP-12E module, there are 3 different modes the moduel can enter:

  • Normal Mode
  • UART Programming Mode
  • SD-Card Boot

Here we only care about the Normal Mode and the UART Programming Mode. Normal Mode or the Flash Start-up Mode, as the name suggests, loads the program saved in the module’s internal flash and starts executing it. This is mode we are most familiar with. The UART Programming Mode is the one which allows you to upload a new program to the module’s flash memory through UART. The bootloader which gets selected when the device powers up or is reset, depends on the state of some of the GPIOs. Below you can find a table that shows the required GPIO states for different bootloader modes.

Bootloader ModeGPIO 0GPIO 2GPIO 15
Normal Mode110
UART Programming Mode010
SD Card Boot001

From the table above, we can easily infer that the state of GPIO 0 is the main deciding factor for our desired bootloader modes as the other two GPIOs have the same state in both cases. Apart from this, if the RESET pin gets connected to GND, the board resets and again selects the bootloader mode accroding to the states of the above GPIOs. Below you can find a pinout diagram of ESP-12E for reference.

ESP-12E module pinout. Credits: Random Nerd Tutorials

So basically this is what we need to do to make the ESP-12E on the Bolt IOT Module Programmable:

  • Pull GPIO 2 up
  • Pull GPIO 15 down
  • Have some sort of mechanism to change the state of GPIO 0 as required
  • Have a push button connected to the RESET pin that connects it GND when pressed

Upon inspecting the ESP12-E on the Bolt IOT Module these are the things I found:

  • RESET Pin was left floating
  • GPIO2 was left floating
  • GPIO15 was connected to the GND Plane
  • GPIO0 was left floating. Since the board already had a program flashed for OTA (over the air) uploads they don’t need the GPIO0

Making the ESP-12E on the Bolt IOT Module Programmable
#

So from the above points I knew I had to only:

  • Connect GPIO2 to VCC through a pull up resistor
  • Connect a push button to RESET that connects it to GND when pressed. We can name this the ‘Reset’ button.
  • Connect a GPIO0 to a push button that connects it to GND when pressed. We can name this the ‘Boot’ button.
  • Have a 6 Pin female header that exposes the TX, RX and GND pins for connecting an external USB-to-UART Converter Module to program the module

Here’s a schematic of how this was done:

A schematic of the setup I made. It does not show the connections of the Bolt IOT module like the voltage regulator, on-board LEDs, etc.

Once this is done, to program the mode we can simply press the Boot button and then reset the board using the Reset button. This will send the board in the Programming Mode and then we can hook up the external USB-to-UART module and upload a program to the board!

Note: You might have seen the same two buttons (Reset and Boot) on some ESP-based boards like the NodeMCU or ESP32. These work on the same principle.

Note: You also might have noticed that you don’t have to do play with these buttons everytime on a board like the NodeMCU. Heck the Arduino UNO does not even have a Boot button. So, how are they changing the bootloader modes? This is where the USB-to-UART IC comes in. It automatically sends some signals to the required pins and changes the bootloader modes when you press the upload button on your Arduino IDE.

Here are some photos of the final soldered setup on a perf board for the final project:

The Bolt IOT wifi module with the wires soldered on required GPIOs
Above schematic soldered on a perf board

And here are some images of the final project:

Related

Making a Servo Tester with 555 Timer - Part 1
Functional Weeder
Built a fleet of two line-following robots with custom 3D-printed pick-and-place mechanisms during the e-Yantra Robotics Competition 2021–22. Developed algorithms for grid-based path planning, mapping, fleet management, PID-based line following and manipulation in Elixir. Selected among the top 5 teams out of nearly 300.
Gazebo Community Meeting August'21
Showcased my internship project at Technoyantra, one of the early open-source demonstrations integrating ROS 2, Nav2, SLAM Toolbox, and Ignition Gazebo for the in-house AMR, IGT.
Gazebo Community Meeting Nov'24
Showcased our project for the NASA SpaceROS Summer Sprint Challenge 2024, featuring custom Gazebo plugins for extraterrestrial simulations.
LED Coffee Table
Made in collaboration with the Hatchnhack Makerspace in Delhi, we made a complete coffe table with a 12x12 LED Matrix inside for playing interactiveness and cool animations. The project used WS2812B LEDs with an ESP32 Dev Board at the heart for the controls
MR (ModulaR) Robot
Our in-house custom designed and fabricated AMR at A.T.O.M. The hardware and software design follows a modular architecture making this fitting for the multiple applications, hence the name MR (ModulaR) Robot.
ROS Meetup, IIT Delhi'22
Showcased my internship project at Acceleration Robotics India about developing custom plugins and 3D models for open world outdoor simulations in Gazebo
ROS Perception Pipeline
An open source project being developed as part of A.T.O.M Robotics Lab. The project is intended to work as a one-stop solution for easily deploying perception pipelines with common applications like object detection, image segmentation, image pre processing, etc. The project follows modular plugin-based architecture much like Nav2 in concept. The project is actively used in A.T.O.M’s in-house mobile robot - MR Robot
ROSCon India 2023
Presented my GSoC’23 project, “Automatic Computation of Moments of Inertia of SDFormat Links,” with the Gazebo team at Open Robotics