Connect nano sense to polar bluetooth heart rate monitor

Making a gyroscopic exercise machine like the Powerball and I want a Nano to connect to a bluetooth heart rate monitor to display heart rate with LED and record performance on an SD card.
I have an Arduino Nano BLE Sense Rev 2 and Polar OH1 Bluetooth heart rate monitor.
I have installed the BLE library.
I used a Bluetooth scanner to get the UUID and custom service UUID which are included in the code which GPT-4 has written.
I've tried three bluetooth scanners but can't figure out what the Custom Characteristic UUID is.

I've been able to get the Arduino to connect momentarily but then gives error: Attribute Discovery Failed. Then repeats Failed to Connect over & over.
I don't understand what's going on here enough to trouble shoot so I'm hoping that some of you can help.

Here is my code:

#include <ArduinoBLE.h>

// Device UUID for the Polar device
const char* deviceUUID = "3975B4DF-8EAE-0E9D-246C-E70F54738420";
// Custom Service UUID for the Polar device
const char* customServiceUUID = "FB005C80-02E7-F387-1CAD-8ACD2D8DF0C8";
// Custom Characteristic UUID
const char* customCharUUID = "your_custom_characteristic_uuid_here"; // Replace this

BLEDevice peripheral;
BLEService customService;
BLECharacteristic customChar;

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

if (!BLE.begin()) {
Serial.println("Failed to initialize BLE!");
while (1);
}

Serial.println("Scanning for Polar device...");
BLE.scan();
}

void loop() {
peripheral = BLE.available();

if (peripheral) {
// Optionally, you can print the device UUID for debugging
// Serial.println(peripheral.address());

Serial.println("Connecting ...");
if (peripheral.connect()) {
  Serial.println("Connected");

  if (peripheral.discoverAttributes()) {
    Serial.println("Attributes discovered");
  } else {
    Serial.println("Attribute discovery failed!");
    peripheral.disconnect();
    return;
  }

  customService = peripheral.service(customServiceUUID);

  if (customService) {
    customChar = customService.characteristic(customCharUUID);
    
    if (customChar) {
      if (!customChar.subscribe()) {
        Serial.println("Subscription failed!");
        peripheral.disconnect();
        return;
      }

      while (peripheral.connected()) {
        if (customChar.valueUpdated()) {
          uint8_t buffer[2];
          customChar.readValue(buffer, 2);
          int customData = buffer[1]; // Assuming data is in the 2nd byte
          Serial.print("Custom Data: ");
          Serial.println(customData);
        }
      }
      Serial.println("Peripheral disconnected!");
    } else {
      Serial.println("Custom characteristic not found!");
    }
  } else {
    Serial.println("Custom service not found!");
  }

  peripheral.disconnect();
} else {
  Serial.println("Failed to connect!");
}

}
}

I suggest that you use LightBlue or nrfConnect to analyze your device to find the services and characteristics.

In previous threads related to a different Polar device it was using the standard Heart Rate GATT Service 180D and 2A37 for the Heart Rate Monitor Characteristic.

https://forum.arduino.cc/t/arduinoble-cant-receive-heart-rate-data/1001231

Thanks cattledog that is useful info. Do you know how to identify the custom characteristic UUID from the list that these apps provide since none of them are labeled that way?

I think Polar likes to keep things proprietary, and If all you have from the scanners is a list of unknown services with no 180D shown as a uuid then I'm not certain where you can go.

You may need to work with Polar

https://www.polar.com/us-en/developers/

https://github.com/polarofficial/create-mobile-app-for-polar-sensors

Cattledog the BLE Scanner says my HR monitor is using the 180D address. I copied the code you posted on the other thread and I'm getting BLE Central for Polar HR Server. but does not seem to connect. do you have any other versions of code for this?

Does LightBlue or nrfconnect connect to that service?

Yes both of those and more. Would you like me to share something from them?

Scanner On.
Device Scanned.
Device Appearance switched from Generic to Heart Monitor.
Connected.
Discovered Device Information, FEEE, Heart Rate, Battery Service, FB005C20-02E7-F387-1CAD-8ACD2D8DF0C8, 6217FF4B-FB31-1140-AD5A-A45545D7ECF3, and FB005C80-02E7-F387-1CAD-8ACD2D8DF0C8 Services.
Discovered Characteristics Manufacturer Name String, Model Number String, Serial Number String, Hardware Revision String, Firmware Revision String, Software Revision String, and System ID for Service Device Information.
Discovered Characteristics FB005C51-02E7-F387-1CAD-8ACD2D8DF0C8, FB005C52-02E7-F387-1CAD-8ACD2D8DF0C8, and FB005C53-02E7-F387-1CAD-8ACD2D8DF0C8 for Service FEEE.
Discovered Characteristics Heart Rate Measurement for Service Heart Rate.
Discovered Characteristics Battery Level for Service Battery Service.
Discovered Characteristics FB005C21-02E7-F387-1CAD-8ACD2D8DF0C8, FB005C22-02E7-F387-1CAD-8ACD2D8DF0C8, and FB005C26-02E7-F387-1CAD-8ACD2D8DF0C8 for Service FB005C20-02E7-F387-1CAD-8ACD2D8DF0C8.
Discovered Characteristics 6217FF4C-C8EC-B1FB-1380-3AD986708E2D and 6217FF4D-91BB-91D0-7E2A-7CD3BDA8A1F3 for Service 6217FF4B-FB31-1140-AD5A-A45545D7ECF3.
Discovered Characteristics FB005C81-02E7-F387-1CAD-8ACD2D8DF0C8 and FB005C82-02E7-F387-1CAD-8ACD2D8DF0C8 for Service FB005C80-02E7-F387-1CAD-8ACD2D8DF0C8.
Characteristic Manufacturer Name String has no Descriptors.
Characteristic Model Number String has no Descriptors.
Characteristic Serial Number String has no Descriptors.
Characteristic Hardware Revision String has no Descriptors.
Characteristic Firmware Revision String has no Descriptors.
Characteristic Software Revision String has no Descriptors.
Characteristic System ID has no Descriptors.
Discovered Client Characteristic Configuration for Characteristic FB005C51-02E7-F387-1CAD-8ACD2D8DF0C8
Discovered Client Characteristic Configuration for Characteristic FB005C52-02E7-F387-1CAD-8ACD2D8DF0C8
Characteristic FB005C53-02E7-F387-1CAD-8ACD2D8DF0C8 has no Descriptors.
Discovered Client Characteristic Configuration for Characteristic Heart Rate Measurement
Discovered Client Characteristic Configuration for Characteristic Battery Level
Characteristic FB005C21-02E7-F387-1CAD-8ACD2D8DF0C8 has no Descriptors.
Discovered Client Characteristic Configuration for Characteristic FB005C22-02E7-F387-1CAD-8ACD2D8DF0C8
Discovered Client Characteristic Configuration for Characteristic FB005C26-02E7-F387-1CAD-8ACD2D8DF0C8
Characteristic 6217FF4C-C8EC-B1FB-1380-3AD986708E2D has no Descriptors.
Discovered Client Characteristic Configuration for Characteristic 6217FF4D-91BB-91D0-7E2A-7CD3BDA8A1F3
Discovered Client Characteristic Configuration for Characteristic FB005C81-02E7-F387-1CAD-8ACD2D8DF0C8
Discovered Client Characteristic Configuration for Characteristic FB005C82-02E7-F387-1CAD-8ACD2D8DF0C8

Light blue shows heart rate is at 2a37

BLE scanner shows heart rate 180d as primary service

Yes. This is what the previous sketch used. Service 180d and characteristic 2a37.
Does it fail to connect or fail to find the chacteristic.

Fail to connect

Now that you know the service aid characteristic you want perhaps try and get some library example code to connect. Reaping the characteristic will be dealt with after you figure out the connection issue.

CONNECTED! Thank you!
But it's not showing heart rate.

I'm getting heart rate as 1350 or 1349 but its not changing with my actual heart.

#include <ArduinoBLE.h>

const char* deviceName = "Polar Sense A8A43128";  // Replace with the exact name of your device
BLEDevice peripheral;

BLECharacteristic heartRateMeasurementCharacteristics;

void setup() {
  Serial.begin(9600);  // Initialize serial communication at 9600 baud
  while (!Serial);  // Wait for Serial to be ready

  if (!BLE.begin()) {  // Initialize BLE
    Serial.println("Failed to initialize BLE!");
    while (1);
  }

  Serial.println("Scanning for Polar Sense A8A43128...");
  BLE.scanForName(deviceName);  // Start scanning for peripherals with the given name
}

void loop() {
  BLEDevice foundPeripheral = BLE.available();  // Check for discovered peripheral devices

  if (foundPeripheral) {
    if (strcmp(foundPeripheral.localName().c_str(), deviceName) == 0) {
      Serial.println("Device found, trying to connect...");
      peripheral = foundPeripheral;
      BLE.stopScan();

      if (peripheral.connect()) {
        Serial.println("Connected");

        if (peripheral.discoverAttributes()) {
          Serial.println("Attributes discovered");

          heartRateMeasurementCharacteristics = peripheral.characteristic("2a37");

          if (!heartRateMeasurementCharacteristics) {
            Serial.println("Peripheral does not have heart rate measurement characteristic!");
            peripheral.disconnect();
            return;
          } else {
            Serial.println("Subscribing to heart rate notifications...");
            heartRateMeasurementCharacteristics.subscribe();
          }
        } else {
          Serial.println("Attribute discovery failed!");
          peripheral.disconnect();
          return;
        }
      } else {
        Serial.println("Failed to connect!");
        return;
      }
    }
  }

  if (peripheral.connected() && heartRateMeasurementCharacteristics.valueUpdated()) {
    byte buffer[8];
    int len = heartRateMeasurementCharacteristics.valueLength();

    Serial.print("Received data length: ");
    Serial.println(len);

    heartRateMeasurementCharacteristics.readValue(buffer, len);

    bool isShort = bitRead(buffer[0], 0);
    int bpm = isShort ? buffer[1] : ((buffer[2] << 8) | buffer[1]);

    Serial.print("Heart rate: ");
    Serial.println(bpm);
  }
}

Try printing ou all bytes read in the chara teristic as hex and see if any make sense to you as beats per minute

Received bytes: 0 4E
Received bytes: 0 4E
Received bytes: 0 4E
Received bytes: 0 4E
Received bytes: 0 4E

This is all I get. Sometimes it goes to 50 or down to 30 but not looking like a HR

I got a heart rate!!!

Peripheral found, stopping scan...
Connected.
Attributes discovered.
Subscribed to heart rate measurements.
Received data length: 2
Heart rate: 67 bpm
No new values.

`#include <ArduinoBLE.h>

const char* deviceName = "Polar Sense A8A43128";
const char* serviceUUID = "180D";
const char* charUUID = "2A37";

BLEDevice peripheral;
BLEService heartRateService;
BLECharacteristic heartRateMeasurementCharacteristics;

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

  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");
    while (1);
  }

  Serial.println("Scanning for peripherals...");
}

void loop() {
  BLE.scan();
  peripheral = BLE.available();
  
  if (peripheral) {
    if (strcmp(peripheral.localName().c_str(), deviceName) == 0) {
      Serial.println("Peripheral found, stopping scan...");
      BLE.stopScan();
      if (peripheral.connect()) {
        Serial.println("Connected.");
        if (peripheral.discoverAttributes()) {
          Serial.println("Attributes discovered.");
          heartRateService = peripheral.service(serviceUUID);
          if (heartRateService) {
            heartRateMeasurementCharacteristics = heartRateService.characteristic(charUUID);
            if (heartRateMeasurementCharacteristics) {
              if (heartRateMeasurementCharacteristics.subscribe()) {
                Serial.println("Subscribed to heart rate measurements.");
              } else {
                Serial.println("Subscription failed!");
              }
            } else {
              Serial.println("Characteristic not found!");
            }
          } else {
            Serial.println("Service not found!");
          }
        } else {
          Serial.println("Attribute discovery failed!");
          peripheral.disconnect();
        }
      } else {
        Serial.println("Failed to connect!");
      }
    }
  }

  if (peripheral.connected() && heartRateMeasurementCharacteristics.valueUpdated()) {
    byte buffer[8];
    int len = heartRateMeasurementCharacteristics.valueLength();

    Serial.print("Received data length: ");
    Serial.println(len);

    heartRateMeasurementCharacteristics.readValue(buffer, len);

    byte flags = buffer[0];
    int bpm = 0;
    if (bitRead(flags, 0) == 0) {
      bpm = buffer[1];
    } else {
      bpm = (buffer[2] << 8) | buffer[1];
    }

    Serial.print("Heart rate: ");
    Serial.print(bpm);
    Serial.println(" bpm");
  }
if (peripheral.connected()) {
  if (heartRateMeasurementCharacteristics.valueUpdated()) {
    Serial.println("Value updated.");
    // ... rest of your code
  } else {
    Serial.println("No new values.");
  }
}

  delay(1000);
}
`

I can read the heart rate once but cannot get it to show current. When I try to get it to loop I get these messages and no BPM.

  • Serial Monitor
    New Line
    9600 baud
    No new values.
    Peripheral found, stopping scan...
    Connected.
    Attribute discovery failed!
    No new values.
    No new values.
    Peripheral found, stopping scan...
    Connected.
    Attribute discovery failed!
#include <ArduinoBLE.h>

const char* deviceName = "Polar Sense A8A43128";
const char* serviceUUID = "180D";
const char* charUUID = "2A37";

BLEDevice peripheral;
BLEService heartRateService;
BLECharacteristic heartRateMeasurementCharacteristics;

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

  if (!BLE.begin()) {
    Serial.println("starting BLE failed!");
    while (1);
  }

  Serial.println("Scanning for peripherals...");
}

void readHeartRate() {
  if (peripheral.connected() && heartRateMeasurementCharacteristics.valueUpdated()) {
    byte buffer[8];
    int len = heartRateMeasurementCharacteristics.valueLength();

    heartRateMeasurementCharacteristics.readValue(buffer, len);

    byte flags = buffer[0];
    int bpm = 0;
    if (bitRead(flags, 0) == 0) {
      bpm = buffer[1];
    } else {
      bpm = (buffer[2] << 8) | buffer[1];
    }

    Serial.print("Heart rate: ");
    Serial.print(bpm);
    Serial.println(" bpm");
  } else {
    Serial.println("No new values.");
  }
}

void loop() {
  BLE.scan();
  peripheral = BLE.available();
  
  if (peripheral) {
    if (strcmp(peripheral.localName().c_str(), deviceName) == 0) {
      Serial.println("Peripheral found, stopping scan...");
      BLE.stopScan();
      if (peripheral.connect()) {
        Serial.println("Connected.");
        if (peripheral.discoverAttributes()) {
          Serial.println("Attributes discovered.");
          heartRateService = peripheral.service(serviceUUID);
          if (heartRateService) {
            heartRateMeasurementCharacteristics = heartRateService.characteristic(charUUID);
            if (heartRateMeasurementCharacteristics) {
              if (heartRateMeasurementCharacteristics.subscribe()) {
                Serial.println("Subscribed to heart rate measurements.");
              } else {
                Serial.println("Subscription failed!");
              }
            } else {
              Serial.println("Characteristic not found!");
            }
          } else {
            Serial.println("Service not found!");
          }
        } else {
          Serial.println("Attribute discovery failed!");
          peripheral.disconnect();
        }
      } else {
        Serial.println("Failed to connect!");
      }
    }
  }

  readHeartRate();
  delay(1000);
}

Maybe sign-up for this webinar: