ledc_fade_example_main.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /* LEDC (LED Controller) fade example
  2. This example code is in the Public Domain (or CC0 licensed, at your option.)
  3. Unless required by applicable law or agreed to in writing, this
  4. software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  5. CONDITIONS OF ANY KIND, either express or implied.
  6. */
  7. #include <stdio.h>
  8. #include "freertos/FreeRTOS.h"
  9. #include "freertos/task.h"
  10. #include "freertos/semphr.h"
  11. #include "driver/ledc.h"
  12. #include "esp_err.h"
  13. /*
  14. * About this example
  15. *
  16. * 1. Start with initializing LEDC module:
  17. * a. Set the timer of LEDC first, this determines the frequency
  18. * and resolution of PWM.
  19. * b. Then set the LEDC channel you want to use,
  20. * and bind with one of the timers.
  21. *
  22. * 2. You need first to install a default fade function,
  23. * then you can use fade APIs.
  24. *
  25. * 3. You can also set a target duty directly without fading.
  26. *
  27. * 4. On ESP32, GPIO18/19/4/5 are used as the LEDC outputs:
  28. * GPIO18/19 are from the high speed channel group
  29. * GPIO4/5 are from the low speed channel group
  30. *
  31. * On other targets, GPIO8/9/4/5 are used as the LEDC outputs,
  32. * and they are all from the low speed channel group.
  33. *
  34. * 5. All the LEDC outputs change the duty repeatedly.
  35. *
  36. */
  37. #if CONFIG_IDF_TARGET_ESP32
  38. #define LEDC_HS_TIMER LEDC_TIMER_0
  39. #define LEDC_HS_MODE LEDC_HIGH_SPEED_MODE
  40. #define LEDC_HS_CH0_GPIO (18)
  41. #define LEDC_HS_CH0_CHANNEL LEDC_CHANNEL_0
  42. #define LEDC_HS_CH1_GPIO (19)
  43. #define LEDC_HS_CH1_CHANNEL LEDC_CHANNEL_1
  44. #endif
  45. #define LEDC_LS_TIMER LEDC_TIMER_1
  46. #define LEDC_LS_MODE LEDC_LOW_SPEED_MODE
  47. #if !CONFIG_IDF_TARGET_ESP32
  48. #define LEDC_LS_CH0_GPIO (8)
  49. #define LEDC_LS_CH0_CHANNEL LEDC_CHANNEL_0
  50. #define LEDC_LS_CH1_GPIO (9)
  51. #define LEDC_LS_CH1_CHANNEL LEDC_CHANNEL_1
  52. #endif
  53. #define LEDC_LS_CH2_GPIO (4)
  54. #define LEDC_LS_CH2_CHANNEL LEDC_CHANNEL_2
  55. #define LEDC_LS_CH3_GPIO (5)
  56. #define LEDC_LS_CH3_CHANNEL LEDC_CHANNEL_3
  57. #define LEDC_TEST_CH_NUM (4)
  58. #define LEDC_TEST_DUTY (4000)
  59. #define LEDC_TEST_FADE_TIME (3000)
  60. /*
  61. * This callback function will be called when fade operation has ended
  62. * Use callback only if you are aware it is being called inside an ISR
  63. * Otherwise, you can use a semaphore to unblock tasks
  64. */
  65. static bool cb_ledc_fade_end_event(const ledc_cb_param_t *param, void *user_arg)
  66. {
  67. portBASE_TYPE taskAwoken = pdFALSE;
  68. if (param->event == LEDC_FADE_END_EVT) {
  69. SemaphoreHandle_t counting_sem = (SemaphoreHandle_t) user_arg;
  70. xSemaphoreGiveFromISR(counting_sem, &taskAwoken);
  71. }
  72. return (taskAwoken == pdTRUE);
  73. }
  74. void app_main(void)
  75. {
  76. int ch;
  77. /*
  78. * Prepare and set configuration of timers
  79. * that will be used by LED Controller
  80. */
  81. ledc_timer_config_t ledc_timer = {
  82. .duty_resolution = LEDC_TIMER_13_BIT, // resolution of PWM duty
  83. .freq_hz = 5000, // frequency of PWM signal
  84. .speed_mode = LEDC_LS_MODE, // timer mode
  85. .timer_num = LEDC_LS_TIMER, // timer index
  86. .clk_cfg = LEDC_AUTO_CLK, // Auto select the source clock
  87. };
  88. // Set configuration of timer0 for high speed channels
  89. ledc_timer_config(&ledc_timer);
  90. #ifdef CONFIG_IDF_TARGET_ESP32
  91. // Prepare and set configuration of timer1 for low speed channels
  92. ledc_timer.speed_mode = LEDC_HS_MODE;
  93. ledc_timer.timer_num = LEDC_HS_TIMER;
  94. ledc_timer_config(&ledc_timer);
  95. #endif
  96. /*
  97. * Prepare individual configuration
  98. * for each channel of LED Controller
  99. * by selecting:
  100. * - controller's channel number
  101. * - output duty cycle, set initially to 0
  102. * - GPIO number where LED is connected to
  103. * - speed mode, either high or low
  104. * - timer servicing selected channel
  105. * Note: if different channels use one timer,
  106. * then frequency and bit_num of these channels
  107. * will be the same
  108. */
  109. ledc_channel_config_t ledc_channel[LEDC_TEST_CH_NUM] = {
  110. #if CONFIG_IDF_TARGET_ESP32
  111. {
  112. .channel = LEDC_HS_CH0_CHANNEL,
  113. .duty = 0,
  114. .gpio_num = LEDC_HS_CH0_GPIO,
  115. .speed_mode = LEDC_HS_MODE,
  116. .hpoint = 0,
  117. .timer_sel = LEDC_HS_TIMER,
  118. .flags.output_invert = 0
  119. },
  120. {
  121. .channel = LEDC_HS_CH1_CHANNEL,
  122. .duty = 0,
  123. .gpio_num = LEDC_HS_CH1_GPIO,
  124. .speed_mode = LEDC_HS_MODE,
  125. .hpoint = 0,
  126. .timer_sel = LEDC_HS_TIMER,
  127. .flags.output_invert = 0
  128. },
  129. #else
  130. {
  131. .channel = LEDC_LS_CH0_CHANNEL,
  132. .duty = 0,
  133. .gpio_num = LEDC_LS_CH0_GPIO,
  134. .speed_mode = LEDC_LS_MODE,
  135. .hpoint = 0,
  136. .timer_sel = LEDC_LS_TIMER,
  137. .flags.output_invert = 0
  138. },
  139. {
  140. .channel = LEDC_LS_CH1_CHANNEL,
  141. .duty = 0,
  142. .gpio_num = LEDC_LS_CH1_GPIO,
  143. .speed_mode = LEDC_LS_MODE,
  144. .hpoint = 0,
  145. .timer_sel = LEDC_LS_TIMER,
  146. .flags.output_invert = 0
  147. },
  148. #endif
  149. {
  150. .channel = LEDC_LS_CH2_CHANNEL,
  151. .duty = 0,
  152. .gpio_num = LEDC_LS_CH2_GPIO,
  153. .speed_mode = LEDC_LS_MODE,
  154. .hpoint = 0,
  155. .timer_sel = LEDC_LS_TIMER,
  156. .flags.output_invert = 1
  157. },
  158. {
  159. .channel = LEDC_LS_CH3_CHANNEL,
  160. .duty = 0,
  161. .gpio_num = LEDC_LS_CH3_GPIO,
  162. .speed_mode = LEDC_LS_MODE,
  163. .hpoint = 0,
  164. .timer_sel = LEDC_LS_TIMER,
  165. .flags.output_invert = 1
  166. },
  167. };
  168. // Set LED Controller with previously prepared configuration
  169. for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
  170. ledc_channel_config(&ledc_channel[ch]);
  171. }
  172. // Initialize fade service.
  173. ledc_fade_func_install(0);
  174. ledc_cbs_t callbacks = {
  175. .fade_cb = cb_ledc_fade_end_event
  176. };
  177. SemaphoreHandle_t counting_sem = xSemaphoreCreateCounting(LEDC_TEST_CH_NUM, 0);
  178. for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
  179. ledc_cb_register(ledc_channel[ch].speed_mode, ledc_channel[ch].channel, &callbacks, (void *) counting_sem);
  180. }
  181. while (1) {
  182. printf("1. LEDC fade up to duty = %d\n", LEDC_TEST_DUTY);
  183. for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
  184. ledc_set_fade_with_time(ledc_channel[ch].speed_mode,
  185. ledc_channel[ch].channel, LEDC_TEST_DUTY, LEDC_TEST_FADE_TIME);
  186. ledc_fade_start(ledc_channel[ch].speed_mode,
  187. ledc_channel[ch].channel, LEDC_FADE_NO_WAIT);
  188. }
  189. for (int i = 0; i < LEDC_TEST_CH_NUM; i++) {
  190. xSemaphoreTake(counting_sem, portMAX_DELAY);
  191. }
  192. printf("2. LEDC fade down to duty = 0\n");
  193. for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
  194. ledc_set_fade_with_time(ledc_channel[ch].speed_mode,
  195. ledc_channel[ch].channel, 0, LEDC_TEST_FADE_TIME);
  196. ledc_fade_start(ledc_channel[ch].speed_mode,
  197. ledc_channel[ch].channel, LEDC_FADE_NO_WAIT);
  198. }
  199. for (int i = 0; i < LEDC_TEST_CH_NUM; i++) {
  200. xSemaphoreTake(counting_sem, portMAX_DELAY);
  201. }
  202. printf("3. LEDC set duty = %d without fade\n", LEDC_TEST_DUTY);
  203. for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
  204. ledc_set_duty(ledc_channel[ch].speed_mode, ledc_channel[ch].channel, LEDC_TEST_DUTY);
  205. ledc_update_duty(ledc_channel[ch].speed_mode, ledc_channel[ch].channel);
  206. }
  207. vTaskDelay(1000 / portTICK_PERIOD_MS);
  208. printf("4. LEDC set duty = 0 without fade\n");
  209. for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
  210. ledc_set_duty(ledc_channel[ch].speed_mode, ledc_channel[ch].channel, 0);
  211. ledc_update_duty(ledc_channel[ch].speed_mode, ledc_channel[ch].channel);
  212. }
  213. vTaskDelay(1000 / portTICK_PERIOD_MS);
  214. }
  215. }