{"id":174268,"date":"2025-09-19T10:39:13","date_gmt":"2025-09-19T10:39:13","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=174268"},"modified":"2026-01-15T16:40:22","modified_gmt":"2026-01-15T16:40:22","slug":"esp-idf-esp32-gpio-pwm-ledc","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp-idf-esp32-gpio-pwm-ledc\/","title":{"rendered":"ESP-IDF: ESP32 GPIO PWM with LEDC (Control LED Brightness)"},"content":{"rendered":"\n<p>In this guide, you&#8217;ll learn how to control the ESP32 board&#8217;s GPIOs using PWM (Pulse Width Modulation) with ESP-IDF (Espressif IoT Development Framework).<\/p>\n\n\n\n<p>The ESP32 is a microcontroller that offers several General Purpose Input\/Output (GPIO) pins. Most ESP32 GPIOs can be configured with the LEDC (LED Control) peripheral which allows to generate PWM signals to control an LED&#8217;s brightness or any other output devices that require a signal with duty cycle and frequency control.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/08\/ESP-IDF-ESP32-GPIO-PWM-LEDC-Control-LED-Brightness.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-IDF: ESP32 GPIO PWM with LEDC Control LED Brightness\" class=\"wp-image-175045\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/08\/ESP-IDF-ESP32-GPIO-PWM-LEDC-Control-LED-Brightness.jpg?w=1920&amp;quality=100&amp;strip=all&amp;ssl=1 1920w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/08\/ESP-IDF-ESP32-GPIO-PWM-LEDC-Control-LED-Brightness.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/08\/ESP-IDF-ESP32-GPIO-PWM-LEDC-Control-LED-Brightness.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/08\/ESP-IDF-ESP32-GPIO-PWM-LEDC-Control-LED-Brightness.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/08\/ESP-IDF-ESP32-GPIO-PWM-LEDC-Control-LED-Brightness.jpg?resize=1536%2C864&amp;quality=100&amp;strip=all&amp;ssl=1 1536w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>Before following this guide, you need to install the ESP-IDF extension on VS Code IDE (Microsoft Visual Studio Code). Follow the next guide to install it, if you haven&#8217;t already:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/programming-esp32-esp-idf-vs-code\/\"><strong>Getting Started Guide:<\/strong> Programming ESP32 with ESP-IDF using VS Code<\/a><\/li>\n<\/ul>\n\n\n\n<p>You will also need an <a href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\" rel=\"noopener\" title=\"\">ESP32 development board<\/a> model of your choice.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">ESP32 LEDC (LED Control)<\/h2>\n\n\n\n<p>In ESP-IDF, to generate PWM signals with the ESP32 GPIOs, you need to use the LEDC (LED Control) peripheral. The ESP32 offers up to 8 channels that can be configured with different duty cycles, frequencies and resolutions.<\/p>\n\n\n\n<p>In a high level overview, in order to use LEDC it is necessary to configure the timer first by using <span class=\"rnthl rntliteral\">ledc_timer_config()<\/span>, and then configure the channels with <span class=\"rnthl rntliteral\">ledc_channel_config()<\/span>. This procedure ensures the PWM frequency is at the desired value. This process will be explained in more detail in the examples (you can also learn more in the official <a href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/stable\/esp32\/api-reference\/peripherals\/ledc.html\" target=\"_blank\" rel=\"noopener\" title=\"\">documentation<\/a>).<\/p>\n\n\n\n<p>The ESP32 has an LED PWM controller with 6 to 16 independent channels (depending on the ESP32 model) that can be configured to generate PWM signals with different properties. All pins that can act as outputs can be used as PWM pins (GPIOs 34 to 39 can\u2019t generate PWM).<\/p>\n\n\n\n<p class=\"rntbox rntclblue\">Learn more about the ESP32 GPIOs: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-pinout-reference-gpios\/\">ESP32 GPIO Reference Guide<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating an ESP-IDF Template App Project for the ESP32<\/h2>\n\n\n\n<p>The ESP-IDF extension provides an easy way to create a project from scratch with all the required files and configurations generated automatically.<\/p>\n\n\n\n<p>To create a new ESP-IDF project on VS Code, follow these steps:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the ESP-IDF Espressif extension<\/li>\n\n\n\n<li>Expand the &#8220;<strong>Advanced<\/strong>&#8221; menu<\/li>\n\n\n\n<li>Click the &#8220;<strong>New Project Wizard<\/strong>&#8221; option<\/li>\n\n\n\n<li>Choose the &#8220;<strong>Use ESP-IDF v5.4.1<\/strong>&#8221; to select the framework version<\/li>\n<\/ol>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"937\" height=\"742\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Create-Open-New-Project-Wizard-Menu.png?resize=937%2C742&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-IDF ESP32 Create Open New Project Wizard Menu\" class=\"wp-image-170511\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Create-Open-New-Project-Wizard-Menu.png?w=937&amp;quality=100&amp;strip=all&amp;ssl=1 937w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Create-Open-New-Project-Wizard-Menu.png?resize=300%2C238&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Create-Open-New-Project-Wizard-Menu.png?resize=768%2C608&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 937px) 100vw, 937px\" \/><\/figure><\/div>\n\n\n<p>A new window opens, you need to fill in these fields:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Project Name:<\/strong> type the desired project name;<\/li>\n\n\n\n<li><strong>Enter Project Directory:<\/strong> click the folder icon and select the target folder to save all your project files. You can use any directory. <strong>Note:<\/strong> <u>do NOT use a Google Drive \/ One Drive \/ Dropbox folder<\/u>, because it will write\/create many files during the building process\u2014if it&#8217;s on a cloud folder, this process might be extremely slow;<\/li>\n\n\n\n<li><strong>ESP-IDF Target:<\/strong> select the target device chip, I&#8217;m using an ESP32 with the <strong>esp32s3<\/strong> chip;<\/li>\n\n\n\n<li><strong>ESP-IDF Board:<\/strong> for the esp32s3 chip, I also need to select the configuration: ESP32-S chip (via builtin USB-JTAG);<\/li>\n\n\n\n<li><strong>Serial Port:<\/strong> while having your ESP32 board connected to your computer, select the correct COM port number that refers to your ESP32;<\/li>\n\n\n\n<li><strong>Choose Template:<\/strong> click the blue button to create a new project using a template.<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"983\" height=\"856\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Create-Open-New-Project-Wizard-Menu-Select-Directory-Board-Template.png?resize=983%2C856&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-IDF ESP32 Create Open New Project Wizard Menu Select Directory Board Template\" class=\"wp-image-170512\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Create-Open-New-Project-Wizard-Menu-Select-Directory-Board-Template.png?w=983&amp;quality=100&amp;strip=all&amp;ssl=1 983w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Create-Open-New-Project-Wizard-Menu-Select-Directory-Board-Template.png?resize=300%2C261&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Create-Open-New-Project-Wizard-Menu-Select-Directory-Board-Template.png?resize=768%2C669&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 983px) 100vw, 983px\" \/><\/figure><\/div>\n\n\n<p>In the menu, select the &#8220;<strong>ESP-IDF Templates<\/strong>&#8221; sample project and press the &#8220;<strong>Create project using template sample project<\/strong>&#8221; button.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1178\" height=\"744\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2026\/01\/ESP-IDF-ESP32-Create-New-Sample-Project-using-IDF-Template.png?resize=1178%2C744&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-IDF ESP32 Create New Sample Project using IDF Template\" class=\"wp-image-187415\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2026\/01\/ESP-IDF-ESP32-Create-New-Sample-Project-using-IDF-Template.png?w=1178&amp;quality=100&amp;strip=all&amp;ssl=1 1178w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2026\/01\/ESP-IDF-ESP32-Create-New-Sample-Project-using-IDF-Template.png?resize=300%2C189&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2026\/01\/ESP-IDF-ESP32-Create-New-Sample-Project-using-IDF-Template.png?resize=1024%2C647&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2026\/01\/ESP-IDF-ESP32-Create-New-Sample-Project-using-IDF-Template.png?resize=768%2C485&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1178px) 100vw, 1178px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">Opening the ESP-IDF Project on VS Code<\/h3>\n\n\n\n<p>After a few seconds, a notification will appear on a new window on VS Code. You can click &#8220;<strong>Open Project<\/strong>&#8221; to open the newly created ESP-IDF sample project template.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"503\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2026\/01\/ESP-IDF-ESP32-Open-New-Project-Sample.png?resize=1024%2C503&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-IDF ESP32 Open New Project Sample\" class=\"wp-image-187416\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2026\/01\/ESP-IDF-ESP32-Open-New-Project-Sample.png?resize=1024%2C503&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2026\/01\/ESP-IDF-ESP32-Open-New-Project-Sample.png?resize=300%2C147&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2026\/01\/ESP-IDF-ESP32-Open-New-Project-Sample.png?resize=768%2C377&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2026\/01\/ESP-IDF-ESP32-Open-New-Project-Sample.png?w=1231&amp;quality=100&amp;strip=all&amp;ssl=1 1231w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n<p><strong>IMPORTANT:<\/strong> if you didn&#8217;t see the notification that allows you to automatically open the ESP-IDF project on VS Code, you can easily do it by following these instructions:<\/p>\n\n\n\n<p>Go to <strong>File <\/strong>&gt; <strong>Open Folder&#8230;<\/strong><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"396\" height=\"315\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Open-Project-Folder-VS-Code-File-Menu.png?resize=396%2C315&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-IDF ESP32 Open Project Folder VS Code File Menu\" class=\"wp-image-170518\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Open-Project-Folder-VS-Code-File-Menu.png?w=396&amp;quality=100&amp;strip=all&amp;ssl=1 396w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Open-Project-Folder-VS-Code-File-Menu.png?resize=300%2C239&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 396px) 100vw, 396px\" \/><\/figure><\/div>\n\n\n<p>Browse on your computer for the <em>esp-idf-project folder<\/em> (your project folder name that you&#8217;ve previously defined) and &#8220;<strong>Select Folder<\/strong>&#8220;.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"667\" height=\"366\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Open-Project-VS-Code-Select-Folder.png?resize=667%2C366&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-IDF ESP32 Open Project VS Code Select Folder\" class=\"wp-image-170517\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Open-Project-VS-Code-Select-Folder.png?w=667&amp;quality=100&amp;strip=all&amp;ssl=1 667w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Open-Project-VS-Code-Select-Folder.png?resize=300%2C165&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 667px) 100vw, 667px\" \/><\/figure><\/div>\n\n\n<p>That&#8217;s it! Your new ESP-IDF project template has been successfully created and opened.<\/p>\n\n\n\n<p>ESP-IDF generates many files, folders, and subfolders for your project. For this guide, I recommend keeping all the default files unchanged; we will only modify the <em>main.c<\/em> file.<\/p>\n\n\n\n<p>The example codes will be written in the <em>main.c<\/em> file. To open it, follow these instructions:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Open the project explorer by clicking the first icon on the left sidebar.<\/li>\n\n\n\n<li>Select your project folder name, in my case it&#8217;s &#8220;<strong>ESP-IDF-PROJECT<\/strong>&#8220;.<\/li>\n\n\n\n<li>Expand the &#8220;<strong>main<\/strong>&#8221; folder.<\/li>\n\n\n\n<li>Click the &#8220;<strong><em>main.c<\/em><\/strong>&#8221; file.<\/li>\n\n\n\n<li>The default <em>main.c<\/em> template file loads in the code window.<\/li>\n<\/ol>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"907\" height=\"571\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Open-Project-in-a-VS-Code-Browse-to-Main-C-File.png?resize=907%2C571&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-IDF ESP32 Open Project in a VS Code Browse to Main C File\" class=\"wp-image-170514\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Open-Project-in-a-VS-Code-Browse-to-Main-C-File.png?w=907&amp;quality=100&amp;strip=all&amp;ssl=1 907w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Open-Project-in-a-VS-Code-Browse-to-Main-C-File.png?resize=300%2C189&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/ESP-IDF-ESP32-Open-Project-in-a-VS-Code-Browse-to-Main-C-File.png?resize=768%2C483&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 907px) 100vw, 907px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Example #1: Control ESP32 LED&#8217;s Brightness with ESP-IDF LEDC (LED Control)<\/h2>\n\n\n\n<p>Here&#8217;s the full <em>main.c<\/em> code that controls the LED brightness using the <span class=\"rnthl rntliteral\">ledc<\/span> peripheral:<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*  \n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n  https:\/\/RandomNerdTutorials.com\/esp-idf-esp32-gpio-pwm-ledc\/\n*\/\n#include &lt;stdio.h&gt;\n#include &lt;freertos\/FreeRTOS.h&gt;\n#include &lt;freertos\/task.h&gt;\n#include &lt;driver\/ledc.h&gt;\n#include &quot;sdkconfig.h&quot;\n\n#define LED_PIN 5           \/\/ LED connected to GPIO 5\n#define LEDC_CHANNEL LEDC_CHANNEL_0\n#define LEDC_TIMER LEDC_TIMER_0\n#define LEDC_MODE LEDC_LOW_SPEED_MODE\n#define LEDC_DUTY_RES LEDC_TIMER_10_BIT \/\/ 10-bit resolution (0-1023)\n#define LEDC_FREQUENCY 1000             \/\/ 1 kHz PWM frequency\n\nvoid app_main(void)\n{\n    \/\/ Configure LEDC timer\n    ledc_timer_config_t ledc_timer = {\n        .speed_mode = LEDC_MODE,\n        .duty_resolution = LEDC_DUTY_RES,\n        .timer_num = LEDC_TIMER,\n        .freq_hz = LEDC_FREQUENCY\n    };\n    ledc_timer_config(&amp;ledc_timer);\n\n    \/\/ Configure LEDC channel\n    ledc_channel_config_t ledc_channel = {\n        .gpio_num = LED_PIN,\n        .speed_mode = LEDC_MODE,\n        .channel = LEDC_CHANNEL,\n        .timer_sel = LEDC_TIMER,\n        .duty = 0\n    };\n    ledc_channel_config(&amp;ledc_channel);\n\n    \/\/ Fading loop\n    while (1) {\n        \/\/ Fade in\n        for (int duty = 0; duty &lt;= 1023; duty += 10) {\n            ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, duty);\n            ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);\n            vTaskDelay(20 \/ portTICK_PERIOD_MS);\n            printf(&quot;LED duty cycle: %d\\n&quot;, duty);\n        }\n        \/\/ Fade out\n        for (int duty = 1023; duty &gt;= 0; duty -= 10) {\n            ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, duty);\n            ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);\n            vTaskDelay(20 \/ portTICK_PERIOD_MS);\n            printf(&quot;LED duty cycle: %d\\n&quot;, duty);\n        }\n    }\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP-IDF\/gpio_pwm\/gpio_pwm.c\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How the Code Works<\/h3>\n\n\n\n<p>In this section, we&#8217;ll take a look at the code to see how it works.<\/p>\n\n\n\n<p><strong>Libraries<\/strong><\/p>\n\n\n\n<p>We start by including the required libraries:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span class=\"rnthl rntliteral\">stdio.h<\/span> &#8211; the standard C library will be used for the <span class=\"rnthl rntliteral\">printf<\/span> function that prints the debugging information in the serial monitor;<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">FreeRTOS.h<\/span> &#8211; provides the core FreeRTOS types and functions;<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">task.h<\/span> &#8211; allows to use of the non-blocking delay function <span class=\"rnthl rntliteral\">vTaskDelay<\/span>;<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">driver\/ledc.h<\/span> &#8211; includes the functions required to configure timers and channels to generate PWM signals;<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">sdkconfig.h<\/span> &#8211; includes the project&#8217;s configuration file.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;stdio.h&gt;\n#include &lt;freertos\/FreeRTOS.h&gt;\n#include &lt;freertos\/task.h&gt;\n#include &lt;driver\/ledc.h&gt;\n#include \"sdkconfig.h\"<\/code><\/pre>\n\n\n\n<p><strong>Pin Assignment<\/strong><\/p>\n\n\n\n<p>This line assigns the LED to <span class=\"rnthl rntclblue\">GPIO 5<\/span>; you can change it to a different number to match your board pinout or to control a different GPIO.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define LED_PIN 5<\/code><\/pre>\n\n\n\n<p><strong>LEDC Configurations<\/strong><\/p>\n\n\n\n<p>Define the configurations for your LEDC channel, LEDC timer, mode, duty cycle resolution and frequency.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define LEDC_CHANNEL LEDC_CHANNEL_0\n#define LEDC_TIMER LEDC_TIMER_0\n#define LEDC_MODE LEDC_LOW_SPEED_MODE\n#define LEDC_DUTY_RES LEDC_TIMER_10_BIT  \/\/ 10-bit resolution (0-1023)\n#define LEDC_FREQUENCY 1000                           \/\/ 1 kHz PWM frequency<\/code><\/pre>\n\n\n\n<p><strong>app_main(void)<\/strong><\/p>\n\n\n\n<p>When creating an ESP-IDF project, this function will always be called to run. This function is where you need to write your code for any ESP-IDF applications; it is the equivalent of the <span class=\"rnthl rntliteral\">setup()<\/span> in Arduino programming. When the ESP32 boots, the ESP-IDF framework calls <span class=\"rnthl rntliteral\">app_main<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>void app_main(void)\n{\n    \/\/ your code goes here\n}<\/code><\/pre>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">app_main(void)<\/span> function, you start by creating the <span class=\"rnthl rntliteral\">ledc_timer<\/span> with the mode, resolution, timer and frequency:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span class=\"rnthl rntliteral\">speed_mode<\/span>: use <span class=\"rnthl rntliteral\">LEDC_LOW_SPEED_MODE<\/span> (some ESP32 also support <span class=\"rnthl rntliteral\">LEDC_HIGH_SPEED_MODE<\/span>)<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">duty_resolution<\/span>: set the PWM resolution (for example: 10-bit gives a 0 to 1023 range)<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">timer_num<\/span>: select one of the available timers<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">freq_hz<\/span>: sets the PWM frequency (1 kHz can be used for LEDs)<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Configure LEDC timer\nledc_timer_config_t ledc_timer = {\n    .speed_mode = LEDC_MODE,\n    .duty_resolution = LEDC_DUTY_RES,\n    .timer_num = LEDC_TIMER,\n    .freq_hz = LEDC_FREQUENCY\n};\nledc_timer_config(&amp;ledc_timer);<\/code><\/pre>\n\n\n\n<p>Then, call the <span class=\"rnthl rntliteral\">ledc_channel_config(&amp;ledc_channel)<\/span> function to configure the LEDC channels with the GPIO number, mode, channel, timer and duty cycle.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span class=\"rnthl rntliteral\">gpio_num<\/span>: assign the GPIO pin connected to the LED<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">speed_mode<\/span>: use <span class=\"rnthl rntliteral\">LEDC_LOW_SPEED_MODE<\/span> (some ESP32 also support <span class=\"rnthl rntliteral\">LEDC_HIGH_SPEED_MODE<\/span>)<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">channel<\/span>: assign an available channel (example: <span class=\"rnthl rntliteral\">LEDC_CHANNEL_0<\/span>)<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">timer_sel<\/span>: assign the channel to the configured timer<\/li>\n\n\n\n<li>duty: set the initial duty cycle (example: 0 = off and 1023 = full brightness for 10-bit range)<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Configure LEDC channel\nledc_channel_config_t ledc_channel = {\n    .gpio_num = LED_PIN,\n    .speed_mode = LEDC_MODE,\n    .channel = LEDC_CHANNEL,\n    .timer_sel = LEDC_TIMER,\n    .duty = 0\n};\nledc_channel_config(&amp;ledc_channel);<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">while(1)<\/span> runs an infinite loop that keeps the LED fading in and fading out creating a dimming LED effect.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>while (1) {\n    \/\/ Fade in\n    for (int duty = 0; duty &lt;= 1023; duty += 10) {\n        ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, duty);\n        ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);\n        vTaskDelay(20 \/ portTICK_PERIOD_MS);\n        printf(\"LED duty cycle: %d\\n\", duty);\n    }\n    \/\/ Fade out\n    for (int duty = 1023; duty &gt;= 0; duty -= 10) {\n        ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, duty);\n        ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);\n        vTaskDelay(20 \/ portTICK_PERIOD_MS);\n        printf(\"LED duty cycle: %d\\n\", duty);\n    }\n}<\/code><\/pre>\n\n\n\n<p>Set the <span class=\"rnthl rntliteral\">LEDC_CHANNEL<\/span> duty cycle to the value stored in <span class=\"rnthl rntliteral\">duty<\/span> and apply it to your LED (example: 0 = off and 1023 = full brightness for 10-bit range).<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, duty);\nledc_update_duty(LEDC_MODE, LEDC_CHANNEL);<\/code><\/pre>\n\n\n\n<p>Then, add a delay of 20 milliseconds, so the LED is brightness is incremented to create a fading in effect.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>vTaskDelay(20 \/ portTICK_PERIOD_MS);<\/code><\/pre>\n\n\n\n<p>Inside the infinite loop, you print a message saying &#8220;LED duty cycle:&#8221; in the Serial Monitor\/Terminal tab to see the current duty cycle that was applied.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>printf(\"LED duty cycle: %d\\n\", duty);<\/code><\/pre>\n\n\n\n<p>A similar process is repeated to fade out the LED.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Build and Flash Code to the ESP32 Board<\/h2>\n\n\n\n<p>To build and flash ESP-IDF code to the ESP32, you always need to follow this procedure. You need to select the flash method (UART), the COM port number, the target device (ESP32), build the code, and finally, flash it to the board. All these commands are available in the bottom menu bar of VS Code.<\/p>\n\n\n\n<p>Make sure all your options are correct (they may already be properly configured if you used the project wizard).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"498\" height=\"28\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Check-All-the-Configured-Settings-UART-COM-Port-Target-Board.png?resize=498%2C28&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code ESP-IDF Check All the Configured Settings UART COM Port Target Board\" class=\"wp-image-170147\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Check-All-the-Configured-Settings-UART-COM-Port-Target-Board.png?w=498&amp;quality=100&amp;strip=all&amp;ssl=1 498w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Check-All-the-Configured-Settings-UART-COM-Port-Target-Board.png?resize=300%2C17&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 498px) 100vw, 498px\" \/><\/figure><\/div>\n\n\n<p>However, if your setup is not correct, follow the next instructions to ensure everything is set up correctly. First, click the &#8220;<strong>Star<\/strong>&#8221; icon and select the flash method as <strong>UART<\/strong>.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"584\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Select-Flash-UART-Option-to-Program-Flash-ESP32-1024x584.png?resize=1024%2C584&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code ESP-IDF Select Flash UART Option to Program Flash ESP32\" class=\"wp-image-170161\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Select-Flash-UART-Option-to-Program-Flash-ESP32.png?resize=1024%2C584&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Select-Flash-UART-Option-to-Program-Flash-ESP32.png?resize=300%2C171&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Select-Flash-UART-Option-to-Program-Flash-ESP32.png?resize=768%2C438&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Select-Flash-UART-Option-to-Program-Flash-ESP32.png?w=1030&amp;quality=100&amp;strip=all&amp;ssl=1 1030w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n<p>While the ESP32 board is connected to your computer, click the COM Port (plug icon) and select the correct port number that refers to your ESP32.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"582\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Programming-ESP32-Board-Select-Correct-COM-Port-Number.png?resize=1024%2C582&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code ESP-IDF Programming ESP32 Board Select Correct COM Port Number\" class=\"wp-image-170160\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Programming-ESP32-Board-Select-Correct-COM-Port-Number.png?resize=1024%2C582&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Programming-ESP32-Board-Select-Correct-COM-Port-Number.png?resize=300%2C171&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Programming-ESP32-Board-Select-Correct-COM-Port-Number.png?resize=768%2C437&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Programming-ESP32-Board-Select-Correct-COM-Port-Number.png?w=1032&amp;quality=100&amp;strip=all&amp;ssl=1 1032w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n<p>You also need to select the target device. Click on the chip icon at the bottom bar. In my case, I have an ESP32 with the <strong>esp32s3<\/strong> chip.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"579\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Select-the-ESP32-S3-or-Correct-Target-Device.png?resize=1024%2C579&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code Select the ESP32 S3 or Correct Target Device ESP-IDF\" class=\"wp-image-170163\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Select-the-ESP32-S3-or-Correct-Target-Device.png?resize=1024%2C579&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Select-the-ESP32-S3-or-Correct-Target-Device.png?resize=300%2C170&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Select-the-ESP32-S3-or-Correct-Target-Device.png?resize=768%2C434&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Select-the-ESP32-S3-or-Correct-Target-Device.png?w=1031&amp;quality=100&amp;strip=all&amp;ssl=1 1031w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n<p>For this board, I also need to select the configuration: <strong>ESP32-S chip (via builtin USB-JTAG)<\/strong>.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"757\" height=\"579\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Select-the-ESP32-S3-chip-via-built-in-USB-JTAG-Target-Device.png?resize=757%2C579&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code ESP-IDF Select the ESP32 S3 chip via built in USB JTAG Target Device\" class=\"wp-image-170162\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Select-the-ESP32-S3-chip-via-built-in-USB-JTAG-Target-Device.png?w=757&amp;quality=100&amp;strip=all&amp;ssl=1 757w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Select-the-ESP32-S3-chip-via-built-in-USB-JTAG-Target-Device.png?resize=300%2C229&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 757px) 100vw, 757px\" \/><\/figure><\/div>\n\n\n<p>Finally, your command bar on the bottom of VS Code should have similar options selected.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"498\" height=\"28\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Check-All-the-Configured-Settings-UART-COM-Port-Target-Board.png?resize=498%2C28&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code ESP-IDF Check All the Configured Settings UART COM Port Target Board\" class=\"wp-image-170147\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Check-All-the-Configured-Settings-UART-COM-Port-Target-Board.png?w=498&amp;quality=100&amp;strip=all&amp;ssl=1 498w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Check-All-the-Configured-Settings-UART-COM-Port-Target-Board.png?resize=300%2C17&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 498px) 100vw, 498px\" \/><\/figure><\/div>\n\n\n<p>Now, you can build the project by clicking the wrench icon (<strong>Build Project<\/strong>) as shown in the image below.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"581\" height=\"359\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/06\/VS-Code-Build-Project-Example-Code-ESP32-ESP-IDF.png?resize=581%2C359&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code Build Project Example Code ESP32 ESP-IDF\" class=\"wp-image-170743\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/06\/VS-Code-Build-Project-Example-Code-ESP32-ESP-IDF.png?w=581&amp;quality=100&amp;strip=all&amp;ssl=1 581w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/06\/VS-Code-Build-Project-Example-Code-ESP32-ESP-IDF.png?resize=300%2C185&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 581px) 100vw, 581px\" \/><\/figure><\/div>\n\n\n<p>The first time you build a project, it usually takes a bit more time. Once completed, it should print a similar message in the <strong>Terminal<\/strong> menu and show a &#8220;<strong>Build Successfully<\/strong>&#8221; message.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"648\" height=\"468\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/06\/VS-Code-Build-Example-Project-ESP32-ESP-IDF-Success-Message.jpg?resize=648%2C468&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code Build Example Project ESP32 ESP-IDF Success Message\" class=\"wp-image-170742\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/06\/VS-Code-Build-Example-Project-ESP32-ESP-IDF-Success-Message.jpg?w=648&amp;quality=100&amp;strip=all&amp;ssl=1 648w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/06\/VS-Code-Build-Example-Project-ESP32-ESP-IDF-Success-Message.jpg?resize=300%2C217&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 648px) 100vw, 648px\" \/><\/figure><\/div>\n\n\n<p>This is the final step. You can now flash the ESP-IDF project to the ESP32 by clicking the &#8220;<strong>Flash Device<\/strong>&#8221; button (thunder icon).<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"848\" height=\"170\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Flash-Hello-World-Code-Project-to-ESP32-ESP-IDF.png?resize=848%2C170&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code Flash Hello World Code Project to ESP32 ESP-IDF\" class=\"wp-image-170294\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Flash-Hello-World-Code-Project-to-ESP32-ESP-IDF.png?w=848&amp;quality=100&amp;strip=all&amp;ssl=1 848w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Flash-Hello-World-Code-Project-to-ESP32-ESP-IDF.png?resize=300%2C60&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Flash-Hello-World-Code-Project-to-ESP32-ESP-IDF.png?resize=768%2C154&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 848px) 100vw, 848px\" \/><\/figure><\/div>\n\n\n<p>Depending on your board, you might need to hold down the on-board BOOT button on your ESP32 to put into flashing mode. Once the process is completed, it will pop-up a info message saying &#8220;<strong>Flash Done<\/strong>&#8220;.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"575\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Flash-Hello-Wolrd-Project-to-ESP32-ESP-IDF-Done-Success-Message.png?resize=1024%2C575&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code Flash Hello World Project to ESP32 ESP-IDF Done Success Message\" class=\"wp-image-170155\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Flash-Hello-Wolrd-Project-to-ESP32-ESP-IDF-Done-Success-Message.png?resize=1024%2C575&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Flash-Hello-Wolrd-Project-to-ESP32-ESP-IDF-Done-Success-Message.png?resize=300%2C168&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Flash-Hello-Wolrd-Project-to-ESP32-ESP-IDF-Done-Success-Message.png?resize=768%2C431&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Flash-Hello-Wolrd-Project-to-ESP32-ESP-IDF-Done-Success-Message.png?w=1039&amp;quality=100&amp;strip=all&amp;ssl=1 1039w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Demonstration<\/h2>\n\n\n\n<p>If you followed all the steps, the code example should be running successfully on your board. Open your Terminal window \u2014 click the &#8220;<strong>Monitor Device<\/strong>&#8221; tool that is illustrated with a screen icon.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"780\" height=\"77\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Open-Terminal-Window-Monitor-Device-ESP32-ESP-IDF.png?resize=780%2C77&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"VS Code Open Terminal Window Monitor Device ESP32 ESP-IDF\" class=\"wp-image-170157\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Open-Terminal-Window-Monitor-Device-ESP32-ESP-IDF.png?w=780&amp;quality=100&amp;strip=all&amp;ssl=1 780w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Open-Terminal-Window-Monitor-Device-ESP32-ESP-IDF.png?resize=300%2C30&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/05\/VS-Code-Open-Terminal-Window-Monitor-Device-ESP32-ESP-IDF.png?resize=768%2C76&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 780px) 100vw, 780px\" \/><\/figure><\/div>\n\n\n<p>The terminal should be printing a message saying &#8220;<strong>LED duty cycle: 1023<\/strong>&#8221; and it will increment\/decrement from 0 to 1023. This process is repeated indefinitely.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"559\" height=\"417\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-Control-LED-Brightness-LEDC-duty-cycle-demonstration.png?resize=559%2C417&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-IDF ESP32 Control LED Brightness LEDC duty cycle demonstration\" class=\"wp-image-174720\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-Control-LED-Brightness-LEDC-duty-cycle-demonstration.png?w=559&amp;quality=100&amp;strip=all&amp;ssl=1 559w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-Control-LED-Brightness-LEDC-duty-cycle-demonstration.png?resize=300%2C224&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 559px) 100vw, 559px\" \/><\/figure><\/div>\n\n\n<p>You should have an LED that increases and decreases its brightness.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"506\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-PWM-LED-Brightness.jpg?resize=900%2C506&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-IDF ESP32 PWM LED Brightness\" class=\"wp-image-174722\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-PWM-LED-Brightness.jpg?w=900&amp;quality=100&amp;strip=all&amp;ssl=1 900w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-PWM-LED-Brightness.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-PWM-LED-Brightness.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 900px) 100vw, 900px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Example #2: Control Multiple LEDs&#8217; Brightness with ESP-IDF LEDC<\/h2>\n\n\n\n<p>Here&#8217;s the full <em>main.c<\/em> code that controls the brightness of 2 LEDs at different speeds:<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*  \n  Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n  https:\/\/RandomNerdTutorials.com\/esp-idf-esp32-gpio-pwm-ledc\/\n*\/\n#include &lt;stdio.h&gt;\n#include &lt;freertos\/FreeRTOS.h&gt;\n#include &lt;freertos\/task.h&gt;\n#include &lt;driver\/ledc.h&gt;\n#include &quot;sdkconfig.h&quot;\n\n#define LED_PIN_1 4\n#define LED_PIN_2 5\n#define LEDC_CHANNEL_0 LEDC_CHANNEL_0\n#define LEDC_CHANNEL_1 LEDC_CHANNEL_1\n#define LEDC_TIMER_0 LEDC_TIMER_0\n#define LEDC_MODE LEDC_LOW_SPEED_MODE\n#define LEDC_DUTY_RES LEDC_TIMER_10_BIT  \/\/ 10-bit resolution (0-1023)\n#define LEDC_FREQUENCY 1000              \/\/ 1 kHz for smooth fading\n\nvoid app_main(void)\n{\n    \/\/ Configure LEDC timer (one timer for all channels)\n    ledc_timer_config_t ledc_timer = {\n        .speed_mode = LEDC_MODE,\n        .duty_resolution = LEDC_DUTY_RES,\n        .timer_num = LEDC_TIMER_0,\n        .freq_hz = LEDC_FREQUENCY,\n    };\n    ledc_timer_config(&amp;ledc_timer);\n\n    \/\/ Configure LEDC channels\n    ledc_channel_config_t ledc_channel_0 = {\n        .gpio_num = LED_PIN_1,\n        .speed_mode = LEDC_MODE,\n        .channel = LEDC_CHANNEL_0,\n        .timer_sel = LEDC_TIMER_0,\n        .duty = 0\n    };\n    ledc_channel_config(&amp;ledc_channel_0);\n\n    ledc_channel_config_t ledc_channel_1 = {\n        .gpio_num = LED_PIN_2,\n        .speed_mode = LEDC_MODE,\n        .channel = LEDC_CHANNEL_1,\n        .timer_sel = LEDC_TIMER_0,\n        .duty = 0\n    };\n    ledc_channel_config(&amp;ledc_channel_1);\n\n    \/\/ Fading loop\n    int duty1 = 0, duty2 = 0;\n    int step1 = 10, step2 = 20;\n    while (1) {\n        \/\/ LED 1: slow fade\n        duty1 += step1;\n        if (duty1 &gt; 1023) {\n            duty1 = 1023;\n            step1 = -step1;\n        } else if (duty1 &lt; 0) {\n            duty1 = 0;\n            step1 = -step1;\n        }\n        ledc_set_duty(LEDC_MODE, LEDC_CHANNEL_0, duty1);\n        ledc_update_duty(LEDC_MODE, LEDC_CHANNEL_0);\n\n        \/\/ LED 2: fast fade\n        duty2 += step2;\n        if (duty2 &gt; 1023) {\n            duty2 = 1023;\n            step2 = -step2;\n        } else if (duty2 &lt; 0) {\n            duty2 = 0;\n            step2 = -step2;\n        }\n        ledc_set_duty(LEDC_MODE, LEDC_CHANNEL_1, duty2);\n        ledc_update_duty(LEDC_MODE, LEDC_CHANNEL_1);\n\n        printf(&quot;LED #1 duty cycle: %d, LED #2 duty cycle: %d\\n&quot;, duty1, duty2);\n        vTaskDelay(20 \/ portTICK_PERIOD_MS);\n    }\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP-IDF\/gpio_pwm\/gpio_multiple_pwm.c\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How the Code Works<\/h3>\n\n\n\n<p><strong>Libraries<\/strong><\/p>\n\n\n\n<p>We start by including the required libraries as shown in the previous example:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;stdio.h&gt;\n#include &lt;freertos\/FreeRTOS.h&gt;\n#include &lt;freertos\/task.h&gt;\n#include &lt;driver\/ledc.h&gt;\n#include \"sdkconfig.h\"<\/code><\/pre>\n\n\n\n<p><strong>Pin Assignment<\/strong><\/p>\n\n\n\n<p>This line assigns the 2 LED pins to GPIO 4 and GPIO 5.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define LED_PIN_1 4\n#define LED_PIN_2 5<\/code><\/pre>\n\n\n\n<p><strong>LEDC Configurations<\/strong><\/p>\n\n\n\n<p>Then, define the configurations for your LEDC channel, LEDC timer, mode, duty cycle resolution and frequency.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define LEDC_CHANNEL_0 LEDC_CHANNEL_0\n#define LEDC_CHANNEL_1 LEDC_CHANNEL_1\n#define LEDC_TIMER_0 LEDC_TIMER_0\n#define LEDC_MODE LEDC_LOW_SPEED_MODE\n#define LEDC_DUTY_RES LEDC_TIMER_10_BIT  \/\/ 10-bit resolution (0-1023)\n#define LEDC_FREQUENCY 1000              \/\/ 1 kHz for smooth fading<\/code><\/pre>\n\n\n\n<p><strong>app_main(void)<\/strong><\/p>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">app_main(void)<\/span> function, you need to create only one <span class=\"rnthl rntliteral\">ledc_timer<\/span> that will be used by the two channels to set the mode, resolution, timer and frequency:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span class=\"rnthl rntliteral\">speed_mode<\/span>: use <span class=\"rnthl rntliteral\">LEDC_LOW_SPEED_MODE<\/span> (some ESP32 also support <span class=\"rnthl rntliteral\">LEDC_HIGH_SPEED_MODE<\/span>)<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">duty_resolution<\/span>: set the PWM resolution (for example: 10-bit gives a 0 to 1023 range)<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">timer_num<\/span>: select one of the available timers<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">freq_hz<\/span>: sets the PWM frequency (1 kHz can be used for LEDs)<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Configure LEDC timer\nledc_timer_config_t ledc_timer = {\n    .speed_mode = LEDC_MODE,\n    .duty_resolution = LEDC_DUTY_RES,\n    .timer_num = LEDC_TIMER,\n    .freq_hz = LEDC_FREQUENCY\n};\nledc_timer_config(&amp;ledc_timer);<\/code><\/pre>\n\n\n\n<p>Then, call the <span class=\"rnthl rntliteral\">ledc_channel_config(&amp;ledc_channel_0)<\/span> and <span class=\"rnthl rntliteral\">ledc_channel_config(&amp;ledc_channel_1)<\/span> functions to configure the LEDC channels with the GPIO number, mode, channel, timer and duty cycle.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><span class=\"rnthl rntliteral\">gpio_num<\/span>: assign the GPIO pin connected to the LED<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">speed_mode<\/span>: use <span class=\"rnthl rntliteral\">LEDC_LOW_SPEED_MODE<\/span> (some ESP32 also support <span class=\"rnthl rntliteral\">LEDC_HIGH_SPEED_MODE<\/span>)<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">channel<\/span>: assign an available channel (example: <span class=\"rnthl rntliteral\">LEDC_CHANNEL_0<\/span>)<\/li>\n\n\n\n<li><span class=\"rnthl rntliteral\">timer_sel<\/span>: assign the channel to the configured timer<\/li>\n\n\n\n<li>duty: set the initial duty cycle (example: 0 = off and 1023 = full brightness for 10-bit range)<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>ledc_channel_config_t ledc_channel_0 = {\n    .gpio_num = LED_PIN_1,\n    .speed_mode = LEDC_MODE,\n    .channel = LEDC_CHANNEL_0,\n    .timer_sel = LEDC_TIMER_0,\n    .duty = 0\n};\nledc_channel_config(&amp;ledc_channel_0);\n\nledc_channel_config_t ledc_channel_1 = {\n    .gpio_num = LED_PIN_2,\n    .speed_mode = LEDC_MODE,\n    .channel = LEDC_CHANNEL_1,\n    .timer_sel = LEDC_TIMER_0,\n    .duty = 0\n};\nledc_channel_config(&amp;ledc_channel_1);<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">while(1)<\/span> runs an infinite loop that keeps the 2 LEDs fading in and fading out creating a dimming LED effect at different speeds.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>\/\/ Fading loop\nint duty1 = 0, duty2 = 0;\nint step1 = 10, step2 = 20;\nwhile (1) {\n    \/\/ LED 1: slow fade\n    duty1 += step1;\n    if (duty1 &gt; 1023) {\n        duty1 = 1023;\n        step1 = -step1;\n    } else if (duty1 &lt; 0) {\n        duty1 = 0;\n        step1 = -step1;\n    }\n    ledc_set_duty(LEDC_MODE, LEDC_CHANNEL_0, duty1);\n    ledc_update_duty(LEDC_MODE, LEDC_CHANNEL_0);\n\n    \/\/ LED 2: fast fade\n    duty2 += step2;\n    if (duty2 &gt; 1023) {\n        duty2 = 1023;\n        step2 = -step2;\n    } else if (duty2 &lt; 0) {\n        duty2 = 0;\n        step2 = -step2;\n    }\n    ledc_set_duty(LEDC_MODE, LEDC_CHANNEL_1, duty2);\n    ledc_update_duty(LEDC_MODE, LEDC_CHANNEL_1);\n\n    printf(\"LED #1 duty cycle: %d, LED #2 duty cycle: %d\\n\", duty1, duty2);\n    vTaskDelay(20 \/ portTICK_PERIOD_MS);\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Schematic Diagram<\/h3>\n\n\n\n<p>Here\u2019s a list of the parts you need to build the circuit:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/esp32-dev-board-wi-fi-bluetooth\/\" target=\"_blank\" rel=\"noreferrer noopener\">ESP32<\/a>&nbsp;(read&nbsp;<a href=\"https:\/\/makeradvisor.com\/esp32-development-boards-review-comparison\/\" target=\"_blank\" rel=\"noreferrer noopener\">Best ESP32 Dev Boards<\/a>)<\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/3mm-5mm-leds-kit-storage-box\/\" target=\"_blank\" rel=\"noopener\" title=\"\">2x 5 mm LED<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/resistors-kits\/\" target=\"_blank\" rel=\"noopener\" title=\"\">2x 220 Ohm resistor<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/mb-102-solderless-breadboard-830-points\/\" target=\"_blank\" rel=\"noreferrer noopener\">Breadboard<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/makeradvisor.com\/tools\/jumper-wires-kit-120-pieces\/\" target=\"_blank\" rel=\"noreferrer noopener\">Jumper wires<\/a><\/li>\n<\/ul>\n\n\n\n<p>Connect 2 LEDs to <span class=\"rnthl rntcred\">GPIO 4,<\/span> and <span class=\"rnthl rntcblue\">GPIO 5<\/span> as shown in the schematic diagram below.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"764\" height=\"825\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/08\/ESP32-S3-Two-LEDs-PWM-Circuit-Diagram-ESP-IDF.png?resize=764%2C825&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32-S3 Two LEDs PWM Circuit Diagram ESP-IDF\" class=\"wp-image-175053\" style=\"width:563px;height:auto\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/08\/ESP32-S3-Two-LEDs-PWM-Circuit-Diagram-ESP-IDF.png?w=764&amp;quality=100&amp;strip=all&amp;ssl=1 764w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/08\/ESP32-S3-Two-LEDs-PWM-Circuit-Diagram-ESP-IDF.png?resize=278%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 278w\" sizes=\"(max-width: 764px) 100vw, 764px\" \/><\/figure><\/div>\n\n\n<p>The terminal should be printing a message saying &#8220;<strong>LED #1 duty cycle: 1023, LED #2 duty cycle: 700<\/strong>&#8221; and it will increment\/decrement from 0 to 1023. This process is repeated indefinitely.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"779\" height=\"289\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-Control-Multiple-LED-Brightness-LEDC-duty-cycle-demonstration.png?resize=779%2C289&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-IDF ESP32 Control Multiple LED Brightness LEDC duty cycle demonstration\" class=\"wp-image-174721\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-Control-Multiple-LED-Brightness-LEDC-duty-cycle-demonstration.png?w=779&amp;quality=100&amp;strip=all&amp;ssl=1 779w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-Control-Multiple-LED-Brightness-LEDC-duty-cycle-demonstration.png?resize=300%2C111&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-Control-Multiple-LED-Brightness-LEDC-duty-cycle-demonstration.png?resize=768%2C285&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 779px) 100vw, 779px\" \/><\/figure><\/div>\n\n\n<p>You can build and flash the code into your ESP32. This code fades in and out the 2 connected LEDs continuously at different speeds.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"900\" height=\"506\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-PWM-Multiple-LED-Brightness-Control.jpg?resize=900%2C506&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP-IDF ESP32 PWM Multiple LED Brightness Control\" class=\"wp-image-174723\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-PWM-Multiple-LED-Brightness-Control.jpg?w=900&amp;quality=100&amp;strip=all&amp;ssl=1 900w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-PWM-Multiple-LED-Brightness-Control.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/07\/ESP-IDF-ESP32-PWM-Multiple-LED-Brightness-Control.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 900px) 100vw, 900px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial, you learned how to program the ESP32 with the ESP-IDF framework using VS Code to generate PWM signals to control the ESP32 GPIOs.<\/p>\n\n\n\n<p>Other ESP-IDF guides:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/programming-esp32-esp-idf-vs-code\/\">Programming ESP32 with ESP-IDF using VS Code \u2013 Getting Started Guide<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp-idf-esp32-blink-led\/\">ESP-IDF: ESP32 Blink LED Example (VS Code)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp-idf-esp32-gpio-outputs\/\">ESP-IDF: ESP32 GPIO \u2013 Control Digital Outputs<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp-idf-esp32-gpio-inputs\/\">ESP-IDF: ESP32 GPIO \u2013 Read Digital Inputs<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp-idf-esp32-gpio-analog-adc\/\">ESP-IDF: ESP32 GPIO \u2013 Read Analog Input (ADC \u2013 Analog to Digital Converter)<\/a><\/li>\n<\/ul>\n\n\n\n<p>Meanwhile, you can check our ESP32 resources (with Arduino IDE) to learn more about the ESP32 board:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-cam-projects-ebook\/\">Learn ESP32 with Arduino IDE (eBook)<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\">More ESP32 Projects and Tutorials\u2026<\/a><\/li>\n<\/ul>\n\n\n\n<p>Thanks for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this guide, you&#8217;ll learn how to control the ESP32 board&#8217;s GPIOs using PWM (Pulse Width Modulation) with ESP-IDF (Espressif IoT Development Framework). The ESP32 is a microcontroller that offers &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP-IDF: ESP32 GPIO PWM with LEDC (Control LED Brightness)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp-idf-esp32-gpio-pwm-ledc\/#more-174268\" aria-label=\"Read more about ESP-IDF: ESP32 GPIO PWM with LEDC (Control LED Brightness)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":1,"featured_media":175045,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[327,328,264],"tags":[],"class_list":["post-174268","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp-idf","category-esp32-esp-idf","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2025\/08\/ESP-IDF-ESP32-GPIO-PWM-LEDC-Control-LED-Brightness.jpg?fit=1920%2C1080&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/174268","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=174268"}],"version-history":[{"count":15,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/174268\/revisions"}],"predecessor-version":[{"id":187420,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/174268\/revisions\/187420"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/175045"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=174268"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=174268"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=174268"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}