esp32 ULP and Flowcode

Tips, Tricks and methods for programming, learn ways of making your programming life easier, and share your knowledge with others.
Post Reply
mnfisher
Valued Contributor
Posts: 2119
http://meble-kuchenne.info.pl
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 167 times
Been thanked: 978 times

esp32 ULP and Flowcode

Post by mnfisher »

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)

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
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

Code: Select all

ulp_embed_binary(ulp_main "ulp/ulp_main.S" "esp-project.c")
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
Attachments
ULP_Test.fcfx
(10.73 KiB) Downloaded 17 times
ulp_main.zip
(604 Bytes) Downloaded 17 times

mnfisher
Valued Contributor
Posts: 2119
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 167 times
Been thanked: 978 times

Re: esp32 ULP and Flowcode

Post by mnfisher »

For completeness - and because I like to fiddle:

I did a version in C for an esp32-s3

There a few changes:

I created a ulp_main.c file (in project/main/ulp)

Code: Select all

#include <stdint.h>
#include <stdbool.h>
#include "ulp_riscv_utils.h"
#include "ulp_riscv_gpio.h"

#define TOGGLE_PIN GPIO_NUM_2
volatile static bool pin_state = false;

int main(void) {
    pin_state = !pin_state;
    ulp_riscv_gpio_output_level(TOGGLE_PIN, pin_state);
    
    return 0; 
}
CMakeLists.txt requires the line:

Code: Select all

ulp_embed_binary(ulp_main "ulp/ulp_main.c" "esp-project.c")
menuconfig requires the RISCV ULP to be selected (not FSM)

The setup needs to use the riscv component instead of the FSM.

Here a delay of 100000 gives the expected 100ms too :-)

Martin
Attachments
ULP_Test_s3.fcfx
(10.47 KiB) Downloaded 5 times

mnfisher
Valued Contributor
Posts: 2119
Joined: Wed Dec 09, 2020 9:37 pm
Has thanked: 167 times
Been thanked: 978 times

Re: esp32 ULP and Flowcode

Post by mnfisher »

The s3 also has a much lower power consumption - powered via the 3v3 pin (at 3300mV) - the board uses an average of ~410 microamps (again this is in deep sleep - with the coprocessor toggling pin 2 every 100ms). The trace appears to show power use 'peaking' at 3mA every 100ms....

One - gotcha - the s3 (at least the zero) doesn't automatically switch into/out of bootloader mode - so I needed to press and hold 0, momentary 1 to enter and reset again to leave.. One little button was 'wedged' down due to the metal surround being slightly bent - which gave some time fiddling :-(

Martin

stefan.erni
Valued Contributor
Posts: 1275
Joined: Wed Dec 02, 2020 10:53 am
Has thanked: 242 times
Been thanked: 256 times

Re: esp32 ULP and Flowcode

Post by stefan.erni »

Hi Martin

That's interesting what you're doing.
I'm also trying to put an S3 into deep sleep right now
I'm guessing the name “Zero” comes from Waveshare.

Yes, depending on how the USB connection is used, you may need to manually put the board into bootloader mode. To do this, press and hold the BOOT button, briefly press the RESET button, and then release the BOOT button. After that, you can flash the firmware. Once flashing is complete, briefly press RESET again to start the program.

Here are a few useful links for the Zero:
https://www.waveshare.com/esp32-s3-zero.htm

https://docs.waveshare.com/ESP32-S3-Zer ... 32-S3-Zero

Schema:
https://files.waveshare.com/wiki/ESP32- ... ro-Sch.pdf

for step file 3D Model:
https://docs.waveshare.com/ESP32-S3-Zer ... -Documents

2026-08-18_08-24-55.PNG
2026-08-18_08-24-55.PNG (225.54 KiB) Viewed 48 times

Post Reply