Newbie confused with libraries


I’m new with PlatformIO. At the moment I’m using ESP32-boards. And I want to use “Esspressif IoT Development Framework”, not Arduino. Until now simple programms like the blinking LED or writing something to a SD-card via SPI are working. So I think, I installed Python, GIT and the ESP-components correctly.

  1. When I’m searching for a library inside PIO home, there is for each listing member a “compactible framework”-hint. I only see “Arduino” or “Mbed” but no “ESP-IDF”. Is “Arduino” the correct choise for my ESP-IDF-framework?

  2. I also looked around gtihub for libraries. And I add a lib_deps line to the platformio.ini file of my project. But compiler throws error, that he can’t find header-file.
    It is very surprising to go to PIO home/Libraries again and see under “installed” the library I placed a lib_deps line to my project.

  3. At github i often see in the readme something like “installation for ESP32” with several lines:
    git clone GitHub - nopnop2002/esp-idf-st7789: ST7789 Driver for esp-idf
    cd esp-idf-st7789/ set-target esp32 menuconfig flash
    It is only for people using what Esspresif calls toolchain? Nothing for PlatformIO?

  4. I also can download library as zip-file. Is folder lib of my project the right place to unzip it? I found a readme there, but it is not useful, because the examples use only one header and one c-file and the folder has the same name like the header-file.

  5. Can I see inside PlatformIO the pathes and folders, where compiler is looking for header-files?

Thanks for help …

Hi @platt-io,

I find the easiest way to get hold of libraries is to go to PlatformIO Registry and fill in the form there. So if I was looking for a library such as “fred” for an ESP-IDF, I would fill in the search term:

"platform:Espressif IoT Development Framework"   fred

alternatively, as I don;t like typing (that will surprise some people who know me!), this:

"platform:ESP-IDF"   fred

Either way, a quick check just now without a library name, just the two options above for the platform, returned 8,656 as the number of libraries which are flagged as being compatible with the development platform you want to use.

Apparently, there is no library called “fred”! :grin:

So, once I’ve found my library and clicked its name to open its page, I see three tabs: “Exaples” - example sketches using the library, “Installation” - a list of different methods of installing the library, “Headers” - a list of the headers provided in the library, to be #included in your code as required.

I usually just add the lib_deps = vendor_name/library_name@^n.n.n option in the platformio.ini file for whichever project needs to use the library.

Looking around GitHub can lead you down all sorts of incorrect rabbit holes, causing much wailing and gnashing of teeth etc. Use the library search feature as described above and it should just work.

Not all libraries you find on GitHub are usable with PlatformIO (or even, with the Arduino IDE). You also need to consider the framework in use, you can have a library that will work with a project in PlatformIO, but only if you are using the Arduino framework as the library is written to use various bits (technical term) from the Arduino Language, or #defines created in the various Arduino header files. (I’m looking at you Helios! :wink:)

Having said that, some libraries (on GitHub and elsewhere, even in the PlatformIO library system, do strange things and cause the occasional header file not to be found. I believe Adafruit’s Software Serial library has a problem which causes the Library Dependency Finder a small problem in locating the header file that it needs. Other libraries may be similarly affected.

Assuming that the library on GitHub is written in a “proper” manner, which PlatformO understands, then using the GitHub URL in lib_deps is perfectly acceptable and should result in the library being downloaded and used. Of course, libraries in GitHub can change frequently and I’m not a big fan, even with my own library (libraries) on GitHub!

The library author is probably unaware of PlatformIO. Hard to believe I know, but that’s life. You are better off looking elsewhere, or, if you feel the urge and the licence allows, clone the repo or download a zipfile and modify the library to work with PlatformIO.

You can unzip the files anywhere you like. As long as you end up with a structure where the source and header files are readable by the compiler. When I write my own libraries I use a couple of methods:

  • If I’m creating a class (C++) to use in a single project, I will just drop the files into the src directory, or, I might occasionally, drop my class headers and .cpp files into lib in a folder reflecting the class name.

  • If I’m writing a library to use in Arduino, or PlatformIO, I’ll create a separate library directory (Mine is called PlatformIO_Libraries at the top level, and under than have a separate directory for each library, viz:


    In my platformio.ini file, I point lib_extra_dirs = /home/norman/SourceCode/PlatformIO_Libraries/ and whatever library I have #included the header for, is found and compiled into a static library (libAVRusart.a for example) and linked with my code to create the final executable. With this option, I have no need for lib_deps for my own stuff, but if I’m using some other libraries, I would use that too. Obviously?

Another alternative which I don’t use often, is to have lib_deps point at the full path to the folder where the source and header files live:

lib_deps = 

(Yes, if you have lib_deps spread over many lines, you must indent at least 3 spaces. ask me how I know!)

You can indeed. Add build_flags = --verbose and the full command lines passed to the various stages of compilation will be revealed in horrific detail!



Hello Norman,

thanks for your fast and detailed answer. I have to read and understand it.

But one remark about the first point:
From my understanding “platform” describes a family of microcontrollers. So I find in the pull-down list at PlatformIO Registry entries like “Atmel AVR”, “Espressiv 32” or “Espressiv 8266”.

“Framework” should be the environment to build a programm. So “arduino” or “espidf”. Differences start with the typical setup() and loop() in Arduino comparing with main() in ESP-IDF. So I’m not sure, if all libraries marked as compatible with Arduino are also compatible with ESP-IDF.

Kind regards

Hi Jürgen,

Platforms/frameworks confuse me too! :grin:


  • Platforms and frameworks can be confusing;
  • Compatability between multiple platforms usually relies on each platform using the same framework, most likely “Arduino”;
  • You can write code that is cross platform, but this will most likely be only cross platform in as much as the same underlying microcontroller family is concerned. Arduino and plain AVR C/C++ for example.
  • I would be very surprised if there was an STM32 library that was compatible with AVR, for example, unless the compatability was facilitated through the Arduin framework for both devices.

Long Winded Stuff

I mostly do Arduino or plain AVR C/C++ but I have a couple of other microcontroller boards that I’m starting to play with – Blue Pill and such like. (STM32 mainly.)

To my mind, when I load a library for some framework I would not expect to find setup() or loop() as part of the library. I expect my “sketch” to either have those, for the Arduino framework, or not in the case of plain AVR stuff. I would be using the library to supply some feature that is not possible directly I the framework – accessing the Analogue Comparator, for example, in the Arduino framework.

The Arduino framework is pretty much identical to the latest Arduino IDE offerings, while, for my Blue Pill, there appear to be a number of frameworks; MBED, freeRTOS, libMaple and such like, with libMaple being an Arduino compatible framework so I can use the Arduino Language with my STM32 kit.

If I find a library that is compatible with STM32 and Arduino, I suspect that it requires the STM32 boards to be running with an Arduino framework and libMaple, and not running MBED or freeRTOS etc.

The problem with libraries which are compatible across frameworks is that some of them expect you to have, for example, the Arduino framework. So a library that works with the Uno, for example, will also work with a Blue Pill but only if the BP was using the Arduino framework – because it’s written that way.

There are plenty of libraries around that are compatible with the Arduino, but cannot be used in plain AVR C/C++ unfortunately. I’m working with a library (similar to an RTOS) called Helios – GitHub - MannyPeterson/HeliOS: The free embedded operating system. – at the moment, and I can only use it in the Arduino framework. I’m looking into it but the obvious reasons are that:

  • It does a #include "Arduino.h";
  • It uses millis();

There may be other stuff too. If yo go to the libray details at PlatformIO Registry you will see that it is compatible with a huge number of platforms. The caveat is, it looks to be the case, at least with my AVR devices, that it’s compatible only with the appropriate Arduino framework for all those platforms.

I’ve managed to get around the millis() “problem” with my own library – GitHub - NormanDunbar/AVRmillis: PlatformIO example code to replace the Arduino `micros` and `millis` functions. Harnesses the Timer/counter 0 overflow interrupt in exactly the same manner as the Arduino does. – which provides me with an AVR C/C++ replacement for the Arduino micros() and millis() functions, without needing the full Arduino core brought in.

So, that’s a library, that allows plain AVR C/C++ to be able, with minor changes, to be able to run Arduino code that uses those functions.

I have other libraries that I’m working on which use exactly the same code for the Arduin and PlatformIO versions. They are AVR specific though and the way I’ve written them is simply to use AVR C/C++ rather than requiring the Arduino Language. So if I need:

pinMode(1, INPUT_PULLUP);

I would write it as:

DDRD |= (1 << DDD1);
PORTD |= (1 << PORTD1);

The Arduino framework does this under the covers whenever you call pinMode(1, INPUT_PULLUP) and such like. The Arduino can compile the above code quite happily, so by using plain AVR C/C++ in my source, I get the free bonus of using the code unchanged on my plain AVR projects and in my Arduino sketches too. Did I mention that I’m a lazy developer? :wink:



This is a special case. Usually, for different frameworks for a microcontroller, a library written for one framework is not compatible with another framework, if that library uses some API functions that don’t exist in the other framework.

Arduino-ESP32 and ESP-IDF are a special case: Arduino-ESP32 is an extension on top of the ESP-IDF code. When building ESP-IDF, you can actually specify that the Arduino core is built, too, and thus you gain compatibility with all Arduino-ESP32 libraries. This was also discussed at Using esp-idf library within the Arduino Framework (ESP32) - #2 by maxgerhardt.

An example of such a configuration is seen at platform-espressif32/examples/espidf-arduino-blink at develop · platformio/platform-espressif32 · GitHub.

That also actually means that if you write an Arduino-ESP32 firmware, you do have full access to the underlying ESP-IDF framework that was prebuilt / statically compiled and linked for the the Arduino core. So there isn’t a lot of difference…

Of course you can also just use plain ESP-IDF with its set of “libraries”, or rather components as we would call them in ESP-IDF.

The hello-world example for ESP-IDF is at platform-espressif32/examples/espidf-hello-world at develop · platformio/platform-espressif32 · GitHub and an example with a component (AWS-IoT) is at platform-espressif32/examples/espidf-aws-iot at develop · platformio/platform-espressif32 · GitHub. The entire documentation for it is at Espressif IoT Development Framework — PlatformIO latest documentation.

Hello Normal,
hello Max,

thanks for your explanations.

In between I tried a different way. I see an #include “driver/timer.h” in one example. So I made a right click on this line in PlatformIO and choose “go to definition”. .platformio\packages\framework-espidf\components is the path inside my user-directory.

In the folder driver I see the timer.c and inside \include\driver the header-file.
So I copied the unzipped library for ePaper-Displays to components and named it epaper. Header-files were directly inside include. Platform seems not to recognize that. So I made again a folder epaper and moved header-files inside. Now compiler messages about missing header-files are gone.

Kind regards

Can you link to the component you’re trying to use here? It’s a ESP-IDF component so it has a CMakeLists.txt file, right? If yes,this needs to be in the component/ folder of the project. If not, try using it by copying the library folder into lib/.

Link is: GitHub - VedantParanjape/esp-epaper-display: ESP-IDF component for waveshare epaper displays

And yes, it seems to be a ESP-IDF. It is a copy from original Waveshare library, where you find digitalWrite() and sleep()-calls. In this copy are gpio_set_level() and vTaskDelay().

There is a CMakeLists.txt at Github. And there is a file with the same name directly in my project folder and another one in the src-folder.

Kind regards

Works for me.

I start by creating a new ESP-IDF project from the PIO Home screen.

Then I follow the instructions from GitHub - VedantParanjape/esp-epaper-display: ESP-IDF component for waveshare epaper displays to clone it into my project under the components folder.

Then, per doc I configure it with pio run -t menuconfig. Notice the possible caveat for how to navigate the menu. I’ll use the default config for the display here.

I’ll press S and Q to save.

Further I use the given example code. Notice that the code is in C++, so I’ll have to rename my src\main.c file into src\main.cpp

Then I hit “Build” and…

Success. Flashing it my ESP32 and starting the serial monitor my clicking “Upload & Monitor” gives…

Some output. There’s no actual ePaper display connected via SPI, so that fails of course. But it all builds and uploads nicely.

Project files for reference are uploaded at GitHub - maxgerhardt/pio-esp32-epaper-demo: PlatformIO compilable project for the ePaper library at

Hello Max,

thank you.

Well … with some DOS commands it is simple to get a copy on my local computer. Important is to add this set(EXTRA_COMPONENT_DIRS <relative_path_to_component_folder>) line to the CMakeList.txt. Without this compiler can’t find the header files.

I don’t know how to do the pio run -t menuconfig. But it is only for setting display size and pin numbers? Normally I do this by #DEFINEs in the code.

There was a last obstacle: as main.c compiler complains class Epd : EpdIf in header-file epd1in54_V2.h, as main.cpp it is ok. At this point I was also with my manually copy action.

So I will look witch pins I need and then try to build and upload.

Kind regards

This is needed to modify the sdkconfig, from which defines are generated. You should not #define stuff yourself in those components, since you conflict with them. You need to open a CLI in VSCode and run pio run -t menuconfig there.

This was not necessary for me, just that it needs to be in the component folder. IntelliSense is updated after the Build, so before that, IntelliSense errors are expected.

Expected – you can’t include a C++ class definition from a C file, the C compiler does not understand C++. It needs to be main.cpp, I’ve also written that above

One last reply:

Program wasn’t working with my ePaper module. So I added a lot of printf()-functions in the code and found out, that it didn’t come out of the WaitUntilIdle() because BUSY-Pin was not getting low.

In the end it is a wrong module. I bougth some in 2018. They have levelshifter on the backside and seems to be a V2-module. But they are not. With a newer V2.1-module program is working.

Kind regards