MKR WiFi 1010 Bluetooth® Low Energy

Learn how to access your board from your phone via Bluetooth®.

Enabling Bluetooth® Low Energy

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 today.

This tutorial is a great starting point for any maker interested in creating their own Bluetooth® projects.

Hardware & Software Needed

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 level 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:


Circuit

Follow the wiring diagram below to connect the LED to the MKR WiFi 1010 board.

Board circuit with breadboard, LED and resistor.
Board circuit with breadboard, LED and resistor.

Schematic

Follow the wiring diagram below to connect the LED to the MKR WiFi 1010 board.

Schematic of the board, LED and resistor circuit.
Schematic of the board, LED and resistor circuit.

Creating the Program

The goal with this tutorial is to be able to access our MKR WiFi 1010 board via Bluetooth®, and control an LED onboard it. We will also retrieve the latest readings from an analog pin. We will then use UUIDs from the official Bluetooth® page, that are compliant with GATT (Generic Attribute Profile). This way, when we access our device later, the service and characteristics can be recognized!

We will go through the following steps in order to create our sketch:

  • Create a new service.
  • Create an LED characteristic.
  • Create an analog pin characteristic.
  • Set the name for our device.
  • Start advertising the device.
  • Create a conditional that works only if an external device is connected (smartphone).
  • Create a conditional that turns on an LED over Bluetooth®.
  • Read an analog pin over Bluetooth®.

1. First, let's make sure we have the drivers installed. If we are using the Web Editor, we do not need to install anything. If we are using an offline editor, we need to install it manually. This can be done by navigating to Tools > Board > Board Manager.... Here we need to look for the Arduino SAMD boards (32-bits Arm® Cortex®-M0+) and install it.

2. Now, we need to install the library needed. If we are using the Web Editor, there is no need to install anything. If we are using an offline editor, simply go to Tools > Manage libraries.., and search for ArduinoBLE and install it.

Library Manager Search for ArduinoBLE.
Library Manager Search for ArduinoBLE.

With the dependencies installed, we will now move on to the programming part.


Code Explanation

NOTE: This section is optional, you can find the complete code further down on this tutorial.

First, we need to include the ArduinoBLE library, and create a new service. We will name the service "180A" which is translated to "Device Information". We will then create two characteristics, one for the LED, and one for the analog pin. The name "2A57" is translated to "Digital Output" and "2A58 is translated to "Analog".

1#include <ArduinoBLE.h>
2BLEService newService("180A"); // creating the service
3
4BLEUnsignedCharCharacteristic randomReading("2A58", BLERead | BLENotify); // creating the Analog Value characteristic
5BLEByteCharacteristic switchChar("2A57", BLERead | BLEWrite); // creating the LED characteristic
6
7const int ledPin = 2;
8long previousMillis = 0;

In the

setup()
, we will start by initializing serial communication, define both the in-built LED and the LED we connected to pin 2, and initialize the ArduinoBLE library.

We then set the name for our device, using the command

BLE.setLocalName("MKR WiFi 1010");
, then add the characteristics we defined previously to the service created earlier,
newService
. After they have been added, we will also add the service, using the command
BLE.addService(newService);
.

The final steps we will take is to set the starting value of 0 for both characteristics. This is mostly important for the LED, since 0 means it will be OFF from the start.

The setup is finished by using the command

BLE.advertise();
, which makes it visible for other devices to connect to.

1void setup() {
2 Serial.begin(9600); // initialize serial communication
3 while (!Serial); //starts the program if we open the serial monitor.
4
5 pinMode(LED_BUILTIN, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected
6 pinMode(ledPin, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected
7
8 //initialize ArduinoBLE library
9 if (!BLE.begin()) {
10 Serial.println("starting Bluetooth® Low Energy failed!");
11 while (1);
12 }
13
14 BLE.setLocalName("MKR WiFi 1010"); //Setting a name that will appear when scanning for Bluetooth® devices
15 BLE.setAdvertisedService(newService);
16
17 newService.addCharacteristic(switchChar); //add characteristics to a service
18 newService.addCharacteristic(randomReading);
19
20 BLE.addService(newService); // adding the service
21
22 switchChar.writeValue(0); //set initial value for characteristics
23 randomReading.writeValue(0);
24
25 BLE.advertise(); //start advertising the service
26 Serial.println(" Bluetooth® device active, waiting for connections...");
27}

In the

loop()
we will use the command
BLEDevice central = BLE.central();
to start waiting for a connection. When a device connects, the address of the connecting device (the central) will be printed in the Serial Monitor, and the in-built LED will turn ON.

After this, we use a

while
loop that only runs as long as a device is connected. Here, we do a reading of Analog pin 1, which will record random values between 0 and 1023. We then use a conditional to check if there's an incoming value: if any value other than 0 comes in, the LED turns ON, but if 0 comes in, it turns it OFF.

If our device (smartphone) disconnects, we exit the

while
loop. Once it exits, it turns off the in-built LED and the message "Disconnected from central" prints in the Serial Monitor.

1void loop() {
2
3 BLEDevice central = BLE.central(); // wait for a Bluetooth® Low Energy central
4
5 if (central) { // if a central is connected to the peripheral
6 Serial.print("Connected to central: ");
7
8 Serial.println(central.address()); // print the central's BT address
9
10 digitalWrite(LED_BUILTIN, HIGH); // turn on the LED to indicate the connection
11
12
13
14 while (central.connected()) { // while the central is connected:
15 long currentMillis = millis();
16
17 if (currentMillis - previousMillis >= 200) {
18 previousMillis = currentMillis;
19
20 int randomValue = analogRead(A1);
21 randomReading.writeValue(randomValue);
22
23 if (switchChar.written()) {
24 if (switchChar.value()) { // any value other than 0
25 Serial.println("LED on");
26 digitalWrite(ledPin, HIGH); // will turn the LED on
27 } else { // a 0 value
28 Serial.println(F("LED off"));
29 digitalWrite(ledPin, LOW); // will turn the LED off
30 }
31 }
32
33 }
34 }
35
36 digitalWrite(LED_BUILTIN, LOW); // when the central disconnects, turn off the LED
37 Serial.print("Disconnected from central: ");
38 Serial.println(central.address());
39 }
40}

Complete Code

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

1#include <ArduinoBLE.h>
2BLEService newService("180A"); // creating the service
3
4BLEUnsignedCharCharacteristic randomReading("2A58", BLERead | BLENotify); // creating the Analog Value characteristic
5BLEByteCharacteristic switchChar("2A57", BLERead | BLEWrite); // creating the LED characteristic
6
7const int ledPin = 2;
8long previousMillis = 0;
9
10
11void setup() {
12 Serial.begin(9600); // initialize serial communication
13 while (!Serial); //starts the program if we open the serial monitor.
14
15 pinMode(LED_BUILTIN, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected
16 pinMode(ledPin, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected
17
18 //initialize ArduinoBLE library
19 if (!BLE.begin()) {
20 Serial.println("starting Bluetooth® Low Energy failed!");
21 while (1);
22 }
23
24 BLE.setLocalName("MKR WiFi 1010"); //Setting a name that will appear when scanning for Bluetooth® devices
25 BLE.setAdvertisedService(newService);
26
27 newService.addCharacteristic(switchChar); //add characteristics to a service
28 newService.addCharacteristic(randomReading);
29
30 BLE.addService(newService); // adding the service
31
32 switchChar.writeValue(0); //set initial value for characteristics
33 randomReading.writeValue(0);
34
35 BLE.advertise(); //start advertising the service
36 Serial.println(" Bluetooth® device active, waiting for connections...");
37}
38
39void loop() {
40
41 BLEDevice central = BLE.central(); // wait for a Bluetooth® Low Energy central
42
43 if (central) { // if a central is connected to the peripheral
44 Serial.print("Connected to central: ");
45
46 Serial.println(central.address()); // print the central's BT address
47
48 digitalWrite(LED_BUILTIN, HIGH); // turn on the LED to indicate the connection
49
50 // check the battery level every 200ms
51 // while the central is connected:
52 while (central.connected()) {
53 long currentMillis = millis();
54
55 if (currentMillis - previousMillis >= 200) { // if 200ms have passed, we check the battery level
56 previousMillis = currentMillis;
57
58 int randomValue = analogRead(A1);
59 randomReading.writeValue(randomValue);
60
61 if (switchChar.written()) {
62 if (switchChar.value()) { // any value other than 0
63 Serial.println("LED on");
64 digitalWrite(ledPin, HIGH); // will turn the LED on
65 } else { // a 0 value
66 Serial.println(F("LED off"));
67 digitalWrite(ledPin, LOW); // will turn the LED off
68 }
69 }
70
71 }
72 }
73
74 digitalWrite(LED_BUILTIN, LOW); // when the central disconnects, turn off the LED
75 Serial.print("Disconnected from central: ");
76 Serial.println(central.address());
77 }
78}

Testing It Out

Once we are finished with the coding, we can upload the sketch to the board. When it has been successfully uploaded, open the Serial Monitor. In the Serial Monitor, the text " Bluetooth® device active, waiting for connections..." will appear.

Waiting for connections.
Waiting for connections.

We can now discover our MKR WiFi 1010 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:

Connecting to your device through a smartphone.
Connecting to your device through a smartphone.

To control the LED, we simply need to write any value other than 0 to turn it on, and 0 to turn it off. This is within the "Digital Output" characteristic, which is located under "Device Information". We can also go into the "Analog" characteristic, where we need to change the data format to "Unsigned Little-Endian", and click the "Read Again" button. Once we click the button, we will retrieve the latest value.

Troubleshoot

If the code is not working, there are some common issues we can troubleshoot:

  • We haven't updated the latest firmware for the board.
  • We haven't installed the Board Package required for the board.
  • We haven't installed the ArduinoBLE library.
  • 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. In this tutorial, we did two practical things: turning an LED, ON and OFF, and reading a value from an analog pin. You can now start experimenting with this code, and create your own amazing Bluetooth® applications!

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 MKR WiFi 1010 board. You can also check out the ArduinoBLE library for more examples and inspiration for creating Bluetooth® projects!

Suggest changes

The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything wrong, you can edit this page here.

License

The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.