Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API mbed nRF51822 MPU6050_lib
main.cpp
- Committer:
- fruediger
- Date:
- 2015-07-13
- Revision:
- 7:af3e2b9c137a
- Parent:
- 6:c1db7e82d76a
- Child:
- 9:6a28d9c0e486
File content as of revision 7:af3e2b9c137a:
/** Includes */ #include "common.h" #include "mbed.h" #include "BLE.h" #include "MPU6050Service.h" #include "services/BatteryService.h" #include "services/DeviceInformationService.h" /***/ #include "LedPwmService.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 tickerTimeout = 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 }; //static const uint8_t batteryCritThreshold = 30; // 30% /** Power determination stuff: * * The following is the schematic circuit ... * * I0-> ____ * --------*-|____|-*----------- ... where ... * | | R2 | | * | | | _____|_____ | * | | | | | | | | | ____ * | 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 220.0f #define R4 1000.0f #define R5 1000.0f #define NANO_OP_VOLT 3.3f 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; /** Global variables */ Serial pc(USBTX, USBRX); BLE ble; Gap::ConnectionParams_t fast; BatteryService *battery = NULL; DeviceInformationService *deviceInformation = NULL; MPU6050Service *mpu6050 = NULL; LedPwmService *ledService = NULL; PwmOut btLed(P0_28); PwmOut batLed(P0_29); //DigitalOut aliveLed(LED1); AnalogIn uRef1(P0_4); AnalogIn uRef2(P0_5); Ticker ticker; /** Helpers */ inline Gap &gap() { // get us the corresponding Gap instance only once and then save and reuse that instance // (the underlying Gap instance shouldn't change on the BLE object) static Gap &gap = ble.gap(); return gap; } float funitf(char *cunit_out, float value, int unit = 0, float divisor = 1000.0f, float upper_bound = 900.0f, float lower_bound = 0.9f) { static const char prefix[] = { 'y', 'z', 'a', 'f', 'p', 'n', 'u', 'm', 0, 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' }; static const int prefixOffset = 8; if (unit < -8) do { unit++; value *= divisor; } while (unit < -8); else if (unit > 8) do { unit--; value /= divisor; } while (unit > 8); else while (unit != -8 && unit != 8) if (value > upper_bound) { unit++; value /= divisor; } else if (value < lower_bound) { unit--; value *= divisor; } else break; cunit_out[0] = prefix[prefixOffset + unit]; return value; } /** Callback functions */ void periodicCallback() { static int batCnt = -1; static int conCnt = -1; static const int batteryCritBlinkSequSize = sizeof(batteryCritBlinkSequ) / sizeof(float); static const int connectedBlinkSequSize = sizeof(connectedBlinkSequ) / sizeof(float); static const int disconnectedBlinkSequSize = sizeof(disconnectedBlinkSequ) / sizeof(float); // alive state led // aliveLed = !aliveLed; // battery level led /* uint8_t batteryLevel = (uint8_t)(batteryLevelRescale * batLevel * 100.0f); if (batteryLevel > 100) { batteryLevel = 100; batLed = 1.0f; } else if (batteryLevel <= batteryCritThreshold) { batCnt = (batCnt + 1) % (batteryCritBlinkSequSize); batLed = batteryCritBlinkSequ[batCnt]; } else batLed = 1.0f; // also update BatteryService characteristic if needed static uint8_t oldBatteryLevel = 0xFF; if (batteryLevel != oldBatteryLevel && battery != NULL) { battery->updateBatteryLevel(batteryLevel); pc.printf("Battery level is now: %i%%.", batteryLevel); oldBatteryLevel = batteryLevel; } */ // log source voltage and current static char unitV[] = "\0"; static char unitA[] = "\0"; float u0 = funitf(&unitV[0], voltFac * uRef1.read()); float i0 = funitf(&unitA[0], (currFac1 * uRef1.read()) - (currFac2 * uRef2.read())); pc.printf("U0 = %10.6f%2sV, I0 = %10.6f%2sA\r\n", u0, unitV, i0, unitA); // bluetooth connection state led if (gap().getState().connected) { conCnt = ((conCnt + 1) % connectedBlinkSequSize); btLed = connectedBlinkSequ[conCnt]; } else { conCnt = ((conCnt + 1) % disconnectedBlinkSequSize); btLed = disconnectedBlinkSequ[conCnt]; } } void timeoutCallback(Gap::TimeoutSource_t source) { pc.printf("\r\nGot TIMEOUT "); switch (source) { case Gap::TIMEOUT_SRC_ADVERTISING: pc.printf("while advertising!\r\n"); break; case Gap::TIMEOUT_SRC_SECURITY_REQUEST: pc.printf("during security request!\r\n"); break; case Gap::TIMEOUT_SRC_SCAN: pc.printf("while scanning!\r\n"); break; case Gap::TIMEOUT_SRC_CONN: pc.printf("during connection!\r\n"); break; } gap().startAdvertising(); pc.printf("Restarting ADVERTISING...\r\n"); } void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) { pc.printf("\r\nDISCONNECTED because "); switch (reason) { case Gap::CONNECTION_TIMEOUT: pc.printf("of connection timeout!\r\n"); break; case Gap::REMOTE_USER_TERMINATED_CONNECTION: pc.printf("the remote user terminated the connection!\r\n"); break; case Gap::REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES: pc.printf("the remote device is low on resources!\r\n"); break; case Gap::REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF: pc.printf("the remote device is off!\r\n"); break; case Gap::LOCAL_HOST_TERMINATED_CONNECTION: pc.printf("we terminated the connection!\r\n"); break; case Gap::CONN_INTERVAL_UNACCEPTABLE: pc.printf("the connection interval is unacceptable!\r\n"); break; } gap().startAdvertising(); pc.printf("Restarting ADVERTISING...\r\n"); } void connectionCallback(const Gap::ConnectionCallbackParams_t *params) { pc.printf("\r\nGot a CONNECTION from %02X:%02X:%02X:%02X:%02X:%02X (we are a ", (params->peerAddr)[0], (params->peerAddr)[1], (params->peerAddr)[2], (params->peerAddr)[3], (params->peerAddr)[4], (params->peerAddr)[5]); switch(params->role) { case Gap::PERIPHERAL: pc.printf("peripheral)!\r\n"); break; case Gap::CENTRAL: pc.printf("central)!\r\n"); break; } pc.printf("Updating connection parameters to be faster...\r\n"); // update the connection parameters with the tuned fast ones ble.updateConnectionParams(params->handle, &fast); pc.printf("Starting MPU-6050 service...\r\n"); // start polling and sending sensor data mpu6050->start(); } /** Main */ int main() { btLed = 1.0f; //batLed = 1.0f; //aliveLed = 1; ble.init(); ticker.attach(periodicCallback, tickerTimeout); 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); gap().startAdvertising(); pc.printf("\r\nStart ADVERTISING...\r\n"); BatteryService _battery(ble); battery = &_battery; DeviceInformationService _deviceInformation(ble, deviceManufacturers, deviceModelNumber, deviceSerialNumber, deviceHardwareRev, deviceFirmwareRev, deviceSoftwareRev); deviceInformation = &_deviceInformation; MPU6050Service _mpu6050(ble); mpu6050 = &_mpu6050; LedPwmService _ledService(ble, LED); ledService = &_ledService; while (true) ble.waitForEvent(); }