BLE上的加速计数据未同步发送



我通过BLE发送温度、湿度、压力和加速度计数据,从Arduino(外围(到Raspberry Pi 4(中央(。我创建了每个加速度维度(accX, accY, accZ)的BLE特征,并且我订阅了这些特征。

然而,我为每个特征设置了计数器,并意识到数据没有按顺序发送:

18 Nov 12:27:35 - [info] [BLE Connect:bf9be48b4648f12e] x = 233
18 Nov 12:27:35 - [info] [BLE Connect:bf9be48b4648f12e] y = 230
18 Nov 12:27:35 - [info] [BLE Connect:bf9be48b4648f12e] z = 236

因此x被读取233次,而y

230次我发布了我的完整Arduino代码减去评论,因此我相信它可能是必要的:

#include <ArduinoBLE.h>
#include <Arduino_HTS221.h>
#include <Arduino_LPS22HB.h>
#include <Arduino_LSM9DS1.h>

#define BLE_UUID_ENVIRONMENTAL_SENSING_SERVICE    "181A"
#define BLE_UUID_TEMPERATURE                      "2A6E"
#define BLE_UUID_HUMIDITY                         "2A6F"
#define BLE_UUID_PRESSURE                         "2A6D"
#define BLE_UUID_ACCELEROMETER_SERVICE            "1101"
#define BLE_UUID_ACCELEROMETER_X                  "2101"
#define BLE_UUID_ACCELEROMETER_Y                  "2102"
#define BLE_UUID_ACCELEROMETER_Z                  "2103"
#define BLE_DEVICE_NAME                           "Hako"
#define BLE_LOCAL_NAME                            "Hako"
BLEService environmentalSensingService(BLE_UUID_ENVIRONMENTAL_SENSING_SERVICE);
BLEService accelerometerService(BLE_UUID_ACCELEROMETER_SERVICE);

BLEShortCharacteristic temperatureCharacteristic(BLE_UUID_TEMPERATURE, BLERead | BLENotify);
BLEUnsignedShortCharacteristic humidityCharacteristic(BLE_UUID_HUMIDITY, BLERead | BLENotify);
BLEUnsignedLongCharacteristic pressureCharacteristic(BLE_UUID_PRESSURE, BLERead | BLENotify);
BLEShortCharacteristic accelerometerCharacteristic_X(BLE_UUID_ACCELEROMETER_X, BLERead | BLENotify);
BLEShortCharacteristic accelerometerCharacteristic_Y(BLE_UUID_ACCELEROMETER_Y, BLERead | BLENotify);
BLEShortCharacteristic accelerometerCharacteristic_Z(BLE_UUID_ACCELEROMETER_Z, BLERead | BLENotify);
#define ENV_SENSOR_UPDATE_INTERVAL                (1000)
#define ACC_SENSOR_UPDATE_INTERVAL                (1000)
typedef struct __attribute__((packed))
{
float temperature;
float humidity;
float pressure;
bool updated = false;
} env_sensor_data_t;
env_sensor_data_t envSensorData;
typedef struct __attribute__((packed))
{
float accX;
float accY;
float accZ;
bool updated = false;
} acc_sensor_data_t;
acc_sensor_data_t accSensorData;
#define BLE_LED_PIN                               LED_BUILTIN

void setup()
{
Serial.begin(9600);
while (!Serial);
Serial.println( "BLE Example - Environmental Sensing Service (ESS)" );
pinMode( BLE_LED_PIN, OUTPUT );
digitalWrite( BLE_LED_PIN, LOW );
// Without Serial when using USB power bank HTS sensor seems to needs some time for setup
delay(10);
if (!HTS.begin()) {
Serial.println("Failed to initialize humidity temperature sensor!");
while (1);
}
if (!BARO.begin()) {
Serial.println( "Failed to initialize pressure sensor!" );
while (1);
}
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
while (1);
}
if (!setupBleMode()) {
while (1);
}
else {
Serial.println( "BLE initialized. Waiting for clients to connect." );
}
}
void loop() {
bleTask();
if (envSensorTask()) {
envPrintTask();
}
if (accSensorTask()) {
accPrintTask();
}
}
bool envSensorTask() {
static long previousMillis = 0;
unsigned long currentMillis = millis(); 
if (currentMillis - previousMillis < ENV_SENSOR_UPDATE_INTERVAL) {
return false;
}
previousMillis = currentMillis;
envSensorData.temperature = HTS.readTemperature();
envSensorData.humidity = HTS.readHumidity();
envSensorData.pressure = BARO.readPressure() * 1000; // kPa -> Pa
envSensorData.updated = true;
return envSensorData.updated;
}
bool accSensorTask() {
static long previousMillis2 = 0;
unsigned long currentMillis2 = millis();
float x = 0.00, y = 0.00, z = 0.00;
if (currentMillis2 - previousMillis2 < ACC_SENSOR_UPDATE_INTERVAL) {
return false;
}
previousMillis2 = currentMillis2;
if(IMU.accelerationAvailable()){
IMU.readAcceleration(x, y, z);
accSensorData.accX = x;
accSensorData.accY = y;
accSensorData.accZ = z;
accSensorData.updated = true;
}
return accSensorData.updated;
}
bool setupBleMode() {
if (!BLE.begin()) {
return false;
}
BLE.setDeviceName(BLE_DEVICE_NAME);
BLE.setLocalName(BLE_LOCAL_NAME);
BLE.setAdvertisedService(environmentalSensingService);
BLE.setAdvertisedService(accelerometerService);
environmentalSensingService.addCharacteristic(temperatureCharacteristic);
environmentalSensingService.addCharacteristic(humidityCharacteristic);
environmentalSensingService.addCharacteristic(pressureCharacteristic);
accelerometerService.addCharacteristic(accelerometerCharacteristic_X);
accelerometerService.addCharacteristic(accelerometerCharacteristic_Y);
accelerometerService.addCharacteristic(accelerometerCharacteristic_Z);

BLE.addService(environmentalSensingService);
BLE.addService(accelerometerService);
temperatureCharacteristic.writeValue(0);
humidityCharacteristic.writeValue(0);
pressureCharacteristic.writeValue(0);
accelerometerCharacteristic_X.writeValue(0);
accelerometerCharacteristic_Y.writeValue(0);
accelerometerCharacteristic_Z.writeValue(0);
BLE.setEventHandler(BLEConnected, blePeripheralConnectHandler);
BLE.setEventHandler(BLEDisconnected, blePeripheralDisconnectHandler);
BLE.advertise();
return true;
}
void bleTask()
{
const uint32_t BLE_UPDATE_INTERVAL = 10;
static uint32_t previousMillis = 0;
uint32_t currentMillis = millis();
if (currentMillis - previousMillis >= BLE_UPDATE_INTERVAL) {
previousMillis = currentMillis;
BLE.poll();
}
if (envSensorData.updated) {
// BLE defines Temperature UUID 2A6E Type sint16 ( see XML links )
// Unit is in degrees Celsius with a resolution of 0.01 degrees Celsius
int16_t temperature = round(envSensorData.temperature * 100.0);
temperatureCharacteristic.writeValue(temperature);
// BLE defines Humidity UUID 2A6F Type uint16
// Unit is in percent with a resolution of 0.01 percent
uint16_t humidity = round(envSensorData.humidity * 100.0);
humidityCharacteristic.writeValue(humidity);
// BLE defines Pressure UUID 2A6D Type uint32
// Unit is in Pascal with a resolution of 0.1 Pa
uint32_t pressure = round(envSensorData.pressure * 10.0);
pressureCharacteristic.writeValue(pressure);
envSensorData.updated = false;
}
if (accSensorData.updated) {
// BLE does not define accelerometer UUID
// Alls units is in G
int16_t accelerometer_X = round(accSensorData.accX * 100.0);
accelerometerCharacteristic_X.writeValue(accelerometer_X);

int16_t accelerometer_Y = round(accSensorData.accY * 100.0);
accelerometerCharacteristic_Y.writeValue(accelerometer_Y);
int16_t accelerometer_Z = round(accSensorData.accZ * 100.0);
accelerometerCharacteristic_Z.writeValue(accelerometer_Z);

envSensorData.updated = false;
}
}
void envPrintTask() {
Serial.print( "Temperature = " );
Serial.print( envSensorData.temperature );
Serial.println( " °C" );
Serial.print( "Humidity    = " );
Serial.print( envSensorData.humidity );
Serial.println( " %" );
Serial.print( "Pressure = " );
Serial.print( envSensorData.pressure );
Serial.println( " Pa" );
Serial.print(temperatureCharacteristic.subscribed());
Serial.print(humidityCharacteristic.subscribed());
Serial.println(pressureCharacteristic.subscribed());
}
void accPrintTask() {
Serial.print("AccX = ");
Serial.print(accSensorData.accX);
Serial.println(" G");
Serial.print("AccY = ");
Serial.print(accSensorData.accY);
Serial.println(" G");
Serial.print("AccZ = ");
Serial.print( accSensorData.accZ );
Serial.println(" G");
Serial.print(accelerometerCharacteristic_X.subscribed());
Serial.print(accelerometerCharacteristic_Y.subscribed());
Serial.println(accelerometerCharacteristic_Z.subscribed());
}
void blePeripheralConnectHandler(BLEDevice central) {
digitalWrite(BLE_LED_PIN, HIGH);
Serial.print(F( "Connected to central: " ));
Serial.println(central.address());
}
void blePeripheralDisconnectHandler( BLEDevice central ) {
digitalWrite(BLE_LED_PIN, LOW);
Serial.print(F("Disconnected from central: "));
Serial.println(central.address());
}

我正在Node.js环境中通过@ardware/noble库读取Pi的数据。

我只会发布相关的部分,在那里我首先订阅了特征,然后我阅读了数据。您可以在末尾看到计数器

for (const [key, character] of Object.entries(ALL.characteristics)) {
// Check the notify bit, if not set, set it. //
if (character.properties.includes("notify")) {
const descriptors = await character.discoverDescriptorsAsync().catch(e => send(e));
for (const [key, descriptor] of Object.entries(descriptors)) {
node.log(descriptor);
let descriptorData = await descriptor.readValueAsync().catch(e => send(e));
if (descriptorData[0] === bufferChecker[0] || descriptorData[1] === bufferChecker [1]) {
node.log(`The ${character.name} ${character.uuid} notify bit is disabled.`);
node.log("Enabling notification bit...");
descriptor.writeValueAsync(notifySetter).catch(e => send(e));
node.log (`Notification for ${character.name} characteristic is enabled.`);
} else {
node.log(`The ${character.name} ${character.uuid} notify bit is already enabled.`);
return;
}
}
} else {
node.log(`Notification is not allowed for ${character.name} characteristic.`)
}
}
for (const [key, character] of Object.entries(ALL.characteristics)) {
character.on('data', (data) => {
if (character.uuid === '2a6d') {
data = data.readUInt32LE() * decimalSetter[1];
environmentalData.payload[character.name] = data.toFixed(2);
counterPres++;
} else if (character.uuid === '2a6e') {
data = data.readUInt16LE() * decimalSetter[0];
environmentalData.payload[character.name] = data.toFixed(2);
counterTemp++;
} else if (character.uuid === '2a6f') {
data = data.readUInt16LE() * decimalSetter[0];
environmentalData.payload[character.name] = data.toFixed(2);
counterHum++;
} else if (character.uuid === '2101') {
data = data.readInt16LE() * decimalSetter[0];
accData.payload[character.name] = data.toFixed(2);
counterAccX++;
} else if (character.uuid === '2102') {
data = data.readInt16LE() * decimalSetter[0];
accData.payload[character.name] = data.toFixed(2);
counterAccY++;
} else if (character.uuid === '2103') {
data = data.readInt16LE() * decimalSetter[0];
accData.payload[character.name] = data.toFixed(2);
counterAccZ++;
}
node.log("x = " + counterAccX);
node.log("y = " + counterAccY);
node.log("z = " + counterAccZ);
// Sends Temp., Hum., and Pres. data together.
if ( (counterHum + counterPres + counterTemp) % 3 == 0 && (counterHum + counterPres + counterTemp) !== 0){
send(environmentalData);
}
});
// Character data event listener END //
}

我在Arduino论坛上也问了同样的问题。

外围设备GATT服务器只有在测量值确实发生变化时才发送数据。这种行为可以节省能源和带宽。因此,我认为你的观察完全正常。

最新更新