Reputation: 21
I'm using ArduinoBLE.h library to connect Polar H10 and refer to this documentation to obtain the ECG data.
I have managed to start streaming and get info from the Custom Characteristic UUID "FB005C82-02E7-F387-1CAD-8ACD2D8DF0C8".
This is the information that was obtained:
(0x) 00-14-D1-22
Is this represent the ECG and how should I extract it?
Also, how to modify the sampling_rate
? It does not show in the documentation.
Below is my code:
#include <ArduinoBLE.h>
#define BLE_ARDUINO_NAME "Arduino"
// Polar Gatt Service and Characteristics
#define PMD_SERVICE_UUID "FB005C80-02E7-F387-1CAD-8ACD2D8DF0C8"
#define PMD_CONTROL_CHARACTERISTIC_UUID "FB005C81-02E7-F387-1CAD-8ACD2D8DF0C8"
#define PMD_DATA_CHARACTERISTIC_UUID "FB005C82-02E7-F387-1CAD-8ACD2D8DF0C8"
#define POLAR_HR_SERVICE_UUID "180D"
#define POLAR_HR_CHARACTERISTIC_UUID "2A37"
// Polar H10 Sampling Frequency
#define POLAR_SAMPLE_RATE 130
// POLAR_HR_CHARACTERISTIC_UUID FLAG VALIDATE
#define ENERGY_EXPENDED_PRESENT_BIT 3
#define RR_INTERVAL_PRESENT_BIT 4
#define HEART_RATE_FORMAT_BIT 0
// Unit Measurement Convert Parameter
#define RR_INTERVAL_UNIT 1024
// Control Parameters
bool scanRequried = true;
bool requestStreamRequired = true;
BLEDevice POLAR_Peripheral;
BLEService HR_Service;
BLECharacteristic HR_Characteristic;
BLEService PMD_Service;
BLECharacteristic PMD_Control;
BLECharacteristic PMD_Data;
void polarPMD() {
PMD_Service = POLAR_Peripheral.service(PMD_SERVICE_UUID);
if (!PMD_Service.hasCharacteristic(PMD_CONTROL_CHARACTERISTIC_UUID))
Serial.println("PMD_CONTROL_CHARACTERISTIC_UUID Not Found");
else if (!PMD_Service.hasCharacteristic(PMD_DATA_CHARACTERISTIC_UUID))
Serial.println("PMD_DATA_CHARACTERISTIC_UUID Not Found");
PMD_Control = PMD_Service.characteristic(PMD_CONTROL_CHARACTERISTIC_UUID);
PMD_Data = PMD_Service.characteristic(PMD_DATA_CHARACTERISTIC_UUID);
PMD_Control.subscribe();
PMD_Data.subscribe();
}
void requestECGStream() {
if (requestStreamRequired) {
// Request Stream Setting
const uint8_t REQUEST_STREAM[] = {0x01,0x02};
const uint8_t REQUEST_ECG[] = {0x01,0x00};
if (PMD_Control.writeValue(REQUEST_STREAM, 2))
Serial.println("Success 0x01,0x02");
if (PMD_Control.writeValue(REQUEST_ECG, 2))
Serial.println("Success 0x01,0x00");
requestStreamRequired = false;
}
}
void startStream() {
const uint8_t REQUEST_STREAM[] = {0x02, 0x00, 0x00, 0x01, 0x82, 0x00, 0x01, 0x01, 0x0E, 0x00};
PMD_Control.writeValue(REQUEST_STREAM, 10);
while (POLAR_Peripheral.connected()) {
if (PMD_Data.valueUpdated()) {
PMD_Data.read();
readData(PMD_Data.value());
Serial.println();
}
}
polarDisconnect();
scanRequried = true;
requestStreamRequired = true;
}
void readData(const uint8_t *data) {
int size = sizeof(data) / sizeof(data[0]);
for (int i = 0; i < size; i++) {
unsigned char c = data[i];
Serial.print(c, HEX);
if (i < size - 1) {
Serial.print("-");
}
}
Serial.println("");
}
bool polarDataValid () {
if (!POLAR_Peripheral.discoverAttributes()) {
Serial.println("* Attributes discovery failed!");
Serial.println(" ");
polarDisconnect();
return false;
}
return true;
}
void polarDisconnect() {
POLAR_Peripheral.disconnect();
Serial.println("Decive Disconnected...");
scanRequried = true;
requestStreamRequired = true;
}
void polarConnect() {
Serial.println("Connecting to the device...");
if (POLAR_Peripheral.connect()) {
Serial.println("* Connected");
Serial.println(" ");
} else {
Serial.println("* Ops, Fail Connection");
Serial.println(" ");
scanRequried = true;
requestStreamRequired = true;
}
}
bool polarDiscover () {
BLEDevice peripheral;
Serial.println("Searching HEART RATE SERVICE device...");
do
{
BLE.scanForUuid(POLAR_HR_SERVICE_UUID);
peripheral = BLE.available();
} while (!peripheral);
if (peripheral) {
Serial.println("* POLAR H10 device found!");
Serial.print("* Device MAC address: ");
Serial.println(peripheral.address());
Serial.print("* Device name: ");
Serial.println(peripheral.localName());
Serial.print("* Advertised service UUID: ");
Serial.println(peripheral.advertisedServiceUuid());
Serial.println(" ");
BLE.stopScan();
scanRequried = false;
}
POLAR_Peripheral = peripheral;
}
void setup() {
Serial.begin(9600);
while (!Serial) {
Serial.println("Serial Initialization Failed.");
}
// begin initialization
while (!BLE.begin()) {
Serial.println("starting Bluetooth® Low Energy module failed!");
}
BLE.setDeviceName(BLE_ARDUINO_NAME);
BLE.setLocalName(BLE_ARDUINO_NAME);
BLE.advertise();
Serial.println(String(BLE_ARDUINO_NAME) + " (Central Device)");
Serial.println("");
}
void loop() {
// Find Polar Device and Connect it.
if (scanRequried) {
polarDiscover();
polarConnect();
}
if (polarDataValid()) {
polarPMD();
requestECGStream();
if(!requestStreamRequired) {
startStream();
}
}
}
and below is the output:
Arduino (Central Device)
Searching HEART RATE SERVICE device...
* POLAR H10 device found!
* Device MAC address: c0:d2:62:ca:3d:46
* Device name: Polar H10 B1915225
* Advertised service UUID: 180d
Connecting to the device...
* Connected
Success 0x01,0x02
Success 0x01,0x00
0-5E-AB-8A
0-19-6B-FA
0-56-DB-69
0-E6-31-8
Below is the parts of the information provided by the documentation mentioned.
Upvotes: 0
Views: 1288
Reputation: 141
ECG signal is not my area, but here are some suggestions.
the size of Electrocardiogram
is 3B and its unit is uV as the description of the Frame types ECG
, so extract the leading 3 octets of the outputs and try explaining them in either big-endian or little-endian.
0-5E-AB-8A
would be either 0x005EAB=24235uV or 0xAB5E00=11230720uV
0-19-6B-FA
would be either 0x00196B=6507uV or 0x6B1900=7018752uV
0-56-DB-69
would be either 0x0056DB=22235uV or 0xDB5600=14374400uV
0-E6-31-8
would be either 0x00E631=58929uV or 0x31E600=3270144uV
the results explained by big-endian look more reasonable.
void readData(const uint8_t *data) {
int size = sizeof(data) / sizeof(data[0]);
The expression sizeof(data)
brings out the size of the pointer data
actually, so the value of size
would be a constant number which is determined by the compiler, i.e. 4, not in the runtime and this results in every output has only four octets.
If the total size of the result of PMD_Data.value()
is assigned to size
, the output might have more octets just as the RFU
field described in the Frame types ECG
.
Upvotes: 1