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