Reading SenseAir LP8 CO2 sensor over bluetooth low energy

Dependencies:   BLE_API mbed nRF51822

Revision:
0:ee3787c8e209
Child:
1:b512a405b584
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LP8.h	Fri Apr 21 13:26:06 2017 +0000
@@ -0,0 +1,284 @@
+#ifndef LP8_H
+#define LP8_H
+
+class LP8 
+{
+public:
+
+    //constructor
+    LP8(Serial &device, DigitalOut &vbb, DigitalOut &vbb_en, DigitalIn &rdy, Timer &_timer):                  /* initiate class object */
+        Device(device),
+        VBB(vbb),
+        VBB_EN(vbb_en),
+        RDY(rdy),
+        lp8Wait(_timer)
+        {
+            Device.baud(9600);                                                              //set baud rate to 9600 
+            
+            //initialize arrays with modbus commands. 
+            //initial startup command
+            firstWrite[0] = 0xfe;
+            firstWrite[1] = 0x41;
+            firstWrite[2] = 0x00;
+            firstWrite[3] = 0x80;
+            firstWrite[4] = 0x01;
+            firstWrite[5] = 0x10;
+            firstWrite[6] = 0x28;
+            firstWrite[7] = 0x7e;
+            
+            //write sensor state to lp8 command
+            stateWrite[0] = 0xfe;                                                   //device adress
+            stateWrite[1] = 0x41;                                                   //read/write
+            stateWrite[2] = 0x00;                                                   //
+            stateWrite[3] = 0x80;                                                   //starting adress
+            stateWrite[4] = 0x18;                                                   //nr of bytes to send
+            stateWrite[5] = 0x20;                                                   //Calculation Control 
+            for(int k = 6; k < 31; k++) { stateWrite[k] = 0x00; }
+            
+            //read lp8 state command
+            stateRead[0] = 0xfe;        
+            stateRead[1] = 0x44;
+            stateRead[2] = 0x00;
+            stateRead[3] = 0x80;
+            stateRead[4] = 0x2c;
+            stateRead[5] = 0x00;
+            stateRead[5] = 0x00;
+            //response buffer
+            for(int k = 0; k < 60; k++) { response[k] = 0x00; }
+
+
+//            gC      = 0x00;
+            co2     = 400;                                                              
+            counter = 0;                                                                 
+            CRC     = 0x0000;
+            _timeMe = 0.3;
+        };
+
+    
+    //send startup msg                 .
+    bool lp8Init(){
+            VBB.write( 1 );
+            VBB_EN.write( 1 );                                                              //power on
+            timeIt( _timeMe );
+            
+            transmitPacket(firstWrite, 8);                                                  //Send out msg (and nr of elements) over serial line
+            Response( 4 );                                                                  //read 4 bytes response     
+            
+            if( RDY.read() == 0 ) {
+                lp8Wait.start();
+                while( lp8Wait.read() < 0.5 ) { /* spin */ }
+                lp8Wait.stop();
+                lp8Wait.reset(); 
+            }          
+            
+//compute crc
+            CRC = modbusCrc(stateRead, 5);
+//add crc value to the transmit package
+            stateRead[5] = (uint8_t)CRC;                                                    //crc_H
+            stateRead[6] = (uint8_t)(CRC >> 8);                                             //crc_L
+            timeIt( _timeMe );                                                              //wait for message to be sent and processed
+            transmitPacket(stateRead, 7);                                                   //transmit packet  
+            Response( 49 );                                                                 //read sensor state and co2 value(s)
+ 
+            VBB_EN.write( 0 );                                                              //power off
+            VBB.write( 0 );           
+                        
+//was the talk a success?
+            if ( getValue() < 1 ) {
+                return 1; }
+            else {
+                return 0; }
+            
+        };
+    
+    
+    //send subsequent messages to the lp8
+    void lp8Talk(){
+
+            //transfer previous sensor state to the new msg out
+            for (int u = 4; u < 23+4; u++) {
+                stateWrite[u+2] = response[u];
+                }
+            //compute new crc value
+            CRC = modbusCrc(stateWrite, 29);
+            //add new crc value to send list
+            stateWrite[29] = (uint8_t)CRC;   
+            stateWrite[30] = (uint8_t)(CRC >> 8);
+
+    
+            //initialize new transfer sequence    
+            VBB.write( 1 );
+            VBB_EN.write( 1 );                                                              //power on sensor
+            timeIt( _timeMe );
+            
+            transmitPacket(stateWrite, 31);                                                 //Send out msg with previous state (and nr of elements) over serial line
+            Response( 4 );                                                                  //read 4 bytes response     
+
+            //compute crc
+            CRC = modbusCrc(stateRead, 5);
+            //add crc value to the read request transmit package
+            stateRead[5] = (uint8_t)CRC;                                                    //crc_l
+            stateRead[6] = (uint8_t)(CRC >> 8);                                             //crc_h
+            //send read request
+            transmitPacket(stateRead, 7);                                                   //transmit packet  
+            //read sensor response
+            Response( 49 );                                                                 //read sensor state and co2 value(s)
+
+            VBB_EN.write( 0 );                                                              //power off
+            VBB.write( 0 );
+       };
+    
+    
+    
+    //get co2 value from lp8 response    
+    unsigned long getValue()
+    {
+        int high = response[29];
+        int low = response[30]; 
+        unsigned long val = high * 256 + low; 
+    
+        return val;
+    }
+
+        
+        
+    /************************************************* Helper Functions ********************************************/
+    /*************************************************                  ********************************************/
+    void responsePurge(int bytesToPurge){
+        for (int j = 0; j < bytesToPurge; j++) {
+                response[j] = 0x00;
+            }
+        };
+        
+    
+    //read from the lp8    
+    void Response(int bytesToRead ){
+        lp8Wait.start();                    //poll rx line for x seconds
+        do {
+            if(Device.readable()) {
+                response[counter] = Device.getc(); 
+                counter++;
+                }
+            }
+        while( lp8Wait.read() < 0.5 );
+        counter = 0;
+        lp8Wait.stop();
+        lp8Wait.reset();                                                        
+    };
+    
+    void transmitPacket(uint8_t msg[], int le ){
+            //Send out msg over serial line:
+            while(!Device.writeable() ) { /* wait for serial available*/ }
+            for(int pos = 0; pos < le; pos++) { 
+                Device.putc(msg[pos]);
+            }
+            
+        };
+    
+    //timer
+    void timeIt(float &timeMe){
+            //start amd stop timer...
+            lp8Wait.start();
+            while (lp8Wait.read() < timeMe ) { /* W A I T I N G */ }
+            lp8Wait.stop();
+            lp8Wait.reset();
+        };
+    
+    // Computation for the modbus 16-bit crc
+    uint16_t modbusCrc(uint8_t buffer[], int len){
+      uint16_t crc = 0xFFFF;
+      
+      for (int pos = 0; pos < len; pos++) {
+        crc ^= (uint16_t)buffer[pos];                                                   // XOR byte into least sig. byte of crc
+      
+        for (int i = 8; i != 0; i--) {                                                  // Loop over each bit
+          if ((crc & 0x0001) != 0) {                                                    // If the LSB is set
+            crc >>= 1;                                                                  // shift right and XOR 0xA001
+            crc ^= 0xA001;
+          }
+          else                                                                          // Else LSB is not set
+            crc >>= 1;                                                                  // shift right
+        }
+      }
+      // Note, this number has low and high bytes swapped
+      return crc;  
+    };
+
+
+
+
+private:
+
+    Serial      &Device;
+    DigitalOut  &VBB;
+    DigitalOut  &VBB_EN;    
+    DigitalIn   &RDY;
+    Timer       &lp8Wait;
+    
+    //msg containers (needs to be initialized at constructor level)
+    uint8_t  firstWrite[8];     
+    uint8_t  stateWrite[31]; 
+    uint8_t  stateRead[7];
+    uint8_t  response[60];
+    
+    int         co2;                                                                       //CO2 initial value   
+    int         counter;                                                                   //simple counter 
+    uint16_t    CRC;                                                                       //modbus crc value
+    float       _timeMe;                                                                   //timer value
+//    uint8_t     gC;                                                                         //getCharacter...
+
+
+};
+#endif
+
+/* 
+LP8 Communication Protocol (With no external Pressure Sensor):
+--------------------------------------------------------------------------------
+Initial Measurement (first read after powerup):                                     COMMANDS:
+--------------------------------------------------------------------------------
+1) host powers up sensor:                                                           VBB_EN = 1
+2) host waits until rdy signal goes low:                                            RDY = 0;
+3) host writes command, "write 24 bytes starting from adress 0x0080":               { 0xfe, 0x41, 0x00, 0x80, 0x18, 0x10, ... [any 23 bytes] ..., CRC_low, CRC_high };
+4) host reads response:                                                             { 0xfe, 0x41, 0x81, 0xe0 };
+5) host waits until rdy signal goes high:                                           RDY = 1;
+6) host writes command "read 44 bytes starting from adress 0x0080":                 { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high };
+7) host reads response:                                                             { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high };
+8) host powers down sensor:                                                         VBB_EN = 0;
+
+[------------------------------------------------------------------------------]
+Optional first reading W/O pressure sensor
+[------------------------------------------------------------------------------]
+1) host powers up sensor:                                                           VBB_EN = 1
+2) host waits until rdy signal goes low:                                            RDY = 0;
+3) host writes command, "write 24 bytes starting from adress 0x0080":               { 0xfe, 0x41, 0x00, 0x80, 0x18, 0x10, 0x28, 0x7e };
+4) host reads response:                                                             { 0xfe, 0x41, 0x81, 0xe0 };
+5) host waits until rdy signal goes high:                                           RDY = 1;
+6) host writes command "read 44 bytes starting from adress 0x0080":                 { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high };
+7) host reads response:                                                             { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high };
+8) host powers down sensor:                                                         VBB_EN = 0;
+
+
+--------------------------------------------------------------------------------
+Subsequent readings:
+--------------------------------------------------------------------------------
+1) host powers up sensor:                                                           VBB_EN = 1
+2) host waits until rdy signal goes low:                                            RDY = 0;
+3) host writes command, "write 24 bytes starting from adress 0x0080":               { 0xfe, 0x41, 0x00, 0x80, 0x18, CC, SS1, ..., SS23, CRC_low, CRC_high };
+4) host reads response:                                                             { 0xfe, 0x41, 0x81, 0xe0 };
+5) host waits until rdy signal goes high:                                           RDY = 1;
+6) host writes command "read 44 bytes starting from adress 0x0080":                 { 0xfe, 0x44, 0x00, 0x80, 0x2c, CRC_low, CRC_high };
+7) host reads response:                                                             { 0xfe, 0x44, 0x2c, 0x00, SS1, SS2, ..., SS23, PP_H, PP_L, D1, D2, ..., D18, CRC_low, CRC_high };
+8) host powers down sensor:                                                         VBB_EN = 0;
+
+
+--------------------------------------------------------------------------------
+--------------------------------------------------------------------------------
+CC = Calculation Control, 1 byte
+SS = Sensor State, Sensor State, 23 bytes
+D  = Measured data and Sensor Status, 23 bytes
+PP = Host Pressure Value
+CRC= 16 bit CRC error check 
+--------------------------------------------------------------------------------
+--------------------------------------------------------------------------------
+*/ 
+