micooke / arduino-nRF5-smartwatches

Smartwatch variants for sandeepmistry's Nordic Semiconductor nRF5 core
MIT License
62 stars 13 forks source link

BLE Central Role #2

Closed dmikhalsky closed 5 years ago

dmikhalsky commented 7 years ago

Have you tried to use BLE Central role with the watches? arduino-org library works fine on nrf52 chip, but I wasn't able to make it working with nrf51. I need this to display my external HR sensor data (it works at the bench, but with nrf52 only)

micooke commented 7 years ago

It seems like we have similar goals :smile:

Sorry, can you provide an example? I have a hrm example using sandeeps library https://github.com/sandeepmistry/arduino-BLEPeripheral which is based on https://github.com/sandeepmistry/arduino-BLEPeripheral/blob/master/examples/temp_sensor/temp_sensor.ino

I used dummy data and could see it on my tomtom multisport, as well as my android phone using nordics app https://play.google.com/store/apps/details?id=no.nordicsemi.android.nrftoolbox

micooke commented 7 years ago

Best bet is to post the code and ill give it a try!

dmikhalsky commented 7 years ago

Sure, I'll post my code. It works with Primo (I "emulate" Primo with nrf52DK) The code you mention emulates HR sensor and sends the data to BLE Central device (a phone or TomTom), while my code RECEIVES data from Wahoo HR BLE sensor or any other HRM sensor that has HRM GATT profile

micooke commented 7 years ago

Same coin, different side :) Excellent, thanks for that!

dmikhalsky commented 7 years ago

include

struct buffer { byte flag; byte hrm; byte rr_count; byte rr; //int rr; }; typedef struct buffer Buffer; Buffer wahoo;

// create central instance BLECentralRole bleCentral = BLECentralRole();

// create remote service with UUID compliant to NUS service BLERemoteService remoteService = BLERemoteService("0000180d-0000-1000-8000-00805f9b34fb");

// create remote characteristics with UUID and properties compliant NUS service BLERemoteCharacteristic remoteCharacteristic = BLERemoteCharacteristic("00002a37-0000-1000-8000-00805f9b34fb", BLERead | BLENotify);

void setup() { pinMode(7, OUTPUT); Serial.begin(9600);

// add service and characteristics bleCentral.addRemoteAttribute(remoteService); bleCentral.addRemoteAttribute(remoteCharacteristic); //bleCentral.addRemoteAttribute(remoteRxCharacteristic);

// assign event handlers for central events bleCentral.setEventHandler(BLEScanReceived, receiveAdvPck);
bleCentral.setEventHandler(BLEConnected, bleCentralConnectHandler); bleCentral.setEventHandler(BLEDisconnected, bleCentralDisconnectHandler); bleCentral.setEventHandler(BLERemoteServicesDiscovered, bleCentralRemoteServicesDiscoveredHandler);

// assign event handlers for characteristic remoteCharacteristic.setEventHandler(BLEValueUpdated, bleRemoteCharacteristicValueUpdatedHandle);

// set scan parameters // interval and window in 0.625 ms increments bleCentral.setScanInterval(1600); // 2 sec bleCentral.setScanWindow(800); // 0.5 sec

// begin initialization and start scanning bleCentral.begin();

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

void loop() {

}

void blinkOnScan(){ digitalWrite(7, LOW); delay(300); digitalWrite(7, HIGH); delay(300); }

void receiveAdvPck(BLEPeripheralPeer& peer){ char scannedUuid[31]; byte len; // search for the NUS's uuid peer.getFieldInAdvPck(BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE, scannedUuid, len); if(len == 0) // field not found peer.getFieldInAdvPck(BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, scannedUuid, len); if(len != 0){ // the field was found if(!strcmp(scannedUuid, remoteService.rawUuid())) // the uuids match. Connect to the peripheral Serial.println("Connecting.."); bleCentral.connect(peer); } }

void bleCentralConnectHandler(BLEPeripheralPeer& peer) { // peer connected event handler Serial.print("Connected event, peripheral: "); Serial.println(peer.address()); }

void bleCentralDisconnectHandler(BLEPeripheralPeer& peer) { // peer disconnected event handler Serial.print("Disconnected event, peripheral: "); Serial.println(peer.address()); }

void bleCentralRemoteServicesDiscoveredHandler(BLEPeripheralPeer& peer) { // peer remote services discovered event handler Serial.print("Remote services discovered event, peer: "); Serial.println(peer.address());

// subscribe Tx characteristic in order to automatically receive // messages sent from peripheral if (remoteCharacteristic.canSubscribe()) { Serial.println("Subscriping.."); remoteCharacteristic.subscribe(); } }

void bleRemoteCharacteristicValueUpdatedHandle(BLEPeripheralPeer& peer, BLERemoteCharacteristic& characteristic) { // print the incoming message byte buffer[16]; memcpy(&wahoo, remoteCharacteristic.value(),remoteCharacteristic.valueLength()); //byte message = (byte )remoteCharacteristic.value(); //for(int i=0; i<remoteCharacteristic.valueLength(); i++) int RR = 256*wahoo.rr + wahoo.rr_count; Serial.print(wahoo.flag, BIN); Serial.print(" ");Serial.print(wahoo.hrm); Serial.print(" "); Serial.print(RR); Serial.println(); }

The code is quick'n'dirty, more like a proof of concept, but it works

micooke commented 7 years ago

Thanks, ill try it over the next two days and let you know how i get on. I just need to find my chest strap now.. :confused:

dmikhalsky commented 7 years ago

I found another example that potentially has better chances to work https://github.com/RedBearLab/nRF51822-Arduino/blob/S130/arduino-1.6.x/hardware/RBL/RBL_nRF51822/libraries/BLE_Examples/examples/BLE_CentralTest/BLE_CentralTest.ino

I would test it myseld but my nrf51 is old revision and only supports softdevice v110

micooke commented 7 years ago

Long story short - there's more work involved then i thought. The Arduino library looks to be adapted from sandeeps library, but there are lots of changes that would need to be made. I tried just hacking in the scanning portion, but no dice so it needs more looking in to.

The RBL library is based off the mbed nrf5 core, which isn't compatible with this repo but @rogerclarkmelbourne has a repo designed around this with a smartwatch example variant - https://github.com/rogerclarkmelbourne/Arduino_nrf51822

dmikhalsky commented 7 years ago

Thanks a lot for trying! Lenovo HW01 is currently on sale at Gearbest. It is nrf52832 based so it MIGHT be the way to go, but I have doubts whether I'll be able to open them and locate programming pins

micooke commented 7 years ago

Ill have another crack at it once ive solved some other issues, but maybe raise this in sandeeps repo - ask him if he will support ble central scanning. His repo may work for your example, it might just be my lack of familiarity with it.

Thats a good price for an nrf52832 watch! I went the dearer, but easier to open route and (just) ordered a t28 - i didnt get it on discount like this though https://m.gearbest.com/smart-watches/pp_674645.html

It looks like the back screws off, so fingers crossed!

dmikhalsky commented 7 years ago

I've asked him already. But he doesn't want to do it for some strange reasons (like nrf8001 compatibility. Who cares?). I suspect it relates to the fact he's working for arduino.org now

dmikhalsky commented 7 years ago

T28 have clearly visible screws :-)

micooke commented 7 years ago

But they are double the cost of a id107hr plus.. Oh well, it has gps. Probably a rubbish one at that price

dmikhalsky commented 7 years ago

have you looked at N108?

micooke commented 7 years ago

I did. I was deciding between that and the t28. I decided to take the easy (but uglier) option.

Other watches i looked at were the s908 or g03 (both v. nice, gps ~$50), obviously the id107hr plus, and the dm58 (nrf51822) which is really nice, looks like it can be opened, but is about $35 to $40.

Let me know how you go with the lenovo. It looks like there might be a hidden screw panel at the back, top. Otherw it looks like the best chance to remove it with minimal damage is to hot air gun the glass front, hoping to melt the adhesive (before the lcd :wink:)

Im planning to write these up in a wiki.

micooke commented 7 years ago

Btw - im a recent adopter of the nrf5, can you not flash s130 on older chips? And fyi - i have 4x nrf8001, i even rewrote/hacked a repo to fit some code for it on an attiny85, so theres a few people still with ye olde nrf8 :smile:

micooke commented 7 years ago

@dmikhalsky - i didnt realise but the top panel on the rear of the lenovo HW01 is a rubber shroud for a micro usb charging port.

Also, it's a touchscreen!? The screen and digitiser could be fused to the front panel, so looks like lifting that is probably out.

Another one to add to the list - TRASENSE I8 ~$25 from gearbest. Visible screws, nrf52832.

dmikhalsky commented 7 years ago

As a temporary solution, I am thinking about wrapping Nordic SDK example as arduino library. Shoudn't be very hard to do. Then we'll be able to get HRM data, but send them to OLED instead of UART

micooke commented 7 years ago

Goodluck :+1:

On my progress I uploaded a library for the kx022 accelerometer (https://github.com/micooke/Kx022-1020) and the oled (https://github.com/micooke/sparkfun_OLED). I merged some internal changes for the kx022, so that may not work - i need to retest that - by the oled library works for pretty much any arduino / ssd1306 oled combination now.

I've rewritten major parts of squix78's oled library and in the process, completely stuffed it. His library has some nice UI components, so ill try and get that working in the next week or so.

I also added a SoftwareI2C library (https://github.com/micooke/SoftwareI2C) which can run an oled (which is all writes), but i havent tested it with the hr sensor yet (it didn't work initially). I had that working ages ago, i just keep forgetting to upload it. Its a vert lightly modified seeed studio library.

micooke commented 6 years ago

@dmikhalsky - have you tried the Bluefruit library? https://github.com/adafruit/Adafruit_nRF52_Arduino/tree/master/libraries/Bluefruit52Lib

The Adafruit core is cery similar to sandeep's core

dmikhalsky commented 6 years ago

Not yet. I've tried Adafruit core by itself but (at that time) decided to pursue Primo route as their BLE library is closer to the Sandeeps one. I tried to understand Adafruit examples but they are very "nested". Ino-file includes a .h file, the h-file includes a couple of others and so on. But I have to as it seems Primo implementation is very distant from Sandeep's one. It is actually heavily based on Nordic SDK taking an advantage of the new licensing rules of SDK14

micooke commented 6 years ago

Its probably worth a try. Adafruit is using v2.01 of the softdevice vs sandeepmistry using v2.00.

With luck it should be a drop in library. I know the adafruit core uses sandeeps Wire lib, and a lot of the core files are identical. I found this out while chasing down a bug with using SoftwareSerial

micooke commented 6 years ago

@dmikhalsky - any luck with your watch? It was a bit of a pain unlocking the T28 - i needed a jlink, nothing else would id the nrf52832.

floe commented 6 years ago

Digging up this old thread, just wanted to mention that I have a fork of sandeep's library that also supports Observer role: https://github.com/floe/BLEPeripheralObserver (tested and working on the ID107).

micooke commented 6 years ago

Brilliant! I have been working behind the scenes on this, but not a lot. Fwiw, im using u8g2 for the display and im planning on releasing a few examples. I have a few issues with the hr sensor.. and ideally i would have an associated app for setting time and notifications.. Notifications are very low on the list for the id107hr because of the tiny screen

micooke commented 6 years ago

I have a few PRs on sandeeps repo, some of them are being pulled and some arent

floe commented 6 years ago

Fwiw, im using u8g2 for the display and im planning on releasing a few examples.

Do you need to patch anything for u8g2 to work? The only lib that I could successfully use to access the display is Goran's hacked SmartOLED lib.

micooke commented 6 years ago

Nope, i just used the 64x32 example and it came right up.

The good thing about u8g2 is that it has and sdl example so i use that to design my watch UI.

I also have a sparkfun_OLED repo that works, and the squix one i modified may also work.. I made them both any resolution compatible

micooke commented 6 years ago

I just checked, https://github.com/micooke/squix78_OLED doesn't work (its an easy fix) https://github.com/micooke/sparkfun_OLED does Regarding u8g2 - see https://github.com/olikraus/u8g2/issues/361#issuecomment-331624009 (Im pretty sure that's what i use)

floe commented 6 years ago

Sorry for sort-of hijacking this thread, but are you sure that it's actually a SSD1306 in the ID107? From what I've found on various Chinese supplier sites, it's more likely a SH1106...

micooke commented 6 years ago

You are correct, so ill try it again. If it doesn't work ill fire off an issue requesting it as olikraus is very responsive. From memory it worked anyway as the two are very similar. There are differences, but not many

micooke commented 6 years ago

Hi @floe, you were right. I checked this yesterday, and sent a request to olikraus to support the screen. I woke this morning and he had created an instance for us:

U8G2_SH1106_64X32_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);

Keep an eye on https://github.com/olikraus/U8g2_Arduino, which has this instance but needs a merge of https://github.com/olikraus/u8g2/pull/570 (which i just created). Knowing Oliver, this may only take a day.

micooke commented 5 years ago

Im closing this, feel free to open it up if central role is supported. Cheers