如何在 Polar H10 中解码心电图数据帧?

问题描述 投票:0回答:2

我使用ArduinoBLE.h库连接Polar H10并参考此文档获取心电图数据。

我已成功开始流式传输并从自定义特征 UUID“FB005C82-02E7-F387-1CAD-8ACD2D8DF0C8”获取信息。

这是获得的信息:

(0x) 00-14-D1-22

这代表心电图吗?我应该如何提取它?

另外,如何修改

sampling_rate
?它没有显示在文档中。

下面是我的代码:

#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();
    }
  }
}

下面是输出:

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

以下是提到的文档提供的部分信息。 enter image description here enter image description here

c arduino bluetooth-lowenergy arduino-c++
2个回答
1
投票

心电图信号不是我的领域,但这里有一些建议。

Electrocardiogram
的大小是3B,其单位是uV作为
Frame types ECG
的描述,因此提取输出的前3个八位字节并尝试用大端或小端来解释它们。

0-5E-AB-8A
将为 0x005EAB=24235uV 或 0xAB5E00=11230720uV

0-19-6B-FA
将为 0x00196B=6507uV 或 0x6B1900=7018752uV

0-56-DB-69
将为 0x0056DB=22235uV 或 0xDB5600=14374400uV

0-E6-31-8
将为 0x00E631=58929uV 或 0x31E600=3270144uV

big-endian解释的结果看起来更合理。

void readData(const uint8_t *data) {
  int size = sizeof(data) / sizeof(data[0]);

表达式

sizeof(data)
实际上显示了指针
data
的大小,因此
size
的值将是一个由编译器确定的常量,即4,而不是在运行时确定,这会导致每个输出只有四个八位字节。 如果将
PMD_Data.value()
结果的总大小分配给
size
,则输出可能具有更多八位字节,正如
RFU
中描述的
Frame types ECG
字段。


0
投票

我将其开发为一个 Python 示例,说明如何从 Polar 设备捕获 ECG 和 ACC 数据。

[电子邮件受保护]:stuartlynne/bleexplore.git

© www.soinside.com 2019 - 2024. All rights reserved.