Hi, I am trying to send information two ways with two Arduino Nano's but for some reason my code is not working. Can anyone help me?
Code for central:
#include <ArduinoBLE.h>
BLEDevice peripheral;
BLECharacteristic txCharacteristic; // Correct type for the characteristic
BLECharacteristic rxCharacteristic; // Correct type for the characteristic
const int button = 3;
int buttonState = HIGH;
void setup() {
Serial.begin(9600);
while (!Serial);
if (!BLE.begin()) {
Serial.println("Starting BLE failed!");
while (1);
}
Serial.println("Central device started.");
BLE.scanForUuid("180A"); // Scan for the peripheral with the custom service UUID
pinMode(button, INPUT_PULLUP);
}
void loop() {
if (!peripheral) {
peripheral = BLE.available();
if (peripheral) {
Serial.print("Connecting to peripheral: ");
Serial.println(peripheral.address());
BLE.stopScan();
if (peripheral.connect()) {
Serial.println("Connected!");
peripheral.discoverAttributes();
// Find characteristics
txCharacteristic = peripheral.characteristic("2A57");
rxCharacteristic = peripheral.characteristic("2A58");
if (txCharacteristic && rxCharacteristic) {
Serial.println("Characteristics found!");
} else {
Serial.println("Characteristics not found!");
peripheral.disconnect();
}
} else {
Serial.println("Connection failed.");
peripheral = BLEDevice();
}
}
} else if (peripheral.connected()) {
buttonState = digitalRead(button);
if (buttonState == LOW) {
sendAMessage("peripheral on");
}
//const uint8_t* receivedData = txCharacteristic.value();
//String response = String((char*)receivedData); // Cast the byte array to char* and create a String
// Serial.println("Received: " + response);
//Read incoming data
if (rxCharacteristic.valueUpdated()) {
// Convert byte array to string
const uint8_t* receivedData = rxCharacteristic.value();
String response = String((char*)receivedData); // Cast the byte array to char* and create a String
Serial.println("Received: " + response);
}
} else {
Serial.println("Peripheral disconnected, scanning again...");
BLE.scanForUuid("180A");
peripheral = BLEDevice();
}
}
void sendAMessage(String s) {
txCharacteristic.writeValue(s.c_str());
Serial.println("Sent message: " + s);
}
Code for peripheral:
#include <ArduinoBLE.h>
BLEService customService("180A"); // Custom service UUID
BLECharacteristic txCharacteristic("2A57", BLERead | BLENotify, 20); // Transmit data
BLECharacteristic rxCharacteristic("2A58", BLEWrite, 20); // Receive data
const int button = 3;
int buttonState = HIGH;
void setup() {
Serial.begin(9600);
while (!Serial);
if (!BLE.begin()) {
Serial.println("Starting BLE failed!");
while (1);
}
BLE.setLocalName("NanoBLE_Peripheral");
BLE.setAdvertisedService(customService);
customService.addCharacteristic(txCharacteristic);
customService.addCharacteristic(rxCharacteristic);
BLE.addService(customService);
BLE.advertise();
Serial.println("Peripheral advertising...");
pinMode(button, INPUT_PULLUP);
}
void loop() {
BLEDevice central = BLE.central();
if (central) {
Serial.print("Connected to central: ");
Serial.println(central.address());
while (central.connected()) {
buttonState = digitalRead(button);
// Send a message when the button is pressed
if (buttonState == LOW) { // Button pressed (since INPUT_PULLUP)
sendAMessage("central on");
}
// If data is written to the rxCharacteristic, print it
if (txCharacteristic.valueUpdated()) {
const uint8_t* receivedData = txCharacteristic.value();
String response = String((char*)receivedData);
Serial.print("Received: ");
Serial.println(response);
}
}
Serial.println("Central disconnected");
}
}
void sendAMessage(String s) {
rxCharacteristic.writeValue(s.c_str()); // Send data to the central device
Serial.println("Sent message: " + s); // Print what message was sent
}
This is not a very useful problem statement.
What is your Serial output telling you?
My recommendation with these BLE issues is to get the Peripheral working correctly with a phone app like LightBlue or nrfConnect as the central. Once the peripheral is working as you want, then move on to debugging the Central.
I have a version of the code working such that I can send information one way, but I can't get it to work both ways. The problem with the code above is that the Nano's keep connecting to each other and disconnecting on loop, and I cannot find where the bug is in this code. I will try again, but can't seem to figure out where I am going wrong.
When I was trying your code I found several different issues.
My advice again is to start with the peripheral and a phone app.
First work on getting the peripheral to send data to the phone.
Then work on getting the peripheral to read data sent from the phone.
EDIT: When you have code which reliably sends the message to the phone with the button press, please post it. Then we can work on adding the receiving.
I have a similar issue with BT sending and receiving the data on Arduino BLE 33 sense board
Here is the code for Peripheral - where I am reading the Integrated IMU sensor from BLE sense and the ultrasound sensor (external sensor- connected to BLE sense33 board)
#include <ArduinoBLE.h>
#include <Arduino_LSM9DS1.h>
//#include <Arduino_LSM6DS3.h> // Uncomment this if your peripheral is the Nano 33 IoT
// ------------------------------------------ BLE UUIDs ------------------------------------------
#define BLE_UUID_PERIPHERAL "19B10000-E8F2-537E-4F6C-D104768A1214" //please chnage to a unique value that matches BLE_IMU_CENTRAL
#define BLE_UUID_CHARACT_LED "19B10001-E8F2-537E-4F6C-E104768A1214" //please chnage to a unique value that matches BLE_IMU_CENTRAL
#define BLE_UUID_CHARACT_ACCX "29B10001-E8F2-537E-4F6C-a204768A1215" //please chnage to a unique value that matches BLE_IMU_CENTRAL
#define BLE_UUID_CHARACT_ACCY "39B10001-E8F2-537E-4F6C-a204768A1215" //please chnage to a unique value that matches BLE_IMU_CENTRAL
#define BLE_UUID_CHARACT_DISTANCE "49B10001-E8F2-537E-4F6C-a204768A1215" //please chnage to a unique value that matches BLE_IMU_CENTRAL
BLEService LED_IMU_Service(BLE_UUID_PERIPHERAL); // BLE LED Service
// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic switchCharacteristic(BLE_UUID_CHARACT_LED, BLERead | BLEWrite);
BLEFloatCharacteristic accXCharacteristic(BLE_UUID_CHARACT_ACCX, BLERead | BLENotify | BLEWrite);
BLEFloatCharacteristic accYCharacteristic(BLE_UUID_CHARACT_ACCY, BLERead | BLENotify | BLEWrite);
BLEFloatCharacteristic distanceCharacteristic(BLE_UUID_CHARACT_DISTANCE, BLERead | BLENotify | BLEWrite);
const int ledPin = LED_BUILTIN; // pin to use for the LED
float x, y, z;
const int trigPin = 11;
const int echoPin = 12;
// defines variables
long duration;
float distance;
// ------------------------------------------ VOID SETUP ------------------------------------------
void setup() {
Serial.begin(9600);
//while (!Serial); //uncomment to view the IMU data in the peripheral serial monitor
// begin IMU initialization
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
while (1);
}
// set LED pin to output mode for ultrasound sensor
pinMode(ledPin, OUTPUT);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
// begin BLE initialization
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
// set advertised local name and service UUID:
BLE.setLocalName("BLE_IMU");
BLE.setAdvertisedService(LED_IMU_Service);
// add the characteristic to the service
LED_IMU_Service.addCharacteristic(switchCharacteristic);
LED_IMU_Service.addCharacteristic(accXCharacteristic);
LED_IMU_Service.addCharacteristic(accYCharacteristic);
LED_IMU_Service.addCharacteristic(distanceCharacteristic);
// add service
BLE.addService(LED_IMU_Service);
// set the initial value for the characeristic:
switchCharacteristic.writeValue(0);
// start advertising
BLE.advertise();
Serial.println("BLE LED Peripheral");
}
// ------------------------------------------ VOID LOOP ------------------------------------------
void loop() {
// listen for BLE peripherals to connect:
BLEDevice central = BLE.central();
// if a central is connected to peripheral:
if (central) {
Serial.print("Connected to central: ");
// print the central's MAC address:
Serial.println(central.address());
// while the central is still connected to peripheral:
while (central.connected()) {
// if the remote device wrote to the characteristic,
// use the value to control the LED:
if (switchCharacteristic.written()) {
if (switchCharacteristic.value()) { // any value other than 0
Serial.println("LED on");
digitalWrite(ledPin, HIGH); // will turn the LED on
} else { // a 0 value
Serial.println("LED off");
digitalWrite(ledPin, LOW); // will turn the LED off
}
}
if (IMU.gyroscopeAvailable()) {
IMU.readGyroscope(x, y, z);
accXCharacteristic.writeValue(x);
accYCharacteristic.writeValue(y);
Serial.print(x);
Serial.print('\t');
Serial.print(y);
Serial.print('\t');
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = duration * 0.034 / 2 ;
distanceCharacteristic.writeValue(distance);
Serial.print(distance);
Serial.print('\n');
}
}
// when the central disconnects, print it out:
Serial.print(F("Disconnected from central: "));
Serial.println(central.address());
}
}
#include <ArduinoBLE.h>
void setup() {
Serial.begin(9600);
while (!Serial);
// begin initialization
if (!BLE.begin()) {
Serial.println("starting Bluetooth® Low Energy module failed!");
while (1);
}
Serial.println("Bluetooth® Low Energy Central - Peripheral Explorer");
// start scanning for peripherals
BLE.scan();
}
void loop() {
// check if a peripheral has been discovered
BLEDevice peripheral = BLE.available();
if (peripheral) {
// discovered a peripheral, print out address, local name, and advertised service
Serial.print("Found ");
Serial.print(peripheral.address());
Serial.print(" '");
Serial.print(peripheral.localName());
Serial.print("' ");
Serial.print(peripheral.advertisedServiceUuid());
Serial.println();
// see if peripheral is a LED
if (peripheral.localName() == "BLE_IMU") {
// stop scanning
BLE.stopScan();
explorerPeripheral(peripheral);
// peripheral disconnected, we are done
while (1) {
// do nothing
}
}
}
}
void explorerPeripheral(BLEDevice peripheral) {
// connect to the 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;
}
// read and print device name of peripheral
Serial.println();
Serial.print("Device name: ");
Serial.println(peripheral.deviceName());
Serial.print("Appearance: 0x");
Serial.println(peripheral.appearance(), HEX);
Serial.println();
// loop the services of the peripheral and explore each
for (int i = 0; i < peripheral.serviceCount(); i++) {
BLEService service = peripheral.service(i);
exploreService(service);
}
Serial.println();
// we are done exploring, disconnect
Serial.println("Disconnecting ...");
peripheral.disconnect();
Serial.println("Disconnected");
}
void exploreService(BLEService service) {
// print the UUID of the service
Serial.print("Service ");
Serial.println(service.uuid());
// loop the characteristics of the service and explore each
for (int i = 0; i < service.characteristicCount(); i++) {
BLECharacteristic characteristic = service.characteristic(i);
exploreCharacteristic(characteristic);
}
}
void exploreCharacteristic(BLECharacteristic characteristic) {
// print the UUID and properties of the characteristic
Serial.print("\tCharacteristic ");
Serial.print(characteristic.uuid());
Serial.print(", properties 0x");
Serial.print(characteristic.properties(), HEX);
// check if the characteristic is readable
if (characteristic.canRead()) {
// read the characteristic value
characteristic.read();
if (characteristic.valueLength() > 0) {
// print out the value of the characteristic
Serial.print(", value 0x");
printData(characteristic.value(), characteristic.valueLength());
}
}
Serial.println();
// loop the descriptors of the characteristic and explore each
for (int i = 0; i < characteristic.descriptorCount(); i++) {
BLEDescriptor descriptor = characteristic.descriptor(i);
exploreDescriptor(descriptor);
}
}
void exploreDescriptor(BLEDescriptor descriptor) {
// print the UUID of the descriptor
Serial.print("\t\tDescriptor ");
Serial.print(descriptor.uuid());
// read the descriptor value
descriptor.read();
// print out the value of the descriptor
Serial.print(", value 0x");
printData(descriptor.value(), descriptor.valueLength());
Serial.println();
}
void printData(const unsigned char data[], int length) {
for (int i = 0; i < length; i++) {
unsigned char b = data[i];
if (b < 16) {
Serial.print("0");
}
Serial.print(b, HEX);
}
}
The output of the central (periphery_explorer code) is as follows:
Found 1c:af:4a:65:c9:57 ''
Found 47:bc:a7:de:23:ba ''
Found b5:b0:49:a3:9d:6f 'BLE_IMU' 19b10000-e8f2-537e-4f6c-d104768a1214
Connecting ...
Connected
Discovering attributes ...
Attribute discovery failed!
Can you help me how to fix this Attribute discovery failed issue?
Thanks @cattledog for trying out on your environment, and posting the update.
I also tried the same in my environment by commenting out the pulseIn function related to distance sensor, as soon as I did that, the peripheral explorer code started working.
After I uncomment these lines (related to distance sensor), the error starts showing up again. I even moved it to the beginning of loop statement, same error again.
Have anyone tried interfacing the external sensor and sending the sensor data to bluetooth in arduino Ble sense board?
Thanks a ton @cattledog
As you pointed out pulsein function was the culprit. After I incorporated your code, instead of pulseIn function, I was able to see the peripheralExplorer code, read out the characteristics without any issue
Unlike the function used in the ArduinCore-avr pulseIn() on the Nano33BLE is not actually blocking with a while( ) function, and the situation is more complicated.
The implementation of pulseIn( ) in the mbed core used by the Nano 33 BLE uses a hardware timer (Timer2?). Look at wiring_pulse the Arduino mbed core.
I think this is in conflict with a timer used in some Cordio transport layer in the BLE library.