Reading SenseAir LP8 CO2 sensor over bluetooth low energy

Dependencies:   BLE_API mbed nRF51822

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?

UserRevisionLine numberNew 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