BLE device to device with Nano RP2040 Connect

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

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 BLE 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 BLE.
  • 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 BLE peripherals until the one inside paranthesis 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 Service7// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central8BLEByteCharacteristic LEDCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify | BLEWrite);9void setup() {10  Serial.begin(9600);11  pinMode(buttonPin, INPUT_PULLUP);12  // begin initialization13  if (!BLE.begin()) {14    Serial.println("starting BLE 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 service20  LEDService.addCharacteristic(LEDCharacteristic);21  // add service22  BLE.addService(LEDService);23  // start advertising24  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}59

Complete code for central device

Upload the code below to the central device.

1#include <ArduinoBLE.h>2
3void setup() {4  pinMode(LEDB, OUTPUT);5  Serial.begin(9600);6  while (!Serial);7  // initialize the BLE hardware8  BLE.begin();9  Serial.println("BLE Central - LED control");10  // start scanning for LED BLE peripherals11  BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");12}13void loop() {14  // check if a peripheral has been discovered15  BLEDevice peripheral = BLE.available();16  if (peripheral) {17    // discovered a peripheral, print out address, local name, and advertised service18    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("LED") < 0) {26      Serial.println("No 'LED' in name");27      return;  // If the name doeshn't have "LED" in it then ignore it28    }29    // stop scanning30    BLE.stopScan();31    controlLed(peripheral);32    // peripheral disconnected, start scanning again33    BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");34  }35}36void controlLed(BLEDevice peripheral) {37  // connect to the peripheral38  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 attributes46  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 characteristic55  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 connected63    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(LEDB, HIGH);70      }71      else if (value == 0x00) {72        digitalWrite(LEDB, LOW);73        Serial.println("OFF");74      }75    }76    delay(500);77  }78  Serial.println("Peripheral disconnected");79}80

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 BLE, with the same button.

Contribute to Arduino

Join the community and suggest improvements to this article via GitHub. Make sure to read out contribution policy before making your pull request.

Missing something?

Check out our store and get what you need to follow this tutorial.