-
Notifications
You must be signed in to change notification settings - Fork 8
Adding native modules to MicroPython (ESP32)
The following instructions were tested under Ubuntu 20.04 (64 bit), using these sources of information:
- MicroPython port to the ESP32
- Native machine code in .mpy files
- MicroPython external C modules
- Building
ulabfor ESP32
Note: The details of the build process may change relatively quickly. The following recipies are also subject to change.
- Building MicroPython v1.14 with
ulabincluded - Building MicroPython v1.15 and higher with
ulabincluded - Adding own C code modules to the MicroPython firmware
- Generating a .mpy MicroPython library from C code ...
Building MicroPython v1.14 with ulab included
Note: With version 1.14, MicroPython switched to
cmakeon the ESP32 port, thus breaking compatibility with "standard" user modules.ulabcan, however, still be compiled with release 1.14. The following describes how to do this.
-
First update and upgrade your system
sudo apt-get update sudo apt-get upgrade -
Currently, the easiest way to install the build chain for MicroPython and to include
ulabis the scriptesp32.shavailable from theulabrepository. Copy the script from the repository in to a file calledesp32.shand execute it:cd ~ bash ./esp32.shThis should successfully build the MicroPython firmware with
ulabincluded.
The following steps modify the installation from 2., including umqtt and making it easier to re-build the firmware
without always re-running the whole script. We assume here that /micropython/ is located in the home folder (~).
-
Include the
umqttrelated modules:cd ~ git clone https://github.com/micropython/micropython-lib mkdir ~/micropython/ports/esp32/modules/umqtt cp ~/micropython-lib/umqtt.robust/umqtt/robust.py ~/micropython/ports/esp32/modules/umqtt/robust.py cp ~/micropython-lib/umqtt.simple/umqtt/simple.py ~/micropython/ports/esp32/modules/umqtt/simple.py -
Add the following path to the end of the ~/.profile file (e.g. using
nano ~/.profile)export PATH="$HOME/micropython/esp32/esp-idf/xtensa-esp32-elf/bin:$PATH"Important: Under Windows 10, restart the Ubuntu/Linux subssystem to activate the change. Under Ubuntu/Linux, restarting the shell is not sufficient, here log-out and -in again.
-
OPTIONAL: To use double precision, change in file
mpconfigport.hin foldermicropython/ports/esp32the following line:#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)to:
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) -
Generate the following file as
makefileinmicropython/ports/esp32(this configuration is for the HUZZAH32, assuming the device is connected under Windows toCOM4):ESPIDF = $(HOME)/micropython/esp32/esp-idf BOARD = GENERIC PORT = /dev/ttyS4 BAUD = 460800 FLASH_MODE = dio FLASH_SIZE = 4MB #CROSS_COMPILE = xtensa-esp32-elf- USER_C_MODULES = $(HOME)/ulab include MakefileIn the Ubuntu/Linux subsystem, the transmission fails if the baud rate is too high. If
460800does not work, try a lower baud rate, such as230400. -
Allow user to access the HUZZAH32 via USB (replace
<username>):sudo adduser <username> dialout -
Build and deploy MicroPython
cd ~/micropython/ports/esp32 make -j 8 submodules make -j 8Note:
-j 8instructs to compiler to use up to 8 cores, which depending on the system, can accelerate the build process. -
The resulting firmware (
firmware.bin) then resides inmicropython/ports/esp32/build-GENERIC/. To deploy it, run the following commands from theesp32folder:make erase make deployTo access it from the Windows host system, run:
explorer.exe .
Building MicroPython v1.15 and higher with ulab included
The following procedure builds the MicroPython firmware for ESP32 microcontrollers based on the latest version of MicroPython (currently 1.15)
and includes ulab.
It has been tested with Ubuntu 20.04 installed in the Linux subsystem of Windows 10 (64 bit).
Note: The only limitation I noticed is that deploying the firmware seems not to work with the standard baud rate 460800, however, reducing this to 230400 works reliably (see below).
-
The first part largely follows the instructions for the ESP32 in the MicroPython repository.
export BUILD_DIR=$(pwd) git clone https://github.com/v923z/micropython-ulab.git ulab git clone https://github.com/micropython/micropython.git cd $BUILD_DIR/micropython/ git clone -b v4.2.1 --recursive https://github.com/espressif/esp-idf.git cd esp-idf ./install.sh . ./export.sh cd $BUILD_DIR/micropython/ make -C mpy-cross cd $BUILD_DIR/micropython/ports/esp32 make submodulesRun
maketo check if the installation was successful. -
In the following steps, we generate a configuration file and a script to facilitate re-building the firmware and to include
ulab:Still in
$BUILD_DIR/micropython/ports/esp32create amakefilee.g. usingnano makefile:BOARD = GENERIC PORT = /dev/ttyS4 BAUD = 460800 USER_C_MODULES = $(BUILD_DIR)/ulab/code/micropython.cmake include MakefileBOARDselects the board type (e.g.GENERICorUM_TINYPICOetc.);PORTneeds to be changed according to COM port your board connects to (here, e.g. COM4 under Windows). Now, MicroPython can be re-built withulaband deployed:make clean make make deployIf deploy fails, try changing the baud rate in
makefileto230400. This seems to be an issue when deploying from the Windows 10 Linux subsystem.The export of the esp-idf paths is here not permanent. To facilitate re-building the firmware in a new session, the following script helps to set the stage. In
$BUILD_DIRcreate a file e.g. usingnano prep.shcontaining:export BUILD_DIR=$(pwd) cd $BUILD_DIR/micropython/esp-idf source export.sh cd $BUILD_DIR/micropython/ports/esp32When starting a new session, source
prep.shfrom your build folder (. prep.sh), which will export the esp-idf paths and bring you directly to$BUILD_DIR/micropython/ports/esp32.
When selecting BOARD=UM_TINYPICO, the firmware is built but deploy fails, because with ulab, the firmware is too large for the standard partition. To address this issue:
-
Add a new partition table file named
partitions_ulab.cvsto$BUILD_DIR/micropython/ports/esp32/. It increases the size of the partitionfactoryby 128 kB and decreases the sizevfsby the same amount.# Notes: the offset of the partition table itself is set in # $ESPIDF/components/partition_table/Kconfig.projbuild and the # offset of the factory/ota_0 partition is set in makeimg.py # Name, Type, SubType, Offset, Size, Flags nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000, factory, app, factory, 0x10000, 0x200000, vfs, data, fat, 0x220000, 0x180000, -
Change
sdkconfig.boardin$BUILD_DIR/micropython/ports/esp32/boards/UM_TINYPICOby adding following two lines:CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_ulab.csv" -
Finally, make sure that
makefilein$BUILD_DIR/micropython/ports/esp32/contains the correct board type (BOARD=UM_TINYPICO).
Note: These instructions need to be updated.
Follow the instructions in the official documentation. The prerequisite is, of course, that you were able to successfully build the firmware without any additional modules first (see above). A couple of hints:
- If the build process does not throw any errors but the new module cannot be imported, delete the module's
folder from
micropython/ports/esp32/build-GENERIC/and start a clean built (make clean, and then the make line below). - An example for a module with a more complex function is
blob.
When everything is in place, build the firmware by running from the micropython/ports/esp32 folder:
make -j 16 USER_C_MODULES=../../../modules CFLAGS_EXTRA=-DMODULE_BLOB_ENABLED=1 all
make erase
make deploy
Note: These instructions need to be updated.
While this is a very elegant method for adding fast (e.g. C code), custom modules to MicroPython without having to compile an own firmware version, there are currently a number of limitations, in particular with respect to memory access. These need to be considered before deciding whether to add a module to the firmware (see above) or to generate a native .mpy file. For the latter, MicroPython contains a number of examples with increasing complexity that may serve as templates.
In the following, the example from the documentation is used.
-
Make a new folder
factorialinmicropython/examples/natmodand add the following files:(a)
factorial.c// Include the header file to get access to the MicroPython API #include "py/dynruntime.h" // Helper function to compute factorial STATIC mp_int_t factorial_helper(mp_int_t x) { if (x == 0) { return 1; } return x * factorial_helper(x - 1); } // This is the function which will be called from Python, as factorial(x) STATIC mp_obj_t factorial(mp_obj_t x_obj) { // Extract the integer from the MicroPython input object mp_int_t x = mp_obj_get_int(x_obj); // Calculate the factorial mp_int_t result = factorial_helper(x); // Convert the result to a MicroPython integer object and return it return mp_obj_new_int(result); } // Define a Python reference to the function above STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial); // This is the entry point and is called when the module is imported mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { // This must be first, it sets up the globals dict and other things MP_DYNRUNTIME_INIT_ENTRY // Make the function available in the module's namespace mp_store_global(MP_QSTR_factorial, MP_OBJ_FROM_PTR(&factorial_obj)); // This must be last, it restores the globals dict MP_DYNRUNTIME_INIT_EXIT }(b)
MakefileMPY_DIR = ../../.. # Name of module MOD = factorial # Source files (.c or .py) SRC = factorial.c # Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) ARCH = xtensawin # Include to get the rules for compiling and linking the module include $(MPY_DIR)/py/dynruntime.mk -
Build the module:
cd ~/micropython/examples/natmod/factorial make -
Copy
factorial.mpyonto the HUZZAH32 as usual. The test it using the REPL. Run on the HUZZAH32:import factorial factorial.factorial(6)
- Board
- Installation
- Zusammenbau
3.1. Übersicht
3.2. Bauteile
3.3. HexBug-Spinne zerlegen
3.4. Adapter und Sensorarm
3.5. Akku und Platine - "robotling"-Code hochladen und Demo starten
- "Verhalten"
- Sensoren etc.
- Erweiterungen und Modifikationen
- Telemetrie über MQTT
- Adding native modules to MicroPython (Englisch)