XIAO nRF52840(mbed) 1-Central 2-Peripherals Project "Sleeping Posture, Heart rate, Pulse oximetry Monitor"

Sleep apnea sufferers are encouraged to sleep on their side and need to manage pulse oximetry and heart rate Many wearable devices are used, but the number of measurements while sleeping was low and unsatisfactory. I developed this monitor recorder to obtain detailed information. I hope this will be helpful to those interested in this subject.

Peripheral_1 consists of XIAO_BLE_Sense and a 3.7V 220mA(10 hours operation) battery, attached to the chest. Data from the built-in IMU is converted to Roll and Pitch with a Madgwick filter. Roll, Pitch, and battery voltage data are sent to Central every 240mS. To obtain stable sleeping posture data, it is important to attache Peripheral _1 closely to the chest.

Peripheral_2 consists of XIAO_BLE, a 3.7V 220mAh(10 hours operation) battery, and an I2C-connected MAX30102 breakout board, attached to the wrist and finger respectively. Two kind of pulse waveform data acquired every 30mS by the MAX30102 are used to calculate Heart rate and SpO2 values. Heart rate, SpO2, Pulse waveform, and battery voltage are sent to Central every 240mS. Pulse waveform data are sent together every 8 data. To obtain stable pulse and PsO2 data, it is important to attache MAX30102 to the finger without moving or shifting.

Central consists of XIAO_BLE, XIAO_Expansion_Board and a 3.7V 2000mAh battery. It detects “right side down”, “left side down”, “on the back”, and “get up” sleeping postures from Roll and Pitch data. Heart rate, SpO2, and battery voltage are displayed along with the pulse waveform. With an optional switch, Roll, Pitch, sleeping Posture, Heart rate, SpO2, and RSSI can be displayed. And Time, Heart rate, SpO2, and sleeping Posture are recorded on an SD card for further analysis on a PC.
A small modification is required to read the battery voltage connected to the XIAO_Expansion_Board.

nRF52_XIAO_mbed_SleepingMonitor.zip (26.4 KB)

The following libraries were downloaded using the Library Manager. Special thanks to the creators of the libraries.

1.Board Service Package : Seeed nRF52 mbed-enable Borads by Seeed Studio Version 2.9.1
Note: To work around a bug in analogRead() that reads the battery voltage, the patch in the link below is required
XIAO_BLE_Sense(mbed 2.7.2) battery charge and voltage monitor, analogRead(P0_31) does not work - #31 by msfujino
2.ArduinoBLE by Arduino Version 1.3.1
Note: Using version 1.3.2 conflicts with XIAO_ESP32C3 compiler
3.Adafruit GFX Library by Adafruit Version 1.11.4
4.Adafruit SSD1306 by Adafruit Version 2.5.7
5.RingBuf by D.Aaron Wisner Version 2.0
6.Madgwick by Arduino Version 1.2.0
7.Seeed Arduino LSM6DS3 by Seeed Studio Version 2.0.3
8.SparkFun MAX3010x Pulse and Proximity Sensor Library by SparkFun Electronics Version 1.1.1

Many thanks for sharing. The project looks very interesting.

The Bluetooth code is fascinating! Someday I may have to have 136 BLE peripherals, so seeing this gives me hope.

XIAO nRF52840(mbed) ArduinoBLE can only connect up to 2 peripherals.

WOW, Really GREAT JOB :star_struck: :+1:
Seeed Should throw you a Bone. You covered it all and fixed there thing along the way.
Thanx for the inspiration.
GL :slight_smile:

@msfujino , Is that an (mbed) limitation only ? or chip ,I thought the Nrf52840 was 8 Peripherals possible when its the central device.? I maybe just wishful thinking and read it somewhere.
GL :wink:

There have been several reports of problems with the third peripheral not connecting when using nano_33_BLE(nRF52840) and ArduinoBLE.
I also tried with XIAO_nRF52840(mbed) and ArduinoBLE, but could not connect the third peripheral.

Have you ever seen this,video?
Looks as though from the links and info it’s the “Softdevice” that limits due to system resources , memory, tasks #'s too great. Depends on implementation of the stack and availability of memory AFAIK.
I want one Central Android Device (phone app) and 8 “Xiao BLE Sense” Units as Peripherals. Basically 8 notifier’s to one central. Two is a good start for proof of concept though.

I know several folks afflicted, my Younger brother has the mask thing too, Your project is very useful and the research is interesting. You ever consider patent it and licensing to other big Co.? Just curious.
Gl :slight_smile:
PJ. :+1:

from Nordic

Yes, the S140 v6.1.0 SoftDevice(i.e. BLE protocol stack) supports up-to 20
concurrent connections and this is a hard limit for our protocol stack.

If you need 30 concurrent connections then I suggest that you take 
a look at Mynewt's Nimble stack. It supports up-to 32 concurrent connections 
and it supports the nRF52840. 

Best regards


I have been using the mask for many years and I developed this tool because I wanted to know the relationship between sleeping posture and pulse oximetry. I am going to take some data and analyze it.
I feel that the combination of nRF52840(mbed) and ArduinoBLE is not suitable for multi-peripherals. it would be better to use the API that matches the nRF52840 hardware, but it is too hard for a holiday programmer.

LOL… Sounds like we are brothers. :grin:
Peace and Great work you do.

I plan to use a Bluetooth mesh network instead of standard connections.

Please show us your mesh network project when it is completed.

I realized that I do not need a mesh network, because there does not need to be a two way communication nor rebroadcasting. Also, Arduino does not have the mesh SDK and I would have to use the Nordic SDK instead.

So instead, I use the concept of Bluetooth mesh, which utilizes only the advertising/scanning states of BLE devices. For each nrf52840 slave I set it to retrieve information from advertising packets by turning on Bluetooth scanning. There is no actual Bluetooth connection.

void setup(){
  // central scan for brightness
  Bluefruit.begin(0, 1);
  Bluefruit.setTxPower(4);    // Check bluefruit.h for supported values
  Bluefruit.Scanner.filterUuid(0x0018); // only invoke callback if detect service
  Bluefruit.Scanner.setInterval(160, 10);       // in units of 0.625 ms
  //Bluefruit.Scanner.useActiveScan(true);        // Request scan response data

Then, in the callback that runs when an advertising packet is detected, I can take the data and change the necessary variable.

void scan_callback(ble_gap_evt_adv_report_t* report)
  uint8_t len = 0;
  uint8_t BTbuffer[32];
  memset(BTbuffer, 0, sizeof(BTbuffer));
  /* Check for Service Data */
  len = Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_SERVICE_DATA , BTbuffer, sizeof(BTbuffer));
  if (len)
    //Serial.printf("%14s ", "SERVICE DATA");
    //Serial.printBuffer(BTbuffer, len, '-');
    if (MaximumBrightness != BTbuffer[2])
      MaximumBrightness = BTbuffer[2];

The advertising packet is sent by an Android phone running the nRF Connect app, with a manually set Service UUID of 0x0018 and manually set Service Data containing an integer. It cannot be done on iPhone because iPhone does not allow customization of advertising packets. Another Seeed Xiao NRF52840 can also probably be used as an advertiser device.

Thanks for the info.
I knew about using advertisement packets to send data unilaterally, but I am concerned about sending data to someone who is not connected.

Nrf52840 contains cryptographic functionality that may be able to encrypt and decrypt messages using a shared secret key.

Is this an example of encryption? What about decryption?
The BSP in use is mbed, so I will consider this next time.