Reading SenseAir LP8 CO2 sensor over bluetooth low energy

Dependencies:   BLE_API mbed nRF51822

Committer:
jony1401
Date:
Mon Aug 14 20:52:48 2017 +0000
Revision:
2:d02255d8c36f
Parent:
1:b512a405b584
Child:
3:933dd59ad44d
v2.0

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 2:d02255d8c36f 7 #define SENSOR_TIMER 20.0 //lp8 polling interval (seconds)
jony1401 2:d02255d8c36f 8 #define BLE_ADV_INTERVAL 500 //advertisment interval (milliseconds)
jony1401 2:d02255d8c36f 9 #define BACKGROUND_CALIBRATION_TIME 180 //timer to do background calibration (seconds)
jony1401 2:d02255d8c36f 10
jony1401 2:d02255d8c36f 11
jony1401 2:d02255d8c36f 12
jony1401 0:ee3787c8e209 13 //setup ble stack
jony1401 0:ee3787c8e209 14 BLE ble; //BLE object
jony1401 0:ee3787c8e209 15
jony1401 2:d02255d8c36f 16 // setup Pins
jony1401 2:d02255d8c36f 17 DigitalOut Res(P0_0, 1); //reset, pull Low for reset
jony1401 2:d02255d8c36f 18 DigitalIn RDY(P0_10); //rdy
jony1401 2:d02255d8c36f 19 DigitalOut VBB_EN(P0_5, 0); //set to low at startup
jony1401 0:ee3787c8e209 20 Serial Device(P0_9, P0_11); //tx, rx
jony1401 2:d02255d8c36f 21
jony1401 2:d02255d8c36f 22 // Timers
jony1401 0:ee3787c8e209 23 Timer lp8Wait; //timer for sensor communication
jony1401 2:d02255d8c36f 24 Timer bCalibration; //timer for background calibration
jony1401 0:ee3787c8e209 25
jony1401 0:ee3787c8e209 26
jony1401 2:d02255d8c36f 27 //BLE device name and uuid list setup
jony1401 0:ee3787c8e209 28 const static char DEVICE_NAME[] = "SenseAir LP8";
jony1401 0:ee3787c8e209 29 static const uint16_t uuid16_list[] = {LP8_Service::LP8_SERVICE_UUID};
jony1401 0:ee3787c8e209 30
jony1401 0:ee3787c8e209 31
jony1401 2:d02255d8c36f 32 //check for sensor triggering and uppdating the GattServer
jony1401 2:d02255d8c36f 33 bool triggerSensor = false; //sensor polling flag
jony1401 2:d02255d8c36f 34 bool doCalibration = false; //background calibration flag
jony1401 2:d02255d8c36f 35
jony1401 2:d02255d8c36f 36 LP8_Service *lp8ServicePtr; //pointer to lp8 BLE service object
jony1401 2:d02255d8c36f 37 uint8_t ccByte = 0x20; //calculation control byte to LP8
jony1401 0:ee3787c8e209 38
jony1401 0:ee3787c8e209 39
jony1401 0:ee3787c8e209 40
jony1401 0:ee3787c8e209 41 //**************************** ble functions *******************************
jony1401 0:ee3787c8e209 42 // on Disconnect, Restart BroadCasting
jony1401 0:ee3787c8e209 43 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
jony1401 0:ee3787c8e209 44 {
jony1401 1:b512a405b584 45 //turn of sensor at ble disconnect
jony1401 1:b512a405b584 46 VBB_EN.write( 0 );
jony1401 0:ee3787c8e209 47 //restart broadcast
jony1401 0:ee3787c8e209 48 ble.gap().startAdvertising();
jony1401 0:ee3787c8e209 49 }
jony1401 2:d02255d8c36f 50 //sensor polling interupt
jony1401 0:ee3787c8e209 51 void triggerSensorPollingInterupt()
jony1401 0:ee3787c8e209 52 {
jony1401 0:ee3787c8e209 53 triggerSensor = true;
jony1401 0:ee3787c8e209 54 };
jony1401 2:d02255d8c36f 55 //app interupt for calibration...
jony1401 2:d02255d8c36f 56 void calibrationCallback(const GattWriteCallbackParams *eventData)
jony1401 2:d02255d8c36f 57 {
jony1401 2:d02255d8c36f 58 ccByte = eventData-> data[0];
jony1401 2:d02255d8c36f 59 doCalibration = true;
jony1401 2:d02255d8c36f 60 }
jony1401 0:ee3787c8e209 61
jony1401 0:ee3787c8e209 62
jony1401 0:ee3787c8e209 63
jony1401 2:d02255d8c36f 64 //**************************** main **************************************
jony1401 2:d02255d8c36f 65 int main()
jony1401 0:ee3787c8e209 66 {
jony1401 1:b512a405b584 67 wait(1);
jony1401 2:d02255d8c36f 68
jony1401 0:ee3787c8e209 69
jony1401 0:ee3787c8e209 70 Ticker lp8Timer; //timer object for sensor polling interupts
jony1401 2:d02255d8c36f 71
jony1401 2:d02255d8c36f 72 //timer callback
jony1401 2:d02255d8c36f 73 lp8Timer.attach(&triggerSensorPollingInterupt, SENSOR_TIMER); //trigger sensor reading every X sec
jony1401 2:d02255d8c36f 74
jony1401 2:d02255d8c36f 75 ble.init();
jony1401 2:d02255d8c36f 76
jony1401 2:d02255d8c36f 77 //disconnect callback
jony1401 2:d02255d8c36f 78 ble.gap().onDisconnection( disconnectionCallback ); //do callback if ble disconnect
jony1401 2:d02255d8c36f 79 //on data recevied callback
jony1401 2:d02255d8c36f 80 ble.onDataWritten( calibrationCallback ); //trigger for calibration control
jony1401 2:d02255d8c36f 81
jony1401 2:d02255d8c36f 82 //************************ LP8 variables *********************************
jony1401 2:d02255d8c36f 83 int co2Value = 400; //initial CO2 value
jony1401 2:d02255d8c36f 84 double tempValue = 20.0; //init temp value
jony1401 2:d02255d8c36f 85 int Vcap = 3000; //mV
jony1401 2:d02255d8c36f 86 uint32_t errorFlag = 0; //error bits from lp8
jony1401 0:ee3787c8e209 87
jony1401 2:d02255d8c36f 88 //************************ Checks *********************************
jony1401 2:d02255d8c36f 89 bool initCheck = true; //check for init sensor state
jony1401 2:d02255d8c36f 90 bool successCheck = false; //check for sensor communication
jony1401 2:d02255d8c36f 91
jony1401 2:d02255d8c36f 92 //************************ Calculation control bytes ********************
jony1401 2:d02255d8c36f 93 // uint8_t sM = 0x20; //lp8 calculation control byte using Subesquent Measurments mode
jony1401 2:d02255d8c36f 94 // uint8_t bC = 0x52; //Background Calibration using unfilterd data + reset filters
jony1401 2:d02255d8c36f 95
jony1401 2:d02255d8c36f 96
jony1401 2:d02255d8c36f 97 //setup LP8 object
jony1401 2:d02255d8c36f 98 LP8 lp8(Device, VBB_EN, RDY, Res, lp8Wait); //pass pins: serial, vbb, rdy, res, timer
jony1401 2:d02255d8c36f 99
jony1401 2:d02255d8c36f 100 //Setup GattService
jony1401 2:d02255d8c36f 101 LP8_Service lp8Service(ble, co2Value, tempValue,
jony1401 2:d02255d8c36f 102 Vcap, errorFlag, ccByte); //
jony1401 2:d02255d8c36f 103 lp8ServicePtr = &lp8Service; //
jony1401 0:ee3787c8e209 104
jony1401 0:ee3787c8e209 105
jony1401 2:d02255d8c36f 106 // setup ble advertising parameters
jony1401 0:ee3787c8e209 107 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); //general bluetooth information(only support for ble
jony1401 0:ee3787c8e209 108 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); //service list
jony1401 0:ee3787c8e209 109 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
jony1401 0:ee3787c8e209 110 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
jony1401 1:b512a405b584 111 ble.gap().setAdvertisingInterval(BLE_ADV_INTERVAL); /* advertising interval in ms. */
jony1401 1:b512a405b584 112 ble.gap().startAdvertising(); //start broadcast
jony1401 0:ee3787c8e209 113
jony1401 2:d02255d8c36f 114 // Wait for initialization to complete.
jony1401 2:d02255d8c36f 115 while (ble.hasInitialized() == false) {
jony1401 2:d02255d8c36f 116 /* spin loop */
jony1401 2:d02255d8c36f 117 }
jony1401 0:ee3787c8e209 118
jony1401 0:ee3787c8e209 119
jony1401 0:ee3787c8e209 120
jony1401 2:d02255d8c36f 121 //*************************** start the main loop ***********************************
jony1401 0:ee3787c8e209 122 while ( true )
jony1401 0:ee3787c8e209 123 {
jony1401 1:b512a405b584 124 if(triggerSensor && ble.gap().getState().connected ) //trigger when timer interupts and there is an established ble connection
jony1401 0:ee3787c8e209 125 {
jony1401 0:ee3787c8e209 126 if ( initCheck ) {
jony1401 2:d02255d8c36f 127
jony1401 1:b512a405b584 128 successCheck = lp8.lp8Init(); //initialize talking with the lp8 (first call on startup)
jony1401 0:ee3787c8e209 129
jony1401 1:b512a405b584 130 if ( successCheck ) {
jony1401 0:ee3787c8e209 131 initCheck = false;
jony1401 1:b512a405b584 132 }
jony1401 0:ee3787c8e209 133 }
jony1401 2:d02255d8c36f 134 /*
jony1401 2:d02255d8c36f 135 else if ( doCalibration && ccByte == bC ){
jony1401 2:d02255d8c36f 136 lp8.lp8Talk( bC ); //do background calibration
jony1401 2:d02255d8c36f 137 bCalibration.start();
jony1401 2:d02255d8c36f 138 if( bCalibration.read() >= BACKGROUND_CALIBRATION_TIME ){
jony1401 2:d02255d8c36f 139 bCalibration.stop();
jony1401 2:d02255d8c36f 140 bCalibration.reset();
jony1401 2:d02255d8c36f 141 doCalibration = false;
jony1401 2:d02255d8c36f 142 ccByte = 0xff;
jony1401 2:d02255d8c36f 143 }
jony1401 2:d02255d8c36f 144 }
jony1401 2:d02255d8c36f 145 */
jony1401 0:ee3787c8e209 146 else {
jony1401 2:d02255d8c36f 147 lp8.lp8Talk( ccByte ); //Communication with lp8, pass Calculation control byte
jony1401 0:ee3787c8e209 148 }
jony1401 2:d02255d8c36f 149
jony1401 1:b512a405b584 150 //reset polling check
jony1401 1:b512a405b584 151 triggerSensor = false;
jony1401 0:ee3787c8e209 152
jony1401 2:d02255d8c36f 153 //update the gattServer
jony1401 2:d02255d8c36f 154 lp8ServicePtr->updateCo2Value( lp8.getValue() ); //get CO2 value
jony1401 2:d02255d8c36f 155 lp8ServicePtr->updateTempValue( lp8.getTempValue() ); //
jony1401 2:d02255d8c36f 156 lp8ServicePtr->updateVcapValue( lp8.getVcapValue() ); //
jony1401 2:d02255d8c36f 157 lp8ServicePtr->updateError( lp8.getErrorStatus() ); //
jony1401 2:d02255d8c36f 158 lp8ServicePtr->updateDataWritten( lp8.getCCbyte() ); //send back the calculation control byte that was used in LP8 measurement
jony1401 0:ee3787c8e209 159 }
jony1401 0:ee3787c8e209 160
jony1401 1:b512a405b584 161 else { ble.waitForEvent(); } //ble save energy
jony1401 0:ee3787c8e209 162 }
jony1401 0:ee3787c8e209 163
jony1401 0:ee3787c8e209 164 };
jony1401 0:ee3787c8e209 165