MicroPython on ESP32

Nick Moore
@mnemote
nick@mnemote.com

ESP32

original image: sherry-aithinker

ESP8266 CPU

ArduinoESP8266
AVR
ATMega328P
Tensilica
Xtensa LX106
8 bit32 bit
1 core1 core
20 MHz80/160 MHz
2 KB RAM160 KB RAM
32 KB Flash4 MB Flash

ESP32 CPU

ArduinoESP8266ESP32
AVR
ATMega328P
Tensilica
Xtensa LX106
Tensilica
Xtensa LX6
8 bit32 bit32 bit
1 core1 core2 core *
20 MHz80/160 MHz160/240 MHz
2 KB RAM160 KB RAM520 KB RAM
32 KB Flash1 - 4 MB Flash4 - 16 MB Flash

ESP32 Networking

ESP32 I/O

ESP IDF

IoT Development Framework

C SDK for building programs to run on ESP32

Contains LWIP, examples, instructions for building toolchain

MicroPython

micropython.org

MicroPython

MicroPython Platforms

For more background, see Damien's talk about the Kickstarter campaign from PyConAU 2016

Development of esp32 port was sponsored in part by Microbric Pty Ltd

MicroPython for ESP32

github: micropython/micropython-esp32

git clone --recursive https://github.com/micropython/micropython-esp32.git

Support for:

Running MicroPython

Connect to REPL

$ cu -l /dev/ttyUSB0 -s 115200
MicroPython v1.8.6-284-g7b3ce01 on 2017-01-13;
ESP32 module with ESP32
Type "help()" for more information.
>>>

Running MicroPython

Connect to REPL

$ cu -l /dev/ttyUSB0 -s 115200
MicroPython v1.8.6-284-g7b3ce01 on 2017-01-13;
ESP32 module with ESP32
Type "help()" for more information.
>>> import machine
>>> pin = machine.Pin(5, machine.Pin.OUT)
>>> pin.value(True)

Running MicroPython

Connect to REPL

>>> import machine
>>> import time
>>> pin = machine.Pin(5, machine.Pin.OUT)
>>> while True:
...     pin.value(True)
...     time.sleep(1)
...     pin.value(False)
...     time.sleep(1)

Running MicroPython

With thanks to apple //jse

Programming MicroPython — Filesystem

>>> import os
>>> os.listdir()
['boot.py']
>>> f = open('hello.world', "w")
>>> f.write("Hello, World!")
13
>>> f.close()
>>> os.listdir()
['boot.py', 'hello.world']

Programming MicroPython — WebREPL

Not actually working on ESP32 yet, this is the ESP8266 version

Programming MicroPython — mpy-utils

github: nickzoic/mpy-utils

Using REPL as a file transfer protocol: slow and very alpha

Programming MicroPython — modules/ and scripts/

Also upip, a micropython package manager

Developing MicroPython

image from iconsplace.com

MicroPython ESP32 Repo Files

ACKNOWLEDGEMENTS    esp32/     minimal/    teensy/
bare-arm/           esp8266/   mpy-cross/  tests/
cc3200/             examples/  pic16bit/   tools/
CODECONVENTIONS.md  extmod/    py/         unix/
CONTRIBUTING.md     lib/       qemu-arm/   windows/
docs/               LICENSE    README.md   zephyr/
drivers/            logo/      stmhal/

MicroPython ESP32 Repo — Files (Docs)

ACKNOWLEDGEMENTS    esp32/     minimal/    teensy/
bare-arm/           esp8266/   mpy-cross/  tests/
cc3200/             examples/  pic16bit/   tools/
CODECONVENTIONS.md  extmod/    py/         unix/
CONTRIBUTING.md     lib/       qemu-arm/   windows/
docs/               LICENSE    README.md   zephyr/
drivers/            logo/      stmhal/

Documentation, Examples, Tests

MicroPython ESP32 Repo — Files (Shared)

ACKNOWLEDGEMENTS    esp32/     minimal/    teensy/
bare-arm/           esp8266/   mpy-cross/  tests/
cc3200/             examples/  pic16bit/   tools/
CODECONVENTIONS.md  extmod/    py/         unix/
CONTRIBUTING.md     lib/       qemu-arm/   windows/
docs/               LICENSE    README.md   zephyr/
drivers/            logo/      stmhal/

Shared between ports

MicroPython ESP32 Repo — Files (Ports)

ACKNOWLEDGEMENTS    esp32/     minimal/    teensy/
bare-arm/           esp8266/   mpy-cross/  tests/
cc3200/             examples/  pic16bit/   tools/
CODECONVENTIONS.md  extmod/    py/         unix/
CONTRIBUTING.md     lib/       qemu-arm/   windows/
docs/               LICENSE    README.md   zephyr/
drivers/            logo/      stmhal/

Ports to specific platforms

MicroPython ESP32 Repo — Files (Ports)

ACKNOWLEDGEMENTS    esp32/     minimal/    teensy/
bare-arm/           esp8266/   mpy-cross/  tests/
cc3200/             examples/  pic16bit/   tools/
CODECONVENTIONS.md  extmod/    py/         unix/
CONTRIBUTING.md     lib/       qemu-arm/   windows/
docs/               LICENSE    README.md   zephyr/
drivers/            logo/      stmhal/

esp32 port — Files

esp32.custom_common.ld  modesp.c        mphalport.c
fatfs_port.c            modmachine.c    mphalport.h
gccollect.c             modmachine.h    qstrdefsport.h
gccollect.h             modnetwork.c    README.md
help.c                  modsocket.c     sdkconfig.h
machine_pin.c           modules/        uart.c
main.c                  moduos.c        uart.h
Makefile                modutime.c
memory.h                mpconfigport.h

esp32 port — Files (Modules)

esp32.custom_common.ld  modesp.c        mphalport.c
fatfs_port.c            modmachine.c    mphalport.h
gccollect.c             modmachine.h    qstrdefsport.h
gccollect.h             modnetwork.c    README.md
help.c                  modsocket.c     sdkconfig.h
machine_pin.c           modules/        uart.c
main.c                  moduos.c        uart.h
Makefile                modutime.c
memory.h                mpconfigport.h

How do C modules work? — 1

>>> import esp
>>> dir(esp)
['__name__', 'flash_read', 'flash_write', 'flash_erase',
 'flash_size', 'flash_user_start']
>>> esp.flash_size()
4194304

How do C modules work? — 2

esp-idf/components/spi_flash/include/esp_spi_flash.h

/**
 * @brief  Get flash chip size, as set in binary image header
 *
 * @note This value does not necessarily match real flash size.
 *
 * @return size of flash chip, in bytes
 */
size_t spi_flash_get_chip_size();

How do C modules work? — 3

esp32/modesp.c

#include "esp_spi_flash.h"

STATIC mp_obj_t esp_flash_size(void) {
    return mp_obj_new_int_from_uint(spi_flash_get_chip_size());
}

How do C modules work? — 4

esp32/modesp.c

#include "esp_spi_flash.h"

STATIC mp_obj_t esp_flash_size(void) {
    return mp_obj_new_int_from_uint(spi_flash_get_chip_size());
}

How do C modules work? — 5

esp32/modesp.c

#include "esp_spi_flash.h"

STATIC mp_obj_t esp_flash_size(void) {
    return mp_obj_new_int_from_uint(spi_flash_get_chip_size());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size);

How do C modules work? — 6

esp32/modesp.c

#include "esp_spi_flash.h"

STATIC mp_obj_t esp_flash_size(void) {
    return mp_obj_new_int_from_uint(spi_flash_get_chip_size());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size);

STATIC const mp_rom_map_elem_t esp_module_globals_table[] = {
    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp) },
    { MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&esp_flash_size_obj) },
};
    

How do C modules work? — 7

esp32/modesp.c

#include "esp_spi_flash.h"

STATIC mp_obj_t esp_flash_size(void) {
    return mp_obj_new_int_from_uint(spi_flash_get_chip_size());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size);

STATIC const mp_rom_map_elem_t esp_module_globals_table[] = {
    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp) },
    { MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&esp_flash_size_obj) },
};
STATIC MP_DEFINE_CONST_DICT(esp_module_globals, esp_module_globals_table);

const mp_obj_module_t esp_module = {
    .base = { &mp_type_module },
    .globals = (mp_obj_dict_t*)&esp_module_globals,
};

How do C modules work? — 8

esp32/mpconfigport.h

extern const struct _mp_obj_module_t esp_module;

#define MICROPY_PORT_BUILTIN_MODULES \
    { MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \

esp32/Makefile

SRC_C = \
        modesp.c \

How do C modules work? — 9

>>> import esp
>>> dir(esp)
['__name__', 'flash_read', 'flash_write', 'flash_erase',
 'flash_size', 'flash_user_start']
>>> esp.flash_size()
4194304

Resources

MicroPython

ESP32

Questions / Comments

Nick Moore
Mnemote Pty Ltd

Slides:

Content and images © Mnemote Pty Ltd except where otherwise noted