esp32 ULP and Flowcode
Posted: Mon Aug 17, 2026 4:55 pm
I am looking at ways to minimise the power consumption of an esp32. Currently I am using a esp32-WROOM board although I will perhaps change to an S3-Zero for the final work.
I wondered about using the ULP (Ultra Low Power) co-processor - which is another powerful feature on the esp32.
The implementation varies slightly - some processors require assembly language (as here) - others can use C or either (and the C3 does without)
Like many things with the esp32 toolchain - the initial setup is the tricky part - but then the tools handle all the magic for you....
So I wrote a simple FC program - which just displays some text - and then loads the ULP code (in supplementary code) - and sleeps the main processors. The (simple) ULP assembly code (thankyou Gemini) - toggles a pin (I used G32 - the ULP access is limited here) every time the co-processor wakes.
Creating the setup:
1) Save the attached program and attempt to compile.
2) In the program folder/main create a 'ulp' directory and save the assembly language file as 'ulp_main.S' (note capital 'S') Name can be adjusted to suit - adjust next step and #include "ulp_main.h" in supplementary code if you do.
3) modify main/CMakeLists.txt:
Add
4) In menucofig - enable ULP coprocessor and ULP_FSM (ULP finite state machine) in Component config ->Ultra Low Power ULP coprocessor - and optionally change the RTC clock configuration in Component config -> Hardware Settings -> RTC Clock config to Internal 8.5Mhz divided by 256 (~33kHz) - more accurate clock.
5) Recompile and flash.
One oddity - ulp_set_wakeup_period(0, 50000); - gives 100ms wakeup rather than the expected 50ms
The ULP processor is fairly powerful - for example it could sample an ADC pin or read an i2c sensor and wake the main MCU is a condition occurs...
It reduced the power consumption to 9.37mA (when in deep sleep) - which is still rather high - might have to look at removing the comms chip and power LED?.
Assembly language code is in attached zip file.
The principle is the same for C code for other esp variants.
Martin
I wondered about using the ULP (Ultra Low Power) co-processor - which is another powerful feature on the esp32.
The implementation varies slightly - some processors require assembly language (as here) - others can use C or either (and the C3 does without)
Code: Select all
ESP32 (Original) ULP-FSM Assembly / Macros
ESP32-S2 ULP-FSM & ULP-RISC-V Assembly or C
ESP32-S3 ULP-FSM & ULP-RISC-V Assembly or C
ESP32-C6 LP Core (RV32IMAC) C More powerful co-processor (20Mhz)
ESP32-P4 LP Core (RV32IMAC) C LP Core runs up to 40 MHz.
ESP32-C2 / C3 None
So I wrote a simple FC program - which just displays some text - and then loads the ULP code (in supplementary code) - and sleeps the main processors. The (simple) ULP assembly code (thankyou Gemini) - toggles a pin (I used G32 - the ULP access is limited here) every time the co-processor wakes.
Creating the setup:
1) Save the attached program and attempt to compile.
2) In the program folder/main create a 'ulp' directory and save the assembly language file as 'ulp_main.S' (note capital 'S') Name can be adjusted to suit - adjust next step and #include "ulp_main.h" in supplementary code if you do.
3) modify main/CMakeLists.txt:
Add
Code: Select all
ulp_embed_binary(ulp_main "ulp/ulp_main.S" "esp-project.c")5) Recompile and flash.
One oddity - ulp_set_wakeup_period(0, 50000); - gives 100ms wakeup rather than the expected 50ms
The ULP processor is fairly powerful - for example it could sample an ADC pin or read an i2c sensor and wake the main MCU is a condition occurs...
It reduced the power consumption to 9.37mA (when in deep sleep) - which is still rather high - might have to look at removing the comms chip and power LED?.
Assembly language code is in attached zip file.
The principle is the same for C code for other esp variants.
Martin