{"id":3864,"date":"2018-04-05T19:04:37","date_gmt":"2018-04-06T02:04:37","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=3864"},"modified":"2025-10-14T20:28:09","modified_gmt":"2025-10-15T03:28:09","slug":"creating-and-referencing-custom-esp-idf-components","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/esp32\/esp-idf\/components\/","title":{"rendered":"Creating and Referencing Custom ESP-IDF Components"},"content":{"rendered":"<p>This tutorial shows how to create custom ESP-IDF components and share them between your ESP32 projects. We will create a basic component\u00a0for running a simple PWM loop and will show how to reference it from 2\u00a0separate projects.<\/p>\n<p>Before you begin, install VisualGDB 5.4 or later.<\/p>\n<ol>\n<li>Start Visual Studio and open the VisualGDB ESP-IDF project wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/01-prj.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3865\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/01-prj.png\" alt=\"01-prj\" width=\"941\" height=\"577\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/01-prj.png 941w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/01-prj-300x184.png 300w\" sizes=\"(max-width: 941px) 100vw, 941px\" \/><\/a><\/li>\n<li>On the first page select &#8220;Create a new\u00a0project based on a sample project&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/02-newprj.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3866\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/02-newprj.png\" alt=\"02-newprj\" width=\"856\" height=\"693\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/02-newprj.png 856w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/02-newprj-300x243.png 300w\" sizes=\"(max-width: 856px) 100vw, 856px\" \/><\/a><\/li>\n<li>Select your ESP32 toolchain and the ESP-IDF checkout you want to use:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/03-toolchain.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3867\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/03-toolchain.png\" alt=\"03-toolchain\" width=\"856\" height=\"693\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/03-toolchain.png 856w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/03-toolchain-300x243.png 300w\" sizes=\"(max-width: 856px) 100vw, 856px\" \/><\/a><\/li>\n<li>Choose a sample project\u00a0that will be cloned when creating your project.\u00a0We will demonstrate the custom component based on the &#8220;blink&#8221; sample:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/04-sample.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3868\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/04-sample.png\" alt=\"04-sample\" width=\"856\" height=\"693\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/04-sample.png 856w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/04-sample-300x243.png 300w\" sizes=\"(max-width: 856px) 100vw, 856px\" \/><\/a><\/li>\n<li>Finally choose the debug method. In this tutorial we won&#8217;t be debugging the code, so\u00a0we can use a\u00a0serial port connection to\u00a0program the firmware into the FLASH memory without configuring JTAG:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/05-com.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3869\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/05-com.png\" alt=\"05-com\" width=\"856\" height=\"693\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/05-com.png 856w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/05-com-300x243.png 300w\" sizes=\"(max-width: 856px) 100vw, 856px\" \/><\/a><\/li>\n<li>Press &#8220;Finish&#8221; to create the project and wait for it to load: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/06-files1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3883\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/06-files1.png\" alt=\"06-files\" width=\"1036\" height=\"657\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/06-files1.png 1036w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/06-files1-300x190.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/06-files1-1024x649.png 1024w\" sizes=\"(max-width: 1036px) 100vw, 1036px\" \/><\/a><\/li>\n<li>All ESP-IDF projects consist of one or more components (i.e. static libraries) that are linked together to build the final executable. Most samples include only one component called &#8220;main&#8221;. For simplicity VisualGDB doesn&#8217;t show it as a separate component, but instead\u00a0displays its contents directly under the project node. Now we will add another component to the project. Right-click on the &#8220;Components&#8221; folder and select &#8220;Add-&gt;New Item&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/06-files.png\"><br \/>\n<\/a> <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/07-newitem.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3871\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/07-newitem.png\" alt=\"07-newitem\" width=\"1055\" height=\"676\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/07-newitem.png 1055w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/07-newitem-300x192.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/07-newitem-1024x656.png 1024w\" sizes=\"(max-width: 1055px) 100vw, 1055px\" \/><\/a><\/li>\n<li>Proceed with the default location, enter the component name and click &#8220;Add&#8221;:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/08-pwm.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3872\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/08-pwm.png\" alt=\"08-pwm\" width=\"1055\" height=\"676\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/08-pwm.png 1055w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/08-pwm-300x192.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/08-pwm-1024x656.png 1024w\" sizes=\"(max-width: 1055px) 100vw, 1055px\" \/><\/a><\/li>\n<li>VisualGDB will add the component files and will\u00a0start refreshing\u00a0the code model from the ESP-IDF. You won&#8217;t see the contents of the component until the refresh is complete:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/09-loading.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3873\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/09-loading.png\" alt=\"09-loading\" width=\"1055\" height=\"676\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/09-loading.png 1055w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/09-loading-300x192.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/09-loading-1024x656.png 1024w\" sizes=\"(max-width: 1055px) 100vw, 1055px\" \/><\/a>WARNING: if the project is configured with<strong> idf_build_set_property(MINIMAL_BUILD ON)<\/strong>, the new component will not appear in the list. You can disable that option by editing the main <strong>CMakeLists.txt file<\/strong>.<\/li>\n<li>Once the code model is refreshed, the new component will be shown in\u00a0Solution Explorer similar to other components:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/10-files.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3874\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/10-files.png\" alt=\"10-files\" width=\"1055\" height=\"676\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/10-files.png 1055w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/10-files-300x192.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/10-files-1024x656.png 1024w\" sizes=\"(max-width: 1055px) 100vw, 1055px\" \/><\/a><\/li>\n<li>Select the main .cpp file and press F2 to start renaming it. Then change the extension to &#8220;.c&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/11-rename.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3875\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/11-rename.png\" alt=\"11-rename\" width=\"1055\" height=\"676\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/11-rename.png 1055w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/11-rename-300x192.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/11-rename-1024x656.png 1024w\" sizes=\"(max-width: 1055px) 100vw, 1055px\" \/><\/a><\/li>\n<li>Right-click on the component and select &#8220;Add-&gt;New File-&gt;C\/C++ Header file&#8221;.\u00a0 Append &#8220;\\PublicIncludes&#8221; to the location field:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/12-pubincl.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3876\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/12-pubincl.png\" alt=\"12-pubincl\" width=\"1229\" height=\"818\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/12-pubincl.png 1229w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/12-pubincl-300x200.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/12-pubincl-1024x682.png 1024w\" sizes=\"(max-width: 1229px) 100vw, 1229px\" \/><\/a><\/li>\n<li>Add the following code to the component:\n<pre class=\"\">#pragma once\r\n\r\n#include \"driver\/gpio.h\"\r\n\r\n#ifdef __cplusplus\r\nextern \"C\"\r\n{\r\n#endif\r\n \r\n void RunGPIOCycle(gpio_num_t gpio, double dutyCycle);\r\n \r\n#ifdef __cplusplus\r\n}\r\n#endif<\/pre>\n<p>Then select the &#8220;RunGPIOCycle&#8221; declaration, press Ctrl+. and select &#8220;Create implementation&#8221;:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/13-makeimpl.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3877\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/13-makeimpl.png\" alt=\"13-makeimpl\" width=\"1229\" height=\"818\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/13-makeimpl.png 1229w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/13-makeimpl-300x200.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/13-makeimpl-1024x682.png 1024w\" sizes=\"(max-width: 1229px) 100vw, 1229px\" \/><\/a>VisualGDB will create an empty implementation\u00a0for the RunGPIOCycle() function, however it won&#8217;t automatically find the\u00a0&#8220;BasicPWM.h&#8221; header as the &#8220;PublicIncludes&#8221; directory is not yet\u00a0added to the include search path.<\/li>\n<li>To fix that, we could add the header directory to either regular include directories (visible only for files inside the component) or exported directories (visible for all components in the same project). As the file will be included by the code that uses the component, add it to the exported directories:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/14-sharedir.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3878\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/14-sharedir.png\" alt=\"14-sharedir\" width=\"1229\" height=\"818\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/14-sharedir.png 1229w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/14-sharedir-300x200.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/14-sharedir-1024x682.png 1024w\" sizes=\"(max-width: 1229px) 100vw, 1229px\" \/><\/a>Note that the exported directories\u00a0must have relative paths. For your convenience you can select &#8220;&lt;Edit&#8230;&gt;&#8221; in the &#8220;Additional Include Directories&#8221; field and let VisualGDB compute the correct relative paths automatically:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/edit.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3884\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/edit.png\" alt=\"edit\" width=\"1229\" height=\"818\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/edit.png 1229w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/edit-300x200.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/edit-1024x682.png 1024w\" sizes=\"(max-width: 1229px) 100vw, 1229px\" \/><\/a><\/li>\n<li>Now you can\u00a0the implementation to the RunGPIOCycle() function:\n<pre class=\"\">void RunGPIOCycle(gpio_num_t gpio, double dutyCycle)\r\n{\r\n    const int TotalCycles = 10000;\r\n    const int position = TotalCycles * dutyCycle;\r\n    gpio_set_level(gpio, 1);\r\n    for (int i = 0; i &lt; position; i++)\r\n        asm(\"nop\");\r\n    gpio_set_level(gpio, 0);\r\n    for (int i = position; i &lt; TotalCycles; i++)\r\n        asm(\"nop\");\r\n}<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/15-pwm.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3879\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/15-pwm.png\" alt=\"15-pwm\" width=\"1229\" height=\"818\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/15-pwm.png 1229w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/15-pwm-300x200.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/15-pwm-1024x682.png 1024w\" sizes=\"(max-width: 1229px) 100vw, 1229px\" \/><\/a><\/li>\n<li>Modify the blink_task() function in the main source file to call the RunGPIOCycle() function:\n<pre class=\"\">#include \"BasicPWM.h\"\r\n#include &lt;math.h&gt;\r\n\r\nvoid blink_task(void *pvParameter)\r\n{\r\n    gpio_pad_select_gpio(BLINK_GPIO);\r\n    \/* Set the GPIO as a push\/pull output *\/\r\n    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);\r\n \r\n    for (double i = 0; ; i += 0.005)\r\n        RunGPIOCycle(BLINK_GPIO, (sin(i) + 1) \/ 2);\r\n}<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/16-call.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3880\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/16-call.png\" alt=\"16-call\" width=\"1229\" height=\"818\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/16-call.png 1229w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/16-call-300x200.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/16-call-1024x682.png 1024w\" sizes=\"(max-width: 1229px) 100vw, 1229px\" \/><\/a><\/li>\n<li>Build the project and select &#8220;Debug-&gt;Program and\u00a0Start Without Debugging&#8221; to program it to the FLASH memory:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/17-program.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3881\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/17-program.png\" alt=\"17-program\" width=\"1229\" height=\"818\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/17-program.png 1229w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/17-program-300x200.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/17-program-1024x682.png 1024w\" sizes=\"(max-width: 1229px) 100vw, 1229px\" \/><\/a>Ensure that the on-board LED gradually turns on and off\u00a0as the PWM duty cycle goes from 0 to 100% and back to 0.<\/li>\n<li>You can change the\u00a0GPIO number of the LED via VisualGDB Project Properties -&gt; ESP-IDF Project -&gt; ESP-IDF Configuration -&gt; Blink GPIO Number:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/gpio.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3885\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/gpio.png\" alt=\"gpio\" width=\"846\" height=\"662\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/gpio.png 846w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/gpio-300x235.png 300w\" sizes=\"(max-width: 846px) 100vw, 846px\" \/><\/a><\/li>\n<li>Now we will show how to import the component from another project.\u00a0Create another\u00a0project in a separate solution using the VisualGDB ESP-IDF\u00a0project wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/18-prj2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3882\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/18-prj2.png\" alt=\"18-prj2\" width=\"941\" height=\"647\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/18-prj2.png 941w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/18-prj2-300x206.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/18-prj2-130x90.png 130w\" sizes=\"(max-width: 941px) 100vw, 941px\" \/><\/a><\/li>\n<li>Click on the &#8220;Components&#8221;\u00a0node\u00a0and select &#8220;Add-&gt;Existing Item&#8221;:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/19-addcomp.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3886\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/19-addcomp.png\" alt=\"19-addcomp\" width=\"1229\" height=\"818\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/19-addcomp.png 1229w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/19-addcomp-300x200.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/19-addcomp-1024x682.png 1024w\" sizes=\"(max-width: 1229px) 100vw, 1229px\" \/><\/a><\/li>\n<li>Then locate the component.mk file of the BasicPWM component:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/20-locatemak.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3887\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/20-locatemak.png\" alt=\"20-locatemak\" width=\"1229\" height=\"818\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/20-locatemak.png 1229w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/20-locatemak-300x200.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/20-locatemak-1024x682.png 1024w\" sizes=\"(max-width: 1229px) 100vw, 1229px\" \/><\/a><\/li>\n<li>See how VisualGDB automatically updates the project&#8217;s Makefile to include the new component:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/21-relpath.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3888\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/21-relpath.png\" alt=\"21-relpath\" width=\"1229\" height=\"818\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/21-relpath.png 1229w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/21-relpath-300x200.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/21-relpath-1024x682.png 1024w\" sizes=\"(max-width: 1229px) 100vw, 1229px\" \/><\/a><\/li>\n<li>You can now use the component exactly the same way as you did in the first project &#8211; include the &lt;BasicPWM.h&gt; file and call the RunGPIOCycle() function. ESP-IDF will automatically\u00a0use\u00a0the correct include paths and will link the component with the final project:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/22-imported.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3889\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/22-imported.png\" alt=\"22-imported\" width=\"1229\" height=\"818\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/22-imported.png 1229w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/22-imported-300x200.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/04\/22-imported-1024x682.png 1024w\" sizes=\"(max-width: 1229px) 100vw, 1229px\" \/><\/a>You can also store your components outside the project directories. Simply pick an arbitrary location when creating a new component and VisualGDB will place it there, updating all necessary Makefiles.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to create custom ESP-IDF components and share them between your ESP32 projects. We will create a<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[142],"tags":[160,138,79],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/3864"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=3864"}],"version-history":[{"count":2,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/3864\/revisions"}],"predecessor-version":[{"id":9077,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/3864\/revisions\/9077"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=3864"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=3864"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=3864"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}