#MicroPython: a three-color E-INK display controlled using an ESP32
MicroPython | 4 min | 15532
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
You may read the steps of this post:
Tutorial: Getting Started with MicroPython on ESP32, M5Stack, and ESP8266,
If you are running Ubuntu 20.04 / Ubuntu mate 20.04 etc.
Python 2.7 is not supported anymore and you need to follow the steps that use/install Python 3.7.
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_modulesas "frozen" modules on your MicroPython firmware. To freeze MicroPython modules, you need to compile MicroPython from scratch. To do that, follow these instructions:
- 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
Download the ESP-IDF framework (I use here the new version V4):
mkdir ~/esp/ cd ~/esp/ git clone https://github.com/espressif/esp-idf.git cd esp-idf git checkout 310beae373446ceb9a4ad9b36b5428d7fdf2705f ## the above hash is defined by the variable ESPIDF_SUPHASH_V4 in the file: # https://github.com/micropython/micropython/blob/master/ports/esp32/Makefile 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
- Download and install the toolchain:
wget https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz 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 install.sh option, it didn't work for me and # I got a lot of errors while compiling MicroPython
Clone MicroPython and compile the cross-compiler:
git clone https://github.com/micropython/micropython.git cd micropython/mpy-cross make cd ../ports/esp32
(Optional) Modify the setup to include support for BLE. If you have a board with pSRAM, change
nano boards/GENERIC/mpconfigboard.mk ## boards/GENERIC/mpconfigboard.mk # add the following line at the end SDKCONFIG += boards/sdkconfig.ble
- Select the board version (change this to
GENERIC_SPIRAMif your board has pSRAM):
- Compile the submodules and MicroPython:
make submodules make
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:
- Flash MicroPython on the ESP32, which should be already connected to a USB port:
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 e7in5.py [...] MPY fonts/monaco16.py [...] MPY widgets/forecast.py [...] GEN build-GENERIC/frozen_content.c [...] Writing build-GENERIC/firmware.bin to the board esptool.py v2.8-dev Serial port /dev/ttyUSB0 Connecting..... 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 Changed. 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. Leaving... Hard resetting via RTS pin...
For this project, copy the complete
frozen_modulefolder 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:
- Clone the project typing the following:
git clone https://github.com/lemariva/uPyEINK.git
- Rename the files:
boot.pyand include your Wi-Fi credentials:
ssid_ = '' wpa2_pass = ''
It is important that your ESP32 is connected to Wi-Fi to update the widgets.
settings.pyand set up the following variables:
news_api_key (info here) weather_api_key (info here)
- 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_intervalin 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:
- A MicroPython implementation for a smaller display
- Database implementation and HTML/CSS designs
- LUT and some code
- Some other code
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.