{"id":150905,"date":"2024-06-13T13:06:06","date_gmt":"2024-06-13T13:06:06","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=150905"},"modified":"2024-06-13T13:25:09","modified_gmt":"2024-06-13T13:25:09","slug":"micropython-esp32-bluetooth-low-energy-ble","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/micropython-esp32-bluetooth-low-energy-ble\/","title":{"rendered":"MicroPython: ESP32 &#8211; Getting Started with Bluetooth Low Energy (BLE)"},"content":{"rendered":"\n<p>This tutorial is a getting started guide to Bluetooth Low Energy (BLE) with the ESP32 programmed with MicroPython firmware. We&#8217;ll introduce you to BLE basic concepts and run some simple examples: advertise and expose data to be read by other BLE devices; and detect when another BLE device writes some data on the ESP32 characteristics.<\/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\/2024\/03\/ESP32-Bluetooth-Low-Energy-MicroPython-Getting-Started.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 with MicroPython Getting Started with Bluetooth Low Energy BLE\" class=\"wp-image-150987\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-Bluetooth-Low-Energy-MicroPython-Getting-Started.jpg?w=1920&amp;quality=100&amp;strip=all&amp;ssl=1 1920w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-Bluetooth-Low-Energy-MicroPython-Getting-Started.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-Bluetooth-Low-Energy-MicroPython-Getting-Started.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-Bluetooth-Low-Energy-MicroPython-Getting-Started.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-Bluetooth-Low-Energy-MicroPython-Getting-Started.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<p class=\"rntbox rntclblue\">Are you using Arduino IDE? Follow this tutorial instead: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-bluetooth-guide\/\" title=\"\">ESP32 with Bluetooth and Bluetooth Low Energy: The Ultimate Guide<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Prerequisites<\/h2>\n\n\n\n<p>Before proceeding with this tutorial, make sure you check the following prerequisites.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"micropython\">MicroPython Firmware<\/h3>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" width=\"250\" height=\"250\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/02\/micropython-logo.png?resize=150%2C150&amp;quality=100&amp;strip=all&amp;ssl=1\" alt=\"micorpython logo\" class=\"wp-image-148797\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/02\/micropython-logo.png?w=250&amp;quality=100&amp;strip=all&amp;ssl=1 250w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/02\/micropython-logo.png?resize=150%2C150&amp;quality=100&amp;strip=all&amp;ssl=1 150w\" sizes=\"(max-width: 250px) 100vw, 250px\" \/><\/figure><\/div>\n\n\n<p>To follow this tutorial you need MicroPython firmware installed in your ESP32 or ESP8266 boards. You also need an IDE to write and upload the code to your board. We suggest using Thonny IDE:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/getting-started-thonny-micropython-python-ide-esp32-esp8266\/\">Installing and getting started with Thonny IDE<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"rntbox rntclgreen\">Learn more about MicroPython:&nbsp;<a href=\"https:\/\/randomnerdtutorials.com\/micropython-programming-with-esp32-and-esp8266\/\">MicroPython Programming with ESP32 and ESP8266<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Introducing Bluetooth Low Energy (BLE)<\/h2>\n\n\n\n<p>Before diving into the examples, we&#8217;ll explain some basic concepts about Bluetooth and Bluetooth Low Energy.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is Bluetooth?<\/h3>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-medium\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"300\" height=\"91\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/03\/bluetooth-1.png?resize=300%2C91&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Introducing Bluetooth Low Energy BLE\" class=\"wp-image-95093\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/03\/bluetooth-1.png?resize=300%2C91&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/03\/bluetooth-1.png?w=400&amp;quality=100&amp;strip=all&amp;ssl=1 400w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/figure><\/div>\n\n\n<p>Bluetooth is a wireless technology that enables devices to communicate over short distances. This variant of Bluetooth is also referred to as \u201cBluetooth Classic\u201d or simply \u201cBluetooth\u201d. It was designed for high-speed data transmission and it\u2019s commonly used for connecting devices like headphones to phones, linking a keyboard or mouse to a computer, or transferring files between devices.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is Bluetooth Low Energy?<\/h3>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-medium\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/03\/Bluetooth-low-energy.png?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"97\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/03\/Bluetooth-low-energy-300x97.png?resize=300%2C97&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-95092\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/03\/Bluetooth-low-energy.png?resize=300%2C97&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/03\/Bluetooth-low-energy.png?w=400&amp;quality=100&amp;strip=all&amp;ssl=1 400w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/figure><\/div>\n\n\n<p>Bluetooth Low Energy, BLE for short (also called Bluetooth Smart), is a power\u2011conserving variant of Bluetooth. BLE\u2019s primary application is short-distance transmission of small amounts of data (low bandwidth). Unlike Bluetooth which is always on, BLE remains in sleep mode constantly except when a connection is initiated. This makes it consume very little power. BLE consumes approximately 100x less power than Bluetooth (depending on the use case).<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Bluetooth Classic vs Bluetooth Low Energy<\/h1>\n\n\n\n<p>So, what are the main differences between Bluetooth Classic and Bluetooth Low Energy?<\/p>\n\n\n\n<p><strong>Bluetooth Classic<\/strong> is known for higher data transfer rates, making it suitable for applications like audio streaming and file transfer. It consumes more power, making it less ideal for battery-operated devices. Usually, Bluetooth Classic is easier to understand and implement for beginners, while Bluetooth Low Energy might take a little more time to understand basic concepts. That\u2019s why many people still prefer using Bluetooth Classic instead of BLE in their IoT projects.<\/p>\n\n\n\n<p>On the other hand, <strong>BLE<\/strong> (<strong>Bluetooth Low Energy<\/strong>) is designed for low power consumption, making it perfect for devices like IoT gadgets and wearables, and is also a great solution for the ESP32 in IoT and Home Automation applications. BLE operates with lower data transfer rates but is energy-efficient and works well in short-range scenarios.<\/p>\n\n\n\n<p>Another big difference between the two versions of Bluetooth is the way to transfer data. Bluetooth Classic uses something similar to Serial Communication (Serial Port Profile), while Bluetooth Low Energy uses a client-server model, where it employs the GATT (Generic Attribute Profile) to structure data.<\/p>\n\n\n\n<p>You can check this website to learn in more detail about the main <a href=\"https:\/\/www.bluetooth.com\/learn-about-bluetooth\/tech-overview\/\" target=\"_blank\" rel=\"noopener\" title=\"\">differences between Bluetooth and Bluetooth Low Energy<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>&nbsp;<\/td><td><strong>Bluetooth Classic<\/strong><\/td><td><strong>Bluetooth Low Energy (BLE)<\/strong><\/td><\/tr><tr><td><strong>Power Consumption<\/strong><\/td><td>Higher power consumption<\/td><td>Low power consumption<\/td><\/tr><tr><td><strong>Data Transfer Rate<\/strong><\/td><td>Higher data transfer rates<\/td><td>Lower data transfer rates<\/td><\/tr><tr><td><strong>Range<\/strong><\/td><td>Longer range<\/td><td>Shorter range<\/td><\/tr><tr><td><strong>Applications<\/strong><\/td><td>Audio streaming, file transfer<\/td><td>IoT devices, wearables, smart home<\/td><\/tr><tr><td><strong>Data Transfer<\/strong><\/td><td>Serial Port Profile (SPP)<\/td><td>Generic Attribute Profile (GATT)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">Bluetooth Low Energy Basic Concepts<\/h1>\n\n\n\n<p>Before proceeding, it\u2019s important to get familiar with some basic BLE concepts.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">BLE Peripheral and Controller (Central Device)<\/h3>\n\n\n\n<p>When using Bluetooth Low Energy (BLE), it\u2019s important to understand the roles of BLE Peripheral and BLE Controller (also referred to as the Central Device).<\/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=\"1200\" height=\"736\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Peripheral-Controller.png?resize=1200%2C736&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Bluetooth Low Energy Basic Concepts Example Overivew\" class=\"wp-image-136349\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Peripheral-Controller.png?w=3126&amp;quality=100&amp;strip=all&amp;ssl=1 3126w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Peripheral-Controller.png?resize=300%2C184&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Peripheral-Controller.png?resize=1024%2C628&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Peripheral-Controller.png?resize=768%2C471&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Peripheral-Controller.png?resize=1536%2C942&amp;quality=100&amp;strip=all&amp;ssl=1 1536w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Peripheral-Controller.png?resize=2048%2C1256&amp;quality=100&amp;strip=all&amp;ssl=1 2048w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Peripheral-Controller.png?w=2400&amp;quality=100&amp;strip=all&amp;ssl=1 2400w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p>The ESP32 can act either as a Peripheral or as a central device. When it acts as a peripheral it sets up a GATT profile and advertises its service with characteristics that the central devices can read or interact with. On the other hand, when it is set as a central device, it can connect to other BLE devices to read or interact with their profiles and read their characteristics.<\/p>\n\n\n\n<p>In the above diagram, the ESP32 takes the role of the BLE Peripheral, serving as the device that provides data or services. Your smartphone or computer acts as the BLE Controller, managing the connection and communication with the ESP32.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">BLE Server and Client<\/h3>\n\n\n\n<p>With Bluetooth Low Energy, there are two types of devices: the server and the client. The ESP32 can act either as a client or as a server. In the picture below it acts as a server, exposing its GATT structure containing data. The BLE Server acts as a provider of data or services, while the BLE Client consumes or uses these services.<\/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=\"1200\" height=\"493\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Client-Server.png?resize=1200%2C493&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Bluetooth Low Energy Basic Concepts BLE Server and Client\" class=\"wp-image-136350\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Client-Server.png?w=3126&amp;quality=100&amp;strip=all&amp;ssl=1 3126w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Client-Server.png?resize=300%2C123&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Client-Server.png?resize=1024%2C421&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Client-Server.png?resize=768%2C315&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Client-Server.png?resize=1536%2C631&amp;quality=100&amp;strip=all&amp;ssl=1 1536w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Client-Server.png?resize=2048%2C841&amp;quality=100&amp;strip=all&amp;ssl=1 2048w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-Client-Server.png?w=2400&amp;quality=100&amp;strip=all&amp;ssl=1 2400w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p>The server advertises its existence, so it can be found by other devices and contains data that the client can read or interact with. The client scans the nearby devices, and when it finds the server, it is looking for, it establishes a connection and can interact with that device by reading or writing on its&nbsp;characteristics.<\/p>\n\n\n\n<p>The BLE server is basically the BLE peripheral before establishing a connection. The BLE Client is the BLE controller before establishing a connection. Many times, these terms are used interchangeably.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">GATT<\/h2>\n\n\n\n<p>GATT, which stands for Generic Attribute Profile, is a fundamental concept in Bluetooth Low Energy (BLE) technology. Essentially, it serves as a blueprint for how BLE devices communicate with each other. Think of it as a structured language that two BLE devices use to exchange information seamlessly.<\/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=\"1200\" height=\"738\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?resize=1200%2C738&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"GATT Generic Attribute Profile Bluetooth Low Energy (BLE) technology\" class=\"wp-image-136351\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?w=3125&amp;quality=100&amp;strip=all&amp;ssl=1 3125w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?resize=300%2C184&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?resize=1024%2C629&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?resize=768%2C472&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?resize=1536%2C944&amp;quality=100&amp;strip=all&amp;ssl=1 1536w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?resize=2048%2C1259&amp;quality=100&amp;strip=all&amp;ssl=1 2048w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?w=2400&amp;quality=100&amp;strip=all&amp;ssl=1 2400w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Profile:<\/strong> standard collection of services for a specific use case;<\/li>\n\n\n\n<li><strong>Service:<\/strong> collection of related information, like sensor readings, battery level, heart rate, etc.;<\/li>\n\n\n\n<li><strong>Characteristic:<\/strong> it is where the actual data is saved on the hierarchy (value);<\/li>\n\n\n\n<li><strong>Descriptor:<\/strong> metadata about the data;<\/li>\n\n\n\n<li><strong>Properties:<\/strong> describe how the characteristic value can be interacted with. For example: read, write, notify, broadcast, indicate, etc.<\/li>\n<\/ul>\n\n\n\n<p>Let\u2019s take a more in-depth look at the BLE Service and Characteristics.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">BLE Service<\/h4>\n\n\n\n<p>The top level of the hierarchy is a profile and is composed of one or more services. Usually, a BLE device contains more than one service, like battery service and heart rate service.<\/p>\n\n\n\n<p>Every service contains at least one characteristic. There are predefined services for several types of data defined by the SIG (Bluetooth Special Interest Group) like: Battery Level, Blood Pressure, Heart Rate, Weight Scale, Environmental Sensing, etc. You can check on the following link for the predefined services:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.bluetooth.com\/specifications\/assigned-numbers\/\" target=\"_blank\" rel=\"noopener\" title=\"\">https:\/\/www.bluetooth.com\/specifications\/assigned-numbers\/<\/a><\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">UUID<\/h4>\n\n\n\n<p>A UUID is a unique digital identifier used in BLE and GATT to distinguish and locate services, characteristics, and descriptors. It\u2019s like a distinct label that ensures every component in a Bluetooth device has a unique name.<\/p>\n\n\n\n<p>Each service, characteristic, and descriptor has a UUID (Universally Unique Identifier). A UUID is a unique 128-bit (16 bytes) number. For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>55072829-bc9e-4c53-938a-74a6d4c78776<\/code><\/pre>\n\n\n\n<p>There are shortened and default UUIDs for services, and characteristics specified in the&nbsp;<a href=\"https:\/\/www.bluetooth.com\/specifications\/gatt\/services\" target=\"_blank\" rel=\"noreferrer noopener\">SIG (Bluetooth Special Interest Group)<\/a>. This means, that if you have a BLE device that uses the default UUIDs for its services and characteristics, you\u2019ll know exactly how to interact with that device to get or interact with the information you\u2019re looking for.<\/p>\n\n\n\n<p>You can also generate your own custom UUIDs if you don\u2019t want to stick with predefined values or if the data you\u2019re exchanging doesn\u2019t fit in any of the categories. You can generate custom UUIDs using this&nbsp;<a href=\"https:\/\/www.uuidgenerator.net\/\" target=\"_blank\" rel=\"noreferrer noopener\">UUID generator website<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Communication between BLE Devices<\/h3>\n\n\n\n<p>Here are the usual steps that describe the communication between BLE Devices.<\/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=\"750\" height=\"742\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-Client-Server-Communication-07.png?resize=750%2C742&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 BLE Server and Client Communicaton\" class=\"wp-image-150952\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-Client-Server-Communication-07.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-Client-Server-Communication-07.png?resize=300%2C297&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<ol class=\"wp-block-list\">\n<li>The BLE Peripheral (server) advertises its existence (ESP32).<\/li>\n\n\n\n<li>The BLE Central Device (client) scans for BLE devices.<\/li>\n\n\n\n<li>When the central device finds the peripheral it is looking for, it connects to it.<\/li>\n\n\n\n<li>After connecting, it reads the GATT profile of the peripheral and searches for the service it is looking for (for example: <em>environmental sensing<\/em>).<\/li>\n\n\n\n<li>If it finds the service, it can now interact with the characteristics. For example, reading the temperature value.<\/li>\n<\/ol>\n\n\n\n<h1 class=\"wp-block-heading\">Installing the <em>aioble<\/em> Package<\/h1>\n\n\n\n<p>To write code to use Bluetooth with the ESP32, we\u2019ll install the <strong><span class=\"rnthl rntliteral\">aioble<\/span> <\/strong>package\u2014that\u2019s currently the recommended library for BLE communication with MicroPython.<\/p>\n\n\n\n<p>Before proceeding to the actual examples, you need to install it on your board.<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Connect the board (with MicroPython installed\u2014<a href=\"#micropython\" title=\"\">check the prerequisites<\/a>) to your computer and connect it to Thonny IDE.<\/li>\n\n\n\n<li>On Thonny IDE, go to <strong>Tools<\/strong> &gt; <strong>Manage Packages\u2026<\/strong><\/li>\n\n\n\n<li>Search for <strong>aioble<\/strong> and click on the aioble option.<\/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=\"644\" height=\"464\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/installing-aioble-micropython.png?resize=644%2C464&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Installing aioble Bluetooth Library MicroPython ESP32\" class=\"wp-image-150954\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/installing-aioble-micropython.png?w=644&amp;quality=100&amp;strip=all&amp;ssl=1 644w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/installing-aioble-micropython.png?resize=300%2C216&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 644px) 100vw, 644px\" \/><\/figure><\/div>\n\n\n<p>Finally, click the <strong>Install<\/strong> 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=\"644\" height=\"464\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/installing-aioble-micropython-2.png?resize=644%2C464&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Installing aioble Bluetooth Library MicroPython ESP32\" class=\"wp-image-150955\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/installing-aioble-micropython-2.png?w=644&amp;quality=100&amp;strip=all&amp;ssl=1 644w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/installing-aioble-micropython-2.png?resize=300%2C216&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 644px) 100vw, 644px\" \/><\/figure><\/div>\n\n\n<p>Wait a few seconds while it installs. After installing, you can proceed to the examples.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The ESP32 as a BLE Peripheral<\/h2>\n\n\n\n<p>In this example, we&#8217;ll set the ESP32 as a BLE Peripheral. We&#8217;ll show you how to advertise services and change the value of characteristics and how to detect if another BLE device wrote on the ESP32 characteristics. Here&#8217;s a quick breakdown of how the project works:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>In this example, the ESP32 will act as a BLE Peripheral\/BLE Server that advertises its existence. <\/li>\n\n\n\n<li>The ESP32 GATT structure will have one&nbsp;<em>service&nbsp;<\/em>with two&nbsp;<em>characteristics<\/em>. One characteristic (let\u2019s call it&nbsp;<em>sensor characteristic<\/em>) will be the place to save a&nbsp;<em>value&nbsp;<\/em>that changes over time (like sensor readings).<\/li>\n\n\n\n<li>The ESP32 will write a new value to the <em>sensor characteristic<\/em> periodically.<\/li>\n\n\n\n<li>The other characteristic (let\u2019s call it&nbsp;<em>LED characteristic<\/em>) will be the place to save the state of a GPIO. By changing the&nbsp;<em>value<\/em>&nbsp;of that&nbsp;<em>characteristic<\/em>, we\u2019ll be able to control an LED connected to that GPIO.<\/li>\n\n\n\n<li>We&#8217;ll use an app called nRF Connect to connect to the ESP32 BLE device to read the <em>sensor characteristic<\/em> and write on the <em>LED characteristic<\/em> to control the onboard LED.<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"738\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?resize=1200%2C738&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"The ESP32 as a BLE Peripheral\" class=\"wp-image-136351\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?w=3125&amp;quality=100&amp;strip=all&amp;ssl=1 3125w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?resize=300%2C184&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?resize=1024%2C629&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?resize=768%2C472&amp;quality=100&amp;strip=all&amp;ssl=1 768w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?resize=1536%2C944&amp;quality=100&amp;strip=all&amp;ssl=1 1536w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?resize=2048%2C1259&amp;quality=100&amp;strip=all&amp;ssl=1 2048w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/BLE-basic-GATT.png?w=2400&amp;quality=100&amp;strip=all&amp;ssl=1 2400w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">ESP32 BLE Peripheral MicroPython Code<\/h3>\n\n\n\n<p>Copy the following code to Thonny IDE.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-python\"># Rui Santos &amp; Sara Santos - Random Nerd Tutorials\n# Complete project details at https:\/\/RandomNerdTutorials.com\/micropython-esp32-bluetooth-low-energy-ble\/\n\nfrom micropython import const\nimport asyncio\nimport aioble\nimport bluetooth\nimport struct\nfrom machine import Pin\nfrom random import randint\n\n# Init LED\nled = Pin(2, Pin.OUT)\nled.value(0)\n\n# Init random value\nvalue = 0\n\n# See the following for generating UUIDs:\n# https:\/\/www.uuidgenerator.net\/\n_BLE_SERVICE_UUID = bluetooth.UUID('19b10000-e8f2-537e-4f6c-d104768a1214')\n_BLE_SENSOR_CHAR_UUID = bluetooth.UUID('19b10001-e8f2-537e-4f6c-d104768a1214')\n_BLE_LED_UUID = bluetooth.UUID('19b10002-e8f2-537e-4f6c-d104768a1214')\n# How frequently to send advertising beacons.\n_ADV_INTERVAL_MS = 250_000\n\n# Register GATT server, the service and characteristics\nble_service = aioble.Service(_BLE_SERVICE_UUID)\nsensor_characteristic = aioble.Characteristic(ble_service, _BLE_SENSOR_CHAR_UUID, read=True, notify=True)\nled_characteristic = aioble.Characteristic(ble_service, _BLE_LED_UUID, read=True, write=True, notify=True, capture=True)\n\n# Register service(s)\naioble.register_services(ble_service)\n\n# Helper to encode the data characteristic UTF-8\ndef _encode_data(data):\n    return str(data).encode('utf-8')\n\n# Helper to decode the LED characteristic encoding (bytes).\ndef _decode_data(data):\n    try:\n        if data is not None:\n            # Decode the UTF-8 data\n            number = int.from_bytes(data, 'big')\n            return number\n    except Exception as e:\n        print(&quot;Error decoding temperature:&quot;, e)\n        return None\n\n# Get sensor readings\ndef get_random_value():\n    return randint(0,100)\n\n# Get new value and update characteristic\nasync def sensor_task():\n    while True:\n        value = get_random_value()\n        sensor_characteristic.write(_encode_data(value), send_update=True)\n        print('New random value written: ', value)\n        await asyncio.sleep_ms(1000)\n        \n# Serially wait for connections. Don't advertise while a central is connected.\nasync def peripheral_task():\n    while True:\n        try:\n            async with await aioble.advertise(\n                _ADV_INTERVAL_MS,\n                name=&quot;ESP32&quot;,\n                services=[_BLE_SERVICE_UUID],\n                ) as connection:\n                    print(&quot;Connection from&quot;, connection.device)\n                    await connection.disconnected()             \n        except asyncio.CancelledError:\n            # Catch the CancelledError\n            print(&quot;Peripheral task cancelled&quot;)\n        except Exception as e:\n            print(&quot;Error in peripheral_task:&quot;, e)\n        finally:\n            # Ensure the loop continues to the next iteration\n            await asyncio.sleep_ms(100)\n\nasync def wait_for_write():\n    while True:\n        try:\n            connection, data = await led_characteristic.written()\n            print(data)\n            print(type)\n            data = _decode_data(data)\n            print('Connection: ', connection)\n            print('Data: ', data)\n            if data == 1:\n                print('Turning LED ON')\n                led.value(1)\n            elif data == 0:\n                print('Turning LED OFF')\n                led.value(0)\n            else:\n                print('Unknown command')\n        except asyncio.CancelledError:\n            # Catch the CancelledError\n            print(&quot;Peripheral task cancelled&quot;)\n        except Exception as e:\n            print(&quot;Error in peripheral_task:&quot;, e)\n        finally:\n            # Ensure the loop continues to the next iteration\n            await asyncio.sleep_ms(100)\n            \n# Run tasks\nasync def main():\n    t1 = asyncio.create_task(sensor_task())\n    t2 = asyncio.create_task(peripheral_task())\n    t3 = asyncio.create_task(wait_for_write())\n    await asyncio.gather(t1, t2)\n    \nasyncio.run(main())\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-MicroPython\/esp32_ble_basic.py\" 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>Let\u2019s take a quick look at the relevant parts of the code for this example.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Include Libraries<\/h4>\n\n\n\n<p>You need to include the <span class=\"rnthl rntliteral\">aioble<\/span> and the <span class=\"rnthl rntliteral\">bluetooth<\/span> libraries to use Bluetooth with the ESP32. We also import the <span class=\"rnthl rntliteral\">randint<\/span> method from the <span class=\"rnthl rntliteral\">random<\/span> module to generate random numbers.Our code will be asynchronous. For that, we\u2019ll use the <span class=\"rnthl rntliteral\">asyncio<\/span> library. <\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>from micropython import const\nimport asyncio\nimport aioble\nimport bluetooth\nimport struct\nfrom machine import Pin\nfrom random import randint<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Define UUIDs and Register the GATT Service and Characteristic<\/h4>\n\n\n\n<p>We define the UUIDs for the service and its characteristics. One characteristic will hold the LED value and another for the hypothetical sensor reading (in this case, a random value).<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>_BLE_SERVICE_UUID = bluetooth.UUID('19b10000-e8f2-537e-4f6c-d104768a1214')\n_BLE_SENSOR_CHAR_UUID = bluetooth.UUID('19b10001-e8f2-537e-4f6c-d104768a1214')\n_BLE_LED_UUID = bluetooth.UUID('19b10002-e8f2-537e-4f6c-d104768a1214')<\/code><\/pre>\n\n\n\n<p>Those UUIDs were created using the&nbsp;<a href=\"https:\/\/www.uuidgenerator.net\/\" target=\"_blank\" rel=\"noreferrer noopener\">uuidgenerator website<\/a>. You can generate your own UUIDs for your application, but for this example, we recommend using the same UUIDs we\u2019re using.<\/p>\n\n\n\n<p>Then, register the GATT service and characteristics.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code># Register GATT server, the service and characteristics\nble_service = aioble.Service(_BLE_SERVICE_UUID)\nsensor_characteristic = aioble.Characteristic(ble_service, _BLE_SENSOR_CHAR_UUID, read=True, notify=True)\nled_characteristic = aioble.Characteristic(ble_service, _BLE_LED_UUID, read=True, write=True, notify=True, capture=True)\n\n# Register service(s)\naioble.register_services(ble_service)<\/code><\/pre>\n\n\n\n<p>When creating the <span class=\"rnthl rntliteral\">sensor_characteristic<\/span>, we set the <span class=\"rnthl rntliteral\">read<\/span> and <span class=\"rnthl rntliteral\">notify<\/span> arguments to <span class=\"rnthl rntliteral\">True<\/span>. This defines the way that the central device can interact with the characteristic. It can read the characteristic and be notified when it changes.<\/p>\n\n\n\n<p>For the <span class=\"rnthl rntliteral\">led_characteristic<\/span>, we have an additional property. The <span class=\"rnthl rntliteral\">capture<\/span> property set to <span class=\"rnthl rntliteral\">True<\/span>. This indicates that other BLE devices can write to that characteristic\u2014this is how other devices can control the ESP32 LED.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>led_characteristic = aioble.Characteristic(ble_service, _BLE_LED_UUID, read=True, write=True, notify=True, capture=True)<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Encode and Decode Data<\/h4>\n\n\n\n<p>The data to be written on the characteristic needs to be in a specific format. The <span class=\"rnthl rntliteral\">_encode_data()<\/span> function converts the data to UTF-8 format.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code># Helper to encode the data characteristic UTF-8\ndef _encode_data(data):\n    return str(data).encode('utf-8')<\/code><\/pre>\n\n\n\n<p>When other devices write to the <span class=\"rnthl rntliteral\">led_characteristic<\/span>, the data will be in byte format. The following function converts the bytes to an integer.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code># Helper to decode the LED characteristic encoding (bytes).\ndef _decode_data(data):\n    try:\n        if data is not None:\n            # Decode the UTF-8 data\n            number = int.from_bytes(data, 'big')\n            return number\n    except Exception as e:\n        print(\"Error decoding temperature:\", e)\n        return None<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Get a New Value and Write on Characteristic<\/h4>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">sensor_task()<\/span> is an asynchronous function that gets a new random value and writes on the characteristic using the <span class=\"rnthl rntliteral\">write()<\/span> method on the <span class=\"rnthl rntliteral\">sensor_characteristic<\/span>.This task is repeated continuously every second. You can adjust the delay time as needed.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code># Get new value and update characteristic\nasync def sensor_task():\n    while True:\n        value = get_random_value()\n        sensor_characteristic.write(_encode_data(value), send_update=True)\n        #print('New random value written: ', value)\n        await asyncio.sleep_ms(1000)<\/code><\/pre>\n\n\n\n<p>The <span class=\"rnthl rntliteral\">get_random_value()<\/span> function, in a real-world scenario, should be replaced with a function that will get sensor data\u2014like temperature from a <a href=\"https:\/\/randomnerdtutorials.com\/micropython-ds18b20-esp32-esp8266\/\" title=\"\">DS18B20 temperature sensor<\/a>, for example.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Advertising<\/h4>\n\n\n\n<p>Besides writing to the sensor characteristic, we also need to advertise the ESP32 as a BLE service. For that, we use the <span class=\"rnthl rntliteral\">peripheral_task()<\/span> function.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code># Serially wait for connections. Don't advertise while a central is connected.\nasync def peripheral_task():\n    while True:\n        try:\n            async with await aioble.advertise(\n                _ADV_INTERVAL_MS,\n                name=\"ESP32\",\n                services=&#091;_BLE_SERVICE_UUID],\n                ) as connection:\n                    print(\"Connection from\", connection.device)\n                    await connection.disconnected()             \n        except asyncio.CancelledError:\n            # Catch the CancelledError\n            print(\"Peripheral task cancelled\")\n        except Exception as e:\n            print(\"Error in peripheral_task:\", e)\n        finally:\n            # Ensure the loop continues to the next iteration\n            await asyncio.sleep_ms(100)<\/code><\/pre>\n\n\n\n<p>In that function, we define the BLE device name (&#8216;<strong>ESP32<\/strong>&#8216;). You can change its name if you want to. But, to follow our examples, we recommend that you&#8217;ll leave that name.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Waiting for a Write<\/h4>\n\n\n\n<p>In the <span class=\"rnthl rntliteral\">wait_for_write()<\/span> function, we&#8217;re continuously checking if the <span class=\"rnthl rntliteral\">led_characteristic<\/span> was written on. When it is, we decode the data and turn the ESP32 onboard LED on or off accordingly.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>async def wait_for_write():\n    while True:\n        try:\n            connection, data = await led_characteristic.written()\n            print(data)\n            print(type)\n            data = _decode_data(data)\n            print('Connection: ', connection)\n            print('Data: ', data)\n            if data == 1:\n                print('Turning LED ON')\n                led.value(1)\n            elif data == 0:\n                print('Turning LED OFF')\n                led.value(0)\n            else:\n                print('Unknown command')\n        except asyncio.CancelledError:\n            # Catch the CancelledError\n            print(\"Peripheral task cancelled\")\n        except Exception as e:\n            print(\"Error in peripheral_task:\", e)\n        finally:\n            # Ensure the loop continues to the next iteration\n            await asyncio.sleep_ms(100)<\/code><\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">Main Function<\/h4>\n\n\n\n<p>Finally, we create an asynchronous <span class=\"rnthl rntliteral\">main()<\/span> function, where we\u2019ll write the base for our code. We create three asynchronous tasks: one for advertising, another to write on the sensor characteristic, and finally, another one to control the LED when other devices write on the <span class=\"rnthl rntliteral\">led_characteristic<\/span>.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>async def main():\n    t1 = asyncio.create_task(sensor_task())\n    t2 = asyncio.create_task(peripheral_task())\n    t3 = asyncio.create_task(wait_for_write())\n    await asyncio.gather(t1, t2)<\/code><\/pre>\n\n\n\n<p>Finally, we run the code as follows.<\/p>\n\n\n\n<pre class=\"wp-block-code language-python\"><code>asyncio.run(main())<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Testing the Code<\/h2>\n\n\n\n<p>Run the previous code on the ESP32. It will start writing the temperature on the <em>sensor characteristic <\/em>and it will advertise its service.<\/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=\"741\" height=\"334\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-write-on-characteristic-sensor.png?resize=741%2C334&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"\" class=\"wp-image-150989\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-write-on-characteristic-sensor.png?w=741&amp;quality=100&amp;strip=all&amp;ssl=1 741w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-write-on-characteristic-sensor.png?resize=300%2C135&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 741px) 100vw, 741px\" \/><\/figure><\/div>\n\n\n<p>To connect to this peripheral, read its <em>sensor characteristic<\/em>, and write to the<em> led characteristic<\/em>, we\u2019ll use the nRF connect app. You can also use <a href=\"https:\/\/ruisantosdotme.github.io\/esp32-web-ble\/\" target=\"_blank\" rel=\"noopener\" title=\"\">our Web BLE app<\/a> (only works with Android and Windows computers).<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">nRF Connect App<\/h4>\n\n\n\n<p>The <em>nRF Connect<\/em> app from Nordic works on Android (Google Play Store) and iOS (App Store). Go to Google Play Store or App Store, search for \u201c<strong>nRF Connect for Mobile<\/strong>\u201d and install the app on your smartphone.<\/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=\"250\" height=\"541\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/nRF-connect-app.png?resize=250%2C541&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"nRF Connect for Mobile\" class=\"wp-image-150968\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/nRF-connect-app.png?w=250&amp;quality=100&amp;strip=all&amp;ssl=1 250w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/nRF-connect-app.png?resize=139%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 139w\" sizes=\"(max-width: 250px) 100vw, 250px\" \/><\/figure><\/div>\n\n\n<p>Go to your smartphone, open the <em>nRF Connect app from Nordic<\/em>, and start scanning for new devices. You should find a device called&nbsp;<strong>ESP32<\/strong>\u2014this is the BLE server name you defined earlier.<\/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=\"350\" height=\"108\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-Device-1.png?resize=350%2C108&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"nRF Connect app from Nordic connecting to ESP32\" class=\"wp-image-150979\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-Device-1.png?w=350&amp;quality=100&amp;strip=all&amp;ssl=1 350w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-Device-1.png?resize=300%2C93&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 350px) 100vw, 350px\" \/><\/figure><\/div>\n\n\n<p>Connect to the ESP32 device. On Thonny IDE, you&#8217;ll see that it detected a new connection.<\/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=\"741\" height=\"338\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-new-device-connected.png?resize=741%2C338&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Thonny IDE MicroPython connection from device\" class=\"wp-image-150980\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-new-device-connected.png?w=741&amp;quality=100&amp;strip=all&amp;ssl=1 741w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-new-device-connected.png?resize=300%2C137&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 741px) 100vw, 741px\" \/><\/figure><\/div>\n\n\n<p>You\u2019ll see that it displays the service with the UUID we defined in the code and that it contains two characteristics with the UUIDs we defined previously. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Reading the Characteristic<\/h3>\n\n\n\n<p>On the sensor characteristic, click on the arrows to read the characteristic and activate the notifications. Then, click on the icon to change the data format (set to UTF-8)\u2014on Android devices you don&#8217;t need to change the format.<\/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=\"350\" height=\"664\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-Device-Characteristics.png?resize=350%2C664&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Reading the BLE Characteristic\" class=\"wp-image-150971\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-Device-Characteristics.png?w=350&amp;quality=100&amp;strip=all&amp;ssl=1 350w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-BLE-Device-Characteristics.png?resize=158%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 158w\" sizes=\"(max-width: 350px) 100vw, 350px\" \/><\/figure><\/div>\n\n\n<p>It will start displaying the random values on the <strong>Value <\/strong>field. It is updated every second.<\/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=\"350\" height=\"110\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/reading-EPS32-characteristic-nRF-connect-app.png?resize=350%2C110&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Reading the BLE Characteristic Value\" class=\"wp-image-150972\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/reading-EPS32-characteristic-nRF-connect-app.png?w=350&amp;quality=100&amp;strip=all&amp;ssl=1 350w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/reading-EPS32-characteristic-nRF-connect-app.png?resize=300%2C94&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 350px) 100vw, 350px\" \/><\/figure><\/div>\n\n\n<h3 class=\"wp-block-heading\">Writing to the Characteristic<\/h3>\n\n\n\n<p>To write to the LED characteristic and control the LED, click on the upper arrow on the LED characteristic.<\/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=\"350\" height=\"108\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/LED-characteristic-write-esp32.png?resize=350%2C108&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Writing to the BLE Characteristic value\" class=\"wp-image-150973\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/LED-characteristic-write-esp32.png?w=350&amp;quality=100&amp;strip=all&amp;ssl=1 350w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/LED-characteristic-write-esp32.png?resize=300%2C93&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 350px) 100vw, 350px\" \/><\/figure><\/div>\n\n\n<p>Select the <em>UnsignedInt <\/em>or <em>Bool <\/em>type. Then, write <strong>1<\/strong> or <strong>0<\/strong> to turn the LED on or off. <strong>1<\/strong> turns the LED on and<strong> 0<\/strong> turns the LED off.<\/p>\n\n\n\n<figure class=\"wp-block-gallery aligncenter has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/write-to-characteristic-turn-led-on.png?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"350\" height=\"229\" data-id=\"150975\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/write-to-characteristic-turn-led-on.png?resize=350%2C229&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Write BLE Characteristic value 1\" class=\"wp-image-150975\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/write-to-characteristic-turn-led-on.png?w=350&amp;quality=100&amp;strip=all&amp;ssl=1 350w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/write-to-characteristic-turn-led-on.png?resize=300%2C196&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 350px) 100vw, 350px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/Write-to-characteristic.png?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"350\" height=\"240\" data-id=\"150974\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/Write-to-characteristic.png?resize=350%2C240&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Write BLE Characteristic value 0\" class=\"wp-image-150974\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/Write-to-characteristic.png?w=350&amp;quality=100&amp;strip=all&amp;ssl=1 350w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/Write-to-characteristic.png?resize=300%2C206&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 350px) 100vw, 350px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p>The ESP32 will notice that the other device wrote on the <em>LED characteristic<\/em> and will read its new value.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/characteristic-written-control-led-esp32.png?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"741\" height=\"338\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/characteristic-written-control-led-esp32.png?resize=741%2C338&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Receive the BLE Characteristic value Thonny IDE control LED\" class=\"wp-image-150978\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/characteristic-written-control-led-esp32.png?w=741&amp;quality=100&amp;strip=all&amp;ssl=1 741w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/characteristic-written-control-led-esp32.png?resize=300%2C137&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 741px) 100vw, 741px\" \/><\/a><\/figure><\/div>\n\n\n<p>According to the value written, it will turn the LED on or off.<\/p>\n\n\n\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex\">\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-on-HIGH.jpg?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" data-id=\"96167\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-on-HIGH.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 board Built in LED turned on HIGH\" class=\"wp-image-96167\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-on-HIGH.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-on-HIGH.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/a><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-off-LOW.jpg?quality=100&#038;strip=all&#038;ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"422\" data-id=\"96166\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-off-LOW.jpg?resize=750%2C422&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 board Built in LED turned off LOW\" class=\"wp-image-96166\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-off-LOW.jpg?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2020\/04\/ESP32-board-Built_in-LED-turned-off-LOW.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/a><\/figure>\n<\/figure>\n\n\n\n<p>Alternatively, you can use our <a href=\"https:\/\/ruisantosdotme.github.io\/esp32-web-ble\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Web BLE app<\/a> to connect to the ESP32 BLE device. It works on Google Chrome on Windows and Android devices.<\/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=\"369\" height=\"735\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-Web-BLE-App-Smartphone.png?resize=369%2C735&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Web BLE app ESP32 web browser demonstration\" class=\"wp-image-136342\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-Web-BLE-App-Smartphone.png?w=369&amp;quality=100&amp;strip=all&amp;ssl=1 369w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2023\/09\/ESP32-Web-BLE-App-Smartphone.png?resize=151%2C300&amp;quality=100&amp;strip=all&amp;ssl=1 151w\" sizes=\"(max-width: 369px) 100vw, 369px\" \/><\/figure><\/div>\n\n\n<p>Web Bluetooth (also sometimes referred to as Web BLE) is a relatively recent technology that allows you to connect and control BLE-enabled devices, like the ESP32 or Raspberry Pi Pico, directly from your web browser using JavaScript. You can follow this guide to learn more: <a href=\"https:\/\/randomnerdtutorials.com\/esp32-web-bluetooth\/\" title=\"\">Getting Started with ESP32 Web Bluetooth (BLE)<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>In this tutorial, you learned the basics of using Bluetooth Low Energy with the ESP32 programmed with MicroPython. We&#8217;ve shown you an example of setting the ESP32 as a peripheral device that exposes a GATT structure. In an upcoming tutorial, we&#8217;ll show you how to set the ESP32 as a central device to interact with BLE peripherals.<\/p>\n\n\n\n<p>If you want to learn more about Bluetooth with the ESP32 programmed with Arduino IDE, you can follow the next tutorials instead:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-bluetooth-guide\/\">ESP32 with Bluetooth and Bluetooth Low Energy: The Ultimate Guide<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-web-bluetooth\/\">ESP32 Web Bluetooth (BLE): Getting Started Guide<\/a><\/li>\n<\/ul>\n\n\n\n<p>We hope you&#8217;ve found this tutorial useful. If you want to learn more about MicroPython, check out our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/micropython-programming-with-esp32-and-esp8266\/\" title=\"\">MicroPython Programming with ESP32 and ESP8266 eBook<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32-esp8266-micropython\/\" title=\"\">Free MicroPython Tutorials and Guides with the ESP32 and ESP8266<\/a><\/li>\n<\/ul>\n\n\n\n<p>Thanks for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial is a getting started guide to Bluetooth Low Energy (BLE) with the ESP32 programmed with MicroPython firmware. We&#8217;ll introduce you to BLE basic concepts and run some simple &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"MicroPython: ESP32 &#8211; Getting Started with Bluetooth Low Energy (BLE)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/micropython-esp32-bluetooth-low-energy-ble\/#more-150905\" aria-label=\"Read more about MicroPython: ESP32 &#8211; Getting Started with Bluetooth Low Energy (BLE)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":150987,"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":[310,309,264],"tags":[],"class_list":["post-150905","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-micropython","category-0-esp32-micropython","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2024\/03\/ESP32-Bluetooth-Low-Energy-MicroPython-Getting-Started.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\/150905","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\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=150905"}],"version-history":[{"count":11,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/150905\/revisions"}],"predecessor-version":[{"id":158926,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/150905\/revisions\/158926"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/150987"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=150905"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=150905"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=150905"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}