BLE GATT-service implementation for high quantity sensor data from a MPU6050-accelerator/gyroscope

Dependencies:   BLE_API mbed nRF51822 MPU6050_lib

Committer:
fruediger
Date:
Thu Jun 25 14:35:26 2015 +0000
Revision:
3:d72d9195dc26
Child:
4:a97e6917f731
changed service name to MPU6050Service,; changed service architecture,; prepared service for the MPU6050 communication on I?C,; tweaked blinky a little

Who changed what in which revision?

UserRevisionLine numberNew contents of line
fruediger 3:d72d9195dc26 1 #pragma once
fruediger 3:d72d9195dc26 2 #ifndef __MPU6050_SERVICE_H__
fruediger 3:d72d9195dc26 3 #define __MPU6050_SERVICE_H__
fruediger 3:d72d9195dc26 4
fruediger 3:d72d9195dc26 5 #include "BLE.h"
fruediger 3:d72d9195dc26 6
fruediger 3:d72d9195dc26 7 typedef struct
fruediger 3:d72d9195dc26 8 {
fruediger 3:d72d9195dc26 9 uint16_t a1, a2, a3;
fruediger 3:d72d9195dc26 10 uint16_t temp;
fruediger 3:d72d9195dc26 11 uint16_t g1, g2, g3;
fruediger 3:d72d9195dc26 12 } mpu6050SensorReading_t;
fruediger 3:d72d9195dc26 13
fruediger 3:d72d9195dc26 14 typedef struct
fruediger 3:d72d9195dc26 15 {
fruediger 3:d72d9195dc26 16 mpu6050SensorReading_t data;
fruediger 3:d72d9195dc26 17 uint64_t clock_us;
fruediger 3:d72d9195dc26 18 } mpu6050SensorData_t;
fruediger 3:d72d9195dc26 19
fruediger 3:d72d9195dc26 20 typedef enum
fruediger 3:d72d9195dc26 21 {
fruediger 3:d72d9195dc26 22 ACCEL_RANGE_2G = 0x00, // 0b__00
fruediger 3:d72d9195dc26 23 ACCEL_RANGE_4G = 0x01, // 0b__01
fruediger 3:d72d9195dc26 24 ACCEL_RANGE_8G = 0x02, // 0b__10
fruediger 3:d72d9195dc26 25 ACCEL_RANGE_16G = 0x03, // 0b__11
fruediger 3:d72d9195dc26 26
fruediger 3:d72d9195dc26 27 GYRO_RANGE_250 = 0x00, // 0b00__
fruediger 3:d72d9195dc26 28 GYRO_RANGE_500 = 0x04, // 0b01__
fruediger 3:d72d9195dc26 29 GYRO_RANGE_1000 = 0x08, // 0b10__
fruediger 3:d72d9195dc26 30 GYRO_RANGE_2000 = 0x0C // 0b11__
fruediger 3:d72d9195dc26 31 } mpu6050MeasuringRange_t;
fruediger 3:d72d9195dc26 32
fruediger 3:d72d9195dc26 33 inline mpu6050MeasuringRange_t operator|(mpu6050MeasuringRange_t a, mpu6050MeasuringRange_t b) { return static_cast<mpu6050MeasuringRange_t>(static_cast<int>(a) | static_cast<int>(b)); }
fruediger 3:d72d9195dc26 34
fruediger 3:d72d9195dc26 35 class MPU6050Service
fruediger 3:d72d9195dc26 36 {
fruediger 3:d72d9195dc26 37 public:
fruediger 3:d72d9195dc26 38 enum
fruediger 3:d72d9195dc26 39 {
fruediger 3:d72d9195dc26 40 UUID_MP6050_SERVICE = 0xA123,
fruediger 3:d72d9195dc26 41
fruediger 3:d72d9195dc26 42 UUID_MPU6050_SENSOR_DATA_CHAR = 0xA124,
fruediger 3:d72d9195dc26 43 UUID_MPU6050_MEASURING_RANGE_CHAR = 0xA125,
fruediger 3:d72d9195dc26 44 UUID_MPU6050_MASTER_CLOCK_CHAR = 0xA126
fruediger 3:d72d9195dc26 45 };
fruediger 3:d72d9195dc26 46
fruediger 3:d72d9195dc26 47 MPU6050Service
fruediger 3:d72d9195dc26 48 (
fruediger 3:d72d9195dc26 49 BLE &ble,
fruediger 3:d72d9195dc26 50 const mpu6050SensorData_t *initialData = NULL,
fruediger 3:d72d9195dc26 51 const mpu6050MeasuringRange_t measuringRange = ACCEL_RANGE_2G | GYRO_RANGE_250,
fruediger 3:d72d9195dc26 52 const uint64_t masterClock_us = 0
fruediger 3:d72d9195dc26 53 ) :
fruediger 3:d72d9195dc26 54 gattServer(ble.gattServer()),
fruediger 3:d72d9195dc26 55 sensorDataCharacteristic
fruediger 3:d72d9195dc26 56 (
fruediger 3:d72d9195dc26 57 UUID_MPU6050_SENSOR_DATA_CHAR,
fruediger 3:d72d9195dc26 58 (mpu6050SensorData_t*)initialData,
fruediger 3:d72d9195dc26 59 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY // improving latency by repurposing notifications and "writing" the client
fruediger 3:d72d9195dc26 60 // (i.e. indicating the client but not wait for a response)
fruediger 3:d72d9195dc26 61 ),
fruediger 3:d72d9195dc26 62 measuringRangeCharacteristic
fruediger 3:d72d9195dc26 63 (
fruediger 3:d72d9195dc26 64 UUID_MPU6050_MEASURING_RANGE_CHAR,
fruediger 3:d72d9195dc26 65 (mpu6050MeasuringRange_t*)&measuringRange,
fruediger 3:d72d9195dc26 66 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE // also improving latency
fruediger 3:d72d9195dc26 67 ),
fruediger 3:d72d9195dc26 68 masterClockCharacteristic
fruediger 3:d72d9195dc26 69 (
fruediger 3:d72d9195dc26 70 UUID_MPU6050_MASTER_CLOCK_CHAR,
fruediger 3:d72d9195dc26 71 (uint64_t*)&masterClock_us,
fruediger 3:d72d9195dc26 72 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE // look above again
fruediger 3:d72d9195dc26 73 )
fruediger 3:d72d9195dc26 74 {
fruediger 3:d72d9195dc26 75 static bool serviceAdded = false; // MOS is a one-timer
fruediger 3:d72d9195dc26 76 if (serviceAdded)
fruediger 3:d72d9195dc26 77 return;
fruediger 3:d72d9195dc26 78
fruediger 3:d72d9195dc26 79 GattCharacteristic *charTable[] =
fruediger 3:d72d9195dc26 80 {
fruediger 3:d72d9195dc26 81 &sensorDataCharacteristic,
fruediger 3:d72d9195dc26 82 &measuringRangeCharacteristic,
fruediger 3:d72d9195dc26 83 &masterClockCharacteristic
fruediger 3:d72d9195dc26 84 };
fruediger 3:d72d9195dc26 85
fruediger 3:d72d9195dc26 86 GattService mpu6050Service(UUID_MP6050_SERVICE, charTable, sizeof(charTable) / sizeof(GattCharacteristic*));
fruediger 3:d72d9195dc26 87
fruediger 3:d72d9195dc26 88 gattServer.addService(mpu6050Service);
fruediger 3:d72d9195dc26 89 gattServer.onDataSent(this, &MPU6050Service::dataSentCallback);
fruediger 3:d72d9195dc26 90 gattServer.onDataWritten(this, &MPU6050Service::dataWrittenCallback);
fruediger 3:d72d9195dc26 91
fruediger 3:d72d9195dc26 92 serviceAdded = true;
fruediger 3:d72d9195dc26 93 }
fruediger 3:d72d9195dc26 94
fruediger 3:d72d9195dc26 95 void start()
fruediger 3:d72d9195dc26 96 {
fruediger 3:d72d9195dc26 97 // sending data once will invoke the dataSent(...) callback later on
fruediger 3:d72d9195dc26 98 // which will be looped by the event driven behavior of the BLE API (because it will send data again on it's own)
fruediger 3:d72d9195dc26 99 updateSensorDataCharacteristic();
fruediger 3:d72d9195dc26 100 }
fruediger 3:d72d9195dc26 101
fruediger 3:d72d9195dc26 102 private:
fruediger 3:d72d9195dc26 103 GattServer &gattServer;
fruediger 3:d72d9195dc26 104 ReadOnlyGattCharacteristic<mpu6050SensorData_t> sensorDataCharacteristic;
fruediger 3:d72d9195dc26 105 WriteOnlyGattCharacteristic<mpu6050MeasuringRange_t> measuringRangeCharacteristic;
fruediger 3:d72d9195dc26 106 WriteOnlyGattCharacteristic<uint64_t> masterClockCharacteristic;
fruediger 3:d72d9195dc26 107
fruediger 3:d72d9195dc26 108 union
fruediger 3:d72d9195dc26 109 {
fruediger 3:d72d9195dc26 110 struct
fruediger 3:d72d9195dc26 111 {
fruediger 3:d72d9195dc26 112 uint8_t accel_x_h, accel_x_l;
fruediger 3:d72d9195dc26 113 uint8_t accel_y_h, accel_y_l;
fruediger 3:d72d9195dc26 114 uint8_t accel_z_h, accel_z_l;
fruediger 3:d72d9195dc26 115
fruediger 3:d72d9195dc26 116 uint8_t temp_h, temp_l;
fruediger 3:d72d9195dc26 117
fruediger 3:d72d9195dc26 118 uint8_t gyro_x_h, gyro_x_l;
fruediger 3:d72d9195dc26 119 uint8_t gyro_y_h, gyro_y_l;
fruediger 3:d72d9195dc26 120 uint8_t gyro_z_h, gyro_z_l;
fruediger 3:d72d9195dc26 121 } registers;
fruediger 3:d72d9195dc26 122
fruediger 3:d72d9195dc26 123 mpu6050SensorReading_t data;
fruediger 3:d72d9195dc26 124 } converter;
fruediger 3:d72d9195dc26 125
fruediger 3:d72d9195dc26 126 void dataSentCallback(unsigned count)
fruediger 3:d72d9195dc26 127 {
fruediger 3:d72d9195dc26 128 // we came here, if we just sent data,
fruediger 3:d72d9195dc26 129 // so lets keep the BLE stack busy by sending data again
fruediger 3:d72d9195dc26 130 updateSensorDataCharacteristic();
fruediger 3:d72d9195dc26 131 }
fruediger 3:d72d9195dc26 132
fruediger 3:d72d9195dc26 133 void dataWrittenCallback(const GattWriteCallbackParams *context)
fruediger 3:d72d9195dc26 134 {
fruediger 3:d72d9195dc26 135 // some writable characteristics were updated by the client
fruediger 3:d72d9195dc26 136 }
fruediger 3:d72d9195dc26 137
fruediger 3:d72d9195dc26 138 void updateSensorDataCharacteristic()
fruediger 3:d72d9195dc26 139 {
fruediger 3:d72d9195dc26 140 mpu6050SensorData_t data;
fruediger 3:d72d9195dc26 141 // flood the transmission buffer of the BLE stack until it's full
fruediger 3:d72d9195dc26 142 do
fruediger 3:d72d9195dc26 143 {
fruediger 3:d72d9195dc26 144 // TODO: poll and accumulate data
fruediger 3:d72d9195dc26 145
fruediger 3:d72d9195dc26 146 // ...
fruediger 3:d72d9195dc26 147
fruediger 3:d72d9195dc26 148 data.data = converter.data;
fruediger 3:d72d9195dc26 149 data.clock_us = 0;
fruediger 3:d72d9195dc26 150 // write data in characteristic and repeat
fruediger 3:d72d9195dc26 151 } while (gattServer.write(sensorDataCharacteristic.getValueHandle(), reinterpret_cast<uint8_t*>(&data), sizeof(mpu6050SensorData_t)) == BLE_ERROR_NONE);
fruediger 3:d72d9195dc26 152
fruediger 3:d72d9195dc26 153 // error case or buffer is full (or break out of loop);
fruediger 3:d72d9195dc26 154 // this also means the last data update will be lost, if not sent again
fruediger 3:d72d9195dc26 155 // (we are ignoring this fact and just keep on going, because we're NOT interested in the QUALITY of data, but in the QUANTITY
fruediger 3:d72d9195dc26 156 }
fruediger 3:d72d9195dc26 157 };
fruediger 3:d72d9195dc26 158
fruediger 3:d72d9195dc26 159 #endif