Reading SenseAir LP8 CO2 sensor over bluetooth low energy
Dependencies: BLE_API mbed nRF51822
Diff: LP8.h
- Revision:
- 0:ee3787c8e209
- Child:
- 1:b512a405b584
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LP8.h Fri Apr 21 13:26:06 2017 +0000 @@ -0,0 +1,284 @@ +#ifndef LP8_H +#define LP8_H + +class LP8 +{ +public: + + //constructor + LP8(Serial &device, DigitalOut &vbb, DigitalOut &vbb_en, DigitalIn &rdy, Timer &_timer): /* initiate class object */ + Device(device), + VBB(vbb), + VBB_EN(vbb_en), + RDY(rdy), + lp8Wait(_timer) + { + Device.baud(9600); //set baud rate to 9600 + + //initialize arrays with modbus commands. + //initial startup command + firstWrite[0] = 0xfe; + firstWrite[1] = 0x41; + firstWrite[2] = 0x00; + firstWrite[3] = 0x80; + firstWrite[4] = 0x01; + firstWrite[5] = 0x10; + firstWrite[6] = 0x28; + firstWrite[7] = 0x7e; + + //write sensor state to lp8 command + stateWrite[0] = 0xfe; //device adress + stateWrite[1] = 0x41; //read/write + stateWrite[2] = 0x00; // + stateWrite[3] = 0x80; //starting adress + stateWrite[4] = 0x18; //nr of bytes to send + stateWrite[5] = 0x20; //Calculation Control + for(int k = 6; k < 31; k++) { stateWrite[k] = 0x00; } + + //read lp8 state command + stateRead[0] = 0xfe; + stateRead[1] = 0x44; + stateRead[2] = 0x00; + stateRead[3] = 0x80; + stateRead[4] = 0x2c; + stateRead[5] = 0x00; + stateRead[5] = 0x00; + //response buffer + for(int k = 0; k < 60; k++) { response[k] = 0x00; } + + +// gC = 0x00; + co2 = 400; + counter = 0; + CRC = 0x0000; + _timeMe = 0.3; + }; + + + //send startup msg . + bool lp8Init(){ + VBB.write( 1 ); + VBB_EN.write( 1 ); //power on + timeIt( _timeMe ); + + transmitPacket(firstWrite, 8); //Send out msg (and nr of elements) over serial line + Response( 4 ); //read 4 bytes response + + if( RDY.read() == 0 ) { + lp8Wait.start(); + while( lp8Wait.read() < 0.5 ) { /* spin */ } + lp8Wait.stop(); + lp8Wait.reset(); + } + +//compute crc + CRC = modbusCrc(stateRead, 5); +//add crc value to the transmit package + stateRead[5] = (uint8_t)CRC; //crc_H + stateRead[6] = (uint8_t)(CRC >> 8); //crc_L + timeIt( _timeMe ); //wait for message to be sent and processed + transmitPacket(stateRead, 7); //transmit packet + Response( 49 ); //read sensor state and co2 value(s) + + VBB_EN.write( 0 ); //power off + VBB.write( 0 ); + +//was the talk a success? + if ( getValue() < 1 ) { + return 1; } + else { + return 0; } + + }; + + + //send subsequent messages to the lp8 + void lp8Talk(){ + + //transfer previous sensor state to the new msg out + for (int u = 4; u < 23+4; u++) { + stateWrite[u+2] = response[u]; + } + //compute new crc value + CRC = modbusCrc(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.write( 1 ); + VBB_EN.write( 1 ); //power on sensor + timeIt( _timeMe ); + + transmitPacket(stateWrite, 31); //Send out msg with previous state (and nr of elements) over serial line + Response( 4 ); //read 4 bytes response + + //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 + //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 + VBB.write( 0 ); + }; + + + + //get co2 value from lp8 response + unsigned long getValue() + { + int high = response[29]; + int low = response[30]; + unsigned long val = high * 256 + low; + + return val; + } + + + + /************************************************* Helper Functions ********************************************/ + /************************************************* ********************************************/ + void responsePurge(int bytesToPurge){ + for (int j = 0; j < bytesToPurge; j++) { + response[j] = 0x00; + } + }; + + + //read from the lp8 + void Response(int bytesToRead ){ + lp8Wait.start(); //poll rx line for x seconds + do { + if(Device.readable()) { + response[counter] = Device.getc(); + counter++; + } + } + while( lp8Wait.read() < 0.5 ); + counter = 0; + lp8Wait.stop(); + lp8Wait.reset(); + }; + + void transmitPacket(uint8_t msg[], int le ){ + //Send out msg over serial line: + while(!Device.writeable() ) { /* wait for serial available*/ } + for(int pos = 0; pos < le; pos++) { + Device.putc(msg[pos]); + } + + }; + + //timer + void timeIt(float &timeMe){ + //start amd stop timer... + lp8Wait.start(); + while (lp8Wait.read() < timeMe ) { /* W A I T I N G */ } + lp8Wait.stop(); + lp8Wait.reset(); + }; + + // Computation for the modbus 16-bit crc + uint16_t modbusCrc(uint8_t buffer[], int len){ + uint16_t crc = 0xFFFF; + + for (int pos = 0; pos < len; pos++) { + crc ^= (uint16_t)buffer[pos]; // XOR byte into least sig. byte of crc + + for (int i = 8; i != 0; i--) { // Loop over each bit + if ((crc & 0x0001) != 0) { // If the LSB is set + crc >>= 1; // shift right and XOR 0xA001 + crc ^= 0xA001; + } + else // Else LSB is not set + crc >>= 1; // shift right + } + } + // Note, this number has low and high bytes swapped + return crc; + }; + + + + +private: + + Serial &Device; + DigitalOut &VBB; + DigitalOut &VBB_EN; + DigitalIn &RDY; + Timer &lp8Wait; + + //msg containers (needs to be initialized at constructor level) + uint8_t firstWrite[8]; + uint8_t stateWrite[31]; + uint8_t stateRead[7]; + uint8_t response[60]; + + int co2; //CO2 initial value + int counter; //simple counter + uint16_t CRC; //modbus crc value + float _timeMe; //timer value +// uint8_t gC; //getCharacter... + + +}; +#endif + +/* +LP8 Communication Protocol (With no external Pressure Sensor): +-------------------------------------------------------------------------------- +Initial Measurement (first read after powerup): COMMANDS: +-------------------------------------------------------------------------------- +1) host powers up sensor: VBB_EN = 1 +2) host waits until rdy signal goes low: RDY = 0; +3) host writes command, "write 24 bytes starting from adress 0x0080": { 0xfe, 0x41, 0x00, 0x80, 0x18, 0x10, ... [any 23 bytes] ..., CRC_low, CRC_high }; +4) host reads response: { 0xfe, 0x41, 0x81, 0xe0 }; +5) host waits until rdy signal goes high: RDY = 1; +6) host writes command "read 44 bytes starting from adress 0x0080": { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high }; +7) host reads response: { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high }; +8) host powers down sensor: VBB_EN = 0; + +[------------------------------------------------------------------------------] +Optional first reading W/O pressure sensor +[------------------------------------------------------------------------------] +1) host powers up sensor: VBB_EN = 1 +2) host waits until rdy signal goes low: RDY = 0; +3) host writes command, "write 24 bytes starting from adress 0x0080": { 0xfe, 0x41, 0x00, 0x80, 0x18, 0x10, 0x28, 0x7e }; +4) host reads response: { 0xfe, 0x41, 0x81, 0xe0 }; +5) host waits until rdy signal goes high: RDY = 1; +6) host writes command "read 44 bytes starting from adress 0x0080": { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high }; +7) host reads response: { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high }; +8) host powers down sensor: VBB_EN = 0; + + +-------------------------------------------------------------------------------- +Subsequent readings: +-------------------------------------------------------------------------------- +1) host powers up sensor: VBB_EN = 1 +2) host waits until rdy signal goes low: RDY = 0; +3) host writes command, "write 24 bytes starting from adress 0x0080": { 0xfe, 0x41, 0x00, 0x80, 0x18, CC, SS1, ..., SS23, CRC_low, CRC_high }; +4) host reads response: { 0xfe, 0x41, 0x81, 0xe0 }; +5) host waits until rdy signal goes high: RDY = 1; +6) host writes command "read 44 bytes starting from adress 0x0080": { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high }; +7) host reads response: { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high }; +8) host powers down sensor: VBB_EN = 0; + + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +CC = Calculation Control, 1 byte +SS = Sensor State, Sensor State, 23 bytes +D = Measured data and Sensor Status, 23 bytes +PP = Host Pressure Value +CRC= 16 bit CRC error check +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +*/ +