embernet project fire detection system sensor test

Dependencies:   mbed CCS811 BME280

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Adafruit_SGP30.cpp Source File

Adafruit_SGP30.cpp

Go to the documentation of this file.
00001 /*!
00002  * @file Adafruit_SGP30.cpp
00003  *
00004  * @mainpage Adafruit SGP30 gas sensor driver
00005  *
00006  * @section intro_sec Introduction
00007  *
00008  * This is the documentation for Adafruit's SGP30 driver for the
00009  * Arduino platform.  It is designed specifically to work with the
00010  * Adafruit SGP30 breakout: http://www.adafruit.com/products/3709
00011  *
00012  * These sensors use I2C to communicate, 2 pins (SCL+SDA) are required
00013  * to interface with the breakout.
00014  *
00015  * Adafruit invests time and resources providing this open source code,
00016  * please support Adafruit and open-source hardware by purchasing
00017  * products from Adafruit!
00018  *
00019  *
00020  * @section author Author
00021  * Written by Ladyada for Adafruit Industries.
00022  *
00023  * @section license License
00024  * BSD license, all text here must be included in any redistribution.
00025  *
00026  */
00027 
00028 #include "mbed.h"
00029 #include "Adafruit_SGP30.h "
00030 
00031 //#define I2C_DEBUG 1
00032 
00033 /**************************************************************************/
00034 /*! 
00035     @brief  Instantiates a new SGP30 class
00036 */
00037 /**************************************************************************/
00038 Adafruit_SGP30::Adafruit_SGP30(PinName sda, PinName scl) : _i2c(sda, scl) {
00039 }
00040 
00041 /**************************************************************************/
00042 /*! 
00043     @brief  Setups the hardware and detects a valid SGP30. Initializes I2C
00044     then reads the serialnumber and checks that we are talking to an SGP30
00045     @param  theWire Optional pointer to I2C interface, otherwise use Wire
00046     @returns True if SGP30 found on I2C, False if something went wrong!
00047 */
00048 /**************************************************************************/
00049 bool Adafruit_SGP30::begin() {
00050   //Mbed use 8bit addr
00051   _i2caddr = SGP30_I2CADDR_DEFAULT << 1;
00052   
00053   uint8_t command[3];
00054   command[0] = 0x36;
00055   command[1] = 0x82;
00056   command[2] = 0x0;
00057   if (! readWordFromCommand(command, 2, 5, serialnumber, 3))
00058     return false;
00059 
00060   uint16_t featureset;
00061   command[0] = 0x20;
00062   command[1] = 0x2F;
00063   if (! readWordFromCommand(command, 2, 10, &featureset, 1)) 
00064     return false;
00065   //Serial.print("Featureset 0x"); Serial.println(featureset, HEX);
00066   if (featureset != SGP30_FEATURESET) 
00067     return false;
00068   if (! IAQinit()) 
00069     return false;
00070 
00071   return true;
00072 }
00073 
00074 /**************************************************************************/
00075 /*! 
00076     @brief  Commands the sensor to begin the IAQ algorithm. Must be called after startup.
00077     @returns True if command completed successfully, false if something went wrong!
00078 */
00079 /**************************************************************************/
00080 bool Adafruit_SGP30::IAQinit(void) {
00081   uint8_t command[2];
00082   command[0] = 0x20;
00083   command[1] = 0x03;
00084   return readWordFromCommand(command, 2, 10);
00085 }
00086 
00087 /**************************************************************************/
00088 /*! 
00089     @brief  Commands the sensor to take a single eCO2/VOC measurement. Places results in {@link TVOC} and {@link eCO2}
00090     @returns True if command completed successfully, false if something went wrong!
00091 */
00092 /**************************************************************************/
00093 bool Adafruit_SGP30::IAQmeasure(void) {
00094   uint8_t command[2];
00095   command[0] = 0x20;
00096   command[1] = 0x08;
00097   uint16_t reply[2];
00098   if (! readWordFromCommand(command, 2, 12, reply, 2))
00099     return false;
00100   TVOC = reply[1];
00101   eCO2 = reply[0];
00102   return true;
00103 }
00104  
00105 /**************************************************************************/
00106 /*! 
00107     @brief Request baseline calibration values for both CO2 and TVOC IAQ calculations. Places results in parameter memory locaitons.
00108     @param eco2_base A pointer to a uint16_t which we will save the calibration value to
00109     @param tvoc_base A pointer to a uint16_t which we will save the calibration value to
00110     @returns True if command completed successfully, false if something went wrong!
00111 */
00112 /**************************************************************************/
00113 bool Adafruit_SGP30::getIAQBaseline(uint16_t *eco2_base, uint16_t *tvoc_base) {
00114   uint8_t command[2];
00115   command[0] = 0x20;
00116   command[1] = 0x15;
00117   uint16_t reply[2];
00118   if (! readWordFromCommand(command, 2, 10, reply, 2))
00119     return false;
00120   *eco2_base = reply[0];
00121   *tvoc_base = reply[1];
00122   return true;
00123 }
00124 
00125 bool Adafruit_SGP30::getIAQRaw(uint16_t *H2_raw, uint16_t *Eth_raw) {
00126   uint8_t command[2];
00127   command[0] = 0x20;
00128   command[1] = 0x50;
00129   uint16_t reply[2];
00130   if (! readWordFromCommand(command, 2, 40, reply, 2))
00131     return false;
00132   *H2_raw = reply[0];
00133   *Eth_raw = reply[1];
00134   return true;
00135 }
00136 
00137 /**************************************************************************/
00138 /*! 
00139     @brief Assign baseline calibration values for both CO2 and TVOC IAQ calculations.
00140     @param eco2_base A uint16_t which we will save the calibration value from
00141     @param tvoc_base A uint16_t which we will save the calibration value from
00142     @returns True if command completed successfully, false if something went wrong!
00143 */
00144 /**************************************************************************/
00145 bool Adafruit_SGP30::setIAQBaseline(uint16_t eco2_base, uint16_t tvoc_base) {
00146   uint8_t command[8];
00147   command[0] = 0x20;
00148   command[1] = 0x1e;
00149   command[2] = tvoc_base >> 8;
00150   command[3] = tvoc_base & 0xFF;
00151   command[4] = generateCRC(command+2, 2);
00152   command[5] = eco2_base >> 8;
00153   command[6] = eco2_base & 0xFF;
00154   command[7] = generateCRC(command+5, 2);
00155 
00156   return readWordFromCommand(command, 8, 10);
00157 }
00158 
00159 /**************************************************************************/
00160 /*! 
00161     @brief  I2C low level interfacing
00162 */
00163 /**************************************************************************/
00164 
00165 
00166 bool Adafruit_SGP30::readWordFromCommand(uint8_t command[], uint8_t commandLength, uint16_t delayms, uint16_t *readdata, uint8_t readlen)
00167 {
00168   uint8_t retval;
00169   
00170 
00171 #ifdef I2C_DEBUG
00172   printf("\t\t-> ");
00173 #endif
00174 
00175     retval = _i2c.write((int)_i2caddr, (const char*)command, (int)commandLength);
00176     //0=OK, 1=Fail https://os.mbed.com/docs/v5.9/reference/i2c.html
00177     if ( retval != 0) 
00178         return false;
00179   
00180 #ifdef I2C_DEBUG
00181     for (uint8_t i=0; i<commandLength; i++) {
00182         printf("0x");
00183         printf("%x", command[i]);
00184         printf(", ");
00185     }
00186 #endif
00187 
00188 #ifdef I2C_DEBUG
00189   printf("\n");
00190 #endif
00191 
00192   wait_ms(delayms);
00193   
00194   
00195 
00196   if (readlen == 0) 
00197     return true;
00198 
00199   uint8_t replylen = readlen * (SGP30_WORD_LEN +1);
00200   uint8_t replybuffer[replylen];
00201   
00202   retval = _i2c.read((int)_i2caddr, (char*)replybuffer, (int)replylen);
00203     
00204     //0=OK, 1=Fail https://os.mbed.com/docs/v5.9/reference/i2c.html
00205   if ( retval != 0) 
00206     return false;
00207   
00208 #ifdef I2C_DEBUG
00209     printf("\t\t<- ");
00210     for (uint8_t i=0; i<replylen; i++) {
00211         printf("0x");
00212         printf("%x", replybuffer[i]);
00213         printf(", ");
00214     }
00215 #endif
00216 
00217 
00218 #ifdef I2C_DEBUG
00219   printf("\n");
00220 #endif
00221 
00222   for (uint8_t i=0; i<readlen; i++) {
00223     uint8_t crc = generateCRC(replybuffer+i*3, 2);
00224 #ifdef I2C_DEBUG
00225     printf("\t\tCRC calced: 0x");
00226     printf("%x", crc);
00227     printf(" vs. 0x");
00228     printf("%x\n" ,replybuffer[i * 3 + 2];
00229 #endif
00230     if (crc != replybuffer[i * 3 + 2])
00231       return false;
00232     // success! store it
00233     readdata[i] = replybuffer[i*3];
00234     readdata[i] <<= 8;
00235     readdata[i] |= replybuffer[i*3 + 1];
00236 #ifdef I2C_DEBUG
00237     printf("\t\tRead: 0x");
00238     printf("%x\n", readdata[i]);
00239 #endif
00240   }
00241   return true;
00242 }
00243 
00244 uint8_t Adafruit_SGP30::generateCRC(uint8_t *data, uint8_t datalen) {
00245   // calculates 8-Bit checksum with given polynomial
00246   uint8_t crc = SGP30_CRC8_INIT;
00247 
00248   for (uint8_t i=0; i<datalen; i++) {
00249     crc ^= data[i];
00250     for (uint8_t b=0; b<8; b++) {
00251       if (crc & 0x80)
00252     crc = (crc << 1) ^ SGP30_CRC8_POLYNOMIAL;
00253       else
00254     crc <<= 1;
00255     }
00256   }
00257   return crc;
00258 }