BLE Device to Device with Nano RP2040 Connect

Learn how to connect 2x Nano RP2040 Connect boards with each other, using Bluetooth® Low Energy.

Introduction

In this tutorial, we will learn how to turn on the blue pixel onboard the Arduino® Nano RP2040 Connect board, from another board. For this, we will need two Bluetooth® Low Energy compatible boards, such as the Nano RP2040 Connect board, where we will use the ArduinoBLE library to make the connection.

Note: if you need help setting up your environment to use your Arduino Nano RP2040 board, please refer to this installation guide.

Goals

The goals of this project are:

  • Connect two Nano RP2040 Connect boards using Bluetooth® Low Energy.
  • Set up one board as a "peripheral" and one as a "central" device.
  • Set up a boolean that switches each time a button is pressed.
  • Depending on what state the boolean is in, send a byte to the other board (either 0x00 or 0x01 which represents 0 and 1).

Hardware & Software Needed

Circuit

For the peripheral device, we need to connect a pushbutton the to board.

The circuit for the peripheral device.
The circuit for the peripheral device.

For the central device, we do not need any additional circuit.

The circuit for the central device.
The circuit for the central device.

Programming the Board

We will now get to the programming part of this tutorial.

  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 Mbed OS Nano Boards and install it.

  2. Now, we need to install the libraries 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.

  3. We can now take a look at some of the core functions of the sketches we will use:

  • BLE.begin()
    - initializes the library
  • BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214")
    - scans for Bluetooth® Low Energy peripherals until the one inside parenthesis is found.
  • BLEDevice peripheral = BLE.available()
    checks whether peripheral has been discovered.
  • BLEDevice central = BLE.available()
    checks whether peripheral has been discovered.
  • while (peripheral.connected())
    - while a peripheral is connected, enter a while loop.
  • while (central.connected())
    - while a peripheral is connected, enter a while loop.
  • LEDCharacteristic.writeValue((byte)0x00)
    - sends a "0" to the central.
  • LEDCharacteristic.writeValue((byte)0x01)
    - sends a "1" to the central.
  • byte value = LEDCharacteristic.read()
    - reads incoming data.
  • LEDCharacteristic.readValue(value)
    - stores incoming data in the
    value
    byte.
  • if (value == 0x00)
    - checks if incoming data is "0".
  • if (value == 0x01)
    - checks if incoming data is "1".

Complete Code for Peripheral Device

Upload the code below to the peripheral device.

1#include <ArduinoBLE.h>
2
3int buttonPin = 2;
4boolean ledSwitch;
5
6BLEService LEDService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service
7// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
8BLEByteCharacteristic LEDCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify | BLEWrite);
9void setup() {
10 Serial.begin(9600);
11 pinMode(buttonPin, INPUT_PULLUP);
12 // begin initialization
13 if (!BLE.begin()) {
14 Serial.println("starting Bluetooth® Low Energy failed!");
15 }
16 // set advertised local name and service UUID:
17 BLE.setLocalName("Button Device");
18 BLE.setAdvertisedService(LEDService);
19 // add the characteristic to the service
20 LEDService.addCharacteristic(LEDCharacteristic);
21 // add service
22 BLE.addService(LEDService);
23 // start advertising
24 BLE.advertise();
25 Serial.println("BLE LED Peripheral, waiting for connections....");
26}
27void loop() {
28 // listen for BLE peripherals to connect:
29 BLEDevice central = BLE.central();
30 // if a central is connected to peripheral:
31 if (central) {
32 Serial.print("Connected to central: ");
33 // print the central's MAC address:
34 Serial.println(central.address());
35 // while the central is still connected to peripheral:
36 while (central.connected()) {
37
38 int buttonState = digitalRead(buttonPin);
39
40 if (buttonState == LOW) {
41 ledSwitch = !ledSwitch;
42 delay(500);
43
44 if (ledSwitch) {
45 Serial.println("ON");
46 LEDCharacteristic.writeValue((byte)0x01);
47 }
48 else {
49 LEDCharacteristic.writeValue((byte)0x00);
50 Serial.println("OFF");
51 }
52 }
53 }
54 // when the central disconnects, print it out:
55 Serial.print(F("Disconnected from central: "));
56 Serial.println(central.address());
57 }
58}

Complete Code for Central Device

Upload the code below to the central device.

1#include <ArduinoBLE.h>
2
3void setup() {
4 pinMode(LED_BUILTIN, OUTPUT);
5 Serial.begin(9600);
6 while (!Serial);
7 // initialize the BLE hardware
8 BLE.begin();
9 Serial.println("BLE Central - LED control");
10 // start scanning for Button Device BLE peripherals
11 BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
12}
13void loop() {
14 // check if a peripheral has been discovered
15 BLEDevice peripheral = BLE.available();
16 if (peripheral) {
17 // discovered a peripheral, print out address, local name, and advertised service
18 Serial.print("Found ");
19 Serial.print(peripheral.address());
20 Serial.print(" '");
21 Serial.print(peripheral.localName());
22 Serial.print("' ");
23 Serial.print(peripheral.advertisedServiceUuid());
24 Serial.println();
25 if (peripheral.localName().indexOf("Button Device") < 0) {
26 Serial.println("No 'Button Device' in name");
27 return; // If the name doesn't have "Button Device" in it then ignore it
28 }
29 // stop scanning
30 BLE.stopScan();
31 controlLed(peripheral);
32 // peripheral disconnected, start scanning again
33 BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
34 }
35}
36void controlLed(BLEDevice peripheral) {
37 // connect to the peripheral
38 Serial.println("Connecting ...");
39 if (peripheral.connect()) {
40 Serial.println("Connected");
41 } else {
42 Serial.println("Failed to connect!");
43 return;
44 }
45 // discover peripheral attributes
46 Serial.println("Discovering attributes ...");
47 if (peripheral.discoverAttributes()) {
48 Serial.println("Attributes discovered");
49 } else {
50 Serial.println("Attribute discovery failed!");
51 peripheral.disconnect();
52 return;
53 }
54 // retrieve the LED characteristic
55 BLECharacteristic LEDCharacteristic = peripheral.characteristic("19b10001-e8f2-537e-4f6c-d104768a1214");
56 if (!LEDCharacteristic) {
57 Serial.println("Peripheral does not have LED characteristic!");
58 peripheral.disconnect();
59 return;
60 }
61 while (peripheral.connected()) {
62 // while the peripheral is connected
63 if (LEDCharacteristic.canRead()) {
64 byte value = LEDCharacteristic.read();
65 LEDCharacteristic.readValue(value);
66 //Serial.println(LEDCharacteristic.readValue(value));
67 if (value == 0x01) {
68 Serial.println("ON");
69 digitalWrite(LED_BUILTIN, HIGH);
70 }
71 else if (value == 0x00) {
72 digitalWrite(LED_BUILTIN, LOW);
73 Serial.println("OFF");
74 }
75 }
76 delay(500);
77 }
78 Serial.println("Peripheral disconnected");
79}

Testing It Out

After we have uploaded both the central and peripheral sketches to our boards, we can test out our application.

Let's start by opening the Serial Monitor of the central device. Since we are using the

while(!Serial);
command, the program will not initialize until we open the Serial Monitor. This is done so we don't miss any important information in the Serial Monitor.

When we open it, the central device will start looking for peripherals. When it finds one, it will attempt to connect to it. If all goes well, we should now start receiving the state of the button from the peripheral device. In this case, it is OFF, which we can see being updated continuously.

Serial Monitor printing connection status and "OFF".
Serial Monitor printing connection status and "OFF".

Now, if we press the button on the peripheral device, we can see two things change on the central device. The blue LED will turn ON, and the Serial Monitor will instead print "ON". We can now turn ON or OFF the LED, through pushing the same button.

When the button is pressed, the RGB LED turns blue on the other device.
When the button is pressed, the RGB LED turns blue on the other device.

Troubleshoot

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

  • We have not installed the ArduinoBLE library.
  • We have not uploaded the right sketch for the right board. Remember that the board with the button needs the peripheral sketch, and the other board needs the central sketch.
  • We have not powered both boards. Remember that both programs need to be up and running for this application to work.

Conclusion

In this tutorial, we have created a simple device-to-device application over Bluetooth®. We set up a peripheral device with a button, and used the built-in RGB on the central device. With this, we can simply turn ON and OFF the LED using Bluetooth® Low Energy, with the same button.

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.