Reading SenseAir LP8 CO2 sensor over bluetooth low energy

Dependencies:   BLE_API mbed nRF51822

Committer:
jony1401
Date:
Fri Apr 21 13:26:06 2017 +0000
Revision:
0:ee3787c8e209
Child:
1:b512a405b584
alpha v 1.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jony1401 0:ee3787c8e209 1 #ifndef LP8_H
jony1401 0:ee3787c8e209 2 #define LP8_H
jony1401 0:ee3787c8e209 3
jony1401 0:ee3787c8e209 4 class LP8
jony1401 0:ee3787c8e209 5 {
jony1401 0:ee3787c8e209 6 public:
jony1401 0:ee3787c8e209 7
jony1401 0:ee3787c8e209 8 //constructor
jony1401 0:ee3787c8e209 9 LP8(Serial &device, DigitalOut &vbb, DigitalOut &vbb_en, DigitalIn &rdy, Timer &_timer): /* initiate class object */
jony1401 0:ee3787c8e209 10 Device(device),
jony1401 0:ee3787c8e209 11 VBB(vbb),
jony1401 0:ee3787c8e209 12 VBB_EN(vbb_en),
jony1401 0:ee3787c8e209 13 RDY(rdy),
jony1401 0:ee3787c8e209 14 lp8Wait(_timer)
jony1401 0:ee3787c8e209 15 {
jony1401 0:ee3787c8e209 16 Device.baud(9600); //set baud rate to 9600
jony1401 0:ee3787c8e209 17
jony1401 0:ee3787c8e209 18 //initialize arrays with modbus commands.
jony1401 0:ee3787c8e209 19 //initial startup command
jony1401 0:ee3787c8e209 20 firstWrite[0] = 0xfe;
jony1401 0:ee3787c8e209 21 firstWrite[1] = 0x41;
jony1401 0:ee3787c8e209 22 firstWrite[2] = 0x00;
jony1401 0:ee3787c8e209 23 firstWrite[3] = 0x80;
jony1401 0:ee3787c8e209 24 firstWrite[4] = 0x01;
jony1401 0:ee3787c8e209 25 firstWrite[5] = 0x10;
jony1401 0:ee3787c8e209 26 firstWrite[6] = 0x28;
jony1401 0:ee3787c8e209 27 firstWrite[7] = 0x7e;
jony1401 0:ee3787c8e209 28
jony1401 0:ee3787c8e209 29 //write sensor state to lp8 command
jony1401 0:ee3787c8e209 30 stateWrite[0] = 0xfe; //device adress
jony1401 0:ee3787c8e209 31 stateWrite[1] = 0x41; //read/write
jony1401 0:ee3787c8e209 32 stateWrite[2] = 0x00; //
jony1401 0:ee3787c8e209 33 stateWrite[3] = 0x80; //starting adress
jony1401 0:ee3787c8e209 34 stateWrite[4] = 0x18; //nr of bytes to send
jony1401 0:ee3787c8e209 35 stateWrite[5] = 0x20; //Calculation Control
jony1401 0:ee3787c8e209 36 for(int k = 6; k < 31; k++) { stateWrite[k] = 0x00; }
jony1401 0:ee3787c8e209 37
jony1401 0:ee3787c8e209 38 //read lp8 state command
jony1401 0:ee3787c8e209 39 stateRead[0] = 0xfe;
jony1401 0:ee3787c8e209 40 stateRead[1] = 0x44;
jony1401 0:ee3787c8e209 41 stateRead[2] = 0x00;
jony1401 0:ee3787c8e209 42 stateRead[3] = 0x80;
jony1401 0:ee3787c8e209 43 stateRead[4] = 0x2c;
jony1401 0:ee3787c8e209 44 stateRead[5] = 0x00;
jony1401 0:ee3787c8e209 45 stateRead[5] = 0x00;
jony1401 0:ee3787c8e209 46 //response buffer
jony1401 0:ee3787c8e209 47 for(int k = 0; k < 60; k++) { response[k] = 0x00; }
jony1401 0:ee3787c8e209 48
jony1401 0:ee3787c8e209 49
jony1401 0:ee3787c8e209 50 // gC = 0x00;
jony1401 0:ee3787c8e209 51 co2 = 400;
jony1401 0:ee3787c8e209 52 counter = 0;
jony1401 0:ee3787c8e209 53 CRC = 0x0000;
jony1401 0:ee3787c8e209 54 _timeMe = 0.3;
jony1401 0:ee3787c8e209 55 };
jony1401 0:ee3787c8e209 56
jony1401 0:ee3787c8e209 57
jony1401 0:ee3787c8e209 58 //send startup msg .
jony1401 0:ee3787c8e209 59 bool lp8Init(){
jony1401 0:ee3787c8e209 60 VBB.write( 1 );
jony1401 0:ee3787c8e209 61 VBB_EN.write( 1 ); //power on
jony1401 0:ee3787c8e209 62 timeIt( _timeMe );
jony1401 0:ee3787c8e209 63
jony1401 0:ee3787c8e209 64 transmitPacket(firstWrite, 8); //Send out msg (and nr of elements) over serial line
jony1401 0:ee3787c8e209 65 Response( 4 ); //read 4 bytes response
jony1401 0:ee3787c8e209 66
jony1401 0:ee3787c8e209 67 if( RDY.read() == 0 ) {
jony1401 0:ee3787c8e209 68 lp8Wait.start();
jony1401 0:ee3787c8e209 69 while( lp8Wait.read() < 0.5 ) { /* spin */ }
jony1401 0:ee3787c8e209 70 lp8Wait.stop();
jony1401 0:ee3787c8e209 71 lp8Wait.reset();
jony1401 0:ee3787c8e209 72 }
jony1401 0:ee3787c8e209 73
jony1401 0:ee3787c8e209 74 //compute crc
jony1401 0:ee3787c8e209 75 CRC = modbusCrc(stateRead, 5);
jony1401 0:ee3787c8e209 76 //add crc value to the transmit package
jony1401 0:ee3787c8e209 77 stateRead[5] = (uint8_t)CRC; //crc_H
jony1401 0:ee3787c8e209 78 stateRead[6] = (uint8_t)(CRC >> 8); //crc_L
jony1401 0:ee3787c8e209 79 timeIt( _timeMe ); //wait for message to be sent and processed
jony1401 0:ee3787c8e209 80 transmitPacket(stateRead, 7); //transmit packet
jony1401 0:ee3787c8e209 81 Response( 49 ); //read sensor state and co2 value(s)
jony1401 0:ee3787c8e209 82
jony1401 0:ee3787c8e209 83 VBB_EN.write( 0 ); //power off
jony1401 0:ee3787c8e209 84 VBB.write( 0 );
jony1401 0:ee3787c8e209 85
jony1401 0:ee3787c8e209 86 //was the talk a success?
jony1401 0:ee3787c8e209 87 if ( getValue() < 1 ) {
jony1401 0:ee3787c8e209 88 return 1; }
jony1401 0:ee3787c8e209 89 else {
jony1401 0:ee3787c8e209 90 return 0; }
jony1401 0:ee3787c8e209 91
jony1401 0:ee3787c8e209 92 };
jony1401 0:ee3787c8e209 93
jony1401 0:ee3787c8e209 94
jony1401 0:ee3787c8e209 95 //send subsequent messages to the lp8
jony1401 0:ee3787c8e209 96 void lp8Talk(){
jony1401 0:ee3787c8e209 97
jony1401 0:ee3787c8e209 98 //transfer previous sensor state to the new msg out
jony1401 0:ee3787c8e209 99 for (int u = 4; u < 23+4; u++) {
jony1401 0:ee3787c8e209 100 stateWrite[u+2] = response[u];
jony1401 0:ee3787c8e209 101 }
jony1401 0:ee3787c8e209 102 //compute new crc value
jony1401 0:ee3787c8e209 103 CRC = modbusCrc(stateWrite, 29);
jony1401 0:ee3787c8e209 104 //add new crc value to send list
jony1401 0:ee3787c8e209 105 stateWrite[29] = (uint8_t)CRC;
jony1401 0:ee3787c8e209 106 stateWrite[30] = (uint8_t)(CRC >> 8);
jony1401 0:ee3787c8e209 107
jony1401 0:ee3787c8e209 108
jony1401 0:ee3787c8e209 109 //initialize new transfer sequence
jony1401 0:ee3787c8e209 110 VBB.write( 1 );
jony1401 0:ee3787c8e209 111 VBB_EN.write( 1 ); //power on sensor
jony1401 0:ee3787c8e209 112 timeIt( _timeMe );
jony1401 0:ee3787c8e209 113
jony1401 0:ee3787c8e209 114 transmitPacket(stateWrite, 31); //Send out msg with previous state (and nr of elements) over serial line
jony1401 0:ee3787c8e209 115 Response( 4 ); //read 4 bytes response
jony1401 0:ee3787c8e209 116
jony1401 0:ee3787c8e209 117 //compute crc
jony1401 0:ee3787c8e209 118 CRC = modbusCrc(stateRead, 5);
jony1401 0:ee3787c8e209 119 //add crc value to the read request transmit package
jony1401 0:ee3787c8e209 120 stateRead[5] = (uint8_t)CRC; //crc_l
jony1401 0:ee3787c8e209 121 stateRead[6] = (uint8_t)(CRC >> 8); //crc_h
jony1401 0:ee3787c8e209 122 //send read request
jony1401 0:ee3787c8e209 123 transmitPacket(stateRead, 7); //transmit packet
jony1401 0:ee3787c8e209 124 //read sensor response
jony1401 0:ee3787c8e209 125 Response( 49 ); //read sensor state and co2 value(s)
jony1401 0:ee3787c8e209 126
jony1401 0:ee3787c8e209 127 VBB_EN.write( 0 ); //power off
jony1401 0:ee3787c8e209 128 VBB.write( 0 );
jony1401 0:ee3787c8e209 129 };
jony1401 0:ee3787c8e209 130
jony1401 0:ee3787c8e209 131
jony1401 0:ee3787c8e209 132
jony1401 0:ee3787c8e209 133 //get co2 value from lp8 response
jony1401 0:ee3787c8e209 134 unsigned long getValue()
jony1401 0:ee3787c8e209 135 {
jony1401 0:ee3787c8e209 136 int high = response[29];
jony1401 0:ee3787c8e209 137 int low = response[30];
jony1401 0:ee3787c8e209 138 unsigned long val = high * 256 + low;
jony1401 0:ee3787c8e209 139
jony1401 0:ee3787c8e209 140 return val;
jony1401 0:ee3787c8e209 141 }
jony1401 0:ee3787c8e209 142
jony1401 0:ee3787c8e209 143
jony1401 0:ee3787c8e209 144
jony1401 0:ee3787c8e209 145 /************************************************* Helper Functions ********************************************/
jony1401 0:ee3787c8e209 146 /************************************************* ********************************************/
jony1401 0:ee3787c8e209 147 void responsePurge(int bytesToPurge){
jony1401 0:ee3787c8e209 148 for (int j = 0; j < bytesToPurge; j++) {
jony1401 0:ee3787c8e209 149 response[j] = 0x00;
jony1401 0:ee3787c8e209 150 }
jony1401 0:ee3787c8e209 151 };
jony1401 0:ee3787c8e209 152
jony1401 0:ee3787c8e209 153
jony1401 0:ee3787c8e209 154 //read from the lp8
jony1401 0:ee3787c8e209 155 void Response(int bytesToRead ){
jony1401 0:ee3787c8e209 156 lp8Wait.start(); //poll rx line for x seconds
jony1401 0:ee3787c8e209 157 do {
jony1401 0:ee3787c8e209 158 if(Device.readable()) {
jony1401 0:ee3787c8e209 159 response[counter] = Device.getc();
jony1401 0:ee3787c8e209 160 counter++;
jony1401 0:ee3787c8e209 161 }
jony1401 0:ee3787c8e209 162 }
jony1401 0:ee3787c8e209 163 while( lp8Wait.read() < 0.5 );
jony1401 0:ee3787c8e209 164 counter = 0;
jony1401 0:ee3787c8e209 165 lp8Wait.stop();
jony1401 0:ee3787c8e209 166 lp8Wait.reset();
jony1401 0:ee3787c8e209 167 };
jony1401 0:ee3787c8e209 168
jony1401 0:ee3787c8e209 169 void transmitPacket(uint8_t msg[], int le ){
jony1401 0:ee3787c8e209 170 //Send out msg over serial line:
jony1401 0:ee3787c8e209 171 while(!Device.writeable() ) { /* wait for serial available*/ }
jony1401 0:ee3787c8e209 172 for(int pos = 0; pos < le; pos++) {
jony1401 0:ee3787c8e209 173 Device.putc(msg[pos]);
jony1401 0:ee3787c8e209 174 }
jony1401 0:ee3787c8e209 175
jony1401 0:ee3787c8e209 176 };
jony1401 0:ee3787c8e209 177
jony1401 0:ee3787c8e209 178 //timer
jony1401 0:ee3787c8e209 179 void timeIt(float &timeMe){
jony1401 0:ee3787c8e209 180 //start amd stop timer...
jony1401 0:ee3787c8e209 181 lp8Wait.start();
jony1401 0:ee3787c8e209 182 while (lp8Wait.read() < timeMe ) { /* W A I T I N G */ }
jony1401 0:ee3787c8e209 183 lp8Wait.stop();
jony1401 0:ee3787c8e209 184 lp8Wait.reset();
jony1401 0:ee3787c8e209 185 };
jony1401 0:ee3787c8e209 186
jony1401 0:ee3787c8e209 187 // Computation for the modbus 16-bit crc
jony1401 0:ee3787c8e209 188 uint16_t modbusCrc(uint8_t buffer[], int len){
jony1401 0:ee3787c8e209 189 uint16_t crc = 0xFFFF;
jony1401 0:ee3787c8e209 190
jony1401 0:ee3787c8e209 191 for (int pos = 0; pos < len; pos++) {
jony1401 0:ee3787c8e209 192 crc ^= (uint16_t)buffer[pos]; // XOR byte into least sig. byte of crc
jony1401 0:ee3787c8e209 193
jony1401 0:ee3787c8e209 194 for (int i = 8; i != 0; i--) { // Loop over each bit
jony1401 0:ee3787c8e209 195 if ((crc & 0x0001) != 0) { // If the LSB is set
jony1401 0:ee3787c8e209 196 crc >>= 1; // shift right and XOR 0xA001
jony1401 0:ee3787c8e209 197 crc ^= 0xA001;
jony1401 0:ee3787c8e209 198 }
jony1401 0:ee3787c8e209 199 else // Else LSB is not set
jony1401 0:ee3787c8e209 200 crc >>= 1; // shift right
jony1401 0:ee3787c8e209 201 }
jony1401 0:ee3787c8e209 202 }
jony1401 0:ee3787c8e209 203 // Note, this number has low and high bytes swapped
jony1401 0:ee3787c8e209 204 return crc;
jony1401 0:ee3787c8e209 205 };
jony1401 0:ee3787c8e209 206
jony1401 0:ee3787c8e209 207
jony1401 0:ee3787c8e209 208
jony1401 0:ee3787c8e209 209
jony1401 0:ee3787c8e209 210 private:
jony1401 0:ee3787c8e209 211
jony1401 0:ee3787c8e209 212 Serial &Device;
jony1401 0:ee3787c8e209 213 DigitalOut &VBB;
jony1401 0:ee3787c8e209 214 DigitalOut &VBB_EN;
jony1401 0:ee3787c8e209 215 DigitalIn &RDY;
jony1401 0:ee3787c8e209 216 Timer &lp8Wait;
jony1401 0:ee3787c8e209 217
jony1401 0:ee3787c8e209 218 //msg containers (needs to be initialized at constructor level)
jony1401 0:ee3787c8e209 219 uint8_t firstWrite[8];
jony1401 0:ee3787c8e209 220 uint8_t stateWrite[31];
jony1401 0:ee3787c8e209 221 uint8_t stateRead[7];
jony1401 0:ee3787c8e209 222 uint8_t response[60];
jony1401 0:ee3787c8e209 223
jony1401 0:ee3787c8e209 224 int co2; //CO2 initial value
jony1401 0:ee3787c8e209 225 int counter; //simple counter
jony1401 0:ee3787c8e209 226 uint16_t CRC; //modbus crc value
jony1401 0:ee3787c8e209 227 float _timeMe; //timer value
jony1401 0:ee3787c8e209 228 // uint8_t gC; //getCharacter...
jony1401 0:ee3787c8e209 229
jony1401 0:ee3787c8e209 230
jony1401 0:ee3787c8e209 231 };
jony1401 0:ee3787c8e209 232 #endif
jony1401 0:ee3787c8e209 233
jony1401 0:ee3787c8e209 234 /*
jony1401 0:ee3787c8e209 235 LP8 Communication Protocol (With no external Pressure Sensor):
jony1401 0:ee3787c8e209 236 --------------------------------------------------------------------------------
jony1401 0:ee3787c8e209 237 Initial Measurement (first read after powerup): COMMANDS:
jony1401 0:ee3787c8e209 238 --------------------------------------------------------------------------------
jony1401 0:ee3787c8e209 239 1) host powers up sensor: VBB_EN = 1
jony1401 0:ee3787c8e209 240 2) host waits until rdy signal goes low: RDY = 0;
jony1401 0:ee3787c8e209 241 3) host writes command, "write 24 bytes starting from adress 0x0080": { 0xfe, 0x41, 0x00, 0x80, 0x18, 0x10, ... [any 23 bytes] ..., CRC_low, CRC_high };
jony1401 0:ee3787c8e209 242 4) host reads response: { 0xfe, 0x41, 0x81, 0xe0 };
jony1401 0:ee3787c8e209 243 5) host waits until rdy signal goes high: RDY = 1;
jony1401 0:ee3787c8e209 244 6) host writes command "read 44 bytes starting from adress 0x0080": { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high };
jony1401 0:ee3787c8e209 245 7) host reads response: { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high };
jony1401 0:ee3787c8e209 246 8) host powers down sensor: VBB_EN = 0;
jony1401 0:ee3787c8e209 247
jony1401 0:ee3787c8e209 248 [------------------------------------------------------------------------------]
jony1401 0:ee3787c8e209 249 Optional first reading W/O pressure sensor
jony1401 0:ee3787c8e209 250 [------------------------------------------------------------------------------]
jony1401 0:ee3787c8e209 251 1) host powers up sensor: VBB_EN = 1
jony1401 0:ee3787c8e209 252 2) host waits until rdy signal goes low: RDY = 0;
jony1401 0:ee3787c8e209 253 3) host writes command, "write 24 bytes starting from adress 0x0080": { 0xfe, 0x41, 0x00, 0x80, 0x18, 0x10, 0x28, 0x7e };
jony1401 0:ee3787c8e209 254 4) host reads response: { 0xfe, 0x41, 0x81, 0xe0 };
jony1401 0:ee3787c8e209 255 5) host waits until rdy signal goes high: RDY = 1;
jony1401 0:ee3787c8e209 256 6) host writes command "read 44 bytes starting from adress 0x0080": { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high };
jony1401 0:ee3787c8e209 257 7) host reads response: { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high };
jony1401 0:ee3787c8e209 258 8) host powers down sensor: VBB_EN = 0;
jony1401 0:ee3787c8e209 259
jony1401 0:ee3787c8e209 260
jony1401 0:ee3787c8e209 261 --------------------------------------------------------------------------------
jony1401 0:ee3787c8e209 262 Subsequent readings:
jony1401 0:ee3787c8e209 263 --------------------------------------------------------------------------------
jony1401 0:ee3787c8e209 264 1) host powers up sensor: VBB_EN = 1
jony1401 0:ee3787c8e209 265 2) host waits until rdy signal goes low: RDY = 0;
jony1401 0:ee3787c8e209 266 3) host writes command, "write 24 bytes starting from adress 0x0080": { 0xfe, 0x41, 0x00, 0x80, 0x18, CC, SS1, ..., SS23, CRC_low, CRC_high };
jony1401 0:ee3787c8e209 267 4) host reads response: { 0xfe, 0x41, 0x81, 0xe0 };
jony1401 0:ee3787c8e209 268 5) host waits until rdy signal goes high: RDY = 1;
jony1401 0:ee3787c8e209 269 6) host writes command "read 44 bytes starting from adress 0x0080": { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high };
jony1401 0:ee3787c8e209 270 7) host reads response: { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high };
jony1401 0:ee3787c8e209 271 8) host powers down sensor: VBB_EN = 0;
jony1401 0:ee3787c8e209 272
jony1401 0:ee3787c8e209 273
jony1401 0:ee3787c8e209 274 --------------------------------------------------------------------------------
jony1401 0:ee3787c8e209 275 --------------------------------------------------------------------------------
jony1401 0:ee3787c8e209 276 CC = Calculation Control, 1 byte
jony1401 0:ee3787c8e209 277 SS = Sensor State, Sensor State, 23 bytes
jony1401 0:ee3787c8e209 278 D = Measured data and Sensor Status, 23 bytes
jony1401 0:ee3787c8e209 279 PP = Host Pressure Value
jony1401 0:ee3787c8e209 280 CRC= 16 bit CRC error check
jony1401 0:ee3787c8e209 281 --------------------------------------------------------------------------------
jony1401 0:ee3787c8e209 282 --------------------------------------------------------------------------------
jony1401 0:ee3787c8e209 283 */
jony1401 0:ee3787c8e209 284