Controlling a LED Through Bluetooth® with Nano 33 IoT

Learn how to control the built-in LED on the Nano 33 IoT board over Bluetooth®, using an app on your phone.

In this tutorial we will use an Arduino Nano 33 IoT to turn on the built-in LED over Bluetooth, made possible by the NINA module embedded on the board.

Goals

The goals of this project are:

  • Learn what Bluetooth® Low Energy and Bluetooth® are.
  • Use the Arduino BLE library.
  • Learn how to create a new service.
  • Learn how to control a LED from an external device (smartphone).

Hardware & Software Needed

  • This project uses no external sensors or components.
  • In this tutorial we will use the Arduino Web Editor to program the board.

Bluetooth® Low Energy and Bluetooth®

Bluetooth® Low Energy, referred to as Bluetooth® Low Energy, separates itself from what is now known as “Bluetooth® Classic” by being optimized to use low power with low data rates. There are two different types of Bluetooth® devices: central or peripheral. A central Bluetooth® device is designed to read data from peripheral devices, while the peripheral devices are designed to do the opposite. Peripheral devices continuously post data for other devices to read, and it is precisely what we will be focusing on this tutorial.

Service & Characteristics

A service can be made up of different data measurements. For example, if we have a device that measures wind speed, temperature and humidity, we can set up a service that is called “Weather Data”. Let’s say the device also records battery levels and energy consumption, we can set up a service that is called “Energy information”. These services can then be subscribed to central Bluetooth® devices.

Characteristics are components of the service we mentioned above. For example, the temperature or battery level are both characteristics, which record data and update continuously.

Unique Universal Identifier (UUID)

When we read data from a service, it is important to know what type of data we are reading. For this, we use UUIDs, who basically give a name to the characteristics. For example, if we are recording temperature, we want to label that characteristic as temperature, and to do that, we have to find the UUID, which in this case is “2A6E”. When we are connecting to the device, this service will then appear as “temperature”. This is very useful when tracking multiple values.

If you want to read more about UUIDs, services, and characteristics, check the links below:

Creating the Program

1. Setting up

Let's start by opening the Arduino Web Editor, click on the Libraries tab and search for the ArduinoBLE library. Then in Examples > Peripheral, open the LED sketch and once it opens, you could rename it as desired.

Finding the library in the Web Editor.
Finding the library in the Web Editor.

2. Connecting the board

Now, connect the Arduino Nano 33 IoT to the computer and make sure that the Web Editor recognizes it, if so, the board and port should appear as shown in the image below. If they don't appear, follow the instructions to install the plugin that will allow the Editor to recognize your board.

Selecting the board.
Selecting the board.

3.Turning ON the LED

Now we will need to modify the code on the example, in order to control LED, based on the information we sent through the smartphone.

After including the

ArduinoBLE.h
library, in the
ledService()
function change the argument to
"180A"
which is translated to "Device Information". Then in the
switchCharacteristic()
function change the argument to
"2A57"
which is translated to "Digital Output".

1BLEService ledService("180A"); // BLE LED Service
2
3// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
4BLEByteCharacteristic switchCharacteristic("2A57", BLERead | BLEWrite);

In the

setup()
after initializing the serial communication we set the LED pin as
OUTPUT
.

1Serial.begin(9600);
2 while (!Serial);
3
4 // set built in LED pin to output mode
5 pinMode(LED_BUILTIN, OUTPUT);

Then, inside the

setup()
function, we need to go to the
BLE.setLocalName()
and change the name to
"Nano 33 IoT"
in order to identify the board we are using.

1// set advertised local name and service UUID:
2 BLE.setLocalName("Nano 33 IoT");
3 BLE.setAdvertisedService(ledService);

Now, in the

loop()
, we replace the second
if()
function inside the
while
loop with a
switch case
function, where each case will control the LED in a different manner:

  • The default case will keep the LED OFF
  • Case 01 will turn the LED ON
  • Case 02 will blink the LED each 500 ms
  • Case 03 will blink the LED each second
1// while the central is still connected to peripheral:
2while (central.connected()) {
3 // if the remote device wrote to the characteristic,
4 // use the value to control the LED:
5 if (switchCharacteristic.written()) {
6 switch (switchCharacteristic.value()) { // any value other than 0
7 case 01:
8 Serial.println("LED on");
9 digitalWrite(LED_BUILTIN, HIGH); // will turn the LED on
10 break;
11 case 02:
12 Serial.println("LED fast blink");
13 digitalWrite(LED_BUILTIN, HIGH); // will turn the LED on
14 delay(500);
15 digitalWrite(LED_BUILTIN, LOW); // will turn the LED off
16 delay(500);
17 digitalWrite(LED_BUILTIN, HIGH); // will turn the LED on
18 delay(500);
19 digitalWrite(LED_BUILTIN, LOW); // will turn the LED off
20 break;
21 case 03:
22 Serial.println("LED slow blink");
23 digitalWrite(LED_BUILTIN, HIGH); // will turn the LED on
24 delay(1000);
25 digitalWrite(LED_BUILTIN, LOW); // will turn the LED off
26 delay(1000);
27 digitalWrite(LED_BUILTIN, HIGH); // will turn the LED on
28 delay(1000);
29 digitalWrite(LED_BUILTIN, LOW); // will turn the LED off
30 break;
31 default:
32 Serial.println(F("LED off"));
33 digitalWrite(LED_BUILTIN, LOW); // will turn the LED off
34 break;
35 }
36 }
37}

Lastly, after the last

Serial.println()
function we use the
digitalWrite()
to turn off the LED once the phone is disconnected from the board.

1// when the central disconnects, print it out:
2 Serial.print(F("Disconnected from central: "));
3 Serial.println(central.address());
4 digitalWrite(LED_BUILTIN, LOW); // will turn the LED off
5 }
6}

4. Complete code

If you choose to skip the code building section, the complete code can be found below:

1#include <ArduinoBLE.h>
2
3long previousMillis = 0;
4int interval = 0;
5int ledState = LOW;
6
7BLEService ledService("180A"); // BLE LED Service
8
9// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
10BLEByteCharacteristic switchCharacteristic("2A57", BLERead | BLEWrite);
11
12void setup() {
13 Serial.begin(9600);
14 while (!Serial);
15
16 // set built in LED pin to output mode
17 pinMode(LED_BUILTIN, OUTPUT);
18
19 // begin initialization
20 if (!BLE.begin()) {
21 Serial.println("starting Bluetooth® Low Energy failed!");
22
23 while (1);
24 }
25
26 // set advertised local name and service UUID:
27 BLE.setLocalName("Nano 33 IoT");
28 BLE.setAdvertisedService(ledService);
29
30 // add the characteristic to the service
31 ledService.addCharacteristic(switchCharacteristic);
32
33 // add service
34 BLE.addService(ledService);
35
36 // set the initial value for the characteristic:
37 switchCharacteristic.writeValue(0);
38
39 // start advertising
40 BLE.advertise();
41
42 Serial.println("BLE LED Peripheral");
43}
44
45void loop() {
46 // listen for BLE peripherals to connect:
47 BLEDevice central = BLE.central();
48
49 // if a central is connected to peripheral:
50 if (central) {
51 Serial.print("Connected to central: ");
52 // print the central's MAC address:
53 Serial.println(central.address());
54
55 // while the central is still connected to peripheral:
56 while (central.connected()) {
57 // if the remote device wrote to the characteristic,
58 // use the value to control the LED:
59 if (switchCharacteristic.written()) {
60 switch (switchCharacteristic.value()) { // any value other than 0
61 case 01:
62 Serial.println("LED on");
63 digitalWrite(LED_BUILTIN, HIGH); // will turn the LED on
64 break;
65 case 02:
66 Serial.println("LED fast blink");
67 digitalWrite(LED_BUILTIN, HIGH); // will turn the LED on
68 delay(500);
69 digitalWrite(LED_BUILTIN, LOW); // will turn the LED off
70 delay(500);
71 digitalWrite(LED_BUILTIN, HIGH); // will turn the LED on
72 delay(500);
73 digitalWrite(LED_BUILTIN, LOW); // will turn the LED off
74 break;
75 case 03:
76 Serial.println("LED slow blink");
77 digitalWrite(LED_BUILTIN, HIGH); // will turn the LED on
78 delay(1000);
79 digitalWrite(LED_BUILTIN, LOW); // will turn the LED off
80 delay(1000);
81 digitalWrite(LED_BUILTIN, HIGH); // will turn the LED on
82 delay(1000);
83 digitalWrite(LED_BUILTIN, LOW); // will turn the LED off
84 break;
85 default:
86 Serial.println(F("LED off"));
87 digitalWrite(LED_BUILTIN, LOW); // will turn the LED off
88 break;
89 }
90 }
91 }
92
93 // when the central disconnects, print it out:
94 Serial.print(F("Disconnected from central: "));
95 Serial.println(central.address());
96 digitalWrite(LED_BUILTIN, LOW); // will turn the LED off
97 }
98}

Testing It Out

Once we are finished with the coding, we can upload the sketch to the board. When it has successfully uploaded, open the Serial Monitor. In the Serial Monitor, the text "BLE LED Peripheral" will appear as seen in the image below.

Serial Monitor output.
Serial Monitor output.

We can now discover our Nano 33 IoT board in the list of available Bluetooth® devices. To access the service and characteristic we recommend using the LightBlue application. Follow this link for iPhones or this link for Android phones.

Once we have the application open, follow the image below for instructions:

Accessing through a Bluetooth® phone app.
Accessing through a Bluetooth® phone app.

To control the LED, we simply need to write 1,2 or 3 in the "WRITTEN VALUES" field to turn on the LED, make the LED blink fast or slow and any other value to turn them off. This is within the "Digital Output" characteristic, which is located under "Device Information".

Troubleshoot

Sometimes errors occur, if the code is not working there are some common issues we can troubleshoot:

  • Missing a bracket or a semicolon.
  • Arduino board connected to the wrong port.
  • We haven't opened the Serial Monitor to initialize the program.
  • The device you are using to connect has its Bluetooth® turned off.

Conclusion

In this tutorial we have created a basic Bluetooth® peripheral device. We learned how to create services and characteristics, and how to use UUIDs from the official Bluetooth® documentation. Lastly, we control the LED based on the values sent from the smartphone.

Now that you have learned a little bit how to use the ArduinoBLE library, you can try out some of our other tutorials for the Nano 33 IoT. You can also check out the ArduinoBLE library for more examples and inspiration for creating Bluetooth® projects!