LED Control¶
Introduction¶
The LED control (LEDC) module is primarily designed to control the intensity of LEDs, although it can be used to generate PWM signals for other purposes as well. It has 16 channels which can generate independent waveforms, that can be used to drive e.g. RGB LED devices.
Half of all LEDC’s channels provide high speed mode of operation. This mode offers implemented in hardware, automatic and glitch free change of PWM duty cycle. The other half of channels operate in a low speed mode, where the moment of change depends on the application software. Each group of channels is also able to use different clock sources but this feature is not implemented in the API.
The PWM controller also has the ability to automatically increase or decrease the duty cycle gradually, allowing for fades without any processor interference.
Functionality Overview¶
Getting LEDC to work on specific channel in either high or low speed mode is done in three steps:
- Configure Timer to determine PWM signal’s frequency and the a number (resolution of duty range).
- Configure Channel by associating it with the timer and GPIO to output the PWM signal.
- Change PWM Signal that drives the output to change LED’s intensity. This may be done under full control by software or with help of hardware fading functions.
In an optional step it is also possible to set up an interrupt on the fade end.
Configure Timer¶
Setting of the timer is done by calling function ledc_timer_config()
. This function should be provided with a data structure ledc_timer_config_t
that contains the following configuration settings:
- The timer number
ledc_timer_t
and a speed modeledc_mode_t
.- The PWM signal’s frequency and resolution of PWM’s duty value changes.
The frequency and the duty resolution are interdependent. The higher the PWM frequency, the lower duty resolution is available and vice versa. This relationship may became important, if you are planning to use this API for purposes other that changing intensity of LEDs. Check section Supported Range of Frequency and Duty Resolution for more details.
Configure Channel¶
Having set up the timer, the next step is to configure selected channel (one out of ledc_channel_t
). This is done by calling function ledc_channel_config()
.
In similar way, like with the timer configuration, the channel setup function should be provided with specific structure ledc_channel_config_t
, that contains channel’s configuration parameters.
At this point channel should became operational and start generating PWM signal of frequency determined by the timer settings and the duty on selected GPIO, as configured in ledc_channel_config_t
. The channel operation / the signal generation may be suspended at any time by calling function ledc_stop()
.
Change PWM Signal¶
Once the channel is operational and generating the PWM signal of constant duty and frequency, there are couple of ways to change this signal. When driving LEDs we are changing primarily the duty to vary the light intensity. See the two section below how to change the duty by software or with hardware fading. If required, we can change signal’s frequency as well and this is covered in section Change PWM Frequency.
Change PWM Duty by Software¶
Setting of the duty is done by first calling dedicated function ledc_set_duty()
and then calling ledc_update_duty()
to make the change effective. To check the value currently set, there is a corresponding _get_
function ledc_get_duty()
.
Another way to set the duty, and some other channel parameters as well, is by calling ledc_channel_config()
discussed in the previous section.
The range of the duty value entered into functions depends on selected duty_resolution
and should be from 0 to (2 ** duty_resolution) - 1. For example, if selected duty resolution is 10, then the duty range is from 0 to 1023. This provides the resolution of ~0.1%.
Change PWM Duty with Hardware Fading¶
The LEDC hardware provides the means to gradually fade from one duty value to another. To use this functionality first enable fading with ledc_fade_func_install()
. Then configure it by calling one of available fading functions:
Finally start fading with ledc_fade_start()
.
If not required anymore, fading and associated interrupt may be disabled with ledc_fade_func_uninstall()
.
Change PWM Frequency¶
The LEDC API provides several means to change the PWM frequency “on the fly”.
- One of options is to call
ledc_set_freq()
. There is a corresponding functionledc_get_freq()
to check what frequency is currently set.- Another option to change the frequency, and the duty resolution as well, is by calling
ledc_bind_channel_timer()
to bind other timer to the channel.- Finally the channel’s timer may be changed by calling
ledc_channel_config()
.
More Control Over PWM¶
There are couple of lower level timer specific functions, that may be used to provide additional means to change the PWM settings:
The first two functions are called “behind the scenes” by ledc_channel_config()
to provide “clean” start up of a timer after is it configured.
Use Interrupts¶
When configuring a LEDC channel, one of parameters selected within ledc_channel_config_t
is ledc_intr_type_t
and allows to enable an interrupt on fade completion.
Registration of a handler to service this interrupt is done by calling ledc_isr_register()
.
LEDC High and Low Speed Mode¶
Out of the total 8 timers and 16 channels available in the LED PWM Controller, half of them are dedicated to operate in the high speed mode and the other half in the low speed mode. Selection of the low or high speed “capable” timer or the channel is done with parameter ledc_mode_t
that is present in applicable function calls.
The advantage of the high speed mode is h/w supported, glitch-free changeover of the timer settings. This means that if the timer settings are modified, the changes will be applied automatically after the next overflow interrupt of the timer. In contrast, when updating the low-speed timer, the change of settings should be specifically triggered by software. The LEDC API is doing it “behind the scenes”, e.g. when ledc_timer_config()
or ledc_timer_set()
is called.
For additional details regarding speed modes please refer to ESP32 Technical Reference Manual (PDF). Note that support for SLOW_CLOCK
mentioned in this manual is not implemented in the LEDC API.
Supported Range of Frequency and Duty Resolution¶
The LED PWM Controller is designed primarily to drive LEDs and provides wide resolution of PWM duty settings. For instance for the PWM frequency at 5 kHz, the maximum duty resolution is 13 bits. It means that the duty may be set anywhere from 0 to 100% with resolution of ~0.012% (13 ** 2 = 8192 discrete levels of the LED intensity).
The LEDC may be used for providing signals at much higher frequencies to clock other devices, e.g. a digital camera module. In such a case the maximum available frequency is 40 MHz with duty resolution of 1 bit. This means that duty is fixed at 50% and cannot be adjusted.
The API is designed to report an error when trying to set a frequency and a duty resolution that is out of the range of LEDC’s hardware. For example, an attempt to set the frequency at 20 MHz and the duty resolution of 3 bits will result in the following error reported on a serial monitor:
E (196) ledc: requested frequency and duty resolution can not be achieved, try reducing freq_hz or duty_resolution. div_param=128
In such a case either the duty resolution or the frequency should be reduced. For example setting the duty resolution at 2 will resolve this issue and provide possibility to set the duty with 25% steps, i.e. at 25%, 50% or 75%.
The LEDC API will also capture and report an attempt to configure frequency / duty resolution combination that is below the supported minimum, e.g.:
E (196) ledc: requested frequency and duty resolution can not be achieved, try increasing freq_hz or duty_resolution. div_param=128000000
Setting of the duty resolution is normally done using ledc_timer_bit_t
. This enumeration covers the range from 10 to 15 bits. If a smaller duty resolution is required (below 10 down to 1), enter the equivalent numeric values directly.
Application Example¶
The LEDC change duty cycle and fading control example: peripherals/ledc.
API Reference¶
Header File¶
Functions¶
-
esp_err_t
ledc_channel_config
(const ledc_channel_config_t *ledc_conf)¶ LEDC channel configuration Configure LEDC channel with the given channel/output gpio_num/interrupt/source timer/frequency(Hz)/LEDC duty resolution.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
ledc_conf
: Pointer of LEDC channel configure struct
-
esp_err_t
ledc_timer_config
(const ledc_timer_config_t *timer_conf)¶ LEDC timer configuration Configure LEDC timer with the given source timer/frequency(Hz)/duty_resolution.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_FAIL Can not find a proper pre-divider number base on the given frequency and the current duty_resolution.
- Parameters
timer_conf
: Pointer of LEDC timer configure struct
-
esp_err_t
ledc_update_duty
(ledc_mode_t speed_mode, ledc_channel_t channel)¶ LEDC update channel parameters Call this function to activate the LEDC updated parameters. After ledc_set_duty, ledc_set_fade, we need to call this function to update the settings.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed mode,channel
: LEDC channel (0-7), select from ledc_channel_t
-
esp_err_t
ledc_stop
(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_level)¶ LEDC stop. Disable LEDC output, and set idle level.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modechannel
: LEDC channel (0-7), select from ledc_channel_tidle_level
: Set output idle level after LEDC stops.
-
esp_err_t
ledc_set_freq
(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t freq_hz)¶ LEDC set channel frequency (Hz)
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- ESP_FAIL Can not find a proper pre-divider number base on the given frequency and the current duty_resolution.
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modetimer_num
: LEDC timer index (0-3), select from ledc_timer_tfreq_hz
: Set the LEDC frequency
-
uint32_t
ledc_get_freq
(ledc_mode_t speed_mode, ledc_timer_t timer_num)¶ LEDC get channel frequency (Hz)
- Return
- 0 error
- Others Current LEDC frequency
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modetimer_num
: LEDC timer index (0-3), select from ledc_timer_t
-
esp_err_t
ledc_set_duty
(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty)¶ LEDC set duty Only after calling ledc_update_duty will the duty update.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modechannel
: LEDC channel (0-7), select from ledc_channel_tduty
: Set the LEDC duty, the range of duty setting is [0, (2**duty_resolution) - 1]
-
uint32_t
ledc_get_duty
(ledc_mode_t speed_mode, ledc_channel_t channel)¶ LEDC get duty.
- Return
- LEDC_ERR_DUTY if parameter error
- Others Current LEDC duty
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modechannel
: LEDC channel (0-7), select from ledc_channel_t
-
esp_err_t
ledc_set_fade
(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, ledc_duty_direction_t gradule_direction, uint32_t step_num, uint32_t duty_cyle_num, uint32_t duty_scale)¶ LEDC set gradient Set LEDC gradient, After the function calls the ledc_update_duty function, the function can take effect.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Parameter error
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modechannel
: LEDC channel (0-7), select from ledc_channel_tduty
: Set the start of the gradient duty, the range of duty setting is [0, (2**duty_resolution) - 1]gradule_direction
: Set the direction of the gradientstep_num
: Set the number of the gradientduty_cyle_num
: Set how many LEDC tick each time the gradient lastsduty_scale
: Set gradient change amplitude
-
esp_err_t
ledc_isr_register
(void (*fn)(void *), void *arg, int intr_alloc_flags, ledc_isr_handle_t *handle, )¶ Register LEDC interrupt handler, the handler is an ISR. The handler will be attached to the same CPU core that this function is running on.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_ARG Function pointer error.
- Parameters
fn
: Interrupt handler function.arg
: User-supplied argument passed to the handler function.intr_alloc_flags
: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.arg
: Parameter for handler functionhandle
: Pointer to return handle. If non-NULL, a handle for the interrupt will be returned here.
-
esp_err_t
ledc_timer_set
(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t clock_divider, uint32_t duty_resolution, ledc_clk_src_t clk_src)¶ Configure LEDC settings.
- Return
- (-1) Parameter error
- Other Current LEDC duty
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modetimer_sel
: Timer index (0-3), there are 4 timers in LEDC moduleclock_divider
: Timer clock divide value, the timer clock is divided from the selected clock sourceduty_resolution
: Resolution of duty setting in number of bits. The range of duty values is [0, (2**duty_resolution) - 1]clk_src
: Select LEDC source clock.
-
esp_err_t
ledc_timer_rst
(ledc_mode_t speed_mode, uint32_t timer_sel)¶ Reset LEDC timer.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modetimer_sel
: LEDC timer index (0-3), select from ledc_timer_t
-
esp_err_t
ledc_timer_pause
(ledc_mode_t speed_mode, uint32_t timer_sel)¶ Pause LEDC timer counter.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modetimer_sel
: LEDC timer index (0-3), select from ledc_timer_t
-
esp_err_t
ledc_timer_resume
(ledc_mode_t speed_mode, uint32_t timer_sel)¶ Resume LEDC timer.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modetimer_sel
: LEDC timer index (0-3), select from ledc_timer_t
-
esp_err_t
ledc_bind_channel_timer
(ledc_mode_t speed_mode, uint32_t channel, uint32_t timer_idx)¶ Bind LEDC channel with the selected timer.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modechannel
: LEDC channel index (0-7), select from ledc_channel_ttimer_idx
: LEDC timer index (0-3), select from ledc_timer_t
-
esp_err_t
ledc_set_fade_with_step
(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int scale, int cycle_num)¶ Set LEDC fade function. Should call ledc_fade_func_install() before calling this function. Call ledc_fade_start() after this to start fading.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- ESP_ERR_INVALID_STATE Fade function not installed.
- ESP_FAIL Fade function init error
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed mode,channel
: LEDC channel index (0-7), select from ledc_channel_ttarget_duty
: Target duty of fading [0, (2**duty_resolution) - 1]scale
: Controls the increase or decrease step scale.cycle_num
: increase or decrease the duty every cycle_num cycles
-
esp_err_t
ledc_set_fade_with_time
(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms)¶ Set LEDC fade function, with a limited time. Should call ledc_fade_func_install() before calling this function. Call ledc_fade_start() after this to start fading.
- Return
- ESP_ERR_INVALID_ARG Parameter error
- ESP_OK Success
- ESP_ERR_INVALID_STATE Fade function not installed.
- ESP_FAIL Fade function init error
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed mode,channel
: LEDC channel index (0-7), select from ledc_channel_ttarget_duty
: Target duty of fading.( 0 - (2 ** duty_resolution - 1)))max_fade_time_ms
: The maximum time of the fading ( ms ).
-
esp_err_t
ledc_fade_func_install
(int intr_alloc_flags)¶ Install ledc fade function. This function will occupy interrupt of LEDC module.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_STATE Fade function already installed.
- Parameters
intr_alloc_flags
: Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
-
void
ledc_fade_func_uninstall
()¶ Uninstall LEDC fade function.
-
esp_err_t
ledc_fade_start
(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t wait_done)¶ Start LEDC fading.
- Return
- ESP_OK Success
- ESP_ERR_INVALID_STATE Fade function not installed.
- ESP_ERR_INVALID_ARG Parameter error.
- Parameters
speed_mode
: Select the LEDC speed_mode, high-speed mode and low-speed modechannel
: LEDC channel numberwait_done
: Whether to block until fading done.
Structures¶
-
struct
ledc_channel_config_t
¶ Configuration parameters of LEDC channel for ledc_channel_config function.
Public Members
-
int
gpio_num
¶ the LEDC output gpio_num, if you want to use gpio16, gpio_num = 16
-
ledc_mode_t
speed_mode
¶ LEDC speed speed_mode, high-speed mode or low-speed mode
-
ledc_channel_t
channel
¶ LEDC channel (0 - 7)
-
ledc_intr_type_t
intr_type
¶ configure interrupt, Fade interrupt enable or Fade interrupt disable
-
ledc_timer_t
timer_sel
¶ Select the timer source of channel (0 - 3)
-
uint32_t
duty
¶ LEDC channel duty, the range of duty setting is [0, (2**duty_resolution) - 1]
-
int
-
struct
ledc_timer_config_t
¶ Configuration parameters of LEDC Timer timer for ledc_timer_config function.
Public Members
-
ledc_mode_t
speed_mode
¶ LEDC speed speed_mode, high-speed mode or low-speed mode
-
ledc_timer_bit_t
duty_resolution
¶ LEDC channel duty resolution
-
ledc_timer_bit_t
bit_num
¶ Deprecated in ESP-IDF 3.0. This is an alias to ‘duty_resolution’ for backward compatibility with ESP-IDF 2.1
-
ledc_timer_t
timer_num
¶ The timer source of channel (0 - 3)
-
uint32_t
freq_hz
¶ LEDC timer frequency (Hz)
-
ledc_mode_t
Type Definitions¶
-
typedef intr_handle_t
ledc_isr_handle_t
¶
Enumerations¶
-
enum
ledc_mode_t
¶ Values:
-
LEDC_HIGH_SPEED_MODE
= 0¶ LEDC high speed speed_mode
-
LEDC_LOW_SPEED_MODE
¶ LEDC low speed speed_mode
-
LEDC_SPEED_MODE_MAX
¶ LEDC speed limit
-
-
enum
ledc_intr_type_t
¶ Values:
-
LEDC_INTR_DISABLE
= 0¶ Disable LEDC interrupt
-
LEDC_INTR_FADE_END
¶ Enable LEDC interrupt
-
-
enum
ledc_duty_direction_t
¶ Values:
-
LEDC_DUTY_DIR_DECREASE
= 0¶ LEDC duty decrease direction
-
LEDC_DUTY_DIR_INCREASE
= 1¶ LEDC duty increase direction
-
-
enum
ledc_clk_src_t
¶ Values:
-
LEDC_REF_TICK
= 0¶ LEDC timer clock divided from reference tick (1Mhz)
-
LEDC_APB_CLK
¶ LEDC timer clock divided from APB clock (80Mhz)
-
-
enum
ledc_timer_t
¶ Values:
-
LEDC_TIMER_0
= 0¶ LEDC timer 0
-
LEDC_TIMER_1
¶ LEDC timer 1
-
LEDC_TIMER_2
¶ LEDC timer 2
-
LEDC_TIMER_3
¶ LEDC timer 3
-
-
enum
ledc_channel_t
¶ Values:
-
LEDC_CHANNEL_0
= 0¶ LEDC channel 0
-
LEDC_CHANNEL_1
¶ LEDC channel 1
-
LEDC_CHANNEL_2
¶ LEDC channel 2
-
LEDC_CHANNEL_3
¶ LEDC channel 3
-
LEDC_CHANNEL_4
¶ LEDC channel 4
-
LEDC_CHANNEL_5
¶ LEDC channel 5
-
LEDC_CHANNEL_6
¶ LEDC channel 6
-
LEDC_CHANNEL_7
¶ LEDC channel 7
-
LEDC_CHANNEL_MAX
¶
-
-
enum
ledc_timer_bit_t
¶ Values:
-
LEDC_TIMER_10_BIT
= 10¶ LEDC PWM duty resolution of 10 bits
-
LEDC_TIMER_11_BIT
= 11¶ LEDC PWM duty resolution of 11 bits
-
LEDC_TIMER_12_BIT
= 12¶ LEDC PWM duty resolution of 12 bits
-
LEDC_TIMER_13_BIT
= 13¶ LEDC PWM duty resolution of 13 bits
-
LEDC_TIMER_14_BIT
= 14¶ LEDC PWM duty resolution of 14 bits
-
LEDC_TIMER_15_BIT
= 15¶ LEDC PWM duty resolution of 15 bits
-