Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using BLE for Heart Rate Monitors, newer belts don't work #837

Closed
Vulture-in-the-woods opened this issue Mar 18, 2019 · 15 comments
Closed

Comments

@Vulture-in-the-woods
Copy link

Vulture-in-the-woods commented Mar 18, 2019

Hi Neil.

First of all thank you for your library and the subsequent work you've been putting in it.

I've been using your library together with the ESP32 and a 64x32 RGB LED matrices to show my Heart rate while I work out. The idea is based on a sketch by Andreas Spiess, which I use as a test/benchmark file.
I've been using it toghter with a Polar H7 pulse belt and everything has been working like a charm, so far.

Now I've gotten two new puls pelts, the Polar H10 and the Wahoo Tickr.
Both of them show the same GATT with the Service UUID 0x180D and CharUUID 0x2A37
Neither connects to the ESP32, that is, they get to the "- Created client" step, but not the "- Connected to server" which is given by these lines of code:

BLEClient* pClient = BLEDevice::createClient();
Serial.println(" - Created client");

// Connect to the remove BLE Server.
pClient->connect(pAddress);
Serial.println(" - Connected to server");

I've tried changing the CharUUID in case the sensor had 0x2A38 or 0x2A39 instead for what ever reason, but nothing helps.

I can find both belts on my Iphone SE, and connect to them via apps like the Wahoo Fitness app, Polar Beat and Endomondo.

I can also see them via the nRF Connect app and verify that the serviceUUID infact is 0x180D

The common denominator for these belt are that they have some sort of extra capacity, primarily memory function

My questions are:

What is the difference which prohibits me from connecting the ESP32 to the pulse belt?
Which measures could be taken to make the BLE connection work in order for the belts to connect to the ESP32?

Best Regards
Erik

bluetooth_andreass_spiess.zip

@chegewara
Copy link
Collaborator

Hi,
if you are using latest ble arduino version then try this:
pClient->connect(pAddress, 1);

@Vulture-in-the-woods
Copy link
Author

Hi chegewara

Thank you for your input.

Unfortunately that did not compile.
I have update the library.

//Erik

error message:
.....Arduino\libraries\ESP32_BLE_Arduino-master\src/BLEClient.h:37:45: note: initializing argument 2 of 'bool BLEClient::connect(BLEAddress, esp_ble_addr_type_t)'

bool connect(BLEAddress address, esp_ble_addr_type_t type = BLE_ADDR_TYPE_PUBLIC); // Connect to the remote BLE Server

exit status 1
invalid conversion from 'int' to 'esp_ble_addr_type_t' [-fpermissive]

@chegewara
Copy link
Collaborator

pClient->connect(pAddress, (esp_ble_addr_type_t)1);
or
pClient->connect(pAddress, BLE_ADDR_TYPE_RANDOM);

Sorry, i didnt remember that enum value: BLE_ADDR_TYPE_RANDOM

@Vulture-in-the-woods
Copy link
Author

pClient->connect(pAddress,(esp_ble_addr_type_t)1) compiles nicely, but I'm not at the lab right now, I will test it in a few hours, thanks.

But I didn't get why? what is BLE_ADDR_TYPE_RANDOM and what difference does it do?
Sorry for being daft, I'm a Master student doing Microwave Hardware design, programming is a useful tool for me, but not the core of my abilities/understanding.

@chegewara
Copy link
Collaborator

It just tells what kind of address should expect.
Some time ago i thought i will add this option to fix some issues with connecting to sensors/servers. I know it is confusing and for backward compatibility i left this parameter with value that was hardcoded earlier.

esp-idf stack is evaluating and some options and/or functionalities are introduced, so ive been trying to follow it.

@Vulture-in-the-woods
Copy link
Author

It works.!

Thank you Chegewara.

I have tested several pulse belts, and for some the line "pClient->connect(pAddress);" work well

and for others the line "pClient->connect(pAddress, (esp_ble_addr_type_t)1);" works

I see no difference on using
pClient->connect(pAddress, (esp_ble_addr_type_t)1);
or
pClient->connect(pAddress, BLE_ADDR_TYPE_RANDOM);

but neither is generic for the four different HRM devices I've tested.

But for all practical purposes it works, and I am gratefull.

//Erik

@chegewara
Copy link
Collaborator

pClient->connect(pAddress, (esp_ble_addr_type_t)1);
and
pClient->connect(pAddress, BLE_ADDR_TYPE_RANDOM);
are equal.
BLE_ADDR_TYPE_RANDOM is equal 1 in enumerator definition.

@me-chiel
Copy link

I wonder if any of you can help. I've got the Polar H9 and with the code it finds the service, and connects, and then crashes due to a stack overflow error.
I'm rather new to this, and tried the other connect options you proposed...
the result ending in the same stack overflow error.

  • Created client
  • Connected to server
    Guru Meditation Error: Core 0 panic'ed (Unhandled debug exception).
    Debug exception reason: Stack canary watchpoint triggered (BTU_TASK)
    Core 0 register dump:
    PC : 0x40093ed6 PS : 0x00050d36 A0 : 0x40092007 A1 : 0x3ffd6a50
    A2 : 0x00050d23 A3 : 0x00000000 A4 : 0x3ffd6c50 A5 : 0x40091f34
    A6 : 0x00000000 A7 : 0x00000008 A8 : 0x8008b8cc A9 : 0x3ffbe830
    A10 : 0x00000001 A11 : 0x00000000 A12 : 0x3ffc230c A13 : 0x3ffb9274
    A14 : 0x3ff71010 A15 : 0x00060823 SAR : 0x0000001c EXCCAUSE: 0x00000001
    EXCVADDR: 0x00000000 LBEG : 0x4008f668 LEND : 0x4008f67e LCOUNT : 0xffffffff

Backtrace:0x40093ed3:0x3ffd6a500x40092004:0x3ffd6a90 0x40091fb6:0xa5a5a5a5 |<-CORRUPTED

any idea how I could fix this? And sorry for posting on this old link. Any help would be appreciated..

@chegewara
Copy link
Collaborator

Stack canary watchpoint triggered (BTU_TASK)

You have problem with your code.

@me-chiel
Copy link

I wonder if any of you can help. I've got the Polar H9 and with the code it finds the service, and connects, and then crashes due to a stack overflow error.
I'm rather new to this, and tried the other connect options you proposed...
the result ending in the same stack overflow error.

  • Created client
  • Connected to server
    Guru Meditation Error: Core 0 panic'ed (Unhandled debug exception).
    Debug exception reason: Stack canary watchpoint triggered (BTU_TASK)
    Core 0 register dump:
    PC : 0x40093ed6 PS : 0x00050d36 A0 : 0x40092007 A1 : 0x3ffd6a50
    A2 : 0x00050d23 A3 : 0x00000000 A4 : 0x3ffd6c50 A5 : 0x40091f34
    A6 : 0x00000000 A7 : 0x00000008 A8 : 0x8008b8cc A9 : 0x3ffbe830
    A10 : 0x00000001 A11 : 0x00000000 A12 : 0x3ffc230c A13 : 0x3ffb9274
    A14 : 0x3ff71010 A15 : 0x00060823 SAR : 0x0000001c EXCCAUSE: 0x00000001
    EXCVADDR: 0x00000000 LBEG : 0x4008f668 LEND : 0x4008f67e LCOUNT : 0xffffffff

Backtrace:0x40093ed3:0x3ffd6a500x40092004:0x3ffd6a90 0x40091fb6:0xa5a5a5a5 |<-CORRUPTED

any idea how I could fix this? And sorry for posting on this old link. Any help would be appreciated..

Stack canary watchpoint triggered (BTU_TASK)

You have problem with your code.

sadly it happens a bit random. I'll do my best to have a closer look at it later this weekend!

@imaimai17468
Copy link

imaimai17468 commented Dec 6, 2021

I am now in the same situation as me-chiel.
In my case, this happens when I use getService().
We are not using a particularly large array, and there seems to be plenty of free memory space.
I also increased the stack size in xTaskCreateUniversal() in the esp32 settings, but it did not improve the problem.
Here is the code used and the output of the serial communication.

I would appreciate it if you could tell me how to improve this problem.

//===== header file & define & global variable =====
#include <M5Stack.h>
#include "BLEDevice.h"

#include <esp_bt_main.h>
#include "esp_pm.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#define sleep_ms(ms)  vTaskDelay( (ms)/portTICK_PERIOD_MS )

static bool doConnect = false;
static bool isConnected = false;
static bool doScan = false;
static bool isScanContinue = true;
static int count = 0;

static BLEUUID serviceUUID ("0000180d-0000-1000-8000-00805f9b34fb");
static BLEUUID charUUID ("00002a37-0000-1000-8000-00805f9b34fb");

static BLEAdvertisedDevice* myh10;
static BLEClient* pClient_h10;

String h10Name = "Polar H10 68D9F22F";

int time_h10 = 0;
int h10_dot = 0;

File h10file;

#define IP5306_ADDR (117) // 0x75
#define IP5306_REG_SYS_CTL1 (0x01)
#define BOOST_ENABLE_BIT (0x20)
//===========================================


//===== class & function ====================
void poweroff(){
  uint8_t data;
  M5.Lcd.setBrightness(0);
  M5.Lcd.sleep();
  if (M5.I2C.readByte(IP5306_ADDR, IP5306_REG_SYS_CTL1, &data) == true){
    M5.I2C.writeByte(IP5306_ADDR, IP5306_REG_SYS_CTL1, (data & (~BOOST_ENABLE_BIT)));
  }
  esp_bluedroid_disable();
  esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
  gpio_deep_sleep_hold_dis();
  M5.Power.setPowerBoostKeepOn(false);
  M5.Power.setLowPowerShutdownTime(POWER::ShutdownTime::SHUTDOWN_8S);
  M5.Power.setPowerBtnEn(true);
  esp_deep_sleep_start();
}

class MyClientCallback: public BLEClientCallbacks {
    void onConnect(BLEClient* pclient) { }
    void onDisconnect(BLEClient* pclient) {
      isConnected = false;
      Serial.print("onDisconnect: ");
      Serial.println(++count);
      M5.Lcd.println("onDisconnetct");

      if(isScanContinue){
        BLEDevice::getScan()->erase(pClient_h10->getPeerAddress());
      }
      delete myh10;
      delete pClient_h10;
    }
};

class MyAdvertisedDeviceCallback: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      // Serial.println(advertisedDevice.toString().c_str());

      if (h10Name.equals(advertisedDevice.getName().c_str())) {
        Serial.print("Connect BLE device : ");
        Serial.println(advertisedDevice.toString().c_str());
        myh10 = new BLEAdvertisedDevice(advertisedDevice);
        BLEDevice::getScan()->stop();
        doConnect = true;
        doScan = true;
      }
    }
};

void notifyCallback_h10(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) {
  int hr = pData[1];
  int16_t ppi = 0;
  std::vector<int> times;
  for (int i = 2; i < length; i += 2) {
    ppi = pData[i] | (pData[i + 1] << 8);

    times.push_back(ppi);
  }

  for (int i = 0; i < times.size(); i++) {
    times[i] /= 1.024;
  }

  for (int i = 0; i < times.size(); i++) {
    time_h10 += times[i];
    h10_dot++;

    String data = "[H10] count : " + String(h10_dot) + ", ppi [ms] : " + String(times[i]) + ", time sum [s] : " + String(time_h10 / 1000.0, 3);
    Serial.println(data);

    String sd_data = String(h10_dot) + "," + String(times[i]) + "," + String(time_h10 / 1000.0, 3);
    h10file.println(sd_data);

    M5.Lcd.fillRect(0, 95, 1000, 50, BLACK);
    M5.Lcd.setCursor(0, 95);
    M5.Lcd.setTextSize(4);
    M5.Lcd.print(time_h10 / 1000.0, 3);
    M5.Lcd.print(", ");
    M5.Lcd.print(times[i]);
  }
}

void indicateCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) {
  Serial.print("Indicate callback for characteristic ");
  Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
  Serial.print(" of data length ");
  Serial.println(length);
  Serial.print("data: ");
  for (int i = 0; i < length; i++) {
    Serial.printf("%02x", pData[i]);
    Serial.print(" ");
  }
  Serial.println();
}

bool connectToServer() {
  Serial.print("connection to : ");
  Serial.println(myh10->getAddress().toString().c_str());
  pClient_h10 = BLEDevice::createClient();
  Serial.println(" - Created client (h10)");

  Serial.print("1-BLE FreeHeap: ");
  Serial.println(ESP.getFreeHeap());
  pClient_h10->setClientCallbacks(new MyClientCallback() );
  
  bool _connected = pClient_h10->connect(myh10);
  if(!_connected){
    Serial.println(" - failed to server (h10)");
    delete pClient_h10;
    delete myh10;
    return false;
  }
  Serial.println(" - Created to server (h10)");
  
  Serial.print("2-BLE FreeHeap: ");
  Serial.println(ESP.getFreeHeap());

  // service uuid
  BLERemoteService* pRemoteService_h10 = pClient_h10->getService(serviceUUID);
  if (pRemoteService_h10 == nullptr) {
    Serial.println("Failed to find our service UUID: ");
    Serial.println(serviceUUID.toString().c_str());
    pClient_h10->disconnect();
    return false;
  }
  Serial.print(" - Found service ( ");
  Serial.print(serviceUUID.toString().c_str());
  Serial.println(" )");

  Serial.print("3-BLE FreeHeap: ");
  Serial.println(ESP.getFreeHeap());

  // char uuid
  static BLERemoteCharacteristic* pRemoteCharacteristic;
  pRemoteCharacteristic = pRemoteService_h10->getCharacteristic(charUUID);
  if ( pRemoteCharacteristic == nullptr ) {
    Serial.print("Failed to find out characteristic UUID : ");
    Serial.println(charUUID.toString().c_str());
    pClient_h10->disconnect();
    return false;
  }
  Serial.print(" - Add Notify ( ");
  Serial.print(charUUID.toString().c_str());
  Serial.println(" )");

  Serial.print("4-BLE FreeHeap: ");
  Serial.println(ESP.getFreeHeap());

  // notify h10
  if (pRemoteCharacteristic->canNotify()) {
    Serial.println(" - Can Notify h10");
    pRemoteCharacteristic->registerForNotify(notifyCallback_h10);
  }

  isConnected = true;
  return true;
}
//===========================================


//===== setting =============================
void setup() {
  M5.begin();
  M5.Power.begin();

  esp_pm_config_esp32_t esp_pm_config_esp32;
  esp_pm_config_esp32.max_freq_mhz = RTC_CPU_FREQ_240M;
  esp_pm_config_esp32.min_freq_mhz = RTC_CPU_FREQ_XTAL;
  esp_pm_config_esp32.light_sleep_enable = true;
  esp_pm_configure(&esp_pm_config_esp32);

  // LCD settings
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setBrightness(128);
  M5.Lcd.setCursor(0, 0);

  if (!SD.begin()) {
    M5.Lcd.println("Card failed, or not present");
    while (1) { sleep_ms(1); }
  }

  // SD card
  M5.Lcd.println("check csv...");
  if ( SD.exists("/h10.csv") == true ) {
    M5.Lcd.println("csv will be destroyed. OK? ");
    M5.Lcd.println("OK -> Button A");
    M5.Lcd.println("NO -> Button B (stop)");
    while ( M5.BtnA.wasReleased() == false ) {
      M5.update();
      if ( M5.BtnB.wasReleased() ){
        while(1){ sleep_ms(1); }
      }
    }
  }
  SD.remove("/h10.csv");
  h10file = SD.open("/h10.csv", FILE_WRITE);
  M5.Lcd.println("opened h10.csv!");
  M5.Lcd.clear(BLACK);

  // display settings
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextSize(2);
  M5.Lcd.println(h10Name.c_str());
  M5.Lcd.setTextSize(4);
  M5.Lcd.println("Unknown");
  M5.Lcd.println();
  M5.Lcd.setTextSize(2);
  M5.Lcd.println("Button A -> finish");
  M5.Lcd.println("Button B -> display off");
  M5.Lcd.println("Button C -> display on");

  // start ble
  Serial.print("BLE FreeHeap: ");
  Serial.println(ESP.getFreeHeap());
  Serial.println("Starting Arduino BLE Client application...");
  BLEDevice::init("");
  BLEDevice::setMTU(232);
  static BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallback());
  pBLEScan->setInterval(1349);
  pBLEScan->setWindow(449);
  pBLEScan->setActiveScan(true);
  pBLEScan->start(5, false);
}
//===========================================


//===== main ================================
void loop() {
  M5.update();

  // A:finish, B:diplay off, C:display on
  if ( M5.BtnA.wasReleased() || M5.Power.getBatteryLevel() == 0 ) {
    M5.Lcd.clear(BLACK);
    M5.Lcd.setTextSize(2);
    M5.Lcd.setCursor(0, 0);

    pClient_h10->disconnect();
    delete(pClient_h10);
    h10file.close();
    Serial.println("SD Filse close");
    while (isConnected == true){
      sleep_ms(1);
    }

    poweroff();
  }
  if ( M5.BtnB.wasReleased() ) {
    M5.Lcd.setBrightness(0);
  }
  if ( M5.BtnC.wasReleased() ) {
    M5.Lcd.setBrightness(128);
  }

  if (doConnect == true) {
    if (connectToServer()) {
      Serial.println("now connected to BLE Server.");
    } else {
      Serial.println("faild to connect to the server.");
    }
    doConnect = false;
  }

  if ( isConnected == false && doScan == true ) BLEDevice::getScan()->start(0);
  
  sleep_ms(1000);
}
//===========================================
BLE FreeHeap: 218096
Starting Arduino BLE Client application...
Connect BLE device : Name: Polar H10 68D9F22F, Address: de:e1:43:dd:bc:64, manufacturer data: 6b00230b5251, serviceUUID: 0000180d-0000-1000-8000-00805f9b34fb, serviceUUID: 0000feee-0000-1000-8000-00805f9b34fb, txPower: 4
connection to : de:e1:43:dd:bc:64
 - Created client (h10)
1-BLE FreeHeap: 133216
 - Created to server (h10)
2-BLE FreeHeap: 127088
Guru Meditation Error: Core  0 panic'ed (Unhandled debug exception). 
Debug exception reason: Stack canary watchpoint triggered (BTU_TASK) 
Core  0 register dump:
PC      : 0x40095f22  PS      : 0x00050036  A0      : 0x400945c7  A1      : 0x3ffd7b50  
A2      : 0x00050023  A3      : 0x00000000  A4      : 0x00000001  A5      : 0x400944f4  
A6      : 0x00060a23  A7      : 0x00000008  A8      : 0x80085a6e  A9      : 0x3ffbe900  
A10     : 0x00000000  A11     : 0x3ffbe900  A12     : 0x00000000  A13     : 0x00060023  
A14     : 0x00000001  A15     : 0x3ffd1820  SAR     : 0x00000008  EXCCAUSE: 0x00000001  
EXCVADDR: 0x00000000  LBEG    : 0x40090cec  LEND    : 0x40090d02  LCOUNT  : 0xffffffff  


Backtrace:0x40095f1f:0x3ffd7b500x400945c4:0x3ffd7b90 0x40094576:0xa5a5a5a5  |<-CORRUPTED

@FIXMBR
Copy link

FIXMBR commented Dec 25, 2021

I was having the same issue as @me-chiel and @imaimai17468 with Polar H10. I switched from arduino to platfrom.io and it just magically worked.

@FIXMBR
Copy link

FIXMBR commented Dec 25, 2021

As it turns out platformio uses outdated arduino-esp32 1.0, the issue happens when you use 2.0.0+ version of the library.
You can simply change esp version to 1.0.6 in boards manager to make it work. I'm gonna write an issue on the official repo to get it fixed in future.

@me-chiel
Copy link

me-chiel commented Dec 25, 2021 via email

@adojang
Copy link

adojang commented Jun 10, 2022

As it turns out platformio uses outdated arduino-esp32 1.0, the issue happens when you use 2.0.0+ version of the library. You can simply change esp version to 1.0.6 in boards manager to make it work. I'm gonna write an issue on the official repo to get it fixed in future.

Just wanted to say thank you for this, this fixed the issue for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants