ledc.rst 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. LED Control (LEDC)
  2. ==================
  3. {IDF_TARGET_LEDC_CHAN_NUM: default="6", esp32="16", esp32s2="8", esp32s3="8"}
  4. {IDF_TARGET_LEDC_MAX_FADE_RANGE_NUM: default="1", esp32c6="16", esp32h2="16"}
  5. :link_to_translation:`zh_CN:[中文]`
  6. Introduction
  7. ------------
  8. The LED control (LEDC) peripheral is primarily designed to control the intensity of LEDs, although it can also be used to generate PWM signals for other purposes.
  9. It has {IDF_TARGET_LEDC_CHAN_NUM} channels which can generate independent waveforms that can be used, for example, to drive RGB LED devices.
  10. .. only:: esp32
  11. LEDC channels are divided into two groups of 8 channels each. One group of LEDC channels operates in high speed mode. This mode is implemented in hardware and offers automatic and glitch-free changing of the PWM duty cycle. The other group of channels operate in low speed mode, the PWM duty cycle must be changed by the driver in software. Each group of channels is also able to use different clock sources.
  12. The PWM controller can automatically increase or decrease the duty cycle gradually, allowing for fades without any processor interference.
  13. Functionality Overview
  14. ----------------------
  15. .. only:: esp32
  16. Setting up a channel of the LEDC in either :ref:`high or low speed mode <ledc-api-high_low_speed_mode>` is done in three steps:
  17. .. only:: not esp32
  18. Setting up a channel of the LEDC is done in three steps. Note that unlike ESP32, {IDF_TARGET_NAME} only supports configuring channels in "low speed" mode.
  19. 1. :ref:`ledc-api-configure-timer` by specifying the PWM signal's frequency and duty cycle resolution.
  20. 2. :ref:`ledc-api-configure-channel` by associating it with the timer and GPIO to output the PWM signal.
  21. 3. :ref:`ledc-api-change-pwm-signal` that drives the output in order to change LED's intensity. This can be done under the full control of software or with hardware fading functions.
  22. As an optional step, it is also possible to set up an interrupt on fade end.
  23. .. figure:: ../../../_static/ledc-api-settings.jpg
  24. :align: center
  25. :alt: Key Settings of LED PWM Controller's API
  26. :figclass: align-center
  27. Key Settings of LED PWM Controller's API
  28. .. note::
  29. For an initial setup, it is recommended to configure for the timers first (by calling :cpp:func:`ledc_timer_config`), and then for the channels (by calling :cpp:func:`ledc_channel_config`). This ensures the PWM frequency is at the desired value since the appearance of the PWM signal from the IO pad.
  30. .. _ledc-api-configure-timer:
  31. Timer Configuration
  32. ^^^^^^^^^^^^^^^^^^^
  33. Setting the timer is done by calling the function :cpp:func:`ledc_timer_config` and passing the data structure :cpp:type:`ledc_timer_config_t` that contains the following configuration settings:
  34. .. list::
  35. :esp32: - Speed mode :cpp:type:`ledc_mode_t`
  36. :not esp32: - Speed mode (value must be ``LEDC_LOW_SPEED_MODE``)
  37. - Timer number :cpp:type:`ledc_timer_t`
  38. - PWM signal frequency
  39. - Resolution of PWM duty
  40. - Source clock :cpp:type:`ledc_clk_cfg_t`
  41. The frequency and the duty resolution are interdependent. The higher the PWM frequency, the lower the duty resolution which is available, and vice versa. This relationship might be important if you are planning to use this API for purposes other than changing the intensity of LEDs. For more details, see Section :ref:`ledc-api-supported-range-frequency-duty-resolution`.
  42. The source clock can also limit the PWM frequency. The higher the source clock frequency, the higher the maximum PWM frequency can be configured.
  43. .. only:: esp32
  44. .. list-table:: Characteristics of {IDF_TARGET_NAME} LEDC source clocks
  45. :widths: 5 5 5 20
  46. :header-rows: 1
  47. * - Clock name
  48. - Clock freq
  49. - Speed mode
  50. - Clock capabilities
  51. * - APB_CLK
  52. - 80 MHz
  53. - High / Low
  54. - /
  55. * - REF_TICK
  56. - 1 MHz
  57. - High / Low
  58. - Dynamic Frequency Scaling compatible
  59. * - RC_FAST_CLK
  60. - ~8 MHz
  61. - Low
  62. - Dynamic Frequency Scaling compatible, Light sleep compatible
  63. .. only:: esp32s2
  64. .. list-table:: Characteristics of {IDF_TARGET_NAME} LEDC source clocks
  65. :widths: 15 15 30
  66. :header-rows: 1
  67. * - Clock name
  68. - Clock freq
  69. - Clock capabilities
  70. * - APB_CLK
  71. - 80 MHz
  72. - /
  73. * - REF_TICK
  74. - 1 MHz
  75. - Dynamic Frequency Scaling compatible
  76. * - RC_FAST_CLK
  77. - ~8 MHz
  78. - Dynamic Frequency Scaling compatible, Light sleep compatible
  79. * - XTAL_CLK
  80. - 40 MHz
  81. - Dynamic Frequency Scaling compatible
  82. .. only:: esp32s3 or esp32c3
  83. .. list-table:: Characteristics of {IDF_TARGET_NAME} LEDC source clocks
  84. :widths: 15 15 30
  85. :header-rows: 1
  86. * - Clock name
  87. - Clock freq
  88. - Clock capabilities
  89. * - APB_CLK
  90. - 80 MHz
  91. - /
  92. * - RC_FAST_CLK
  93. - ~20 MHz
  94. - Dynamic Frequency Scaling compatible, Light sleep compatible
  95. * - XTAL_CLK
  96. - 40 MHz
  97. - Dynamic Frequency Scaling compatible
  98. .. only:: esp32c2
  99. .. list-table:: Characteristics of {IDF_TARGET_NAME} LEDC source clocks
  100. :widths: 15 15 30
  101. :header-rows: 1
  102. * - Clock name
  103. - Clock freq
  104. - Clock capabilities
  105. * - PLL_60M_CLK
  106. - 60 MHz
  107. - /
  108. * - RC_FAST_CLK
  109. - ~20 MHz
  110. - Dynamic Frequency Scaling compatible, Light sleep compatible
  111. * - XTAL_CLK
  112. - 40 MHz
  113. - Dynamic Frequency Scaling compatible
  114. .. only:: esp32c6
  115. .. list-table:: Characteristics of {IDF_TARGET_NAME} LEDC source clocks
  116. :widths: 15 15 30
  117. :header-rows: 1
  118. * - Clock name
  119. - Clock freq
  120. - Clock capabilities
  121. * - PLL_80M_CLK
  122. - 80 MHz
  123. - /
  124. * - RC_FAST_CLK
  125. - ~20 MHz
  126. - Dynamic Frequency Scaling compatible, Light sleep compatible
  127. * - XTAL_CLK
  128. - 40 MHz
  129. - Dynamic Frequency Scaling compatible
  130. .. only:: esp32h2
  131. .. list-table:: Characteristics of {IDF_TARGET_NAME} LEDC source clocks
  132. :widths: 15 15 30
  133. :header-rows: 1
  134. * - Clock name
  135. - Clock freq
  136. - Clock capabilities
  137. * - PLL_96M_CLK
  138. - 96 MHz
  139. - /
  140. * - RC_FAST_CLK
  141. - ~8 MHz
  142. - Dynamic Frequency Scaling compatible, Light sleep compatible
  143. * - XTAL_CLK
  144. - 32 MHz
  145. - Dynamic Frequency Scaling compatible
  146. .. only:: esp32h4
  147. .. list-table:: Characteristics of {IDF_TARGET_NAME} LEDC source clocks
  148. :widths: 15 15 30
  149. :header-rows: 1
  150. * - Clock name
  151. - Clock freq
  152. - Clock capabilities
  153. * - APB_CLK
  154. - 96 MHz
  155. - /
  156. * - RC_FAST_CLK
  157. - ~8 MHz
  158. - Dynamic Frequency Scaling compatible, Light sleep compatible
  159. * - XTAL_CLK
  160. - 32 MHz
  161. - Dynamic Frequency Scaling compatible
  162. .. note::
  163. .. only:: SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
  164. 1. On {IDF_TARGET_NAME}, if RC_FAST_CLK is chosen as the LEDC clock source, an internal calibration will be performed to get the exact frequency of the clock. This ensures the accuracy of output PWM signal frequency.
  165. .. only:: not SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
  166. 1. On {IDF_TARGET_NAME}, if RC_FAST_CLK is chosen as the LEDC clock source, you may see the frequency of output PWM signal is not very accurate. This is because no internal calibration is performed to get the exact frequency of the clock due to hardware limitation, a theoretic frequency value is used.
  167. .. only:: not SOC_LEDC_HAS_TIMER_SPECIFIC_MUX
  168. 2. For {IDF_TARGET_NAME}, all timers share one clock source. In other words, it is impossible to use different clock sources for different timers.
  169. .. _ledc-api-configure-channel:
  170. Channel Configuration
  171. ^^^^^^^^^^^^^^^^^^^^^
  172. When the timer is set up, configure the desired channel (one out of :cpp:type:`ledc_channel_t`). This is done by calling the function :cpp:func:`ledc_channel_config`.
  173. Similar to the timer configuration, the channel setup function should be passed a structure :cpp:type:`ledc_channel_config_t` that contains the channel's configuration parameters.
  174. At this point, the channel should start operating and generating the PWM signal on the selected GPIO, as configured in :cpp:type:`ledc_channel_config_t`, with the frequency specified in the timer settings and the given duty cycle. The channel operation (signal generation) can be suspended at any time by calling the function :cpp:func:`ledc_stop`.
  175. .. _ledc-api-change-pwm-signal:
  176. Change PWM Signal
  177. ^^^^^^^^^^^^^^^^^
  178. Once the channel starts operating and generating the PWM signal with the constant duty cycle and frequency, there are a couple of ways to change this signal. When driving LEDs, primarily the duty cycle is changed to vary the light intensity.
  179. The following two sections describe how to change the duty cycle using software and hardware fading. If required, the signal's frequency can also be changed; it is covered in Section :ref:`ledc-api-change-pwm-frequency`.
  180. .. only:: not esp32
  181. .. note::
  182. All the timers and channels in the {IDF_TARGET_NAME}'s LED PWM Controller only support low speed mode. Any change of PWM settings must be explicitly triggered by software (see below).
  183. Change PWM Duty Cycle Using Software
  184. """"""""""""""""""""""""""""""""""""
  185. To set the duty cycle, use the dedicated function :cpp:func:`ledc_set_duty`. After that, call :cpp:func:`ledc_update_duty` to activate the changes. To check the currently set value, use the corresponding ``_get_`` function :cpp:func:`ledc_get_duty`.
  186. Another way to set the duty cycle, as well as some other channel parameters, is by calling :cpp:func:`ledc_channel_config` covered in Section :ref:`ledc-api-configure-channel`.
  187. The range of the duty cycle values passed to functions depends on selected ``duty_resolution`` and should be from ``0`` to ``(2 ** duty_resolution) - 1``. For example, if the selected duty resolution is 10, then the duty cycle values can range from 0 to 1023. This provides the resolution of ~0.1%.
  188. Change PWM Duty Cycle using Hardware
  189. """"""""""""""""""""""""""""""""""""
  190. The LEDC hardware provides the means to gradually transition from one duty cycle value to another. To use this functionality, enable fading with :cpp:func:`ledc_fade_func_install` and then configure it by calling one of the available fading functions:
  191. * :cpp:func:`ledc_set_fade_with_time`
  192. * :cpp:func:`ledc_set_fade_with_step`
  193. * :cpp:func:`ledc_set_fade`
  194. .. only:: SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED
  195. On {IDF_TARGET_NAME}, the hardware additionally allows to perform up to {IDF_TARGET_LEDC_MAX_FADE_RANGE_NUM} consecutive linear fades without CPU intervention. This feature can be useful if you want to do a fade with gamma correction.
  196. The luminance perceived by human eyes does not have a linear relationship with the PWM duty cycle. In order to make human feel the LED is dimming or lightening linearly, the change in duty cycle should be non-linear, which is the so-called gamma correction. The LED controller can simulate a gamma curve fading by piecewise linear approximation. :cpp:func:`ledc_fill_multi_fade_param_list` is a function that can help to construct the parameters for the piecewise linear fades. First, you need to allocate a memory block for saving the fade parameters, then by providing start/end PWM duty cycle values, gamma correction function, and the total number of desired linear segments to the helper function, it will fill the calculation results into the allocated space. You can also construct the array of :cpp:type:`ledc_fade_param_config_t` manually. Once the fade parameter structs are prepared, a consecutive fading can be configured by passing the pointer to the prepared :cpp:type:`ledc_fade_param_config_t` list and the total number of fade ranges to :cpp:func:`ledc_set_multi_fade`.
  197. .. only:: esp32
  198. Start fading with :cpp:func:`ledc_fade_start`. A fade can be operated in blocking or non-blocking mode, please check :cpp:enum:`ledc_fade_mode_t` for the difference between the two available fade modes. Note that with either fade mode, the next fade or fixed-duty update will not take effect until the last fade finishes. Due to hardware limitations, there is no way to stop a fade before it reaches its target duty.
  199. .. only:: not esp32
  200. Start fading with :cpp:func:`ledc_fade_start`. A fade can be operated in blocking or non-blocking mode, please check :cpp:enum:`ledc_fade_mode_t` for the difference between the two available fade modes. Note that with either fade mode, the next fade or fixed-duty update will not take effect until the last fade finishes or is stopped. :cpp:func:`ledc_fade_stop` has to be called to stop a fade that is in progress.
  201. To get a notification about the completion of a fade operation, a fade end callback function can be registered for each channel by calling :cpp:func:`ledc_cb_register` after the fade service being installed. The fade end callback prototype is defined in :cpp:type:`ledc_cb_t`, where you should return a boolean value from the callback function, indicating whether a high priority task is woken up by this callback function. It is worth mentioning, the callback and the function invoked by itself should be placed in IRAM, as the interrupt service routine is in IRAM. :cpp:func:`ledc_cb_register` will print a warning message if it finds the addresses of callback and user context are incorrect.
  202. If not required anymore, fading and an associated interrupt can be disabled with :cpp:func:`ledc_fade_func_uninstall`.
  203. .. _ledc-api-change-pwm-frequency:
  204. Change PWM Frequency
  205. """"""""""""""""""""
  206. The LEDC API provides several ways to change the PWM frequency "on the fly":
  207. * Set the frequency by calling :cpp:func:`ledc_set_freq`. There is a corresponding function :cpp:func:`ledc_get_freq` to check the current frequency.
  208. * Change the frequency and the duty resolution by calling :cpp:func:`ledc_bind_channel_timer` to bind some other timer to the channel.
  209. * Change the channel's timer by calling :cpp:func:`ledc_channel_config`.
  210. More Control Over PWM
  211. """""""""""""""""""""
  212. There are several lower level timer-specific functions that can be used to change PWM settings:
  213. * :cpp:func:`ledc_timer_set`
  214. * :cpp:func:`ledc_timer_rst`
  215. * :cpp:func:`ledc_timer_pause`
  216. * :cpp:func:`ledc_timer_resume`
  217. The first two functions are called "behind the scenes" by :cpp:func:`ledc_channel_config` to provide a startup of a timer after it is configured.
  218. Use Interrupts
  219. ^^^^^^^^^^^^^^
  220. When configuring an LEDC channel, one of the parameters selected within :cpp:type:`ledc_channel_config_t` is :cpp:type:`ledc_intr_type_t` which triggers an interrupt on fade completion.
  221. For registration of a handler to address this interrupt, call :cpp:func:`ledc_isr_register`.
  222. .. only:: esp32
  223. .. _ledc-api-high_low_speed_mode:
  224. LEDC High and Low Speed Mode
  225. ----------------------------
  226. High speed mode enables a glitch-free changeover of timer settings. This means that if the timer settings are modified, the changes will be applied automatically on the next overflow interrupt of the timer. In contrast, when updating the low-speed timer, the change of settings should be explicitly triggered by software. The LEDC driver handles it in the background, e.g., when :cpp:func:`ledc_timer_config` or :cpp:func:`ledc_timer_set` is called.
  227. For additional details regarding speed modes, see *{IDF_TARGET_NAME} Technical Reference Manual* > *LED PWM Controller (LEDC)* [`PDF <{IDF_TARGET_TRM_EN_URL}#ledpwm>`__].
  228. .. _ledc-api-supported-range-frequency-duty-resolution:
  229. .. only:: not esp32
  230. .. _ledc-api-supported-range-frequency-duty-resolution:
  231. Supported Range of Frequency and Duty Resolutions
  232. -------------------------------------------------
  233. The LED PWM Controller is designed primarily to drive LEDs. It provides a large flexibility of PWM duty cycle settings. For instance, the PWM frequency of 5 kHz can have the maximum duty resolution of 13 bits. This means that the duty can be set anywhere from 0 to 100% with a resolution of ~0.012% (2 ** 13 = 8192 discrete levels of the LED intensity). Note, however, that these parameters depend on the clock signal clocking the LED PWM Controller timer which in turn clocks the channel (see :ref:`timer configuration<ledc-api-configure-timer>` and the *{IDF_TARGET_NAME} Technical Reference Manual* > *LED PWM Controller (LEDC)* [`PDF <{IDF_TARGET_TRM_EN_URL}#ledpwm>`__]).
  234. The LEDC can be used for generating signals at much higher frequencies that are sufficient enough to clock other devices, e.g., a digital camera module. In this case, the maximum available frequency is 40 MHz with duty resolution of 1 bit. This means that the duty cycle is fixed at 50% and cannot be adjusted.
  235. The LEDC API is designed to report an error when trying to set a frequency and a duty resolution that exceed the range of LEDC's hardware. For example, an attempt to set the frequency to 20 MHz and the duty resolution to 3 bits will result in the following error reported on a serial monitor:
  236. .. highlight:: none
  237. ::
  238. E (196) ledc: requested frequency and duty resolution cannot be achieved, try reducing freq_hz or duty_resolution. div_param=128
  239. In such a situation, either the duty resolution or the frequency must be reduced. For example, setting the duty resolution to 2 will resolve this issue and will make it possible to set the duty cycle at 25% steps, i.e., at 25%, 50% or 75%.
  240. The LEDC driver will also capture and report attempts to configure frequency / duty resolution combinations that are below the supported minimum, e.g.:
  241. ::
  242. E (196) ledc: requested frequency and duty resolution cannot be achieved, try increasing freq_hz or duty_resolution. div_param=128000000
  243. The duty resolution is normally set using :cpp:type:`ledc_timer_bit_t`. This enumeration covers the range from 10 to 15 bits. If a smaller duty resolution is required (from 10 down to 1), enter the equivalent numeric values directly.
  244. Application Example
  245. -------------------
  246. The LEDC basic example: :example:`peripherals/ledc/ledc_basic`.
  247. The LEDC change duty cycle and fading control example: :example:`peripherals/ledc/ledc_fade`.
  248. .. only:: SOC_LEDC_GAMMA_CURVE_FADE_SUPPORTED
  249. The LEDC color control with Gamma correction on RGB LED example: :example:`peripherals/ledc/ledc_gamma_curve_fade`.
  250. API Reference
  251. -------------
  252. .. include-build-file:: inc/ledc.inc
  253. .. include-build-file:: inc/ledc_types.inc