# NimBLE-Arduino: the NimBLE stack with the Bluedroid API, on ESP32 and nRF5x

> NimBLE-Arduino is a refactoring of the NimBLE Bluetooth stack for compilation in the Arduino IDE, keeping the API of the Bluedroid based ESP32 library while using much less of the microcontroller. It supports seven Espressif chips and the Nordic nRF51 and nRF52 families, and it is not an ESP-IDF component.

**h2zero/NimBLE-Arduino** — A fork of the NimBLE library structured for compilation with Arduino, for use with ESP32, nRF5x.

- Repository: https://github.com/h2zero/NimBLE-Arduino
- Website: https://h2zero.github.io/NimBLE-Arduino/
- Stars: 1,134 · Forks: 222
- Language: C
- License: Apache-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/h2zero-nimble-arduino

## Same API, different stack, smaller footprint

NimBLE-Arduino is a fork of the NimBLE stack refactored for compilation in the Arduino IDE, and the reason it exists is stated in one paragraph of the README.

This library significantly reduces resource usage and improves performance for ESP32 BLE applications as compared with the bluedroid based library. The goal is to maintain, as much as reasonable, compatibility with the original library but using the NimBLE stack. In addition, it is meant to be more actively developed and maintained to provide improved capabilities and stability over the original.

The trade is therefore between footprint and familiarity, and the fork takes the familiar side. A project that already has Bluedroid code, with the classes and functions the original library exposes, can move to the NimBLE stack without rewriting the application. The README makes the same point in the usage section: the library is intended to be compatible with the original ESP32 BLE functions and classes with minor changes.

The origin is credited in the acknowledgements. The project was derived from the original ESP32 BLE library by nkolban and chegewara, and the acknowledgements also credit beegee-tokyo, who contributed time to testing and debugging as well as the beacon examples, and Jeroen88 for help debugging and improving the client code.

For Nordic devices the argument is different and stronger. The library provides access to a completely open source and configurable BLE stack. There is no softdevice to work around, which allows full debugging and resource management, continuous updates, and a cross platform API.

The project is Apache-2.0 licensed with the text in the `LICENSE` file, there is a `NOTICE` file, the primary language is C, and the last push was on 2026-10-19. The recent releases are 2.5.1 from 2026-07-30, 2.5.0 from 2026-04-02 and 2.4.0 from 2026-03-20.

## The chip list, and the ESP-IDF caveat

The supported hardware is listed in two groups.

The Espressif list is long, because the family is: ESP32, ESP32C3, ESP32S3, ESP32C6, ESP32H2, ESP32C2 and ESP32C5. The Nordic list is nRF51 and the nRF52 series, and it carries a requirement in bold: using the n-able Arduino core, which is a separate repository.

That requirement is the practical constraint for Nordic users. A Nordic board that is not running that core cannot compile this library as it stands, so choosing the fork on a Nordic device means adopting a particular core as well.

The ESP-IDF note is the other thing to read before anything else, because it is a hard boundary. The README says that this repository will not compile correctly in ESP-IDF, and that an ESP-IDF component version of the library can be found separately, in the `esp-nimble-cpp` project.

That makes sense as a build-system boundary. The Arduino build compiles the library as a set of C and C++ sources and headers that the Arduino tooling compiles with the sketch, and an ESP-IDF component is a CMake target with its own component registration. The same source can be arranged for both, but the two arrangements are not the same repository, and the Arduino one is the one this project is.

The development status section also says what the fork tracks. The library is tracking the esp-nimble repository, the `nimble-1.5.0-idf` branch, currently at commit `e3cbdc0`. So the upstream it follows is a specific branch of a specific commit, which is the thing to check when comparing this library's behaviour with a newer upstream release.

## Installing in the Arduino IDE and in PlatformIO

There are three installation paths, and the Arduino ones need no tools at all.

The first is the Arduino Library manager: go to `sketch`, then `Include Library`, then `Manage Libraries`, search for NimBLE and install. The second is the archive: download the library as a zip and extract it into the Arduino `libraries` folder, or use the Sketch menu and `Add .Zip library`.

Either way, the sketch starts with the single header:

```cpp
#include "NimBLEDevice.h"
```

PlatformIO is the third path and it is the one that pins a version. The `platformio.ini` file in the root of a PlatformIO project gets one line added to the `lib_deps` option of the `[env:]` section:

```ini
h2zero/NimBLE-Arduino@^2.5.1
```

The version constraint there matches the current release, 2.5.1, and the caret means a compatible range. Building the project makes PlatformIO install the dependency automatically.

The `library.properties` file at the root of the repository is what makes the first path work, since that is the metadata the Library manager reads to decide what the library is called and which versions exist.

Two details are worth knowing for a first build. The library is a fork with a different name from the one it replaces, so a sketch that mixes the two will not compile, and the include is `NimBLEDevice.h` rather than the header of the original library.

## nimconfig.h decides the limits, and the logging

Almost every knob in this library is a compile-time define in one file, and the README points at it twice.

The `src/nimconfig.h` file is where you change the settings to customise NimBLE to your project, and the example given is the maximum number of connections, which defaults to 3 on the ESP32. All the debug configuration options live in the same file, and they are enabled by uncommenting and modifying the desired settings before compiling.

The recommended debug configuration for connection and protocol debugging is four defines:

```cpp
#define MYNEWT_VAL_BLE_HS_LOG_LVL 1
#define MYNEWT_VAL_NIMBLE_CPP_LOG_LEVEL 3
#define MYNEWT_VAL_NIMBLE_CPP_ENABLE_RETURN_CODE_TEXT
#define MYNEWT_VAL_NIMBLE_CPP_ENABLE_GAP_EVENT_CODE_TEXT
```

The names explain themselves once you know the structure. The `MYNEWT_` prefix is the host stack's own configuration namespace, the two log levels are the host stack and the C++ wrapper, and the two `ENABLE` defines turn the numeric return codes and the gap event codes into text, which is the difference between a log full of numbers and a log a human can read.

The mechanism is a source-level configuration rather than a runtime one, which is a deliberate fit for embedded development. A build that has to be small has no room for a runtime configuration system, and a define that is compiled in costs nothing at runtime. The cost is the same as everywhere else with this approach: changing a setting means recompiling, and a setting that differs between the firmware on a device and the firmware in the lab is a bug that only shows up in the lab.

## Version 2 is a breaking release, and the guides are in docs/

The README opens with a notice that version 2 is now released, and it points at two documents: the 1.x to 2.x migration guide in `docs/`, and the release notes.

The `docs/` directory is where the documentation for the different audiences lives, and the README routes each group to its own file.

A user who has not used the original Bluedroid library is sent to the new user guide. A user who is familiar with the original library is sent to the migration guide for details about breaking changes and how to migrate. A user who already uses this library and needs to move to version 2 is sent to the 1.x to 2.x migration guide. A user who wants the performance details is sent to the usage tips.

The separation of the two migration guides is a good sign about how the project treats its users. The Bluedroid to NimBLE move and the 1.x to 2.x move are different operations with different risks, and a project that merged them into one document would be asking a reader to skip a section that happens to matter to them.

The full API documentation and the class list are published separately, at the project site `h2zero.github.io/NimBLE-Arduino/`, which is where a reader goes for the reference rather than the README.

## The examples directory is the feature list

The `examples/` directory is large and it is the most useful thing in the repository, because each folder is a self-contained demonstration of one part of the stack.

The core pair is `NimBLE_Server` and `NimBLE_Client`, which the README points to for advanced examples highlighting many available features. Around them are the specialised ones: `NimBLE_Secure_Server` and `NimBLE_Secure_Client` for authenticated pairing, `NimBLE_Async_Client` for the asynchronous client, the bonding examples in `NimBLE_Bond_Migration`, and the streaming examples `NimBLE_Stream_Server`, `NimBLE_Stream_Client` and `NimBLE_Stream_Echo`.

The scanning and advertising side is covered by `NimBLE_Scan_Continuous`, `NimBLE_Scan_Whitelist`, `NimBLE_Server_Whitelist`, `NimBLE_active_passive_scan` and `NimBLE_iBeacon`. The protocol-level work has `L2CAP` and `Bluetooth_5` folders, and `ANCS` covers the Apple Notification Center Service.

Two of them are credited to a contributor rather than to the maintainers. The beacon examples, `BLE_Beacon_Scanner` and `BLE_EddystoneTLM_Beacon`, are provided by beegee-tokyo, the same person credited in the acknowledgements for testing and debugging work, which is a useful reminder that a library maintained by one person is usually maintained with help from the people who use it.

The list also shows the shape of the API. Secure pairing, bond migration, whitelists, L2CAP channels, streaming and the Apple notification service are all first-class examples rather than documented corners, which is what a library that aims to be a drop-in replacement for the Bluedroid library has to provide.

## Where NimBLE-Arduino is the wrong tool

The limits are clear, and two of them are boundaries rather than defects.

The first is the build system. This repository will not compile correctly in ESP-IDF, and the ESP-IDF component version is a separate project. A team that is on ESP-IDF, which is the vendor framework rather than the Arduino framework, has to use that project instead, and the two will not track each other commit for commit.

The second is the Nordic core. Supporting nRF51 and nRF52 requires the n-able Arduino core, so the fork is only a drop-in on a Nordic board if you also accept that core. The softdevice point from the README cuts the other way here, and it is a real advantage on Nordic: a stack with no softdevice to work around means full debugging and resource management.

The third is the one that needs a decision rather than a workaround. The library is a fork that tracks a specific branch of a specific upstream commit, `nimble-1.5.0-idf` at `e3cbdc0` at the time of writing, and the goal stated in the README is to stay compatible with the original Bluedroid library where reasonable. Both of those are ongoing commitments by a small group of people, and the README itself points at how that is sustained, by asking commercial users to sponsor the development. A team that depends on this fork for a shipping product is depending on that sponsorship, and that is a reasonable thing to know before the dependency is created.

The alternative for an ESP32 project that is not on Arduino at all is the vendor's own stack, the ESP-IDF component version of the same library, which is the same code arranged for a different build system. The alternative for a project that wants the original Bluedroid API without a fork is the original Bluedroid based library, which is the trade this fork exists to improve on, at the cost of the resource usage the README describes.

## Conclusion

NimBLE-Arduino fits an ESP32 project where the Bluetooth stack built into the chip consumes more flash and RAM than the application can spare, and where the existing code is written against the familiar Bluedroid classes, because the point of the fork is that you keep the API and change the stack underneath. It is the wrong tool for an ESP-IDF project, since the README says plainly that this repository does not compile there, and it is the wrong choice on a Nordic board unless you are prepared to use the n-able Arduino core. Before migrating, read the 1.x to 2.x migration guide, because version 2 is a breaking release, and set the compile-time options in `src/nimconfig.h` deliberately, since that file is where the connection limits and the debug logging are decided.

## FAQ

### How do I install NimBLE-Arduino?

In the Arduino IDE, use Sketch, then Include Library, then Manage Libraries and search for NimBLE, or download the zip and extract it into the Arduino libraries folder, then add `#include "NimBLEDevice.h"` to the sketch. For PlatformIO, add `h2zero/NimBLE-Arduino@^2.5.1` to the lib_deps option of the [env:] section of platformio.ini.

### Which microcontrollers does NimBLE-Arduino support?

The Espressif ESP32, ESP32C3, ESP32S3, ESP32C6, ESP32H2, ESP32C2 and ESP32C5, and the Nordic nRF51 and nRF52 series, where the Nordic support requires the n-able Arduino core.

### Can I use NimBLE-Arduino in an ESP-IDF project?

No. The README states that this repository will not compile correctly in ESP-IDF, and points to an ESP-IDF component version of the library maintained in a separate project, the esp-nimble-cpp repository.

### How do I change settings such as the maximum number of connections in NimBLE-Arduino?

Edit the `src/nimconfig.h` file before compiling. The maximum connections defaults to 3 on the ESP32, and the same file holds all the debug options, which are enabled by uncommenting the defines you want.

## Sources

- [h2zero/NimBLE-Arduino on GitHub](https://github.com/h2zero/NimBLE-Arduino)
- [License: Apache-2.0](https://github.com/h2zero/NimBLE-Arduino/blob/master/LICENSE)
- [Project website](https://h2zero.github.io/NimBLE-Arduino/)
- [README](https://github.com/h2zero/NimBLE-Arduino/blob/master/README.md)
- [Releases](https://github.com/h2zero/NimBLE-Arduino/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/h2zero-nimble-arduino
