c++ - Transfering data at fixed rate over bluetooth low energy with itsy bitsy nRF52840 - Stack Overflow
I am building a wireless ppg sensor as a module for my senior design project in engineering but I am struggling to get an adequate data transfer rate over bluetooth. Here you can see I attempt to save 10 seconds of data to a buffer (at 125Hz sampling freq.) Then I print each over bluetooth to my mobile device.
The bluetooth specs of the chip estimate around 2mbps data transfer rate and despite that It takes nearly 4 minutes to simply transfer all 1250 integers.
How can the print time be sped up such that my data transfer rate is 125Hz and I don't need to sit around waiting 4 minutes for each 10 seconds of data to come in?
I would much prefer that the data be printed in real-time but attempting to do that without collecting in a buffer was causing gaps in the signal. At least with the buffer I currently have the 10 seconds is contiguous but printing immediately after reading from my sensor is the goal. I already have an ios app setup that parses the data into 10 second chunks and feeds them into my neural-network so there is no need for it to be sent in 10 second chunks.
#include <bluefruit.h>
#include <Wire.h>
#include "MAX30105.h"
MAX30105 particleSensor;
BLEUart bleuart; // Add BLE UART service
void setup()
{
Serial.begin(230400);
Serial.println("Initializing...");
// Start I2C
Wire.begin();
// Initialize sensor
if (!particleSensor.begin(Wire, I2C_SPEED_FAST))
{
Serial.println("ERROR: MAX30102 not found.");
while (1);
}
Serial.println("MAX30105 initialized.");
// Configure sensor
particleSensor.setup(0x1F, 8, 2, 3200, 69, 4096); // Configure with specific settings
Bluefruit.begin();
Bluefruit.setTxPower(4);
Bluefruit.Periph.setConnInterval(9, 16);
// Initialize BLE UART service
bleuart.begin();
// Start advertising
startAdv();
}
void startAdv(void)
{
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
Bluefruit.Advertising.addService(bleuart); // Include BLE UART service
Bluefruit.Advertising.addName();
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244);
Bluefruit.Advertising.setFastTimeout(30);
Bluefruit.Advertising.start(0);
}
void loop() {
static unsigned long lastSample = 0;
unsigned long currentTime = micros();
static unsigned int numSamples = 0;
static unsigned long last1250 = 0;
// Buffer for 1250 compressed values
static uint16_t dataBuffer[1250] = {0}; // Using uint16_t since I'm only storing the middle 5 digits
if (currentTime - lastSample >= 8000) {
// Get sensor data
uint32_t irValue = particleSensor.getIR();
// Compress the value
uint16_t compressedValue = (irValue % 100000) / 10; // Keep only the middle 5 digits
Serial.println(compressedValue);
// Store the compressed value in the buffer
if (numSamples < 1250) {
dataBuffer[numSamples] = compressedValue;
numSamples++;
}
lastSample = currentTime;
}
if (numSamples >= 1250) {
// Print elapsed time for 1250 samples to Serial
Serial.print("Starting Bluetooth Transfer (1250 samples collected), Time: ");
Serial.println(micros() - last1250);
last1250 = micros();
// Transmit the buffer data
for (int i = 0; i < 1250; i++) {
bleuart.println(dataBuffer[i]);
}
Serial.println("Bluetooth Transfer Complete");
// Reset counters
numSamples = 0;
}
}
I am building a wireless ppg sensor as a module for my senior design project in engineering but I am struggling to get an adequate data transfer rate over bluetooth. Here you can see I attempt to save 10 seconds of data to a buffer (at 125Hz sampling freq.) Then I print each over bluetooth to my mobile device.
The bluetooth specs of the chip estimate around 2mbps data transfer rate and despite that It takes nearly 4 minutes to simply transfer all 1250 integers.
How can the print time be sped up such that my data transfer rate is 125Hz and I don't need to sit around waiting 4 minutes for each 10 seconds of data to come in?
I would much prefer that the data be printed in real-time but attempting to do that without collecting in a buffer was causing gaps in the signal. At least with the buffer I currently have the 10 seconds is contiguous but printing immediately after reading from my sensor is the goal. I already have an ios app setup that parses the data into 10 second chunks and feeds them into my neural-network so there is no need for it to be sent in 10 second chunks.
#include <bluefruit.h>
#include <Wire.h>
#include "MAX30105.h"
MAX30105 particleSensor;
BLEUart bleuart; // Add BLE UART service
void setup()
{
Serial.begin(230400);
Serial.println("Initializing...");
// Start I2C
Wire.begin();
// Initialize sensor
if (!particleSensor.begin(Wire, I2C_SPEED_FAST))
{
Serial.println("ERROR: MAX30102 not found.");
while (1);
}
Serial.println("MAX30105 initialized.");
// Configure sensor
particleSensor.setup(0x1F, 8, 2, 3200, 69, 4096); // Configure with specific settings
Bluefruit.begin();
Bluefruit.setTxPower(4);
Bluefruit.Periph.setConnInterval(9, 16);
// Initialize BLE UART service
bleuart.begin();
// Start advertising
startAdv();
}
void startAdv(void)
{
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
Bluefruit.Advertising.addService(bleuart); // Include BLE UART service
Bluefruit.Advertising.addName();
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244);
Bluefruit.Advertising.setFastTimeout(30);
Bluefruit.Advertising.start(0);
}
void loop() {
static unsigned long lastSample = 0;
unsigned long currentTime = micros();
static unsigned int numSamples = 0;
static unsigned long last1250 = 0;
// Buffer for 1250 compressed values
static uint16_t dataBuffer[1250] = {0}; // Using uint16_t since I'm only storing the middle 5 digits
if (currentTime - lastSample >= 8000) {
// Get sensor data
uint32_t irValue = particleSensor.getIR();
// Compress the value
uint16_t compressedValue = (irValue % 100000) / 10; // Keep only the middle 5 digits
Serial.println(compressedValue);
// Store the compressed value in the buffer
if (numSamples < 1250) {
dataBuffer[numSamples] = compressedValue;
numSamples++;
}
lastSample = currentTime;
}
if (numSamples >= 1250) {
// Print elapsed time for 1250 samples to Serial
Serial.print("Starting Bluetooth Transfer (1250 samples collected), Time: ");
Serial.println(micros() - last1250);
last1250 = micros();
// Transmit the buffer data
for (int i = 0; i < 1250; i++) {
bleuart.println(dataBuffer[i]);
}
Serial.println("Bluetooth Transfer Complete");
// Reset counters
numSamples = 0;
}
}
Share
Improve this question
asked Nov 15, 2024 at 23:57
AceKijaniAceKijani
336 bronze badges
6
|
Show 1 more comment
1 Answer
Reset to default 1The Bluetooth that you are using is Bluetooth Low Energy (BLE). BLE allows devices to leave their transmitters off most of the time and this is what makes it “Low Energy”.
This means when you do a bleuart.println(dataBuffer[i]);
, under the hood it turns on the radio, establishes connection, sends (by default) 20 bytes, and then turns the radio off.
So if you were to send a value of 125
, as you are using println
, it will convert it to ASCII so will be three bytes resulting in a payload of: 3532310000000000000000000000000000000000
An inefficient payload for each turning on and off of the radio.
It would be more efficient to write the value (e.g. 125) as a single byte value of 7d
. This means that you could send 20 values for the same payload with the overhead of the radio being turn on and off.
You could also get your app to negotiate a bigger payload (MTU) and that would allow even greater throughput for the same radio overhead.
Using a "UART" service over BLE might not be the most efficient option for your project. If it is heart rate that you are using, then it might be worth using the Bluetooth standard for transmitting such information. This would allow you to leverage a lot of the examples that are already out there or use an app that follows the standard.
https://www.bluetooth/specifications/specs/heart-rate-service-1-0/
- 2015年形成的计算机发展趋势 Windows10依然强势
- 你知道多少?细数五花八门的生物识别技术
- 忘记安卓电脑 ChromeWin双系统PC更有前途
- 网络购票冲击下的铁路代售点被迫转型
- The uid generator is giving negative value(-8201645565344219221) and using this implementation DefaultUidGenerator.java to gener
- python - Chromadb: Why do results of collection.query() and collection.get() differ? - Stack Overflow
- caching - Django: Slow Dashboard with Aggregated Data and Related Models - Stack Overflow
- TypeScript Error (ts2345) when trying to collect property names in array - Stack Overflow
- swift - How do I know how many times a thread context switch happens on an xcode Instruments? - Stack Overflow
- soa - How to use a variable in a composite or wsdl, as I need to have this variable per environment? - Stack Overflow
- flutter - Uber category selection animation - Stack Overflow
- asp.net - Razor Pages 'asp-page-handler' did not working [POST] - Stack Overflow
- kotlin - How to triegger LauncedEffect on user navigating to page OR value change - Stack Overflow
- python - CERT_PATH points to the wrong directory even though I set it correctly in my Django project - Stack Overflow
- flutter - Retrieving tokens from aad_b2c_webview - Stack Overflow
- epub - When extracting Kobo bookmarks frm KoboReader.sqlite, how do I determine pageslocations - Stack Overflow
- postgresql - Custom stopwords dictionary in Postgres hosted on GCP Cloud SQL - Stack Overflow
println
when data needs to be formatted. Use the binary write method. – Thomas Matthews Commented Nov 16, 2024 at 0:22