Manage cookies

We use cookies to improve our services. Read more about how we use cookies and how you can refuse them.

The necessary cookies help to make the website work properly.

Anonymous statistical cookies help to understand how visitors use the website.

  • MicroPython
    4 min | 4118

    #MicroPython: a three-color E-INK display controlled using an ESP32

    MicroPython | 4 min | 4118

    This is a tutorial to control and display widgets on an E-INK display using an ESP32. Three widgets are available:

    • Weather: weather forecast obtained using the OpenWeatherMap API.
    • News: news highlights obtained using the NewsApi API.
    • Notes: notes that can be added using a web-server that runs on the ESP32.

    The result can be seen in this video:

    Thus, in this tutorial, I will try to achieve the following:

    • A guide to compile MicroPython to freeze modules;
    • A setup guide for the code (Wi-Fi, APIs);
    • Steps to upload the code to the ESP32 board.

    Hardware & Software

    In the following table, you will find the hardware and software that you can use on this tutorial:

    Freeze MicroPython Modules

    The RAM of the ESP32-WROOM (512kb) running MicroPython is very limited. Therefore, it is not possible to load the un-compiled modules and run the code. You will get the annoying error:

    MemoryError: memory allocation failed, allocating xxxx bytes

    To avoid that, you should include the modules under the folder frozen_modules as "frozen" modules on your MicroPython firmware. To freeze MicroPython modules, you need to compile MicroPython from scratch. To do that, follow these instructions:

    1. Install pre-requirements:
      sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-click python-cryptography python-future python-pyparsing python-pyelftools cmake ninja-build ccache libffi-dev libssl-dev
    2. Download the ESP-IDF framework (I use here the new version V4):

      mkdir ~/esp/
      cd ~/esp/
      git clone
      cd esp-idf
      git checkout 310beae373446ceb9a4ad9b36b5428d7fdf2705f 
      ## the above hash is defined by the variable ESPIDF_SUPHASH_V4 in the file:
      git submodule update --init --recursive
      ## if you don't clone the submodules (recursive)
      # you'll get the following error while compiling MicroPython: 
      # xtensa-esp32-elf/bin/ld: cannot find -lrtc
    3. Download and install the toolchain:
      cd ~/esp/
      tar -xzf ~/Downloads/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz
      export PATH="$HOME/esp/xtensa-esp32-elf/bin:$PATH"
      export IDF_PATH="$HOME/esp/esp-idf"
      ## Don't use the option, it didn't work for me and
      # I got a lot of errors while compiling MicroPython
    4. Clone MicroPython and compile the cross-compiler:

      git clone
      cd micropython/mpy-cross
      cd ../ports/esp32
    5. (Optional) Modify the setup to include support for BLE. If you have a board with pSRAM, change GENERIC to GENERIC_SPIRAM:

      nano boards/GENERIC/
      ##  boards/GENERIC/ 
      # add the following line at the end
      SDKCONFIG += boards/sdkconfig.ble
    6. Select the board version (change this to GENERIC_SPIRAM if your board has pSRAM):
      export BOARD=GENERIC
    7. Compile the submodules and MicroPython:
      make submodules

    Freezing modules on MicroPython reduces the memory use on MicroPython and makes your code faster. To do that, copy the module files that you want to freeze into micropython/ports/esp32/modules. Then, repeat step 7 and:

    1. Flash MicroPython on the ESP32, which should be already connected to a USB port:
      make deploy

    You should see something like this:

    Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.
    Building with ESP IDF v3
    MPY fonts/
    MPY widgets/
    GEN build-GENERIC/frozen_content.c
    Writing build-GENERIC/firmware.bin to the board v2.8-dev
    Serial port /dev/ttyUSB0
    Chip is ESP32D0WDQ6 (revision 1)
    Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
    Crystal is 40MHz
    MAC: cc:50:e3:a8:80:cc
    Uploading stub...
    Running stub...
    Stub running...
    Changing baud rate to 460800
    Configuring flash size...
    Auto-detected Flash size: 4MB
    Compressed 1336896 bytes to 816859...
    Wrote 1336896 bytes (816859 compressed) at 0x00001000 in 20.9 seconds (effective 510.7 kbit/s)...
    Hash of data verified.
    Hard resetting via RTS pin...

    For this project, copy the complete frozen_module folder content into micropython/ports/esp32/modules. Then, the modules are compiled (MPY) and added to the MicroPython firmware as frozen modules.

    Upload the uPyEINK project

    Follow these steps to run the project on the ESP32 board:

    1. Clone the project typing the following:
      git clone
    2. Rename the files:
      • to and include your Wi-Fi credentials:
        ssid_ = ''
        wpa2_pass = ''

        It is important that your ESP32 is connected to Wi-Fi to update the widgets.

      • to and set up the following variables:
        news_api_key (info here)
        weather_api_key (info here)
    3. Upload the code to the ESP32, using e.g. VSCode and PyMakr extension and have fun! If you need help, check this tutorial: MicroPython: Visual Studio Code (VSCode) as IDE.

    The web-server is available under http:// and you can add and remove notes that will be displayed on the E-INK display.

    The E-INK update frequency is set to 2 hours (settings.update_interval in milliseconds) and after 5 updates (settings.calibration_interval) the ESP32 cleans the display to avoid ghosting and reset the board to update the clock using a NTP server. If you want to, you can activate the deep sleep functionality (settings.deep_sleep) but you lose the web-server and you can only update the notes only when the ESP32 is updating the display.


    I took code and ideas from following repositories and wikis:


    This tutorial helps you deploy a project to control an E-INK display using an ESP32. The screen is divided into different widgets that can be activated to gather information. Three widgets are included: Weather forecast, news, and notes. The weather forecast and news are obtained from the Internet using APIs and for the notes, the code starts a web server, in which the notes can be managed (written and deleted). The ESP32 wrover has limited RAM, then the steps to freeze modules on MicroPython are also described.