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
Fork of SenseAirLP8 by
Revision 3:933dd59ad44d, committed 2017-08-18
- Comitter:
- jony1401
- Date:
- Fri Aug 18 18:20:41 2017 +0000
- Parent:
- 2:d02255d8c36f
- Child:
- 4:320febe026ed
- Commit message:
- Updated version. Including more functionality.
Changed in this revision
--- a/LP8.h Mon Aug 14 20:52:48 2017 +0000
+++ b/LP8.h Fri Aug 18 18:20:41 2017 +0000
@@ -15,7 +15,8 @@
RES(res),
lp8Wait(_timer)
{
- Device.baud(9600); //set baud rate to 9600
+ Device.baud(9600); //set baud rate to 9600 Hz
+ Device.format(8, SerialBase::None, 2); //set bits, parity and stop bits
//initialize arrays with lp8 modbus commands.
//initial startup command:
@@ -44,15 +45,20 @@
stateRead[3] = 0x80; //starting adress
stateRead[4] = 0x2c; //number of bytes to read
stateRead[5] = 0x00; //crc_l
- stateRead[5] = 0x00; //crc_h
+ stateRead[6] = 0x00; //crc_h
+
+ //communication confirmation sequence (response from lp8)
+ confirmation[0] = 0xfe;
+ confirmation[1] = 0x41;
+ confirmation[2] = 0x81;
+ confirmation[3] = 0xe0;
//response buffer
for(int k = 0; k < 60; k++) { response[k] = 0x00; }
//variable initialization
- co2 = 400; //co2 value
- counter = 0; //
- CRC = 0x0000; //crc value
+ co2 = 400; //
+ CRC = 0x0000; //
};
@@ -60,66 +66,109 @@
//LP8 Initialization and first message
bool lp8Init(){
-// //Reset LP8
-// RES.write( 0 ); //reset
-// timeIt( 1.2 );
-// RES.write( 1 ); //enable
+ Device.format(8, SerialBase::None, 2);
+ //Reset LP8
+ RES.write( 0 ); //reset
+ timeIt( 1.0 );
+ RES.write( 1 ); //enable
+ timeIt(0.2);
//Enable Sensor
VBB_EN.write( 1 ); //power on
+
//wait for rdy signal
- timeIt( 0.35 ); //wait for lp8 rdy signal
+ timeIt( 0.30 ); //wait for lp8 rdy signal
+// while(RDY.read() != 0 ) { /* wait for rdy to go low */}
+
+ //transmit first packet
transmitPacket(firstWrite, 8); //Send out msg (and nr of bytes) over serial line
Response( 4 ); //read 4 bytes response
+
+ //check response
+ if ( responseCompare() != true){
+ //VBB_EN.write( 0 );
+ return false;
+ }
+
//compute crc
CRC = modbusCrc(stateRead, 5);
+
//add crc value to the transmit package
stateRead[5] = (uint8_t)CRC; //crc_l
stateRead[6] = (uint8_t)(CRC >> 8); //crc_h
+
//wait for rdy
- timeIt( 0.35 ); //
+ timeIt( 0.20 ); //
+// while(RDY.read() != 1 ) { /*wait for rdy to go high */}
+
transmitPacket(stateRead, 7); //transmit packet
- Response( 49 ); //read sensor state and co2 value(s)
+ Response( 49 ); //get sensor state and co2 value(s)
VBB_EN.write( 0 ); //power off lp8
- //was the talk a success? (simple check...)
- if ( getValue() < 1 ) {
- return 1; }
- else {
- return 0; }
+ return true;
};
//send subsequent messages to the lp8
- void lp8Talk(uint8_t ccByte){
+ bool lp8Talk(uint8_t inc_ccByte){
+ static const uint8_t A[] = {0xFE,0x41,0x00,0x80,0x20,0x00,0x00,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x7F,0xFF,0x00,0x00,0x95,0xED,0x00,0x03,0x29,0x00,0x27,0x8C, 0xf5, 0x63};
+
+ Device.format(8, SerialBase::None, 2);
//transfer previous sensor state to the new msg out
for (int u = 4; u < 23+4; u++) {
stateWrite[u+2] = response[u];
}
- //Set Calibration Control Byte (see end of page for explantion)
- stateWrite[5] = ccByte;
+ //Set Calibration Control Byte (see end of page for explantion),
+ /* remove this statement if you want to be able to send anything to lp8 calculation control */
+ if( inc_ccByte != 0x20 ){ /* 0x52 is "simple recalibration, needs only one sample */
+ stateWrite[5] = inc_ccByte;
+ }
+ else {
+ stateWrite[5] = 0x20;
+ }
+
+
//compute new crc value
- CRC = modbusCrc(stateWrite, 29);
+ CRC = modbusCrc((uint8_t*)stateWrite, 29);
+
//add new crc value to send list
stateWrite[29] = (uint8_t)CRC;
stateWrite[30] = (uint8_t)(CRC >> 8);
//initialize new transfer sequence
VBB_EN.write( 1 ); //power on sensor
+
timeIt( 0.35 );
- transmitPacket(stateWrite, 31); //Send out msg with previous state (and nr of elements) over serial line
- Response( 4 ); //read 4 bytes response
+// while(RDY.read() != 0 ) { /* wait for rdy */}
+
+ transmitPacket(/*(uint8_t*)A*/(uint8_t*)stateWrite, 31); //Send out msg with previous state (and nr of elements) over serial line
+ Response( 4 ); //read 4 bytes response
+
+ //compare to confirmation sequence
+ if ( responseCompare() != true){
+ //VBB_EN.write( 0 );
+ return false;
+ }
+
//compute crc
CRC = modbusCrc(stateRead, 5);
+
//add crc value to the read request transmit package
stateRead[5] = (uint8_t)CRC; //crc_l
stateRead[6] = (uint8_t)(CRC >> 8); //crc_h
- timeIt( 0.35 );
+
+ timeIt( 0.20 );
+// while(RDY.read() != 1 ) { /* wait for rdy to go high */}
+
//send read request
transmitPacket(stateRead, 7); //transmit packet
+
//read sensor response
- Response( 49 ); //read sensor state and co2 value(s)
- VBB_EN.write( 0 ); //power off
+ Response( 49 ); //get sensor state
+ VBB_EN.write( 0 ); //power off
+
+ return true;
};
//get value from lp8 response
@@ -132,21 +181,22 @@
return val;
}
- double getTempValue()
+ float getTempValue()
{
int h = response[33];
int l = response[34];
unsigned long _temp = h * 256 + l;
- double _tempVal = 0.01 * _temp;
+ float _tempVal = 0.01 * _temp;
return _tempVal;
}
+ /* get Vcap value for at current measurement, [35],[36] is previous Vcap value */
int getVcapValue(){
- int hB = response[35];
- int lB = response[36];
+ int hB = response[37];
+ int lB = response[38];
unsigned long temp = hB * 256 + lB;
return temp;
@@ -165,8 +215,8 @@
//get calculation Control byte from lp8 response
uint8_t getCCbyte(){
- uint8_t responseCCbyte = response[0];
- return responseCCbyte;
+ uint8_t rCCbyte = stateWrite[5];
+ return rCCbyte;
}
@@ -177,21 +227,20 @@
for (int j = 0; j < bytesToPurge; j++) {
response[j] = 0x00;
}
+ //for(int k = 6; k < 31; k++) { stateWrite[k] = 0x00; } //purge sensor state
};
-//read response from lp8 (not energy efficient...)
- void Response(int bytesToRead ){
- lp8Wait.start(); //poll rx line for 0.5 seconds
+//read response from lp8
+ void Response( int bytesToRead ){
+ int Count = 0;
do {
if(Device.readable()) {
- response[counter] = Device.getc();
- counter++;
+ response[Count] = Device.getc();
+ Count++;
+ --bytesToRead;
}
}
- while( lp8Wait.read() < 0.2 );
- counter = 0;
- lp8Wait.stop();
- lp8Wait.reset();
+ while( bytesToRead > 0);
};
//transmit data over serial lines
@@ -233,6 +282,23 @@
return crc;
};
+ bool responseCompare(){
+
+ short seq = 0;
+
+ for(int j=0; j < 4; j++){
+ if(response[j] == confirmation[j]){
+ seq++;
+ }
+ }
+ //return false if check sequence fails
+ if( seq != 4 ){
+ return false;
+ }
+
+ return true;
+ }
+
//variables and buffers
private:
//pins
@@ -244,15 +310,17 @@
Timer &lp8Wait;
//msg containers
+
uint8_t firstWrite[8];
- uint8_t stateWrite[31];
+ volatile uint8_t stateWrite[31];
uint8_t stateRead[7];
- uint8_t response[60];
-
+ uint8_t confirmation[4];
+
+ volatile uint8_t response[60];
+
//
int co2; //CO2 initial value
int tempValue;
- int counter; //simple counter
uint16_t CRC; //modbus crc value
--- a/LP8_Service.h Mon Aug 14 20:52:48 2017 +0000
+++ b/LP8_Service.h Fri Aug 18 18:20:41 2017 +0000
@@ -8,29 +8,36 @@
public:
//UUID descriptors
- const static uint16_t LP8_SERVICE_UUID = 0xA000; //
+ const static uint16_t LP8_SERVICE_UUID = 0xA000; // service identifier
const static uint16_t LP8_STATE_CHARACTERISTIC_UUID = 0xA001; // CO2 concentration characteristic
const static uint16_t LP8_READ_TEMP_UUID = 0x2A1F; // temp (Celsius) characteristic
const static uint16_t LP8_VCAP_UUID = 0xA010; // Vcap characteristic (mV)
- const static uint16_t LP8_ERROR_UUID = 0xA011; // LP8 Error bits characteristic
-
+ const static uint16_t LP8_ERROR_UUID = 0xA011; // LP8 Error bits characteristic
const static uint16_t LP8_WRITE_UUID = 0xA002; // Write calculation control from app to lp8
const static uint16_t LP8_WRITTEN_UUID = 0xB001; // display what was written into lp8 calculation control
+ const static uint16_t LP8_reWrite_uuid = 0xB111;
- //constructor setup for Gatt Service
- LP8_Service(BLE &_ble, int co2ValueInitial, double tempValueInitial,
- int initialVcap, uint32_t initialError, uint8_t initCC): /* Pass variables to ble stack */
+
+//constructor setup for Gatt Service
+ LP8_Service(BLE &_ble, /* Pass variables to characteristics and ble */
+ int co2ValueInitial,
+ float tempValueInitial,
+ int initialVcap,
+ uint32_t initialError,
+ uint8_t initCC,
+ uint8_t initSentCC):
ble(_ble),
lp8State(LP8_STATE_CHARACTERISTIC_UUID, &co2ValueInitial, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
lp8Temp(LP8_READ_TEMP_UUID, &tempValueInitial, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
lp8Vcap(LP8_VCAP_UUID, &initialVcap, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
lp8Error(LP8_ERROR_UUID, &initialError, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
lp8WriteCC(LP8_WRITE_UUID, &initCC),
- lp8Written(LP8_WRITTEN_UUID, &initCC, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)
+ lp8Written(LP8_WRITTEN_UUID, &initSentCC, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
+ lp8reWriteCC(LP8_reWrite_uuid, &initCC, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)
{
//characterisitics
- GattCharacteristic *charTable[] = {&lp8State, &lp8Temp, &lp8Vcap, &lp8Error, &lp8WriteCC, &lp8Written };
+ GattCharacteristic *charTable[] = {&lp8State, &lp8Temp, &lp8Vcap, &lp8Error, &lp8WriteCC, &lp8Written, &lp8reWriteCC };
//Service, Setup for LP8 GattService
GattService lp8Service(LP8_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
@@ -46,7 +53,7 @@
ble.gattServer().write(lp8State.getValueAttribute().getHandle(),(uint8_t *) &co2Value, sizeof(co2Value));
};
- void updateTempValue(double tempValue)
+ void updateTempValue(float tempValue)
{
ble.gattServer().write(lp8Temp.getValueAttribute().getHandle(),(uint8_t *) &tempValue, sizeof(tempValue));
};
@@ -61,11 +68,16 @@
ble.gattServer().write(lp8Error.getValueAttribute().getHandle(),(uint8_t *) &lp8ErrorValue, sizeof(lp8ErrorValue));
};
-//reWrite written data
+//
void updateDataWritten(uint8_t lp8WrittenValue)
{
ble.gattServer().write(lp8Written.getValueAttribute().getHandle(),(uint8_t *) &lp8WrittenValue, sizeof(lp8WrittenValue));
}
+
+ void updateReWrite ( uint8_t lp8ReWrite )
+ {
+ ble.gattServer().write(lp8reWriteCC.getValueAttribute().getHandle(),(uint8_t *) &lp8ReWrite, sizeof(lp8ReWrite));
+ }
private:
@@ -73,14 +85,19 @@
BLE &ble; //
//Service Characteristics
- //Read Values
+
+ //Read sensor values
ReadOnlyGattCharacteristic<int> lp8State; //
- ReadOnlyGattCharacteristic<double> lp8Temp;
+ ReadOnlyGattCharacteristic<float> lp8Temp;
ReadOnlyGattCharacteristic<int> lp8Vcap;
ReadOnlyGattCharacteristic<uint32_t> lp8Error;
+
+ //Write Value
+ WriteOnlyGattCharacteristic<uint8_t> lp8WriteCC;
+
+ //read back written and cc byte(flag)
ReadOnlyGattCharacteristic<uint8_t> lp8Written;
- //Write Values
- WriteOnlyGattCharacteristic<uint8_t> lp8WriteCC;
+ ReadOnlyGattCharacteristic<uint8_t> lp8reWriteCC;
};
--- a/main.cpp Mon Aug 14 20:52:48 2017 +0000
+++ b/main.cpp Fri Aug 18 18:20:41 2017 +0000
@@ -4,10 +4,8 @@
#include "LP8.h"
//Sensor and ble Configuration parameters
-#define SENSOR_TIMER 20.0 //lp8 polling interval (seconds)
+#define SENSOR_TIMER 16.0 //lp8 polling interval (seconds)
#define BLE_ADV_INTERVAL 500 //advertisment interval (milliseconds)
-#define BACKGROUND_CALIBRATION_TIME 180 //timer to do background calibration (seconds)
-
//setup ble stack
@@ -21,42 +19,58 @@
// Timers
Timer lp8Wait; //timer for sensor communication
-Timer bCalibration; //timer for background calibration
-
+Ticker lp8Timer; //timer object for sensor polling
//BLE device name and uuid list setup
const static char DEVICE_NAME[] = "SenseAir LP8";
static const uint16_t uuid16_list[] = {LP8_Service::LP8_SERVICE_UUID};
-
-//check for sensor triggering and uppdating the GattServer
+//check for sensor triggering
bool triggerSensor = false; //sensor polling flag
bool doCalibration = false; //background calibration flag
+bool initCheck = true; //check for init sensor state
-LP8_Service *lp8ServicePtr; //pointer to lp8 BLE service object
+LP8_Service *lp8ServicePtr; //
+
uint8_t ccByte = 0x20; //calculation control byte to LP8
-//**************************** ble functions *******************************
-// on Disconnect, Restart BroadCasting
+
+//**************************** ble callback functions ***************************
+// on Disconnect interupt
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
+ initCheck = true;
//turn of sensor at ble disconnect
VBB_EN.write( 0 );
+ //cancel sensor timer
+ lp8Timer.detach();
+
//restart broadcast
ble.gap().startAdvertising();
}
-//sensor polling interupt
+//sensor polling
void triggerSensorPollingInterupt()
{
triggerSensor = true;
+
+ //reset callback timer
+ lp8Timer.detach();
+ lp8Timer.attach(&triggerSensorPollingInterupt, SENSOR_TIMER);
+
};
-//app interupt for calibration...
+
+void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
+{
+ lp8Timer.attach( triggerSensorPollingInterupt, 4 );
+}
+
+//on BLE data written
void calibrationCallback(const GattWriteCallbackParams *eventData)
{
+ doCalibration = true;
ccByte = eventData-> data[0];
- doCalibration = true;
}
@@ -66,41 +80,30 @@
{
wait(1);
-
- Ticker lp8Timer; //timer object for sensor polling interupts
+ ble.init();
- //timer callback
- lp8Timer.attach(&triggerSensorPollingInterupt, SENSOR_TIMER); //trigger sensor reading every X sec
-
- ble.init();
-
- //disconnect callback
- ble.gap().onDisconnection( disconnectionCallback ); //do callback if ble disconnect
- //on data recevied callback
- ble.onDataWritten( calibrationCallback ); //trigger for calibration control
+ //callbacks
+ ble.gap().onConnection( connectionCallback );
+ ble.gap().onDisconnection( disconnectionCallback ); //
+ ble.gattServer().onDataWritten( calibrationCallback ); //
//************************ LP8 variables *********************************
- int co2Value = 400; //initial CO2 value
- double tempValue = 20.0; //init temp value
- int Vcap = 3000; //mV
- uint32_t errorFlag = 0; //error bits from lp8
+ int co2Value = 99; //initial CO2 value
+ float tempValue = 99; //init temp value
+ int Vcap = 99; //mV
+ uint32_t errorFlag = 0; //error bits from lp8
+ uint8_t sentCCbyte = 0x99;
-//************************ Checks *********************************
- bool initCheck = true; //check for init sensor state
- bool successCheck = false; //check for sensor communication
-//************************ Calculation control bytes ********************
-// uint8_t sM = 0x20; //lp8 calculation control byte using Subesquent Measurments mode
-// uint8_t bC = 0x52; //Background Calibration using unfilterd data + reset filters
+//setup LP8 object
+LP8 *lp8 = new LP8(Device, VBB_EN, RDY, Res, lp8Wait);
-
-//setup LP8 object
- LP8 lp8(Device, VBB_EN, RDY, Res, lp8Wait); //pass pins: serial, vbb, rdy, res, timer
//Setup GattService
- LP8_Service lp8Service(ble, co2Value, tempValue,
- Vcap, errorFlag, ccByte); //
- lp8ServicePtr = &lp8Service; //
+// LP8_Service lp8Service(ble, co2Value, tempValue,
+ // Vcap, errorFlag, ccByte, sentCCbyte);
+ lp8ServicePtr = new LP8_Service(ble, co2Value, tempValue,
+ Vcap, errorFlag, ccByte, sentCCbyte); // lp8Service;
// setup ble advertising parameters
@@ -109,7 +112,7 @@
ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
ble.gap().setAdvertisingInterval(BLE_ADV_INTERVAL); /* advertising interval in ms. */
- ble.gap().startAdvertising(); //start broadcast
+ ble.gap().startAdvertising();
// Wait for initialization to complete.
while (ble.hasInitialized() == false) {
@@ -121,41 +124,40 @@
//*************************** start the main loop ***********************************
while ( true )
{
+
if(triggerSensor && ble.gap().getState().connected ) //trigger when timer interupts and there is an established ble connection
{
if ( initCheck ) {
-
- successCheck = lp8.lp8Init(); //initialize talking with the lp8 (first call on startup)
-
- if ( successCheck ) {
- initCheck = false;
- }
+ lp8->responsePurge(50); //purge buffer
+ if ( lp8->lp8Init() != true ) {
+ //initCheck = true;
+ }
+ else {
+ initCheck = false;
+
+ }
+ }
+
+ else if ( lp8->lp8Talk( ccByte ) != true ) {
+ //restart with init sequence if sensor state is lost or communication fails
+ initCheck = true;
+ ccByte = 0xff; //app error flag
}
-/*
- else if ( doCalibration && ccByte == bC ){
- lp8.lp8Talk( bC ); //do background calibration
- bCalibration.start();
- if( bCalibration.read() >= BACKGROUND_CALIBRATION_TIME ){
- bCalibration.stop();
- bCalibration.reset();
- doCalibration = false;
- ccByte = 0xff;
- }
- }
-*/
- else {
- lp8.lp8Talk( ccByte ); //Communication with lp8, pass Calculation control byte
- }
-
+
//reset polling check
triggerSensor = false;
- //update the gattServer
- lp8ServicePtr->updateCo2Value( lp8.getValue() ); //get CO2 value
- lp8ServicePtr->updateTempValue( lp8.getTempValue() ); //
- lp8ServicePtr->updateVcapValue( lp8.getVcapValue() ); //
- lp8ServicePtr->updateError( lp8.getErrorStatus() ); //
- lp8ServicePtr->updateDataWritten( lp8.getCCbyte() ); //send back the calculation control byte that was used in LP8 measurement
+ //update the gattServer characteristic values
+ lp8ServicePtr->updateCo2Value( lp8->getValue() ); //get CO2 value
+ lp8ServicePtr->updateTempValue( lp8->getTempValue() ); //
+ lp8ServicePtr->updateVcapValue( lp8->getVcapValue() ); //
+ lp8ServicePtr->updateError( lp8->getErrorStatus() ); //
+ lp8ServicePtr->updateDataWritten( lp8->getCCbyte() ); //send back the calculation control byte that was used in LP8 measurement
+ lp8ServicePtr->updateReWrite( ccByte );
+
+ //reset calibration control
+ ccByte = 0x20; /* resets to 0x20 (subs. talk) after one sample.
+ Check lp8Talk() function. */
}
else { ble.waitForEvent(); } //ble save energy
