I got a cheap Espressif ESP8266 development board recently and reworked some of my previous Arduino projects. Comparing to Arduino Mega ATmega1280 that runs at 16 MHz + 8 KB of SRAM, ESP8266 is more powerful and feature rich. It integrates a 32-bit Tensilica MCU reaching a maximum clock speed of 160 MHz and a built-in Wi-Fi stack.

The dev kit ships with an eLua based NodeMcu firmware so I have to refresh a MicroPython firmware. Most of the ESP8266 GPIOs are multiplexed with other features like I2C, SPI, or UART.

NodeMcu Devkit Pin Map

Load MicroPython

Tony DiCola from adafruit has a very decent post on loading MicroPython on a board. The official instructions to deploy a new firmware to your dev board is in the getting started guide, to summarize, you need the following simple steps:

  1. Download latest firmware for ESP8266 boards
  2. Use esptool or to make your life easier, I recommend nodemcu-pyflasher
  • In Flash mode, select Dual Flash I/O (dio) for flash >= 4 MB
  • Remember to Erase flash if you are doing incompatible MicroPython upgrade, e.g., from 1.8 to 1.9
  1. Wait for Hard resetting... in Console and your board will reset
  2. Check for MicroPython REPL prompt if your board is still connected to your machine

REPL Prompt

REPL (Read Evaluate Print Loop) prompt is really an amazing feature in MicroPython. You can access the REPL either via a wired connection through UART serial port, or, more interestingly, via WebREPL (a prompt over WiFi). Unfortunately, I didn’t get WebREFL working on the 1.8.3 firmware image but the UART0 serial REPL works like a charm.

On a Ubuntu box, I can simply run:

$ picocom /dev/ttyUSB0 -b115200

If you get permission errors, you may need to add yourself to the dialout group. Please remember to logout and then log back in to take effect.

$ sudo usermod -a -G dialout $USER

Now, I can turn an LED on and off by the following code:

>>> import machine
>>> pin = machine.Pin(2, machine.Pin.OUT)
>>> pin.on()
>>> pin.off()

Connect to Network

After a fresh install, the device configures itself as a WiFi access point. The ESSID is of the form MicroPython-xxxxxx where x’s are part of the MAC address of your device. To automatically connect to WiFi network, here is a function to put in boot.py. More details are in the network basics.

def do_connect():
    import network
    sta_if = network.WLAN(network.STA_IF)
    if not sta_if.isconnected():
        print('connecting to network...')
        sta_if.active(True)
        sta_if.connect('<essid>', '<password>')
        while not sta_if.isconnected():
            pass
    print('network config:', sta_if.ifconfig())

I am using Tony DiCola’s handy Adafruit MicroPython tool ampy to copy python files to and from the internal file system. It is introduced in his MicroPython Basics: Load Files & Run Code post. Example usage:

$ ampy --port /dev/ttyUSB0 ls  # list contents of a directory on the board
$ ampy --port /dev/ttyUSB0 put boot.py  # put a file on the board
$ ampy --port /dev/ttyUSB0 get main.py  # retrieve a file from the board

Once the board is connected to your WiFi, you can write scripts to upload sensor data to the cloud or do REST calls to retrieve information from the Internet.

Updated on November 20, 2018

I am now building the MicroPython myself to customize the firmware. When I was using the make deploy target in the Makefile, I have to modify PORT and FLASH_MODE paramters to make it work with my dev board.

diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile
index 0bbb990d2..b83513144 100644
--- a/ports/esp8266/Makefile
+++ b/ports/esp8266/Makefile
@@ -17,9 +17,9 @@ FROZEN_MPY_DIR ?= modules
 include $(TOP)/py/py.mk

 FWBIN = $(BUILD)/firmware-combined.bin
-PORT ?= /dev/ttyACM0
+PORT ?= /dev/ttyUSB0
 BAUD ?= 115200
-FLASH_MODE ?= qio
+FLASH_MODE ?= dio
 FLASH_SIZE ?= detect
 CROSS_COMPILE = xtensa-lx106-elf-
 ESP_SDK = $(shell $(CC) -print-sysroot)/usr

I have also upgraded esptool to v2.5.1 in my esp-open-sdk fork to make automatic flash size detection work.