This piece of code demonstrates how to use PWM in ESP-IDF. For more information I recommend visiting the documentation because there are many details that you might need to read about yourself.
There are two primary types of PWM in ESP-IDF:
Note: You may want to check the return values of ledc_timer_config
or other functions casted to void
. For the sake of simplicity I ignored their return values. Read the documentation for further information on how to handle errors.
#include "driver/ledc.h"
#include "freertos/FreeRTOS.h"
ledc_timer_config_t LED_TIMER = {
.speed_mode = LEDC_HIGH_SPEED_MODE,
.duty_resolution = LEDC_TIMER_8_BIT,
.timer_num = LEDC_TIMER_0,
.freq_hz = 1000,
.clk_cfg = LEDC_AUTO_CLK,
.deconfigure = false
};
ledc_channel_config_t LED_CONFIG = {
.gpio_num = 18, // Use GPIO pin 18 (which supports PWM)
.speed_mode = LEDC_HIGH_SPEED_MODE,
.channel = LEDC_CHANNEL_0,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = LEDC_TIMER_0,
.duty = 0, // max is 2^LEDTIMER.duty_resolution - 1
.hpoint = 0 // "delay" after which the counter starts.
};
const int32_t max_duty = 255; // alternatively pow(2, LED_TIMER.duty_resolution) - 1
void app_main() {
(void)ledc_timer_config(&LED_TIMER);
(void)ledc_channel_config(&LED_CONFIG);
while (1) {
for (int32_t duty = 0; duty <= max_duty; duty++) {
(void)ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, duty);
(void)ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
vTaskDelay(pdMS_TO_TICKS(20));
}
for (uint32_t duty = max_duty; duty > 0; duty--) {
(void)ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, duty);
(void)ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
vTaskDelay(pdMS_TO_TICKS(20));
}
}
}