
BLE GATT-service implementation for high quantity sensor data from a MPU6050-accelerator/gyroscope
Dependencies: BLE_API mbed nRF51822 MPU6050_lib
main.cpp
- Committer:
- fruediger
- Date:
- 2015-09-22
- Revision:
- 13:496c0f5e8a61
- Parent:
- 12:dc46aa2edccd
File content as of revision 13:496c0f5e8a61:
/** Includes */ #include "common.h" #include "mbed.h" #include "BLE.h" #include "MPU6050Service.h" #include "PowerService.h" #include "services/DeviceInformationService.h" /** Constants */ static const char deviceName[] = "nano bear"; static const char deviceManufacturers[] = "???"; static const char deviceModelNumber[] = ""; static const char deviceSerialNumber[] = XSTRING_(MBED_BUILD_TIMESTAMP); static const char deviceHardwareRev[] = "0.1"; static const char deviceFirmwareRev[] = "0.1"; static const char deviceSoftwareRev[] = ""; static const uint16_t minimumConnectionInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(20); // 20ms static const uint16_t maximumConnectionInterval = Gap::MSEC_TO_GAP_DURATION_UNITS(40); // 40ms; static const uint16_t slaveLatency = 0; static const float ledTimeout = 0.05f; static const float batteryCritBlinkSequ[] = { 0.000f, 0.146f, 0.500f, 0.854f, 1.000f, 0.854f, 0.500f, 0.146f }; static const float connectedBlinkSequ[] = { 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 0.962f, 0.854f, 0.691f, 0.500f, 0.309f, 0.146f, 0.038f, 0.000f, 0.038f, 0.146f, 0.309f, 0.500f, 0.691f, 0.854f, 0.962f }; static const float disconnectedBlinkSequ[] = { 0.000f, 0.038f, 0.146f, 0.309f, 0.500f, 0.691f, 0.854f, 0.962f, 1.000f, 0.962f, 0.854f, 0.691f, 0.500f, 0.309f, 0.146f, 0.038f, 0.000f, 0.038f, 0.146f, 0.309f, 0.500f, 0.691f, 0.854f, 0.962f, 1.000f, 0.962f, 0.854f, 0.691f, 0.500f, 0.309f, 0.146f, 0.038f, 0.000f, 0.038f, 0.146f, 0.309f, 0.500f, 0.691f, 0.854f, 0.962f, 1.000f, 0.962f, 0.854f, 0.691f, 0.500f, 0.309f, 0.146f, 0.038f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f }; /** Power determination stuff: * * The following is the schematic circuit ... * * I0-> ____ * --------*-|____|-*----------- ... where ... * | | R3 | | * | | | _____|_____ | * | | | | | | | | | ____ * | R1 | | R4 | | | BLE nano | | | and -|____|- are resistors ... * | |_| |_| | |--... |_| * | |~0-> | | | | * | Uref1 *--------|----| P0_4 |--... * + __|__ | |~0->| | ... and ... * U0 ___ | Uref2 *----| P0_5 |--... * | | | | | + __|__ * | | | | | | |--... ___ is the constant voltage source * | R2 | | R5 | | | | | (a battery in this case) * | |_| |_| |___________| * | | | | * | | | | * *-------*--------*----------*--------... * _|_ * * * Therefore the input values are * * U0 = (R1 / R2 + 1) * Uref1 * * I0 = ((R1 + R3) / R2 + 1) / R3 * Uref1 - (R4 / R5 + 1) / R3 * Uref2 * */ #define R1 1000.0f #define R2 1000.0f #define R3 10.0f #define R4 1000.0f #define R5 1000.0f #define NANO_OP_VOLT 3.3f static const float powerAccumulationTimeout = 0.005f; static const float voltFac = ((R1 / R2) + 1.0f) * NANO_OP_VOLT; static const float currFac1 = ((((R1 + R3) / R2) + 1.0f) / R3) * NANO_OP_VOLT; static const float currFac2 = (((R4 / R5) + 1.0f) / R3) * NANO_OP_VOLT; static const float powerServiceUpdateTimeout = 0.1f; /** Global variables */ BLE ble; Gap::ConnectionParams_t fast; MPU6050 mpu(I2C_SDA0, I2C_SCL0, MPU6050::ADDRESS_0); PwmOut btLed(P0_28); PwmOut pwrLed(P0_29); DigitalOut aliveLed(LED); AnalogIn uRef1(P0_4); AnalogIn uRef2(P0_5); InterruptIn intIn(P0_9); Ticker powerAccumulationTicker; Ticker powerServiceUpdateTicker; Ticker ledTicker; /** Callback and handler functions */ // Accumulate discharge static float U0 = 0.0f; static float I0 = 0.0f; static float Q = 0.0f; void powerAccumulationPeriodicCallback() { // we have to do it in here, since we want a good approximation of the dt-timestep // since these are simple calculations this won't take much time register float u1 = uRef1.read(); U0 = u1 * voltFac; I0 = (u1 * currFac1) - (uRef2.read() * currFac2); Q += I0 * powerAccumulationTimeout; } // Update the power service characteristics static bool powerServiceUpdateTrigger = false; void powerServiceUpdateHandler(PowerService* powerService) { powerServiceUpdateTrigger = false; powerService->updateVoltage(U0); powerService->updateCurrent(I0 * 1000); // mA powerService->updateDischarge(Q * 0.277777777f); // mAh } void powerServiceUpdatePeriodicCallback() { powerServiceUpdateTrigger = true; } // Update the bluetooth connection state LED static bool ledTrigger = false; static bool batteryCritical = false; void ledHandler(Gap &gap) { ledTrigger = false; static uint32_t cnt = 0; static const int batteryCritBlinkSequSize = sizeof(batteryCritBlinkSequ) / sizeof(float); static const int connectedBlinkSequSize = sizeof(connectedBlinkSequ) / sizeof(float); static const int disconnectedBlinkSequSize = sizeof(disconnectedBlinkSequ) / sizeof(float); aliveLed = !aliveLed; if (gap.getState().connected) btLed = connectedBlinkSequ[cnt % connectedBlinkSequSize]; else btLed = disconnectedBlinkSequ[cnt % disconnectedBlinkSequSize]; if (batteryCritical) pwrLed = batteryCritBlinkSequ[cnt % batteryCritBlinkSequSize]; else pwrLed = 1; cnt++; } void ledPeriodicCallback() { ledTrigger = true; } // Connection timeout static bool timeoutTrigger = false; void timeoutHandler(Gap &gap, MPU6050Service *mpu) { timeoutTrigger = false; mpu->stop(); gap.startAdvertising(); } void timeoutCallback(Gap::TimeoutSource_t source) { timeoutTrigger = true; } // Disconnection static bool disconnectionTrigger = false; void disconnectionHandler(Gap &gap, MPU6050Service *mpu) { disconnectionTrigger = false; mpu->stop(); gap.startAdvertising(); } void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) { timeoutTrigger = true; } // Connection static bool connectionTrigger = false; void connectionHandler(MPU6050Service *mpu6050) { connectionTrigger = false; mpu6050->start(); } void connectionCallback(const Gap::ConnectionCallbackParams_t *params) { // update the connection parameters with the tuned fast ones ble.updateConnectionParams(params->handle, &fast); connectionTrigger = true; } /** Main */ int main() { btLed = 1.0f; pwrLed = 1.0f; aliveLed = 0; ble.init(); Gap &gap = ble.gap(); powerAccumulationTicker.attach(powerAccumulationPeriodicCallback, powerAccumulationTimeout); powerServiceUpdateTicker.attach(powerServiceUpdatePeriodicCallback, powerServiceUpdateTimeout); ledTicker.attach(ledPeriodicCallback, ledTimeout); gap.onTimeout(timeoutCallback); gap.onDisconnection(disconnectionCallback); gap.onConnection(connectionCallback); gap.setDeviceName((const uint8_t*)deviceName); gap.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); gap.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (const uint8_t*)deviceName, sizeof(deviceName)); gap.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); //TODO: DECISION: advertising at minimal interval may consumes to much power, but is way faster gap.setAdvertisingInterval(gap.getMinAdvertisingInterval()); // tune the preferred connection parameters to enable transfer more often // TODO: DECISION: also waht about power consumption? gap.getPreferredConnectionParams(&fast); fast.minConnectionInterval = minimumConnectionInterval; fast.maxConnectionInterval = maximumConnectionInterval; fast.slaveLatency = slaveLatency; gap.setPreferredConnectionParams(&fast); DeviceInformationService deviceInformation(ble, deviceManufacturers, deviceModelNumber, deviceSerialNumber, deviceHardwareRev, deviceFirmwareRev, deviceSoftwareRev); PowerService powerService(ble); MPU6050Service mpu6050(ble, mpu, &intIn); gap.startAdvertising(); while (true) { // Handle all stuff within the user context if (powerServiceUpdateTrigger) powerServiceUpdateHandler(&powerService); if (ledTrigger) ledHandler(gap); if (connectionTrigger) connectionHandler(&mpu6050); if (disconnectionTrigger) disconnectionHandler(gap, &mpu6050); if (timeoutTrigger) timeoutHandler(gap, &mpu6050); ble.waitForEvent(); mpu6050.handleService(); } }