Private Private / Mbed 2 deprecated SenseAirLP8

Dependencies:   BLE_API mbed nRF51822

Fork of SenseAirLP8 by Jonas Skalman

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LP8.h Source File

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