
BLE GATT-service implementation for high quantity sensor data from a MPU6050-accelerator/gyroscope
Dependencies: BLE_API mbed nRF51822 MPU6050_lib
MPU6050Service.h@3:d72d9195dc26, 2015-06-25 (annotated)
- 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?
User | Revision | Line number | New 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 |