esp32/pwm: Enhance of PWM feature to support ligth sleep mode and selecting clock source of timer. #16033
Replies: 7 comments 9 replies
-
It is totally mind-blowing, that an MCU is capable, in light sleep, to control a PWM output. Is it possible to change the clock src with manipulating the memory? Then you have to know the address of the GPIO and the Value you have to manipulate. It would be nice to have a Pythonic api to change the clk src. |
Beta Was this translation helpful? Give feedback.
-
I'm not sure if we can update the clock source directly from the register; it might be possible. However, I think the best approach would be to update the µPython API. The important thing to know is that each PWM channel needs to be associated with one of the three available timers (which handle the frequency and duty cycle of the PWM signal). In the timer configuration, we can choose the clock source, can be set at least RC_FAST_CLK (available in light sleep mode) or APB_CLK (the main clock, which shuts down when the ESP enters light sleep). |
Beta Was this translation helpful? Give feedback.
-
API proposal to set the clock source for PWM timer: # Set PWM Timer default clock source_timer
PWM_TIMERS.setDefualtClockSource(PWM_TIMER_RC_FAST_CLK)
# PWM_SET_DEFAULT_CLOCK_SOURCE(PWM_TIMER_APB_CLK)
# PWM_SET_DEFAULT_CLOCK_SOURCE(PWM_TIMER_REF_TICK)
# PWM_SET_DEFAULT_CLOCK_SOURCE(PWM_TIMER_XTAL_CLK)
# Set PWM Timer
TM1 = PWM_TIMERS.getTimer(id=0, group=0)
TM1.setClockSource(PWM_TIMER_APB_CLK) # will be ignored or rise an error when used with ESP32-S3
# here we select a specific timer
O_PWM1 = PWM(Pin(PWM_1, Pin.OUT), freq=25000, duty_u16=65535, source_timer = TM1)
# here we go to the actual process to find the best timer
O_PWM2 = PWM(Pin(PWM_2, Pin.OUT), freq=12500, duty_u16=65535) |
Beta Was this translation helpful? Give feedback.
-
The PWM class itself and it's methods are defined as a common interface at extmod/machine_pwm.c, which defines the class and it's methods. Some freedom exist only in the options of the constructor resp. init method. Selecting the clock source would then typically be an keyword option of the PWM constructor and pwm.init() method with the appropriate class constants for APB_CLK and RC_FAST_CLK. There could be more keyword options to select a specific timer/channel pair. See for instance the SAMD port which allows selecting a |
Beta Was this translation helpful? Give feedback.
-
It's a feature very specific to the ESP32 and so an alternative would be to add it to the esp32 module. Something like: import esp32
import machine
pwm = machine.PWM(Pin(1))
esp32.pwm_clock_source(pwm, esp32.RC_FAST_CLK) |
Beta Was this translation helpful? Give feedback.
-
New API Proposal: # Default case
# The first available group/timer/channel is find automaticly
PWM(Pin(PWM_1, Pin.OUT), freq=25000, duty_u16=65535)
# Selecting a specific timer assuming that the group is the first one in case of ESP32, in case of ESP32-S2 and ESP31-S3 the group will be ignored
# The clock source will get the previous configuration set on this timer or the default one APB_CLK
# the channel will be the first available
PWM(Pin(PWM_1, Pin.OUT), freq=25000, duty_u16=65535, timer=0)
# Selecting a specific timer, and setting a clock source
# if ESP32 : group=0, timer=0 and the source clock is set to RC_FAST_CLK
# if ESP32-S2 : group=0 timer=0 and the source clock is set to RC_FAST_CLK
# if ESP32-S3 : group=0 timer=0 and the source clock for all timer will be set to RC_FAST_CLK
# the channel will be the first available
PWM(Pin(PWM_1, Pin.OUT), freq=25000, duty_u16=65535, timer=0, clock=PWM_RC_FAST_CLK)
# for ESP32 we can add the group information
PWM(Pin(PWM_1, Pin.OUT), freq=25000, duty_u16=65535, timer=0, group=1, clock=PWM_RC_FAST_CLK) Open question:
|
Beta Was this translation helpful? Give feedback.
-
Ok, I've successfully installed the development environment to recompile MicroPython and successfully generated ports for the ESP32-S2 and ESP32-S3. I've made some basic changes in the machine_pwm.c file to fix the clock source to LEDC_USE_RC_FAST_CLK instead of LEDC_USE_APB_CLK. And, tada, it works as expected on both targets: the PWM signal continues to run in light sleep mode. Now, I will start coding a nice API interface to support the clock source. Based on my tests, I think we could simplify the previous API proposal. In fact, it’s not necessary to specify the timer instance. We might prefer to keep the current algorithm that selects the best timer source based on the expected frequency compared to the existing timer frequency. We would just add 2 new items to compare: clock and lightSleepEnable. # Default case
# The first available group/timer/channel is find automaticly
PWM(Pin(PWM_1, Pin.OUT), freq=25000, duty_u16=65535)
# Setting a specific clock source
# It will find the first time with a frequence=1K and clock_source = LEDC_USE_RC_FAST_CLK, if not it will select a new timer
# if ESP32 or ESP32-S2 : each timer can have independant clock source
# if ESP32-S3 : the source clock for all timer will be set to LEDC_USE_RC_FAST_CLK
# the channel will be the first available
PWM(Pin(PWM_1, Pin.OUT), freq=1000, duty_u16=65535, clock=PWM_RC_FAST_CLK)
# and if plan to use the PWM signal in light_sleep mode we will need to add ligthSleepEnable=True
# this adds the GPIO in a special list to "not be disabled" by the light sleep mode
PWM(Pin(PWM_1, Pin.OUT), freq=1000, duty_u16=65535, clock=PWM_RC_FAST_CLK, ligthSleepEnable=True) |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Does it possible to add the possibnility to change the clock source of the timer used in the LEDC configuration (for PWM python class).
Maybe, we can add an api entry to set up the timer clock source, then add the possibility to choose the timer source in the PWM constructor.
I would like to use the LEDC_USE_RC_FAST_CLK in order to maintain the PWM signal when the ESP32-S3 enter in LightSleep mode. In this ESP32-S3's mode only the the RC_FAST_CLK still running.
sample code that demonstarte the PWM signal lost in ligth sleep (MicroPython v1.23.0 on 2024-06-02; Generic ESP32S3 module with ESP32S3):
Beta Was this translation helpful? Give feedback.
All reactions