Controlling LEDs with the Web Bluetooth API and Arduino

  • Tutorial

- Kettles, scales, toys, light bulbs, coffee machines ... Bluetooth modules are embedded in these and other devices.
- What for?
- To allow the user to manage their devices through the application. For example, control the lighting in the room.
- Oh, is it possible to collect some of your simple device and manage it directly through the browser?
- Yes! And this article is just about that.

Some theory

Here I will give a few basic terms that we need to translate the task (we will talk about it a little later) into life.


A wireless radio standard linking various types of devices over short distances. To control the hardware through the Web Bluetooth API, we need Bluetooth v4.0.


The Generic Attributes is a constantly broadcast bluetooth device tree.


Inside the bluetooth device there are services. A service in itself is a collection of characteristics and links to other services. Each service has its own UID and name. Often will come across “Unknown services”. This is due to the fact that the number of devices and options for their use is large.


Within each service, there are features that you can write to, read, and subscribe to. The characteristic also has its own UID.


As a task, I chose a site implementation that can:

  • Light LEDs in different colors and extinguish them.
  • Make the LEDs shine with different colors.

And, as can be understood from the statement of the problem, it is necessary to learn how to connect and disconnect from a bluetooth device.


To complete the task, I selected the following list of required:

  • Arduino.
  • Bluetooth module v4.0 (HM-10 in my case).
  • Two tricolor LEDs.
  • Bread board.
  • Connecting wires
  • Resistors.

This list is not strict to implement. I'm sure you can replace the Arduino with something else and choose another bluetooth module. But the article will look at the interaction with these components.

How it should work

In short, the essence is this: we connect to the bluetooth module and transmit some code (from 1 to 4 inclusive). If the code is valid, then one of the three colors will light up, or the LEDs will start blinking in all possible colors (red, green, blue) for some time.


First you need to assemble a working scheme and load the Arduino-sketch. Below I give the scheme (Fig. 1) and the sketch code that I got.

Fig. 1 (Scheme for assembly)

#include<SoftwareSerial.h>int green_pin = 2;
int red_pin = 3;
int blue_pin = 4;
int BLINK_STEPS = 3;
int BLINK_DELAY = 100;
SoftwareSerial mySerial(7, 8); // RX, TXvoidsetup(){
  pinMode(green_pin, OUTPUT);
  pinMode(red_pin, OUTPUT);
  pinMode(blue_pin, OUTPUT);
int code;
  if (mySerial.available()) {
    code =;
    if (code > 0 && code < 5) {
     analogWrite(code, 200);
    if (code == 1) {
  analogWrite(green_pin, 0);
  analogWrite(red_pin, 0);
  analogWrite(blue_pin, 0);
  int steps = 0;
  while(steps <= BLINK_STEPS) {
   analogWrite(green_pin, 200);
   analogWrite(green_pin, 0);
   analogWrite(red_pin, 200);
   analogWrite(red_pin, 0);
   analogWrite(blue_pin, 200);
   analogWrite(blue_pin, 0);
   steps += 1;

Last cooking

So, we loaded the sketch, connected the circuit to the power supply. What's next? To work with the Web Bluetooth API, we need to know the name of our device, and which service we want to access. You can use the “nRF Connect” application for this.

We turn on the application and see a list of Bluetooth devices near us (Fig. 2).

Fig. 2 (List of devices that found the application)

The device with the name “CC41-A” interested me and for good reason.

After connecting to the device, the list of its services becomes available to us (Fig. 3). It is unlikely that we will find something interesting in “Device information”, so feel free to click on the “Unknown service”.

Fig. 3 (List of device services)

In the screenshot below (Fig. 4) you can see the most important thing for us: writing to the testimonial and reading it.

When I solved the problem described above, I tried to send the value “2” to the characteristic. As a result, my pair of LEDs started to turn green. Almost success. Now we need to do the same, but not through a mobile application, but through a browser.

Fig. 4 (Unknown characteristic)

Here is a list of data that we received from the application to continue the task:

  1. The name of the device.
  2. UID of the service.
  3. UID characteristics.

Web implementation

Before you start writing JavaScript code, there are a few points to make:

  1. The API is experimental.
  2. Works in Chrome and Samsung Internet.
  3. Connection via HTTPS is required.
  4. I will not give examples of HTML and CSS-code, because within this article there is nothing interesting in them, but I will leave a link to the repository and the site at the end of the article.


Working with the Web Bluetooth API is built on Promise. Below I will give phased code examples. The full source code will be found in the repository, to which the link will be left.

First we need to connect to the device. We request devices and in the filter we transfer the device name and UID of the service with which we will work. If you do not specify the service in advance, then you will not be able to interact with it in the future.

        { name: MY_BLUETOOTH_NAME },
        { services: [SEND_SERVICE] },

After we click on the “Connect” button, a window will open (fig. 5) in which we need to select a device and click on the connect button.

Fig. 5 (Window with a device available for connection)

When connected, a Promise is returned, containing a “device” to which you can connect. OK, let's write it into a variable and create a connection.

.then(device => {
      myDevice = device;
      return device.gatt.connect();

After that, we are returned a Promise containing “server”. Then we request the “service” from the “server”, passing the UID of the service there (which we watched through the application). Then the Promise containing the “service” is returned to us, from which we request the “characteristic”, passing its UID (which we also watched through the application).

.then(server => server.getPrimaryService(SEND_SERVICE))
.then(service => service.getCharacteristic(SEND_SERVICE_CHARACTERISTIC))

And only now we can begin to do something. For example, I memorize a characteristic in a variable and hang handlers for clicks on buttons. In their data attributes, they contain the code that will be written to the characteristic at the click.

Button handlers contain the following code:

const code = Number(;
  if (code === 1) {
    .then(currentCode => {
      const convertedCode = currentCode.getUint8(0);
        Uint8Array.of(convertedCode === code ? 0 : code)

It is necessary to transfer the uint8 array to the characteristic, therefore it is necessary to use Uint8Array to convert the code that will be passed to it.

As planned, code 1 causes the LEDs to flash in three colors and then go out. But how to turn off the LED if code 3 was passed to it and the LED is still on? Or include another color?

I read the value lying in the characteristic, transform it with getUint8 and, if the code matches, send any non-valid value (for example, 0). If the value is valid, then I convert it into unit8 array and write it to the characteristic.

For the final solution of the task, you only need to learn how to disconnect from the device. We already have an eventListener on the “Disconnect” button, in which a Bluetooth device disconnects, eventListeners are removed, the control buttons are hidden, and undefined is written to the variables.

toggleLigthCharacteristic = undefined;
myDevice = undefined;


We have created a simple web page with which you can connect to a bluetooth device and manage it. As you can see, it's pretty simple. And the devices that you can assemble and manage in this way are limited only by your imagination!

useful links

Also popular now: