
BLE GATT-service implementation for high quantity sensor data from a MPU6050-accelerator/gyroscope
Dependencies: BLE_API mbed nRF51822 MPU6050_lib
Diff: MPU6050Service.h
- Revision:
- 3:d72d9195dc26
- Child:
- 4:a97e6917f731
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MPU6050Service.h Thu Jun 25 14:35:26 2015 +0000 @@ -0,0 +1,159 @@ +#pragma once +#ifndef __MPU6050_SERVICE_H__ +#define __MPU6050_SERVICE_H__ + +#include "BLE.h" + +typedef struct +{ + uint16_t a1, a2, a3; + uint16_t temp; + uint16_t g1, g2, g3; +} mpu6050SensorReading_t; + +typedef struct +{ + mpu6050SensorReading_t data; + uint64_t clock_us; +} mpu6050SensorData_t; + +typedef enum +{ + ACCEL_RANGE_2G = 0x00, // 0b__00 + ACCEL_RANGE_4G = 0x01, // 0b__01 + ACCEL_RANGE_8G = 0x02, // 0b__10 + ACCEL_RANGE_16G = 0x03, // 0b__11 + + GYRO_RANGE_250 = 0x00, // 0b00__ + GYRO_RANGE_500 = 0x04, // 0b01__ + GYRO_RANGE_1000 = 0x08, // 0b10__ + GYRO_RANGE_2000 = 0x0C // 0b11__ +} mpu6050MeasuringRange_t; + +inline mpu6050MeasuringRange_t operator|(mpu6050MeasuringRange_t a, mpu6050MeasuringRange_t b) { return static_cast<mpu6050MeasuringRange_t>(static_cast<int>(a) | static_cast<int>(b)); } + +class MPU6050Service +{ + public: + enum + { + UUID_MP6050_SERVICE = 0xA123, + + UUID_MPU6050_SENSOR_DATA_CHAR = 0xA124, + UUID_MPU6050_MEASURING_RANGE_CHAR = 0xA125, + UUID_MPU6050_MASTER_CLOCK_CHAR = 0xA126 + }; + + MPU6050Service + ( + BLE &ble, + const mpu6050SensorData_t *initialData = NULL, + const mpu6050MeasuringRange_t measuringRange = ACCEL_RANGE_2G | GYRO_RANGE_250, + const uint64_t masterClock_us = 0 + ) : + gattServer(ble.gattServer()), + sensorDataCharacteristic + ( + UUID_MPU6050_SENSOR_DATA_CHAR, + (mpu6050SensorData_t*)initialData, + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY // improving latency by repurposing notifications and "writing" the client + // (i.e. indicating the client but not wait for a response) + ), + measuringRangeCharacteristic + ( + UUID_MPU6050_MEASURING_RANGE_CHAR, + (mpu6050MeasuringRange_t*)&measuringRange, + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE // also improving latency + ), + masterClockCharacteristic + ( + UUID_MPU6050_MASTER_CLOCK_CHAR, + (uint64_t*)&masterClock_us, + GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE // look above again + ) + { + static bool serviceAdded = false; // MOS is a one-timer + if (serviceAdded) + return; + + GattCharacteristic *charTable[] = + { + &sensorDataCharacteristic, + &measuringRangeCharacteristic, + &masterClockCharacteristic + }; + + GattService mpu6050Service(UUID_MP6050_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic*)); + + gattServer.addService(mpu6050Service); + gattServer.onDataSent(this, &MPU6050Service::dataSentCallback); + gattServer.onDataWritten(this, &MPU6050Service::dataWrittenCallback); + + serviceAdded = true; + } + + void start() + { + // sending data once will invoke the dataSent(...) callback later on + // which will be looped by the event driven behavior of the BLE API (because it will send data again on it's own) + updateSensorDataCharacteristic(); + } + + private: + GattServer &gattServer; + ReadOnlyGattCharacteristic<mpu6050SensorData_t> sensorDataCharacteristic; + WriteOnlyGattCharacteristic<mpu6050MeasuringRange_t> measuringRangeCharacteristic; + WriteOnlyGattCharacteristic<uint64_t> masterClockCharacteristic; + + union + { + struct + { + uint8_t accel_x_h, accel_x_l; + uint8_t accel_y_h, accel_y_l; + uint8_t accel_z_h, accel_z_l; + + uint8_t temp_h, temp_l; + + uint8_t gyro_x_h, gyro_x_l; + uint8_t gyro_y_h, gyro_y_l; + uint8_t gyro_z_h, gyro_z_l; + } registers; + + mpu6050SensorReading_t data; + } converter; + + void dataSentCallback(unsigned count) + { + // we came here, if we just sent data, + // so lets keep the BLE stack busy by sending data again + updateSensorDataCharacteristic(); + } + + void dataWrittenCallback(const GattWriteCallbackParams *context) + { + // some writable characteristics were updated by the client + } + + void updateSensorDataCharacteristic() + { + mpu6050SensorData_t data; + // flood the transmission buffer of the BLE stack until it's full + do + { + // TODO: poll and accumulate data + + // ... + + data.data = converter.data; + data.clock_us = 0; + // write data in characteristic and repeat + } while (gattServer.write(sensorDataCharacteristic.getValueHandle(), reinterpret_cast<uint8_t*>(&data), sizeof(mpu6050SensorData_t)) == BLE_ERROR_NONE); + + // error case or buffer is full (or break out of loop); + // this also means the last data update will be lost, if not sent again + // (we are ignoring this fact and just keep on going, because we're NOT interested in the QUALITY of data, but in the QUANTITY + } +}; + +#endif \ No newline at end of file