Felix Rüdiger / Mbed 2 deprecated BLE_Nano_MPU6050Service

Dependencies:   BLE_API mbed nRF51822 MPU6050_lib

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /** Includes */
00002 
00003 #include "common.h"
00004 #include "mbed.h"
00005 #include "BLE.h"
00006 #include "MPU6050Service.h"
00007 #include "PowerService.h"
00008 #include "services/DeviceInformationService.h"
00009 
00010 /** Constants */
00011 
00012 static const char           deviceName[]                    = "nano bear";
00013 static const char           deviceManufacturers[]           = "???";
00014 static const char           deviceModelNumber[]             = "";
00015 static const char           deviceSerialNumber[]            = XSTRING_(MBED_BUILD_TIMESTAMP);
00016 static const char           deviceHardwareRev[]             = "0.1";
00017 static const char           deviceFirmwareRev[]             = "0.1";
00018 static const char           deviceSoftwareRev[]             = "";          
00019 
00020 static const uint16_t       minimumConnectionInterval       = Gap::MSEC_TO_GAP_DURATION_UNITS(20); // 20ms
00021 static const uint16_t       maximumConnectionInterval       = Gap::MSEC_TO_GAP_DURATION_UNITS(40); // 40ms;
00022 static const uint16_t       slaveLatency                    = 0;
00023 
00024 static const float          ledTimeout                      = 0.05f;
00025 static const float          batteryCritBlinkSequ[]          = { 0.000f, 0.146f, 0.500f, 0.854f, 1.000f, 0.854f, 0.500f, 0.146f };
00026 static const float          connectedBlinkSequ[]            = { 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f,
00027                                                                 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f,                                                            
00028                                                                 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f,                                                           
00029                                                                 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 
00030                                                                 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f,                                                           
00031                                                                 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f, 1.000f,                                                           
00032                                                                 1.000f, 0.962f, 0.854f, 0.691f, 0.500f, 0.309f, 0.146f, 0.038f,
00033                                                                 0.000f, 0.038f, 0.146f, 0.309f, 0.500f, 0.691f, 0.854f, 0.962f };
00034 static const float          disconnectedBlinkSequ[]         = { 0.000f, 0.038f, 0.146f, 0.309f, 0.500f, 0.691f, 0.854f, 0.962f,
00035                                                                 1.000f, 0.962f, 0.854f, 0.691f, 0.500f, 0.309f, 0.146f, 0.038f,
00036                                                                 0.000f, 0.038f, 0.146f, 0.309f, 0.500f, 0.691f, 0.854f, 0.962f,
00037                                                                 1.000f, 0.962f, 0.854f, 0.691f, 0.500f, 0.309f, 0.146f, 0.038f,
00038                                                                 0.000f, 0.038f, 0.146f, 0.309f, 0.500f, 0.691f, 0.854f, 0.962f,
00039                                                                 1.000f, 0.962f, 0.854f, 0.691f, 0.500f, 0.309f, 0.146f, 0.038f,
00040                                                                 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,                                                            
00041                                                                 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f,                                                            
00042                                                                 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f, 0.000f };
00043 
00044 /** Power determination stuff:
00045  *
00046  *  The following is the schematic circuit ...
00047  *
00048  *       I0->      ____
00049  *      --------*-|____|-*-----------                   ... where ...
00050  *      |       |   R3   |          |                       
00051  *      |       |        |     _____|_____                    |
00052  *      |      | |      | |   |           |                  | |        ____
00053  *      |   R1 | |   R4 | |   | BLE nano  |                  | |  and -|____|-  are resistors ...
00054  *      |      |_|      |_|   |           |--...             |_|
00055  *      |       |~0->    |    |           |                   |
00056  *      | Uref1 *--------|----| P0_4      |--...
00057  *  + __|__     |        |~0->|           |             ... and ...
00058  * U0  ___      |  Uref2 *----| P0_5      |--...
00059  *      |       |        |    |           |               + __|__  
00060  *      |      | |      | |   |           |--...             ___   is the constant voltage source
00061  *      |   R2 | |   R5 | |   |           |                   |    (a battery in this case)
00062  *      |      |_|      |_|   |___________|
00063  *      |       |        |          |
00064  *      |       |        |          |
00065  *      *-------*--------*----------*--------...
00066  *                                 _|_
00067  *
00068  *
00069  *  Therefore the input values are
00070  *
00071  *    U0 = (R1 / R2 + 1) * Uref1
00072  *
00073  *    I0 = ((R1 + R3) / R2 + 1) / R3 * Uref1 - (R4 / R5 + 1) / R3 * Uref2
00074  *                              
00075  */
00076  
00077 #define R1              1000.0f
00078 #define R2              1000.0f
00079 #define R3              10.0f
00080 #define R4              1000.0f
00081 #define R5              1000.0f
00082 #define NANO_OP_VOLT    3.3f
00083                                                                 
00084 static const float          powerAccumulationTimeout        = 0.005f;
00085 
00086 static const float          voltFac                         = ((R1 / R2) + 1.0f) * NANO_OP_VOLT;
00087 static const float          currFac1                        = ((((R1 + R3) / R2) + 1.0f) / R3) * NANO_OP_VOLT;
00088 static const float          currFac2                        = (((R4 / R5) + 1.0f) / R3) * NANO_OP_VOLT;
00089 
00090 static const float          powerServiceUpdateTimeout       = 0.1f;
00091 
00092 
00093 
00094 /** Global variables */
00095 
00096 BLE                         ble;
00097 Gap::ConnectionParams_t     fast;
00098 
00099 MPU6050                     mpu(I2C_SDA0, I2C_SCL0, MPU6050::ADDRESS_0);
00100 
00101 PwmOut                      btLed(P0_28);
00102 PwmOut                      pwrLed(P0_29);
00103 DigitalOut                  aliveLed(LED);
00104 
00105 AnalogIn                    uRef1(P0_4);
00106 AnalogIn                    uRef2(P0_5);
00107 
00108 InterruptIn                 intIn(P0_9);
00109 
00110 Ticker                      powerAccumulationTicker;
00111 Ticker                      powerServiceUpdateTicker;
00112 Ticker                      ledTicker;
00113 
00114 
00115 
00116 /** Callback and handler functions */
00117 
00118 // Accumulate discharge
00119 
00120 static float U0 = 0.0f;
00121 static float I0 = 0.0f;
00122 static float Q  = 0.0f;
00123 
00124 void powerAccumulationPeriodicCallback()
00125 {
00126     // we have to do it in here, since we want a good approximation of the dt-timestep
00127     // since these are simple calculations this won't take much time
00128     
00129     register float u1 = uRef1.read();
00130     
00131     U0 = u1 * voltFac;
00132     I0 = (u1 * currFac1) - (uRef2.read() * currFac2);
00133     Q += I0 * powerAccumulationTimeout;
00134 }
00135 
00136 
00137 
00138 // Update the power service characteristics
00139 
00140 static bool powerServiceUpdateTrigger = false;
00141 
00142 void powerServiceUpdateHandler(PowerService* powerService)
00143 {    
00144     powerServiceUpdateTrigger = false;
00145     
00146     powerService->updateVoltage(U0);
00147     powerService->updateCurrent(I0 * 1000);             // mA
00148     powerService->updateDischarge(Q * 0.277777777f);    // mAh
00149 }
00150 
00151 void powerServiceUpdatePeriodicCallback()
00152 {    
00153     powerServiceUpdateTrigger = true;
00154 }
00155 
00156 
00157 // Update the bluetooth connection state LED
00158 
00159 static bool ledTrigger = false;
00160 static bool batteryCritical = false;
00161 
00162 void ledHandler(Gap &gap)
00163 {   
00164     ledTrigger = false;
00165     
00166     static uint32_t     cnt                         = 0;
00167     static const int    batteryCritBlinkSequSize    = sizeof(batteryCritBlinkSequ) / sizeof(float);    
00168     static const int    connectedBlinkSequSize      = sizeof(connectedBlinkSequ) / sizeof(float);
00169     static const int    disconnectedBlinkSequSize   = sizeof(disconnectedBlinkSequ) / sizeof(float);  
00170     
00171     aliveLed = !aliveLed;
00172     
00173     if (gap.getState().connected)
00174         btLed = connectedBlinkSequ[cnt % connectedBlinkSequSize];        
00175     else
00176         btLed = disconnectedBlinkSequ[cnt % disconnectedBlinkSequSize];
00177     
00178     if (batteryCritical)
00179         pwrLed = batteryCritBlinkSequ[cnt % batteryCritBlinkSequSize];
00180     else
00181         pwrLed = 1;
00182         
00183     cnt++;
00184 }
00185 
00186 void ledPeriodicCallback()
00187 {
00188     ledTrigger = true;
00189 }
00190 
00191 
00192 
00193 // Connection timeout
00194 
00195 static bool timeoutTrigger = false;
00196 
00197 void timeoutHandler(Gap &gap, MPU6050Service *mpu)
00198 {    
00199     timeoutTrigger = false;
00200     
00201     mpu->stop();    
00202     gap.startAdvertising();
00203 }
00204 
00205 void timeoutCallback(Gap::TimeoutSource_t source)
00206 {    
00207     timeoutTrigger = true;
00208 }
00209 
00210 
00211 
00212 // Disconnection 
00213 
00214 static bool disconnectionTrigger = false;
00215 
00216 void disconnectionHandler(Gap &gap, MPU6050Service *mpu)
00217 {    
00218     disconnectionTrigger = false;
00219     
00220     mpu->stop();
00221     gap.startAdvertising();
00222 }
00223 
00224 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason)
00225 {
00226     timeoutTrigger = true;
00227 }
00228 
00229 
00230 // Connection
00231 
00232 static bool connectionTrigger = false;
00233 
00234 void connectionHandler(MPU6050Service *mpu6050)
00235 {    
00236     connectionTrigger = false;
00237     
00238     mpu6050->start();
00239 }
00240 
00241 void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
00242 {        
00243     // update the connection parameters with the tuned fast ones
00244     ble.updateConnectionParams(params->handle, &fast);
00245     
00246     connectionTrigger = true;
00247 }
00248 
00249 
00250 
00251 /** Main */
00252 
00253 int main()
00254 {   
00255     btLed       = 1.0f;
00256     pwrLed      = 1.0f;
00257     aliveLed    = 0;
00258 
00259     ble.init();
00260     
00261     Gap &gap = ble.gap(); 
00262         
00263     powerAccumulationTicker.attach(powerAccumulationPeriodicCallback, powerAccumulationTimeout);
00264     powerServiceUpdateTicker.attach(powerServiceUpdatePeriodicCallback, powerServiceUpdateTimeout);
00265     ledTicker.attach(ledPeriodicCallback, ledTimeout);
00266     
00267     gap.onTimeout(timeoutCallback);   
00268     gap.onDisconnection(disconnectionCallback);
00269     gap.onConnection(connectionCallback);
00270     
00271     gap.setDeviceName((const uint8_t*)deviceName);
00272     
00273     gap.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
00274     gap.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (const uint8_t*)deviceName, sizeof(deviceName));
00275     gap.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
00276     
00277     //TODO: DECISION: advertising at minimal interval may consumes to much power, but is way faster
00278     gap.setAdvertisingInterval(gap.getMinAdvertisingInterval());
00279     
00280     // tune the preferred connection parameters to enable transfer more often
00281     // TODO: DECISION: also waht about power consumption?
00282     gap.getPreferredConnectionParams(&fast);
00283     fast.minConnectionInterval = minimumConnectionInterval;
00284     fast.maxConnectionInterval = maximumConnectionInterval;
00285     fast.slaveLatency = slaveLatency;
00286     gap.setPreferredConnectionParams(&fast);
00287       
00288     DeviceInformationService    deviceInformation(ble, deviceManufacturers, deviceModelNumber, deviceSerialNumber, deviceHardwareRev, deviceFirmwareRev, deviceSoftwareRev);    
00289     PowerService                powerService(ble);
00290     MPU6050Service              mpu6050(ble, mpu, &intIn);    
00291     
00292     gap.startAdvertising();
00293     
00294     while (true)
00295     {        
00296         // Handle all stuff within the user context
00297             
00298         if (powerServiceUpdateTrigger)
00299             powerServiceUpdateHandler(&powerService);
00300             
00301         if (ledTrigger)
00302             ledHandler(gap);
00303             
00304         if (connectionTrigger)
00305             connectionHandler(&mpu6050);
00306             
00307         if (disconnectionTrigger)
00308             disconnectionHandler(gap, &mpu6050);
00309             
00310         if (timeoutTrigger)
00311             timeoutHandler(gap, &mpu6050);
00312         
00313         ble.waitForEvent();
00314         
00315         mpu6050.handleService();
00316     }
00317 }