Micro Python on ESP8266 (HUZZAH ESP8266)

The ESP8266 is a low cost 80 MHz microcontroller with a full WiFi support. It can be found on several breakout boards, with Adafruit’s HUZZAH ESP8266 being one of the better ones. For about $10 you can own a small internet connected microcontroller that can be programmed in MicroPython.

ESP8266

  • 64 KB of instruction RAM
  • 96 KB of data RAM
  • 4 MB of  FLASH Memory

Breakout Board

  • 1 x Analog input (1.0V max)
  • 9 x GPIO (3.3V logic), which can also be used for I2C or SPI
  • 2 x UART pins
  • 2 x 3-6V power inputs, reset, enable, LDO-disable, 3.3V output

GPIO and Power Levels

RX and TX (aka GPIO1 and GPIO3) are the serial control and bootloading pins and can be found on the right side as well as on the bottom of the board.

RX and V+ are the only 5V compliant pins. TX, the output from the module and is 3.3V logic. All GPIO pins are 3.3V in and out, and are not 5V compatible.

The Analog Pin (A, top left), has a 1.0V maximum voltage.

Micro Python

MicroPython is a tiny open source Python programming language interpreter that runs on small embedded development boards.

Get started by installing Python3, and then pip-install esptool and adafruit-ampy:

pip3 install esptool --upgrade
pip3 install adafruit-ampy --upgrade

The breakout board does not provide a usb socket, a USB to TTL Serial Cable is needed to communicate with the device. Using such a cable with a FTDI chip comes with the advantage that drivers are preinstalled on macOS (even when using an Apple-Silicon based Mac).

Flashing Micro Python on the ESP8266
With an USB to Serial Cable attached to the Mac and the ESP8266 Breakout Board, the ESP needs to be put into “Boot-loading Mode”. For that to happen, press and hold the GPIO button (button on the right) and then press and release the Reset button (button on the left). The red LED between those two buttons should be on now but dim.
Once the device is in boot-loading mode, start with erasing the flash memory:

esptool.py --port /dev/tty.usbserial-A900gcOO erase_flash
esptool.py v4.3
Serial port /dev/tty.usbserial-A900gcOO
Connecting...
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting...
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: 18:fe:34:fe:a3:ba
Stub is already running. No upload is necessary.
Erasing flash (this may take a while)...
Chip erase completed successfully in 0.0s
Hard resetting via RTS pin...

Download the latest stabile MicroPython Firmware for ESP8266 with more than 2MB Espressif boards: (currently v1.19.1) and flash it onto the board:

esptool.py --port /dev/tty.usbserial-A900gcOO --baud 115200 write_flash --flash_size=detect 0 ~/Downloads/esp8266.bin
esptool.py v4.3
Serial port /dev/tty.usbserial-A900gcOO
Connecting....
Detecting chip type... Unsupported detection protocol, switching and trying again...
Connecting...
Detecting chip type... ESP8266
Chip is ESP8266EX
Features: WiFi
Crystal is 26MHz
MAC: 18:fe:34:fe:a3:ba
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Flash will be erased from 0x00000000 to 0x0009afff...
Flash params set to 0x0040
Compressed 634844 bytes to 419808...
Wrote 634844 bytes (419808 compressed) at 0x00000000 in 37.3 seconds (effective 136.1 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

After a reset,

screen /dev/tty.usbserial-A900gcOO 115200

will show the python prompt and entering help(), will display the following output:

Welcome to MicroPython!

For online docs please visit http://docs.micropython.org/en/latest/esp8266/ .
For diagnostic information to include in bug reports execute 'import port_diag'.

Basic WiFi configuration:

import network
sta_if = network.WLAN(network.STA_IF); sta_if.active(True)
sta_if.scan()                             # Scan for available access points
sta_if.connect("", "") # Connect to an AP
sta_if.isconnected()                      # Check for successful connection
# Change name/password of ESP8266's AP:
ap_if = network.WLAN(network.AP_IF)
ap_if.config(essid="", authmode=network.AUTH_WPA_WPA2_PSK, password="")

Control commands:
  CTRL-A        -- on a blank line, enter raw REPL mode
  CTRL-B        -- on a blank line, enter normal REPL mode
  CTRL-C        -- interrupt a running program
  CTRL-D        -- on a blank line, do a soft reset of the board
  CTRL-E        -- on a blank line, enter paste mode

For further help on a specific object, type help(obj)

and CTRL-D shows the current OS version: E.g.,:

MPY: soft reboot
MicroPython v1.19.1 on 2022-06-18; ESP module with ESP8266
Type "help()" for more information.

How much Memory?

>>> import gc
>>> gc.collect()
>>> gc.mem_free()
36512
>>>

.. gc.mem_free() returns the free heap size in bytes. Therefore, about 35 KBytes of Heap Memory is available.

Modules

>>> help('modules')
__main__          math              ucollections      ure
_boot             micropython       ucryptolib        urequests
_onewire          neopixel          uctypes           urllib/urequest
_uasyncio         network           uerrno            uselect
_webrepl          ntptime           uhashlib          usocket
apa102            onewire           uheapq            ussl
btree             port_diag         uio               ustruct
builtins          ssd1306           ujson             usys
dht               uarray            umachine          utime
ds18x20           uasyncio/__init__ umqtt/robust      utimeq
esp               uasyncio/core     umqtt/simple      uwebsocket
flashbdev         uasyncio/event    uos               uzlib
framebuf          uasyncio/funcs    upip              webrepl
gc                uasyncio/lock     upip_utarfile     webrepl_setup
inisetup          uasyncio/stream   upysh             websocket_helper
lwip              ubinascii         urandom
Plus any modules on the filesystem

Builtins

>>> import builtins
>>> dir(builtins)
['__class__', '__name__', 'ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'EOFError', 'Ellipsis', 'Exception', 'GeneratorExit', 'ImportError', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'NotImplementedError', 'OSError', 'OverflowError', 'RuntimeError', 'StopIteration', 'SyntaxError', 'SystemExit', 'TypeError', 'ValueError', 'ZeroDivisionError', 'abs', 'all', 'any', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'dict', 'dir', 'divmod', 'eval', 'exec', 'getattr', 'globals', 'hasattr', 'hash', 'id', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'list', 'locals', 'map', 'next', 'object', 'open', 'ord', 'pow', 'print', 'range', 'repr', 'round', 'set', 'setattr', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'zip', '__build_class__', '__import__', '__repl_print__', 'StopAsyncIteration', 'UnicodeError', 'ViperTypeError', 'bin', 'delattr', 'enumerate', 'filter', 'float', 'frozenset', 'help', 'hex', 'input', 'max', 'memoryview', 'min', 'oct', 'property', 'reversed', 'slice']
>>>

Blinky

Assuming that Wifi won’t work any different than on the ESP32, let’s blink an LED, connected to GPIO5 and GRN.

""" Blinky ESP8266 - main.py
"""
import time
from machine import Pin

p = Pin(5, Pin.OUT)
state = True
while True:  
  p.value(state)
  state = not state
  time.sleep(1)

With adafruit-ampy installed, the main.py script can be deployed like so:

ampy --port /dev/tty.usbserial-A900gcOO put main.py

Demo Video

esp8266blinky

Leave a Reply