Question about machine.idle()

All ESP32 boards running MicroPython.
Target audience: MicroPython users with an ESP32 board.
Post Reply
asmeenk12
Posts: 5
Joined: Fri Feb 26, 2016 7:31 pm
Location: Netherlands

Question about machine.idle()

Post by asmeenk12 » Wed Jul 05, 2017 6:30 pm

The ESP32 is at the moment very power hungry. It needs between 140 to 180 mA.
And that is far too much for battery powered devices.

So I try to tame the power consumption , without success.

ESP firmware here is the latest (branch esp32, commit message: esp32: Update to latest ESP-IDF)

Currently in esp32 firmware in modmachine,c the machine.idle() is implemented as:
STATIC mp_obj_t machine_idle(void) {
taskYIELD();
return mp_const_none;
}

With next snippet I tested the current firmware:
now = time.ticks_ms()
count = 0
while count < 1000:
machine.idle()
count += 1
now1 = time.ticks_ms()
diff = now1- now
print("1000 loops in %s ms. Per loop %s ms" %( diff, diff/1000) )

result: 1000 loops in 20 ms. Per loop 0.02 ms
Quite fast indeed!

I replaced the code with the code as found in the esp8266:
STATIC mp_obj_t machine_idle(void) {
uint32_t t = mp_hal_ticks_cpu();
asm("waiti 0");
t = mp_hal_ticks_cpu() - t;
return MP_OBJ_NEW_SMALL_INT(t);
}
build and flashed the firmware.

Tested with same python snippet as above.
Result: 1000 loops in 9912 ms. Per loop 9.912 ms

This shows that the cpu really sleeps 10 ms at each machine.idle(). So far so good
(apparently there is a timer interrupt each 10 ms. Heartbeat of underlying RTOS?)

But even with the CPU idle, the power consumption stays exactly the same.
So whats wrong or missing here?

Damien
Site Admin
Posts: 647
Joined: Mon Dec 09, 2013 5:02 pm

Re: Question about machine.idle()

Post by Damien » Thu Jul 06, 2017 12:46 pm

I don't think power saving features are yet supported by the ESP IDF. The only thing I know of that will reduce power consumption is to lower the clock speed. It's set at 240MHz by default, but if you edit the sdkconfig.h file you can change it to 80MHz or 160MHz.

asmeenk12
Posts: 5
Joined: Fri Feb 26, 2016 7:31 pm
Location: Netherlands

Re: Question about machine.idle()

Post by asmeenk12 » Thu Jul 06, 2017 7:08 pm

Indeed, thanks
Changing in sdconfig.h:
#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 80

power consumption now 110 mA (with AP en WLAN both switch off)
But running the test python snippet shows that the OS heart beat is now 30 ms. Clearly this trick is not yet fully supported.
Note that now and then the chip will not boot at 80 Mhz


I like dirty tricks. (Not following the official API, here I think in Mhz, not in Hz)

I modified in modmachine.c the function machine_freq.
Notice that esp_idf in file clk.c states:

Code: Select all

/*
 * This function is not exposed as an API at this point,
 * because FreeRTOS doesn't yet support dynamic changing of
 * CPU frequency. Also we need to implement hooks for
 * components which want to be notified of CPU frequency
 * changes.
 */
modmachine.c:

Code: Select all

#include "soc/rtc.h"

STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
    if (n_args == 0) {
        // get
        return mp_obj_new_int(ets_get_cpu_frequency() );
    } else {
        // set
        mp_int_t freq = mp_obj_get_int(args[0])  ;
        int enumFreq = RTC_CPU_FREQ_240M;
        switch (freq) {
                case 240:
                    enumFreq = RTC_CPU_FREQ_240M;
                    break;
//                case 160:
//                    enumFreq = RTC_CPU_FREQ_160M;
//                    break;
                case 80:
                    enumFreq = RTC_CPU_FREQ_80M;
                    break;
//                case 2:
//                    enumFreq = RTC_CPU_FREQ_2M;
//                    break;
                default:    
            nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
                "frequency can only be either 80 or 240 (MHz)"));
        }
        rtc_clk_cpu_freq_set(enumFreq);
        return mp_const_none;
    }
}
Build and flashed.

Now I can dynamically switch.
Not fully stable, one gets funny chars at the prompt.
No guarantee that it always works!
80 Mhz takes about 110 mA. 240 Mhz takes about 140 mA. (ap and wlan both off).
Disappointed about powerconsumption at 80 Mhz. Did expect it would be less (70 mA)

I could switch to 160 (= 80 mA) and 2 Mhz (= 20 mA) but the cpu did not run at all at both frequencies.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Question about machine.idle()

Post by Roberthh » Fri Jul 07, 2017 6:49 am

There is a known issue about switching frequencies. Look at the espressif site, esp32 section, into the document about known bugs.

Post Reply