Arduino Nano 33 BLE 2 way communication

So I'm trying to establish a 2 way communication between two Arduino Nano 33 BLE using BLE, and I can only seem to get the Control arduino to send data to the Peripheral, and not the other way round. My code is below for the control and peripheral respectively. It is pretty much a re written version of the LED examples in the BLE examples library, except it receives a string in the Serial box and prints it to the other Arduino's serial terminal.

What I would like the program to have the ability to do is:

  • User types data into the serial terminal of the first Arduino.
  • The second arduino reads this input, processes it accordingly and sends back a result based on the input (If input is 'a', send back '1', input 'b', send back '2')
  • The first Arduino accepts this value and prints it to its terminal.

CONTROL (SEND TO PERIPHERAL) CODE:

/*
 * 
 * INPUT BUTTON TO CHANGE LED OF THE OTHER
  LED Control

  This example scans for BLE peripherals until one with the advertised service
  "19b10000-e8f2-537e-4f6c-d104768a1214" UUID is found. Once discovered and connected,
  it will remotely control the BLE Peripheral's LED, when the button is pressed or released.

  The circuit:
  - Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
    Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.
  - Button with pull-up resistor connected to pin 2.

  You can use it with another board that is compatible with this library and the
  Peripherals -> LED example.

  This example code is in the public domain.
*/

const unsigned char HX__ = 0x5f;
const unsigned char HX_0 = 0x00;
const unsigned char HX_1 = 0x01;
const unsigned char HX_2 = 0x02;
const unsigned char HX_3 = 0x03;
const unsigned char HX_4 = 0x04;
const unsigned char HX_5 = 0x05;
const unsigned char HX_6 = 0x06;
const unsigned char HX_7 = 0x07;
const unsigned char HX_8 = 0x08;
const unsigned char HX_9 = 0x09;
const unsigned char HX_HIF = 0x2d;
const unsigned char HX_$ = 0x24;

#include <ArduinoBLE.h>

// variables for button
//const int buttonPin = 2;
bool buttonState = false;
String inputString = "";
bool stringComplete = false;



void setup() {
  Serial.begin(9600);
  while (!Serial);

  BLE.begin();
  Serial.println("BLE Central - LED control");
  BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
}

void loop() {

  BLEDevice peripheral = BLE.available();

  if (peripheral) {
    Serial.print("Found ");
    Serial.print(peripheral.address());
    Serial.print(" '");
    Serial.print(peripheral.localName());
    Serial.print("' ");
    Serial.print(peripheral.advertisedServiceUuid());
    Serial.println();

    if (peripheral.localName() != "LED") {
      return;
    }

    // stop scanning
    BLE.stopScan();

    controlLed(peripheral);

    BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
  }
}

void controlLed(BLEDevice peripheral) {
  Serial.println("Connecting ...");

  if (peripheral.connect()) {
    Serial.println("Connected");
  } else {
    Serial.println("Failed to connect!");
    return;
  }

  // discover peripheral attributes
  Serial.println("Discovering attributes ...");
  if (peripheral.discoverAttributes()) {
    Serial.println("Attributes discovered");
  } else {
    Serial.println("Attribute discovery failed!");
    peripheral.disconnect();
    return;
  }
  BLECharacteristic ledCharacteristic = peripheral.characteristic("19b10001-e8f2-537e-4f6c-d104768a1214");

  if (!ledCharacteristic) {
    Serial.println("Peripheral does not have LED characteristic!");
    peripheral.disconnect();
    return;
  } else if (!ledCharacteristic.canWrite()) {
    Serial.println("Peripheral does not have a writable LED characteristic!");
    peripheral.disconnect();
    return;
  }
  String testing = "Test";
  
  while (peripheral.connected()) {
      char sndString[20];
      byte tstchar;
      serialEvent();
      while(stringComplete)
      {
        testing = inputString;
        testing.toCharArray(sndString, testing.length());
        stringComplete = false;
        inputString = "";
        ledCharacteristic.writeValue(sndString);
      }
      if(ledCharacteristic.written())
      {
        Serial.println("Test");
        Serial.println(ledCharacteristic.readValue(tstchar));
      }
  }
  Serial.println("Peripheral disconnected");
}

void serialEvent() 
{
  while(Serial.available())
  {
    char inChar = (char)Serial.read();
    inputString+=inChar;

    if (inChar == '\n')
    {
      stringComplete = true;
    }
  }
}

RECEIVE (AND SEND BACK) CODE:

/*
  LED

  This example creates a BLE peripheral with service that contains a
  characteristic to control an LED.

  The circuit:
  - Arduino MKR WiFi 1010, Arduino Uno WiFi Rev2 board, Arduino Nano 33 IoT,
    Arduino Nano 33 BLE, or Arduino Nano 33 BLE Sense board.

  You can use a generic BLE central app, like LightBlue (iOS and Android) or
  nRF Connect (Android), to interact with the services and characteristics
  created in this sketch.

  This example code is in the public domain.
*/

#include <ArduinoBLE.h>

BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service

// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEStringCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite, 10);

const int ledPin = LED_BUILTIN; // pin to use for the LED

void setup() {
  Serial.begin(9600);
  while (!Serial);

  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");
    while (1);
  }
  BLE.setLocalName("LED");
  BLE.setAdvertisedService(ledService);
  ledService.addCharacteristic(switchCharacteristic);
  BLE.addService(ledService);
  switchCharacteristic.writeValue(" ");
  BLE.advertise();
  Serial.println("BLE LED Peripheral");
  // RECEIVE -->
  BLE.scanForUuid("19b10001-e8f2-537e-4f6c-d104768a1214");
}

void loop() {
  // listen for BLE peripherals to connect:
  BLEDevice central = BLE.central();
  if (central) {
    Serial.print("Connected to central: ");
    Serial.println(central.address());
    while (central.connected()) {
      if (switchCharacteristic.written()) {
          Serial.println(switchCharacteristic.value());
          switchCharacteristic.writeValue("Received");
          if(switchCharacteristic.canWrite())
          {
            Serial.println("can write"); // CODE NEVER GETS HERE
          }
      }
    }
    Serial.print(F("Disconnected from central: "));
    Serial.println(central.address());
  }
}

You are using the wrong functions. Here are a few points that may help you understand the issue better.

  • The peripheral / server at the application level does not send data. It updates its characteristics and that is it. So, canWrite() does not make any sense, because the peripheral can always write.

  • The central / client application cannot detect when the data has been written. It can subscribe and then gets the notification that tells it the value has been updated. So, written() is wrong in this case and valueUpdated() must be used.

  • The peripheral / server does not scan. It just advertises a service that may be of interest to others. Like a weather news station. They do not look for their own service. You need to remove the scanForUuid.

Regarding your service and characteristic. Make life easy for yourself.

  • Use separate characteristics for writing and reading stuff.
  • use Individual characteristics for every value and do not switch according to some input, leave the selection to the central (maybe I miss-understood your intentions), if bandwidth is an issue, you can combine values into a structure and leave the decoding to the central ​
  • do not use String characteristics for numerical values
  • avoid floating point data types and use fixed point values with a known exponent instead

Have a look into the peripheral example I posted in the following thread reply #2. Maybe you find a few useful things.

https://forum.arduino.cc/t/bluetooth-communications/902610/2

did you sort this?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.