admin管理员组文章数量:1026989
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/
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
- 3 This is not C language. Very few C language projects are written like C++. – Thomas Matthews Commented Nov 16, 2024 at 0:17
-
1
Only use
println
when data needs to be formatted. Use the binary write method. – Thomas Matthews Commented Nov 16, 2024 at 0:22 - 1 You should profile or benchmark your code to find out where most of the time is spent. Optimize those sections. – Thomas Matthews Commented Nov 16, 2024 at 0:23
- Choose a naming convention where types and variable names differ by more than case. – Thomas Matthews Commented Nov 16, 2024 at 0:25
- You're waiting to transmit the data until the buffer is 1250 full. Then, trying to burst it out. That waiting time is wasted (when it could have been used to transmit). And, once the buffer is full, you're not servicing any incoming data from the bluetooth device. During that time period, it could drop data. You should use two buffers (i.e. double buffering) so that you always pull in data as soon as available. And, you should send out data byte-by-byte as soon as you get it to prevent large idle periods on the UART. – Craig Estey Commented Nov 16, 2024 at 4:07
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/
本文标签: cTransfering data at fixed rate over bluetooth low energy with itsy bitsy nRF52840Stack Overflow
版权声明:本文标题:c++ - Transfering data at fixed rate over bluetooth low energy with itsy bitsy nRF52840 - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745670534a2162430.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
println
when data needs to be formatted. Use the binary write method. – Thomas Matthews Commented Nov 16, 2024 at 0:22