Reading SenseAir LP8 CO2 sensor over bluetooth low energy
Dependencies: BLE_API mbed nRF51822
main.cpp@3:933dd59ad44d, 2017-08-18 (annotated)
- Committer:
- jony1401
- Date:
- Fri Aug 18 18:20:41 2017 +0000
- Revision:
- 3:933dd59ad44d
- Parent:
- 2:d02255d8c36f
Updated version. Including more functionality.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jony1401 | 0:ee3787c8e209 | 1 | #include "mbed.h" |
jony1401 | 0:ee3787c8e209 | 2 | #include "BLE.h" |
jony1401 | 0:ee3787c8e209 | 3 | #include "LP8_Service.h" |
jony1401 | 0:ee3787c8e209 | 4 | #include "LP8.h" |
jony1401 | 0:ee3787c8e209 | 5 | |
jony1401 | 2:d02255d8c36f | 6 | //Sensor and ble Configuration parameters |
jony1401 | 3:933dd59ad44d | 7 | #define SENSOR_TIMER 16.0 //lp8 polling interval (seconds) |
jony1401 | 2:d02255d8c36f | 8 | #define BLE_ADV_INTERVAL 500 //advertisment interval (milliseconds) |
jony1401 | 2:d02255d8c36f | 9 | |
jony1401 | 2:d02255d8c36f | 10 | |
jony1401 | 0:ee3787c8e209 | 11 | //setup ble stack |
jony1401 | 0:ee3787c8e209 | 12 | BLE ble; //BLE object |
jony1401 | 0:ee3787c8e209 | 13 | |
jony1401 | 2:d02255d8c36f | 14 | // setup Pins |
jony1401 | 2:d02255d8c36f | 15 | DigitalOut Res(P0_0, 1); //reset, pull Low for reset |
jony1401 | 2:d02255d8c36f | 16 | DigitalIn RDY(P0_10); //rdy |
jony1401 | 2:d02255d8c36f | 17 | DigitalOut VBB_EN(P0_5, 0); //set to low at startup |
jony1401 | 0:ee3787c8e209 | 18 | Serial Device(P0_9, P0_11); //tx, rx |
jony1401 | 2:d02255d8c36f | 19 | |
jony1401 | 2:d02255d8c36f | 20 | // Timers |
jony1401 | 0:ee3787c8e209 | 21 | Timer lp8Wait; //timer for sensor communication |
jony1401 | 3:933dd59ad44d | 22 | Ticker lp8Timer; //timer object for sensor polling |
jony1401 | 0:ee3787c8e209 | 23 | |
jony1401 | 2:d02255d8c36f | 24 | //BLE device name and uuid list setup |
jony1401 | 0:ee3787c8e209 | 25 | const static char DEVICE_NAME[] = "SenseAir LP8"; |
jony1401 | 0:ee3787c8e209 | 26 | static const uint16_t uuid16_list[] = {LP8_Service::LP8_SERVICE_UUID}; |
jony1401 | 0:ee3787c8e209 | 27 | |
jony1401 | 3:933dd59ad44d | 28 | //check for sensor triggering |
jony1401 | 2:d02255d8c36f | 29 | bool triggerSensor = false; //sensor polling flag |
jony1401 | 2:d02255d8c36f | 30 | bool doCalibration = false; //background calibration flag |
jony1401 | 3:933dd59ad44d | 31 | bool initCheck = true; //check for init sensor state |
jony1401 | 2:d02255d8c36f | 32 | |
jony1401 | 3:933dd59ad44d | 33 | LP8_Service *lp8ServicePtr; // |
jony1401 | 3:933dd59ad44d | 34 | |
jony1401 | 2:d02255d8c36f | 35 | uint8_t ccByte = 0x20; //calculation control byte to LP8 |
jony1401 | 0:ee3787c8e209 | 36 | |
jony1401 | 0:ee3787c8e209 | 37 | |
jony1401 | 0:ee3787c8e209 | 38 | |
jony1401 | 3:933dd59ad44d | 39 | |
jony1401 | 3:933dd59ad44d | 40 | //**************************** ble callback functions *************************** |
jony1401 | 3:933dd59ad44d | 41 | // on Disconnect interupt |
jony1401 | 0:ee3787c8e209 | 42 | void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
jony1401 | 0:ee3787c8e209 | 43 | { |
jony1401 | 3:933dd59ad44d | 44 | initCheck = true; |
jony1401 | 1:b512a405b584 | 45 | //turn of sensor at ble disconnect |
jony1401 | 1:b512a405b584 | 46 | VBB_EN.write( 0 ); |
jony1401 | 3:933dd59ad44d | 47 | //cancel sensor timer |
jony1401 | 3:933dd59ad44d | 48 | lp8Timer.detach(); |
jony1401 | 3:933dd59ad44d | 49 | |
jony1401 | 0:ee3787c8e209 | 50 | //restart broadcast |
jony1401 | 0:ee3787c8e209 | 51 | ble.gap().startAdvertising(); |
jony1401 | 0:ee3787c8e209 | 52 | } |
jony1401 | 3:933dd59ad44d | 53 | //sensor polling |
jony1401 | 0:ee3787c8e209 | 54 | void triggerSensorPollingInterupt() |
jony1401 | 0:ee3787c8e209 | 55 | { |
jony1401 | 0:ee3787c8e209 | 56 | triggerSensor = true; |
jony1401 | 3:933dd59ad44d | 57 | |
jony1401 | 3:933dd59ad44d | 58 | //reset callback timer |
jony1401 | 3:933dd59ad44d | 59 | lp8Timer.detach(); |
jony1401 | 3:933dd59ad44d | 60 | lp8Timer.attach(&triggerSensorPollingInterupt, SENSOR_TIMER); |
jony1401 | 3:933dd59ad44d | 61 | |
jony1401 | 0:ee3787c8e209 | 62 | }; |
jony1401 | 3:933dd59ad44d | 63 | |
jony1401 | 3:933dd59ad44d | 64 | void connectionCallback(const Gap::ConnectionCallbackParams_t *params) |
jony1401 | 3:933dd59ad44d | 65 | { |
jony1401 | 3:933dd59ad44d | 66 | lp8Timer.attach( triggerSensorPollingInterupt, 4 ); |
jony1401 | 3:933dd59ad44d | 67 | } |
jony1401 | 3:933dd59ad44d | 68 | |
jony1401 | 3:933dd59ad44d | 69 | //on BLE data written |
jony1401 | 2:d02255d8c36f | 70 | void calibrationCallback(const GattWriteCallbackParams *eventData) |
jony1401 | 2:d02255d8c36f | 71 | { |
jony1401 | 3:933dd59ad44d | 72 | doCalibration = true; |
jony1401 | 2:d02255d8c36f | 73 | ccByte = eventData-> data[0]; |
jony1401 | 2:d02255d8c36f | 74 | } |
jony1401 | 0:ee3787c8e209 | 75 | |
jony1401 | 0:ee3787c8e209 | 76 | |
jony1401 | 0:ee3787c8e209 | 77 | |
jony1401 | 2:d02255d8c36f | 78 | //**************************** main ************************************** |
jony1401 | 2:d02255d8c36f | 79 | int main() |
jony1401 | 0:ee3787c8e209 | 80 | { |
jony1401 | 1:b512a405b584 | 81 | wait(1); |
jony1401 | 2:d02255d8c36f | 82 | |
jony1401 | 3:933dd59ad44d | 83 | ble.init(); |
jony1401 | 2:d02255d8c36f | 84 | |
jony1401 | 3:933dd59ad44d | 85 | //callbacks |
jony1401 | 3:933dd59ad44d | 86 | ble.gap().onConnection( connectionCallback ); |
jony1401 | 3:933dd59ad44d | 87 | ble.gap().onDisconnection( disconnectionCallback ); // |
jony1401 | 3:933dd59ad44d | 88 | ble.gattServer().onDataWritten( calibrationCallback ); // |
jony1401 | 2:d02255d8c36f | 89 | |
jony1401 | 2:d02255d8c36f | 90 | //************************ LP8 variables ********************************* |
jony1401 | 3:933dd59ad44d | 91 | int co2Value = 99; //initial CO2 value |
jony1401 | 3:933dd59ad44d | 92 | float tempValue = 99; //init temp value |
jony1401 | 3:933dd59ad44d | 93 | int Vcap = 99; //mV |
jony1401 | 3:933dd59ad44d | 94 | uint32_t errorFlag = 0; //error bits from lp8 |
jony1401 | 3:933dd59ad44d | 95 | uint8_t sentCCbyte = 0x99; |
jony1401 | 0:ee3787c8e209 | 96 | |
jony1401 | 2:d02255d8c36f | 97 | |
jony1401 | 3:933dd59ad44d | 98 | //setup LP8 object |
jony1401 | 3:933dd59ad44d | 99 | LP8 *lp8 = new LP8(Device, VBB_EN, RDY, Res, lp8Wait); |
jony1401 | 2:d02255d8c36f | 100 | |
jony1401 | 2:d02255d8c36f | 101 | |
jony1401 | 2:d02255d8c36f | 102 | //Setup GattService |
jony1401 | 3:933dd59ad44d | 103 | // LP8_Service lp8Service(ble, co2Value, tempValue, |
jony1401 | 3:933dd59ad44d | 104 | // Vcap, errorFlag, ccByte, sentCCbyte); |
jony1401 | 3:933dd59ad44d | 105 | lp8ServicePtr = new LP8_Service(ble, co2Value, tempValue, |
jony1401 | 3:933dd59ad44d | 106 | Vcap, errorFlag, ccByte, sentCCbyte); // lp8Service; |
jony1401 | 0:ee3787c8e209 | 107 | |
jony1401 | 0:ee3787c8e209 | 108 | |
jony1401 | 2:d02255d8c36f | 109 | // setup ble advertising parameters |
jony1401 | 0:ee3787c8e209 | 110 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); //general bluetooth information(only support for ble |
jony1401 | 0:ee3787c8e209 | 111 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); //service list |
jony1401 | 0:ee3787c8e209 | 112 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); |
jony1401 | 0:ee3787c8e209 | 113 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
jony1401 | 1:b512a405b584 | 114 | ble.gap().setAdvertisingInterval(BLE_ADV_INTERVAL); /* advertising interval in ms. */ |
jony1401 | 3:933dd59ad44d | 115 | ble.gap().startAdvertising(); |
jony1401 | 0:ee3787c8e209 | 116 | |
jony1401 | 2:d02255d8c36f | 117 | // Wait for initialization to complete. |
jony1401 | 2:d02255d8c36f | 118 | while (ble.hasInitialized() == false) { |
jony1401 | 2:d02255d8c36f | 119 | /* spin loop */ |
jony1401 | 2:d02255d8c36f | 120 | } |
jony1401 | 0:ee3787c8e209 | 121 | |
jony1401 | 0:ee3787c8e209 | 122 | |
jony1401 | 0:ee3787c8e209 | 123 | |
jony1401 | 2:d02255d8c36f | 124 | //*************************** start the main loop *********************************** |
jony1401 | 0:ee3787c8e209 | 125 | while ( true ) |
jony1401 | 0:ee3787c8e209 | 126 | { |
jony1401 | 3:933dd59ad44d | 127 | |
jony1401 | 1:b512a405b584 | 128 | if(triggerSensor && ble.gap().getState().connected ) //trigger when timer interupts and there is an established ble connection |
jony1401 | 0:ee3787c8e209 | 129 | { |
jony1401 | 0:ee3787c8e209 | 130 | if ( initCheck ) { |
jony1401 | 3:933dd59ad44d | 131 | lp8->responsePurge(50); //purge buffer |
jony1401 | 3:933dd59ad44d | 132 | if ( lp8->lp8Init() != true ) { |
jony1401 | 3:933dd59ad44d | 133 | //initCheck = true; |
jony1401 | 3:933dd59ad44d | 134 | } |
jony1401 | 3:933dd59ad44d | 135 | else { |
jony1401 | 3:933dd59ad44d | 136 | initCheck = false; |
jony1401 | 3:933dd59ad44d | 137 | |
jony1401 | 3:933dd59ad44d | 138 | } |
jony1401 | 3:933dd59ad44d | 139 | } |
jony1401 | 3:933dd59ad44d | 140 | |
jony1401 | 3:933dd59ad44d | 141 | else if ( lp8->lp8Talk( ccByte ) != true ) { |
jony1401 | 3:933dd59ad44d | 142 | //restart with init sequence if sensor state is lost or communication fails |
jony1401 | 3:933dd59ad44d | 143 | initCheck = true; |
jony1401 | 3:933dd59ad44d | 144 | ccByte = 0xff; //app error flag |
jony1401 | 0:ee3787c8e209 | 145 | } |
jony1401 | 3:933dd59ad44d | 146 | |
jony1401 | 1:b512a405b584 | 147 | //reset polling check |
jony1401 | 1:b512a405b584 | 148 | triggerSensor = false; |
jony1401 | 0:ee3787c8e209 | 149 | |
jony1401 | 3:933dd59ad44d | 150 | //update the gattServer characteristic values |
jony1401 | 3:933dd59ad44d | 151 | lp8ServicePtr->updateCo2Value( lp8->getValue() ); //get CO2 value |
jony1401 | 3:933dd59ad44d | 152 | lp8ServicePtr->updateTempValue( lp8->getTempValue() ); // |
jony1401 | 3:933dd59ad44d | 153 | lp8ServicePtr->updateVcapValue( lp8->getVcapValue() ); // |
jony1401 | 3:933dd59ad44d | 154 | lp8ServicePtr->updateError( lp8->getErrorStatus() ); // |
jony1401 | 3:933dd59ad44d | 155 | lp8ServicePtr->updateDataWritten( lp8->getCCbyte() ); //send back the calculation control byte that was used in LP8 measurement |
jony1401 | 3:933dd59ad44d | 156 | lp8ServicePtr->updateReWrite( ccByte ); |
jony1401 | 3:933dd59ad44d | 157 | |
jony1401 | 3:933dd59ad44d | 158 | //reset calibration control |
jony1401 | 3:933dd59ad44d | 159 | ccByte = 0x20; /* resets to 0x20 (subs. talk) after one sample. |
jony1401 | 3:933dd59ad44d | 160 | Check lp8Talk() function. */ |
jony1401 | 0:ee3787c8e209 | 161 | } |
jony1401 | 0:ee3787c8e209 | 162 | |
jony1401 | 1:b512a405b584 | 163 | else { ble.waitForEvent(); } //ble save energy |
jony1401 | 0:ee3787c8e209 | 164 | } |
jony1401 | 0:ee3787c8e209 | 165 | |
jony1401 | 0:ee3787c8e209 | 166 | }; |
jony1401 | 0:ee3787c8e209 | 167 |