MKR WiFi 1010 Bluetooth® Low Energy

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

Enabling BLE

Bluetooth® Low Energy, referred to as BLE, 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.

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.h2BLEService newService("180A"); // creating the service3
4BLEUnsignedCharCharacteristic randomReading("2A58", BLERead | BLENotify); // creating the Analog Value characteristic5BLEByteCharacteristic switchChar("2A57", BLERead | BLEWrite); // creating the LED characteristic6
7const int ledPin = 2;8long previousMillis = 0;9
10

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 communication3  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 connected6  pinMode(ledPin, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected7
8  //initialize BLE library9  if (!BLE.begin()) {10    Serial.println("starting BLE failed!");11    while (1);12  }13
14  BLE.setLocalName("MKR WiFi 1010"); //Setting a name that will appear when scanning for Bluetooth devices15  BLE.setAdvertisedService(newService);16
17  newService.addCharacteristic(switchChar); //add characteristics to a service18  newService.addCharacteristic(randomReading);19
20  BLE.addService(newService);  // adding the service21
22  switchChar.writeValue(0); //set initial value for characteristics23  randomReading.writeValue(0);24
25  BLE.advertise(); //start advertising the service26  Serial.println("Bluetooth device active, waiting for connections...");27}28

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 BLE central4
5  if (central) {  // if a central is connected to the peripheral6    Serial.print("Connected to central: ");7    8    Serial.println(central.address()); // print the central's BT address9    10    digitalWrite(LED_BUILTIN, HIGH); // turn on the LED to indicate the connection11
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 025            Serial.println("LED on");26            digitalWrite(ledPin, HIGH);         // will turn the LED on27          } else {                              // a 0 value28            Serial.println(F("LED off"));29            digitalWrite(ledPin, LOW);          // will turn the LED off30          }31        }32
33      }34    }35    36    digitalWrite(LED_BUILTIN, LOW); // when the central disconnects, turn off the LED37    Serial.print("Disconnected from central: ");38    Serial.println(central.address());39  }40}41

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 service3
4BLEUnsignedCharCharacteristic randomReading("2A58", BLERead | BLENotify); // creating the Analog Value characteristic5BLEByteCharacteristic switchChar("2A57", BLERead | BLEWrite); // creating the LED characteristic6
7const int ledPin = 2;8long previousMillis = 0;9
10
11void setup() {12  Serial.begin(9600);    // initialize serial communication13  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 connected16  pinMode(ledPin, OUTPUT); // initialize the built-in LED pin to indicate when a central is connected17
18  //initialize BLE library19  if (!BLE.begin()) {20    Serial.println("starting BLE failed!");21    while (1);22  }23
24  BLE.setLocalName("MKR WiFi 1010"); //Setting a name that will appear when scanning for bluetooth devices25  BLE.setAdvertisedService(newService);26
27  newService.addCharacteristic(switchChar); //add characteristics to a service28  newService.addCharacteristic(randomReading);29
30  BLE.addService(newService);  // adding the service31
32  switchChar.writeValue(0); //set initial value for characteristics33  randomReading.writeValue(0);34
35  BLE.advertise(); //start advertising the service36  Serial.println("Bluetooth device active, waiting for connections...");37}38
39void loop() {40  41  BLEDevice central = BLE.central(); // wait for a BLE central42
43  if (central) {  // if a central is connected to the peripheral44    Serial.print("Connected to central: ");45    46    Serial.println(central.address()); // print the central's BT address47    48    digitalWrite(LED_BUILTIN, HIGH); // turn on the LED to indicate the connection49
50    // check the battery level every 200ms51    // 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 level56        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 063            Serial.println("LED on");64            digitalWrite(ledPin, HIGH);         // will turn the LED on65          } else {                              // a 0 value66            Serial.println(F("LED off"));67            digitalWrite(ledPin, LOW);          // will turn the LED off68          }69        }70
71      }72    }73    74    digitalWrite(LED_BUILTIN, LOW); // when the central disconnects, turn off the LED75    Serial.print("Disconnected from central: ");76    Serial.println(central.address());77  }78}79

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 core 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!