
BLE GATT-service implementation for high quantity sensor data from a MPU6050-accelerator/gyroscope
Dependencies: BLE_API mbed nRF51822 MPU6050_lib
MPU6050Service.h@4:a97e6917f731, 2015-06-26 (annotated)
- 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?
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 | 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 |