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

Dependencies:   BLE_API mbed nRF51822 MPU6050_lib

Committer:
fruediger
Date:
Fri Jun 26 14:44:27 2015 +0000
Revision:
4:a97e6917f731
Parent:
3:d72d9195dc26
Child:
5:ea4d280a0a2f
tweaked blinky again =); + fixed battery monitoring

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