Jonas Skalman / Mbed 2 deprecated SenseAirLP8

Dependencies:   BLE_API mbed nRF51822

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             //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