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
LP8.h
00001 #ifndef LP8_H 00002 #define LP8_H 00003 00004 /* To initialize the lp8 object, you need to pass a serial (tx, rx), a DigitalOut signal for the en_vbb, 00005 an DigitalIn for the ready signal, DigitalOut for Reset and a timer object. */ 00006 00007 class LP8 00008 { 00009 public: 00010 //constructor 00011 LP8(Serial &device, DigitalOut &vbb_en, DigitalIn &rdy, DigitalOut &res ,Timer &_timer): 00012 Device(device), 00013 VBB_EN(vbb_en), 00014 RDY(rdy), 00015 RES(res), 00016 lp8Wait(_timer) 00017 { 00018 Device.baud(9600); //set baud rate to 9600 Hz 00019 Device.format(8, SerialBase::None, 2); //set bits, parity and stop bits 00020 00021 //initialize arrays with lp8 modbus commands. 00022 //initial startup command: 00023 firstWrite[0] = 0xfe; //device adress 00024 firstWrite[1] = 0x41; //write to ram 00025 firstWrite[2] = 0x00; // 00026 firstWrite[3] = 0x80; //starting adress 00027 firstWrite[4] = 0x01; //nr of bytes to send 00028 firstWrite[5] = 0x10; //calculation control byte 00029 firstWrite[6] = 0x28; //crc low 00030 firstWrite[7] = 0x7e; //crc high 00031 00032 //write previous sensor state to lp8, command: 00033 stateWrite[0] = 0xfe; //device adress 00034 stateWrite[1] = 0x41; //write to ram 00035 stateWrite[2] = 0x00; // 00036 stateWrite[3] = 0x80; //starting adress 00037 stateWrite[4] = 0x18; //nr of bytes to send 00038 stateWrite[5] = 0x20; //Calculation Control 00039 for(int k = 6; k < 31; k++) { stateWrite[k] = 0x00; } // 00040 00041 //read request from the lp8: 00042 stateRead[0] = 0xfe; //adress 00043 stateRead[1] = 0x44; //read from ram 00044 stateRead[2] = 0x00; // 00045 stateRead[3] = 0x80; //starting adress 00046 stateRead[4] = 0x2c; //number of bytes to read 00047 stateRead[5] = 0x00; //crc_l 00048 stateRead[6] = 0x00; //crc_h 00049 00050 //communication confirmation sequence (response from lp8) 00051 confirmation[0] = 0xfe; 00052 confirmation[1] = 0x41; 00053 confirmation[2] = 0x81; 00054 confirmation[3] = 0xe0; 00055 00056 //response buffer 00057 for(int k = 0; k < 60; k++) { response[k] = 0x00; } 00058 00059 //variable initialization 00060 co2 = 400; // 00061 CRC = 0x0000; // 00062 00063 }; 00064 00065 00066 //LP8 Initialization and first message 00067 bool lp8Init(){ 00068 00069 Device.format(8, SerialBase::None, 2); 00070 00071 //Enable Sensor 00072 VBB_EN.write( 1 ); //power on 00073 00074 //wait for rdy signal 00075 timeIt( 0.21 ); //wait for lp8 rdy signal 00076 // while(RDY.read() != 0 ) { /* wait for rdy to go low */} 00077 00078 //transmit first packet 00079 transmitPacket(firstWrite, 8); //Send out msg (and nr of bytes) over serial line 00080 Response( 4 ); //read 4 bytes response 00081 00082 //check response 00083 if ( responseCompare() != true){ 00084 VBB_EN.write(0); 00085 return false; 00086 } 00087 00088 //compute crc 00089 CRC = modbusCrc(stateRead, 5); 00090 00091 //add crc value to the transmit package 00092 stateRead[5] = (uint8_t)CRC; //crc_l 00093 stateRead[6] = (uint8_t)(CRC >> 8); //crc_h 00094 00095 //wait for rdy 00096 timeIt( 0.25 ); // 00097 // while(RDY.read() != 1 ) { /*wait for rdy to go high */} 00098 00099 transmitPacket(stateRead, 7); //transmit packet 00100 Response( 49 ); //get sensor state and co2 value(s) 00101 VBB_EN.write( 0 ); //power off lp8 00102 00103 return true; 00104 }; 00105 00106 //send subsequent messages to the lp8 00107 bool lp8Talk(uint8_t inc_ccByte){ 00108 00109 static const uint8_t A[] = {0xFE,0x41,0x00,0x80,0x20,0x00,0x00,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 00110 0x00,0x7F,0xFF,0x00,0x00,0x95,0xED,0x00,0x03,0x29,0x00,0x27,0x8C, 0xf5, 0x63}; 00111 00112 Device.format(8, SerialBase::None, 2); 00113 //transfer previous sensor state to the new msg out 00114 for (int u = 4; u < 23+4; u++) { 00115 stateWrite[u+2] = response[u]; 00116 } 00117 //Set Calibration Control Byte (see end of page for explantion), 00118 /* remove this statement if you want to be able to send anything to lp8 calculation control */ 00119 if( inc_ccByte != 0x20 ){ /* 0x52 is "simple recalibration, needs only one sample */ 00120 stateWrite[5] = inc_ccByte; 00121 } 00122 else { 00123 stateWrite[5] = 0x20; 00124 } 00125 00126 00127 //compute new crc value 00128 CRC = modbusCrc((uint8_t*)stateWrite, 29); 00129 00130 //add new crc value to send list 00131 stateWrite[29] = (uint8_t)CRC; 00132 stateWrite[30] = (uint8_t)(CRC >> 8); 00133 00134 //initialize new transfer sequence 00135 VBB_EN.write( 1 ); //power on sensor 00136 00137 timeIt( 0.35 ); 00138 // while(RDY.read() != 0 ) { /* wait for rdy */} 00139 00140 transmitPacket(/*(uint8_t*)A*/(uint8_t*)stateWrite, 31); //Send out msg with previous state (and nr of elements) over serial line 00141 Response( 4 ); //read 4 bytes response 00142 00143 //compare to confirmation sequence 00144 if ( responseCompare() != true){ 00145 VBB_EN.write( 0 ); 00146 return false; 00147 } 00148 00149 //compute crc 00150 CRC = modbusCrc(stateRead, 5); 00151 00152 //add crc value to the read request transmit package 00153 stateRead[5] = (uint8_t)CRC; //crc_l 00154 stateRead[6] = (uint8_t)(CRC >> 8); //crc_h 00155 00156 timeIt( 0.20 ); 00157 // while(RDY.read() != 1 ) { /* wait for rdy to go high */} 00158 00159 //send read request 00160 transmitPacket(stateRead, 7); //transmit packet 00161 00162 //read sensor response 00163 Response( 49 ); //get sensor state 00164 VBB_EN.write( 0 ); //power off 00165 00166 return true; 00167 }; 00168 00169 //get value from lp8 response 00170 unsigned long getValue() /* CO2 Value */ 00171 { 00172 int high = response[29]; 00173 int low = response[30]; 00174 unsigned long val = high * 256 + low; 00175 00176 return val; 00177 } 00178 00179 float getTempValue() 00180 { 00181 int h = response[33]; 00182 int l = response[34]; 00183 unsigned long _temp = h * 256 + l; 00184 00185 float _tempVal = 0.01 * _temp; 00186 00187 return _tempVal; 00188 } 00189 00190 /* get Vcap value for at current measurement, [35],[36] is previous Vcap value */ 00191 int getVcapValue(){ 00192 00193 int hB = response[37]; 00194 int lB = response[38]; 00195 unsigned long temp = hB * 256 + lB; 00196 00197 return temp; 00198 } 00199 00200 uint32_t getErrorStatus(){ 00201 00202 uint32_t tmp = 0; 00203 tmp += response[39] << (32-8); 00204 tmp += response[40] << (32-16); 00205 tmp += response[41] << (32-24); 00206 tmp += response[42]; 00207 00208 return tmp; 00209 } 00210 00211 //get calculation Control byte from lp8 response 00212 uint8_t getCCbyte(){ 00213 uint8_t rCCbyte = stateWrite[5]; 00214 return rCCbyte; 00215 } 00216 00217 00218 /************************************************* Helper Functions ********************************************/ 00219 00220 //purge response buffer 00221 void responsePurge(int bytesToPurge){ 00222 for (int j = 0; j < bytesToPurge; j++) { 00223 response[j] = 0x00; 00224 } 00225 //for(int k = 6; k < 31; k++) { stateWrite[k] = 0x00; } //purge sensor state 00226 }; 00227 00228 //read response from lp8 00229 void Response( int bytesToRead ){ 00230 int Count = 0; 00231 00232 lp8Wait.start(); /* timeout timer if something goes wrong */ 00233 00234 do { 00235 if(Device.readable()) { 00236 response[Count] = Device.getc(); 00237 Count++; 00238 --bytesToRead; 00239 } 00240 } 00241 while( (bytesToRead > 0) || (lp8Wait.read() < 0.2 )); 00242 00243 lp8Wait.stop(); 00244 lp8Wait.reset(); 00245 }; 00246 00247 //transmit data over serial lines 00248 void transmitPacket(uint8_t msg[], int le ){ 00249 //Send out msg over serial line: 00250 while(!Device.writeable() ) { /* wait for serial available*/ } 00251 for(int pos = 0; pos < le; pos++) { 00252 Device.putc(msg[pos]); 00253 } 00254 00255 }; 00256 00257 //timer 00258 void timeIt(float timeMe){ 00259 //start amd stop timer... 00260 lp8Wait.start(); 00261 while (lp8Wait.read() < timeMe ) { /* W A I T I N G */ } 00262 lp8Wait.stop(); 00263 lp8Wait.reset(); 00264 }; 00265 00266 // Computation for the modbus 16-bit crc 00267 uint16_t modbusCrc(uint8_t buffer[], int len){ 00268 uint16_t crc = 0xFFFF; 00269 00270 for (int pos = 0; pos < len; pos++) { 00271 crc ^= (uint16_t)buffer[pos]; // XOR byte into least sig. byte of crc 00272 00273 for (int i = 8; i != 0; i--) { // Loop over each bit 00274 if ((crc & 0x0001) != 0) { // If the LSB is set 00275 crc >>= 1; // shift right and XOR 0xA001 00276 crc ^= 0xA001; 00277 } 00278 else // Else LSB is not set 00279 crc >>= 1; // shift right 00280 } 00281 } 00282 // Note, this number has low and high bytes swapped 00283 return crc; 00284 }; 00285 00286 bool responseCompare(){ 00287 00288 short seq = 0; 00289 00290 for(int j=0; j < 4; j++){ 00291 if(response[j] == confirmation[j]){ 00292 seq++; 00293 } 00294 } 00295 //return false if check sequence fails 00296 if( seq != 4 ){ 00297 return false; 00298 } 00299 00300 return true; 00301 } 00302 00303 //variables and buffers 00304 private: 00305 //pins 00306 Serial &Device; 00307 DigitalOut &VBB_EN; 00308 DigitalIn &RDY; 00309 DigitalOut &RES; 00310 00311 Timer &lp8Wait; 00312 00313 //msg containers 00314 00315 uint8_t firstWrite[8]; 00316 volatile uint8_t stateWrite[31]; 00317 uint8_t stateRead[7]; 00318 uint8_t confirmation[4]; 00319 00320 volatile uint8_t response[60]; 00321 00322 // 00323 int co2; //CO2 initial value 00324 int tempValue; 00325 uint16_t CRC; //modbus crc value 00326 00327 00328 }; 00329 #endif 00330 00331 /* 00332 LP8 Modbus Communication Protocol (With no external Pressure Sensor): 00333 -------------------------------------------------------------------------------- 00334 Initial Measurement (first read after powerup): COMMANDS: 00335 -------------------------------------------------------------------------------- 00336 1) host powers up sensor: VBB_EN = 1 00337 2) host waits until rdy signal goes low: RDY = 0; 00338 3) host writes command, "write 24 bytes starting from adress 0x0080": { 0xfe, 0x41, 0x00, 0x80, 0x18, 0x10, ... [any 23 bytes] ..., CRC_low, CRC_high }; 00339 4) host reads response: { 0xfe, 0x41, 0x81, 0xe0 }; 00340 5) host waits until rdy signal goes high: RDY = 1; 00341 6) host writes command "read 44 bytes starting from adress 0x0080": { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high }; 00342 7) host reads response: { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high }; 00343 8) host powers down sensor: VBB_EN = 0; 00344 00345 [------------------------------------------------------------------------------] 00346 Optional first reading W/O pressure sensor 00347 [------------------------------------------------------------------------------] 00348 1) host powers up sensor: VBB_EN = 1 00349 2) host waits until rdy signal goes low: RDY = 0; 00350 3) host writes command, "write 24 bytes starting from adress 0x0080": { 0xfe, 0x41, 0x00, 0x80, 0x18, 0x10, 0x28, 0x7e }; 00351 4) host reads response: { 0xfe, 0x41, 0x81, 0xe0 }; 00352 5) host waits until rdy signal goes high: RDY = 1; 00353 6) host writes command "read 44 bytes starting from adress 0x0080": { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high }; 00354 7) host reads response: { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high }; 00355 8) host powers down sensor: VBB_EN = 0; 00356 00357 00358 -------------------------------------------------------------------------------- 00359 Subsequent readings: 00360 -------------------------------------------------------------------------------- 00361 1) host powers up sensor: VBB_EN = 1 00362 2) host waits until rdy signal goes low: RDY = 0; 00363 3) host writes command, "write 24 bytes starting from adress 0x0080": { 0xfe, 0x41, 0x00, 0x80, 0x18, CC, SS1, ..., SS23, CRC_low, CRC_high }; 00364 4) host reads response: { 0xfe, 0x41, 0x81, 0xe0 }; 00365 5) host waits until rdy signal goes high: RDY = 1; 00366 6) host writes command "read 44 bytes starting from adress 0x0080": { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high }; 00367 7) host reads response: { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high }; 00368 8) host powers down sensor: VBB_EN = 0; 00369 00370 00371 -------------------------------------------------------------------------------- 00372 LP8 Background Calibration, Calculation Control Byte 00373 -------------------------------------------------------------------------------- 00374 To calibrate the lp8, commands needs to be sent with the calculation control byte 00375 Calculation: 00376 CC = 00377 0x10 Initial measurement (filters reset, ABC sample reset and other, 00378 0x20 Subsequent measurement, 00379 0x40 Zero calibration using unfiltered data, 00380 0x41 Zero calibration using filtered data, 00381 0x42 Zero calibration using unfiltered data + reset filters, 00382 0x43 Zero calibration using filtered data + reset filters, 00383 0x50 Background calibration using unfiltered data, 00384 0x51 Background calibration using filtered data, 00385 0x52 Background calibration using unfiltered data + reset filters, 00386 0x53 Background calibration using filtered data + reset filters, 00387 0x70 ABC (based on filtered data), 00388 0x72 ABC (based on filtered data) + reset filters 00389 00390 00391 -------------------------------------------------------------------------------- 00392 -------------------------------------------------------------------------------- 00393 CC = Calculation Control, 1 byte 00394 SS = Sensor State, Sensor State, 23 bytes 00395 D = Measured data and Sensor Status, 23 bytes 00396 PP = Host Pressure Value 00397 CRC= 16 bit CRC error check 00398 -------------------------------------------------------------------------------- 00399 -------------------------------------------------------------------------------- 00400 */ 00401
Generated on Thu Jul 21 2022 11:53:51 by
1.7.2
