ESP32

Controlling an LED using ESP32 BLE (Bluetooth Low Energy)

Introduction

In the rapidly evolving landscape of the Internet of Things (IoT) and embedded systems, the ESP32 microcontroller has emerged as a cornerstone technology. Renowned for its versatility and advanced features, it finds extensive use in a myriad of applications. Among its many capabilities, one that stands out is Bluetooth Low Energy (BLE) connectivity. BLE represents a paradigm shift in wireless communication, emphasizing energy efficiency and ease of use. This article delves into a practical application of this technology – controlling an LED using ESP32 BLE.

This project exemplifies the fusion of hardware interaction and wireless communication, two pillars of modern IoT solutions. On one hand, the ESP32 offers robust processing capabilities and diverse functionalities, including Wi-Fi and BLE. On the other, Bluetooth Low Energy brings to the table its low power consumption and wide acceptance in consumer electronics, making it an ideal choice for IoT applications.

Controlling an LED may seem simple, yet it encapsulates the essence of IoT, interacting with physical devices through wireless commands. This project serves not just as a technical exercise but as a window into the possibilities unlocked by combining ESP32 with BLE. It’s a stepping stone for enthusiasts and professionals alike to explore the vast potential of IoT and smart device integration.




Understanding ESP32 and BLE

The ESP32 is a sophisticated, yet cost-effective system on a chip (SoC) that has revolutionized the way we approach embedded systems, particularly in the Internet of Things (IoT) domain. At its core, the ESP32 is designed for efficiency and versatility, featuring a dual-core processor that can run at up to 240 MHz, with substantial memory allocation, including up to 520 KB of SRAM and up to 16 MB of flash memory. This makes it robust enough to handle complex tasks yet efficient for battery-operated devices.

One of the most notable features of the ESP32 is its wireless communication capability. It natively supports Wi-Fi and Bluetooth, including Bluetooth Low Energy (BLE), a technology designed for short-range communication. Bluetooth Low Energy is a power-conserving variant of Bluetooth, ideal for scenarios where energy efficiency is paramount. Unlike traditional Bluetooth, which is optimized for continuous, high-data-rate streaming, BLE is tailored for intermittent transmissions of small data packets.



The integration of BLE in ESP32 allows it to interact seamlessly with a vast array of devices, from smartphones to other IoT devices. This interaction is vital in scenarios where constant data transmission is unnecessary and power conservation is crucial. Bluetooth Low Energy achieves this efficiency by staying in sleep mode until a connection is initiated, significantly reducing power consumption compared to classic Bluetooth.

BLE’s architecture is structured around two key concepts: the Generic Attribute Profile (GATT) and the Generic Access Profile (GAP). GATT deals with how data is structured and communicated between devices, while GAP manages device discovery and connectivity. In the context of ESP32, this means it can serve as both a publisher (server) and a subscriber (client) of data, depending on the application’s requirements.

In summary, ESP32’s incorporation of BLE not only enhances its utility in the IoT space but also makes it a preferred choice for developers looking to create energy-efficient, wireless embedded systems. Whether it’s a simple project like controlling an LED or more complex IoT applications, ESP32’s BLE functionality opens up a world of possibilities in the realm of wireless communication.



BLE vs Classic Bluetooth

Aspect Bluetooth Low Energy (BLE) Classic Bluetooth
Primary Use Designed for short, intermittent transmissions of small data packets. Suited for continuous wireless communication with higher data throughput.
Power Consumption Significantly lower power consumption, ideal for battery-operated devices. Higher power consumption due to continuous connectivity and higher data rates.
Data Transfer Rate Lower data transfer rates (up to 2 Mbps in the latest versions). Higher data transfer rates (up to 3 Mbps in Bluetooth 2.0+EDR).
Connectivity Model Asynchronous connection-less (ACL) model, suitable for periodic communication. Synchronous connection-oriented model for continuous data streaming.
Latency Lower latency (a few milliseconds), beneficial for quick, periodic data transfers. Higher latency compared to BLE, but suitable for its use-cases like audio streaming.
Complexity & Cost Simpler modulation scheme leading to lower complexity and cost. More complex modulation scheme, generally more expensive to implement.
Range Comparable range to Classic Bluetooth, typically up to 100 meters. Similar range, up to 100 meters under optimal conditions.
Application Examples Ideal for IoT devices, health monitors, beacons, and small sensors. Best suited for audio streaming, file transfers, and hands-free calling.
Version Introduced Introduced with Bluetooth 4.0. Part of the original Bluetooth specification.
Use Case Frequency Suitable for applications requiring data updates at regular intervals. Better for applications requiring continuous, uninterrupted data flow.



Setting Up the Development Environment

Software Setup

Arduino IDE: The Arduino Integrated Development Environment (IDE) is widely used for ESP32 development due to its simplicity and extensive support community. Download and install it from the official Arduino website.

ESP32 Board Package in Arduino IDE: Add the ESP32 board to the Arduino IDE. This is done by including the following ESP32 board manager URL in the IDE’s preferences

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

ESP32 BLE

Then install the ESP32 package using the Board Manager in the Arduino IDE. To do this, click on ‘Tools’, then hover over ‘Board’ and from the submenu, select ‘Boards Manager…

ESP32 BLE

In the Board Manager window, type ‘esp32’ in the search bar. You will see the ESP32 package listed. Simply click to install it. In my case, it is already installed.

ESP32 BLE




Installing Necessary Libraries

BLE Library for ESP32  is essential for BLE projects on the ESP32 using Arduino IDE. It can be installed via the Library Manager in the Arduino IDE.

To install the ESP32 BLE library, first click on ‘Sketch’ in the Arduino IDE. Then, select ‘Include Library’ from the dropdown menu, and finally, choose ‘Manage Libraries…

ESP32 BLE

In the Library Manager window, type ‘esp32 ble arduino’ in the search bar. You will see ‘ESP32 BLE Arduino’ by Neil Kolban. Simply select it and click on Install.

ESP32 BLE

As you can the esp32 ble arduino library is successfully installed

ESP32 BLE



IDE Configuration

In the Arduino IDE, to select the appropriate ESP32 board, first click on ‘Tools’, then hover over ‘Board’, and from the submenu, select ‘ESP32 Dev Module’.

ESP32 BLE

Now select the correct port

ESP32 BLE

Now our Development Environment is ready to use for making esp32 BLE(Bluetooth Low Energy) projects.



Controlling an LED using ESP32 via BLE Project:

Components Required

ESP32 Development Board: The core of the project, capable of BLE communication.

LED: A standard light-emitting diode, used as the output device.

Resistor: A 330-ohm resistor to limit the current to the LED and prevent it from burning out.

Breadboard: A breadboard for making the connections without soldering.

Jumper Wires: Wires to connect the components together on the breadboard.



Controlling leds with ESP32 BLE Circuit diagram:

ESP32 BLE

circuit diagram featuring an ESP32 microcontroller used to control LEDs via BLE (Bluetooth Low Energy). The ESP32 is a popular microcontroller for IoT projects because of its dual-core processor and built-in Wi-Fi and BLE capabilities.

In this circuit, there are four LEDs, and each one is connected to a specific GPIO (General Purpose Input/Output) pin on the ESP32. The GPIO pins used are 27, 26, 25, and 33. Each LED is connected in series with a resistor to its corresponding GPIO pin. The resistors are there to limit the current flowing through the LEDs to prevent them from burning out. The other end of each LED (the cathode, marked typically by a shorter leg) is connected to the common ground (GND) of the ESP32.

The GPIO pins serve as digital outputs that can be controlled by software running on the ESP32. When a GPIO pin is set to a high state, it outputs the operating voltage (typically 3.3V for the ESP32), allowing current to flow through the resistor, then the LED, causing it to light up. When the pin is set to a low state, no current flows, and the LED is off.

Using BLE, the ESP32 can communicate with other BLE-enabled devices, like smartphones. A user can send commands from a smartphone app to the ESP32 to control the state of the GPIO pins. This allows for wireless control of the LEDs, which can be used for indicators, notifications, or simply as a part of a larger system requiring visual output.

The circuit is powered through the ESP32, which is likely connected to a power source via USB, as indicated by the USB port on the diagram. The colors in the diagram are typically used to differentiate between different connections and to provide an easy way to trace the circuit. Black is usually for ground connections, and other colors represent connections to the GPIO pins with their respective resistors and LEDs.

In summary, this circuit diagram describes a basic LED control setup using an ESP32 microcontroller, where the LEDs are individually controlled by GPIO pins and can be remotely operated via BLE.




Android Studio Application for esp32 BLE

ESP32 BLE

I designed This Android application,  in Android Studio, serves as a specialized interface for wirelessly controlling LEDs through the ESP32 BLE(Bluetooth Low Energy ) technology. The intuitive layout features toggle buttons that facilitate the on and off operations of the LEDs, signifying a seamless integration of user-friendly controls with the advanced capabilities of BLE communication. The application is crafted to cater to those who are keen on home automation, hobbyists in the realm of electronics, and educators in the field of technology who wish to demonstrate the practical interactions between digital interfaces and physical hardware.

Download ESP32 BLE Application:

for project testing download the Android application 



Controlling an LED using ESP32 BLE Programming:



Code Explanation:

#include <BLEDevice.h>: This header file is included to use the BLEDevice class, which encapsulates the overall BLE device functionality. It’s responsible for initializing the BLE stack on the ESP32, setting up the device with a name, and managing the state of the BLE device (e.g., whether it’s discoverable, connectable, etc.).

#include <BLEServer.h>: This includes the definitions required to create and manage a BLE server on the ESP32. A BLE server is a device that offers data to other devices. When you create a BLE server, you’re allowing other BLE devices to connect and interact with your ESP32.

#include <BLEUtils.h>: This file includes utility functions and definitions that are helpful when working with BLE on the ESP32. It may contain tools for debugging, such as printing out BLE addresses, status codes, and other useful information that can help with development.

#include <BLE2902.h>: This includes the definition of the BLE2902 descriptor, which is commonly used for client configuration. This descriptor is attached to a characteristic to allow a BLE client to subscribe to notifications or indications of the characteristic’s value changes.

#include <BLEClient.h>: This provides the necessary classes and functions to create a BLE client. A BLE client is a device that scans for, connects to, and interacts with BLE servers. With this library, the ESP32 can connect to other BLE devices that offer services, read and write characteristics, and subscribe to notifications.



BLEClient* pClient; creates a pointer to a BLEClient object, which would be used if the ESP32 is to act as a client that connects to other BLE servers. However, in the context of the rest of your code, this pointer is not utilized since the ESP32 is configured as a server.

BLEServer* pServer; declares a pointer to a BLEServer object. This will be used to instantiate and manage a BLE(Bluetooth Low Energy) server on the ESP32, allowing other BLE clients (like a smartphone app) to connect and communicate with it.

BLECharacteristic* pCharacteristic; declares a pointer to a BLECharacteristic object. Characteristics in BLE are data points through which a server and a client communicate. This particular characteristic will likely be used to send data from the ESP32 to a connected client.




BLECharacteristic* pReceiveCharacteristic; also declares a pointer to a BLECharacteristic, which suggests that there may be plans to use a separate characteristic to receive data from a client. However, this characteristic is not set up or used in the rest of the code you’ve provided.

bool deviceConnected = false; is a boolean variable that tracks whether a BLE client is currently connected to the server. It starts as false and will be set to true when a connection is established.

bool oldDeviceConnected = false; is a boolean variable that helps track changes in the connection status. It’s used in the loop to detect when a device has disconnected.

const int ledPin1 = 27; to const int ledPin4 = 33; declare constants representing the GPIO pin numbers to which four LEDs are connected. The const keyword indicates that the values will not change after they are set.

bool led1State = false; to bool led4State = false; declare boolean variables for each LED’s state, starting as false, which corresponds to the LEDs being off. These will be toggled to true or false to turn the corresponding LED on or off based on BLE commands received from the client.

This setup is typical in IoT applications where the ESP32 serves as a bridge between a user interface (like a mobile app) and physical hardware (like LEDs, motors, sensors, etc.). The ESP32 waits for commands from the app and controls hardware accordingly, while also reporting the hardware’s status back to the app.



The MyCallbacks class is a custom class that inherits from the BLECharacteristicCallbacks class provided by the BLE library for the ESP32. This custom class overrides the onWrite method to define a specific behavior when a BLE client writes data to the characteristic associated with this callback.

Here’s a breakdown of the onWrite method inside MyCallbacks:

  • When the onWrite method is triggered, it first retrieves the value written to the characteristic using pCharacteristic->getValue(), which returns a std::string.
  • It then checks if the received string value is not empty using value.length() > 0. If there is data, it proceeds to compare the value to predefined commands (like “199”, “222”, etc.).
  • Depending on the command received, the state variables for the LEDs (led1State, led2State, led3State, led4State) are updated to true or false, representing the “on” and “off” states of the LEDs, respectively.
  • For each command, there is an accompanying Serial.println call that outputs a message to the serial monitor indicating which LED is turned on or off. This is helpful for debugging and monitoring the system’s behavior during development.
  • Lastly, the digitalWrite function is called with the corresponding LED pin number and state (HIGH for “on”, LOW for “off”). This directly controls the GPIO pins on the ESP32, turning the connected LEDs on or off.

For example:

  • If the BLE client sends “199”, the ESP32 receives this value and sets led1State to true, prints “LED 1 is ON” to the serial monitor, and sets the GPIO pin connected to LED 1 to HIGH, turning the LED on.
  • If it receives “222”, it turns LED 1 off, and similar actions are taken for the other LEDs based on their corresponding values.



The MyServerCallbacks class is a custom class that inherits from BLEServerCallbacks, which is part of the ESP32 BLE Arduino library. This class is designed to handle events related to the server’s BLE connection status. By inheriting from BLEServerCallbacks, MyServerCallbacks can override two key event handler methods: onConnect and onDisconnect.

Here’s what each method does:

  • void onConnect(BLEServer* pServer): This method is called whenever a BLE client establishes a connection with the ESP32 BLE server. Inside this method, the global variable deviceConnected is set to true to indicate an active device connection. Immediately after a connection is established, the BLEDevice::startAdvertising() function is called to restart advertising. This allows the ESP32 to be discoverable by other clients even while connected to one, which is useful for devices that support multiple connections.
  • void onDisconnect(BLEServer* pServer): This method is called when the connected BLE client disconnects from the ESP32 BLE server. The deviceConnected variable is set to false, reflecting that the server is no longer connected to a client.

The use of these callbacks within the BLE server setup is crucial for managing the state of the server and for taking appropriate actions when clients connect or disconnect. For instance, knowing when a device is connected can help manage power consumption by advertising only when necessary or can be used to trigger other actions that should only occur during an active connection. Similarly, detecting disconnection can be essential for cleaning up the connection state and preparing the server for future connections.



The setup() function is a fundamental part of an Arduino sketch, which runs once when the program starts. It’s used to initialize variables, pin modes, start using libraries, etc. In the context of the given code, the setup() function is configuring the ESP32 to work as a BLE server and initializing the pins connected to LEDs. Here’s a breakdown of what each section of the code does:

  • begin(9600); initializes serial communication at 9600 bits per second. This allows you to send messages from the ESP32 to the computer for debugging purposes.
  • println(“Connect to MyESP32”); sends a message to the serial monitor, which can be useful for debugging and confirming that the code has started running.
  • BLEDevice::init(“MyESP32”); initializes the BLE stack and sets the device name as “MyESP32”, which will be visible to other BLE devices during scanning.
  • pServer = BLEDevice::createServer(); creates a BLE server instance on the ESP32 and assigns it to the global pointer pServer.
  • pServer->setCallbacks(new MyServerCallbacks()); assigns the custom server callback class MyServerCallbacks to the server, which will handle connect and disconnect events.
  • pinMode(ledPin1, OUTPUT); to pinMode(ledPin4, OUTPUT); sets the GPIO pins connected to the LEDs as outputs. This enables the ESP32 to control the LEDs by setting these pins HIGH or LOW.
  • BLEService *pService = pServer->createService(…); creates a new BLE service with a specified UUID (Universally Unique Identifier), which is a standard way to identify BLE services.
  • pCharacteristic = pService->createCharacteristic(…); creates a characteristic associated with the service, which clients can read or write. The characteristic is given properties to allow both reading and writing.
  • pCharacteristic->addDescriptor(new BLE2902()); adds a descriptor to the characteristic. The BLE2902 descriptor is typically used to enable notifications or indications, allowing clients to subscribe to updates of the characteristic’s value.
  • pCharacteristic->setCallbacks(new MyCallbacks()); sets the custom callbacks for when the characteristic is written to by a BLE client.
  • pService->start(); starts the BLE service, making it active and discoverable to clients.
  • BLEAdvertising *pAdvertising = pServer->getAdvertising(); pAdvertising->start(); starts advertising the BLE service, making it visible to BLE clients that are scanning for devices.
  • pClient = BLEDevice::createClient(); creates a BLE client instance. This line seems out of context for a BLE server setup, and it’s not used elsewhere in the provided code snippets. It would typically be used if the ESP32 was also meant to connect to other BLE devices as a client.

The setup() function establishes the necessary BLE environment for the ESP32 to communicate with BLE clients and control the connected LEDs based on the received BLE commands.




In the loop() function of your ESP32 program, continuous monitoring and handling of BLE connections and the state of the LEDs are performed. Initially, the function checks if a BLE device is connected. When a device is indeed connected, it concatenates the states of the four LEDs into a single string, separated by commas. This string is then set as the value of the BLE characteristic and a notification is sent to the connected BLE client, ensuring that the client is updated with the latest state of the LEDs. This process repeats every second, as indicated by the delay(1000) statement, to provide regular updates.

In scenarios where a device disconnects, the function detects this change in connection status by comparing deviceConnected and oldDeviceConnected. If a device has just disconnected (deviceConnected is false and oldDeviceConnected is true), the ESP32 waits for a short duration to ensure the BLE stack is ready, then restarts advertising itself to allow other clients to connect. A message indicating that advertising has started is printed to the serial monitor for debugging purposes.



Conversely, when a new connection is established (detected by deviceConnected being true and oldDeviceConnected being false), the code currently does not perform any specific action, but this condition can be used to execute tasks right after a new connection is made.

Overall, this loop efficiently manages the BLE connectivity, ensuring the ESP32 is always ready for new connections while continuously updating the connected client about the LED states, making it a robust system for wireless control and monitoring.

Practical demonstration:

 First, power up your ESP32 module using a USB cable. In my case, I am using an ESP32 development board. Once you have powered up the ESP32 module, open the Bluetooth settings on your phone and pair it with the device

ESP32 BLE



Then, open the application that is designed for the ESP32 BLE (Bluetooth Low Energy).

ESP32 BLE

When you open the Android application, it will automatically connect to the ESP32 BLE (Bluetooth Low Energy) and display a toast message saying ‘Device Connected’. After this, it will be ready to control the LEDs.

ESP32 BLE



Finally, test your project.

ESP32 BLE

ESP32 BLE

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button