hg

Dependents:   Example_DS3231_test

Committer:
etiene32
Date:
Wed Mar 06 14:01:31 2019 +0000
Revision:
1:fedfd309fb3c
Parent:
0:41a622cdd86d
sd

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ndrs_cwt 0:41a622cdd86d 1 /*!
ndrs_cwt 0:41a622cdd86d 2 * @file Adafruit_SGP30.cpp
ndrs_cwt 0:41a622cdd86d 3 *
ndrs_cwt 0:41a622cdd86d 4 * @mainpage Adafruit SGP30 gas sensor driver
ndrs_cwt 0:41a622cdd86d 5 *
ndrs_cwt 0:41a622cdd86d 6 * @section intro_sec Introduction
ndrs_cwt 0:41a622cdd86d 7 *
ndrs_cwt 0:41a622cdd86d 8 * This is the documentation for Adafruit's SGP30 driver for the
ndrs_cwt 0:41a622cdd86d 9 * Arduino platform. It is designed specifically to work with the
ndrs_cwt 0:41a622cdd86d 10 * Adafruit SGP30 breakout: http://www.adafruit.com/products/3709
ndrs_cwt 0:41a622cdd86d 11 *
ndrs_cwt 0:41a622cdd86d 12 * These sensors use I2C to communicate, 2 pins (SCL+SDA) are required
ndrs_cwt 0:41a622cdd86d 13 * to interface with the breakout.
ndrs_cwt 0:41a622cdd86d 14 *
ndrs_cwt 0:41a622cdd86d 15 * Adafruit invests time and resources providing this open source code,
ndrs_cwt 0:41a622cdd86d 16 * please support Adafruit and open-source hardware by purchasing
ndrs_cwt 0:41a622cdd86d 17 * products from Adafruit!
ndrs_cwt 0:41a622cdd86d 18 *
ndrs_cwt 0:41a622cdd86d 19 *
ndrs_cwt 0:41a622cdd86d 20 * @section author Author
ndrs_cwt 0:41a622cdd86d 21 * Written by Ladyada for Adafruit Industries.
ndrs_cwt 0:41a622cdd86d 22 *
ndrs_cwt 0:41a622cdd86d 23 * @section license License
ndrs_cwt 0:41a622cdd86d 24 * BSD license, all text here must be included in any redistribution.
ndrs_cwt 0:41a622cdd86d 25 *
ndrs_cwt 0:41a622cdd86d 26 */
ndrs_cwt 0:41a622cdd86d 27
ndrs_cwt 0:41a622cdd86d 28 #include "mbed.h"
ndrs_cwt 0:41a622cdd86d 29 #include "Adafruit_SGP30.h"
ndrs_cwt 0:41a622cdd86d 30
ndrs_cwt 0:41a622cdd86d 31 //#define I2C_DEBUG
ndrs_cwt 0:41a622cdd86d 32
ndrs_cwt 0:41a622cdd86d 33 /**************************************************************************/
ndrs_cwt 0:41a622cdd86d 34 /*!
ndrs_cwt 0:41a622cdd86d 35 @brief Instantiates a new SGP30 class
ndrs_cwt 0:41a622cdd86d 36 */
ndrs_cwt 0:41a622cdd86d 37 /**************************************************************************/
ndrs_cwt 0:41a622cdd86d 38 Adafruit_SGP30::Adafruit_SGP30(PinName sda, PinName scl) : _i2c(sda, scl) {
ndrs_cwt 0:41a622cdd86d 39 }
ndrs_cwt 0:41a622cdd86d 40
ndrs_cwt 0:41a622cdd86d 41 /**************************************************************************/
ndrs_cwt 0:41a622cdd86d 42 /*!
ndrs_cwt 0:41a622cdd86d 43 @brief Setups the hardware and detects a valid SGP30. Initializes I2C
ndrs_cwt 0:41a622cdd86d 44 then reads the serialnumber and checks that we are talking to an SGP30
ndrs_cwt 0:41a622cdd86d 45 @param theWire Optional pointer to I2C interface, otherwise use Wire
ndrs_cwt 0:41a622cdd86d 46 @returns True if SGP30 found on I2C, False if something went wrong!
ndrs_cwt 0:41a622cdd86d 47 */
ndrs_cwt 0:41a622cdd86d 48 /**************************************************************************/
ndrs_cwt 0:41a622cdd86d 49 bool Adafruit_SGP30::begin() {
ndrs_cwt 0:41a622cdd86d 50 //Mbed use 8bit addr
ndrs_cwt 0:41a622cdd86d 51 _i2caddr = SGP30_I2CADDR_DEFAULT << 1;
ndrs_cwt 0:41a622cdd86d 52
ndrs_cwt 0:41a622cdd86d 53 uint8_t command[3];
ndrs_cwt 0:41a622cdd86d 54 command[0] = 0x36;
ndrs_cwt 0:41a622cdd86d 55 command[1] = 0x82;
ndrs_cwt 0:41a622cdd86d 56 command[2] = 0x0;
etiene32 1:fedfd309fb3c 57 if (! readWordFromCommand(command, 2, 5, serialnumber, 3)){
etiene32 1:fedfd309fb3c 58 printf("1111111");
ndrs_cwt 0:41a622cdd86d 59 return false;
etiene32 1:fedfd309fb3c 60 }
ndrs_cwt 0:41a622cdd86d 61
ndrs_cwt 0:41a622cdd86d 62 uint16_t featureset;
ndrs_cwt 0:41a622cdd86d 63 command[0] = 0x20;
ndrs_cwt 0:41a622cdd86d 64 command[1] = 0x2F;
etiene32 1:fedfd309fb3c 65 if (! readWordFromCommand(command, 2, 10, &featureset, 1)) {
etiene32 1:fedfd309fb3c 66 printf("2222222");
ndrs_cwt 0:41a622cdd86d 67 return false;
etiene32 1:fedfd309fb3c 68 }
ndrs_cwt 0:41a622cdd86d 69 //Serial.print("Featureset 0x"); Serial.println(featureset, HEX);
etiene32 1:fedfd309fb3c 70 if (featureset != SGP30_FEATURESET) {
etiene32 1:fedfd309fb3c 71 printf("3333333");
ndrs_cwt 0:41a622cdd86d 72 return false;
etiene32 1:fedfd309fb3c 73 }
etiene32 1:fedfd309fb3c 74 if (! IAQinit()) {
etiene32 1:fedfd309fb3c 75 printf("4444444");
ndrs_cwt 0:41a622cdd86d 76 return false;
etiene32 1:fedfd309fb3c 77 }
ndrs_cwt 0:41a622cdd86d 78
ndrs_cwt 0:41a622cdd86d 79 return true;
ndrs_cwt 0:41a622cdd86d 80 }
ndrs_cwt 0:41a622cdd86d 81
ndrs_cwt 0:41a622cdd86d 82 /**************************************************************************/
ndrs_cwt 0:41a622cdd86d 83 /*!
ndrs_cwt 0:41a622cdd86d 84 @brief Commands the sensor to begin the IAQ algorithm. Must be called after startup.
ndrs_cwt 0:41a622cdd86d 85 @returns True if command completed successfully, false if something went wrong!
ndrs_cwt 0:41a622cdd86d 86 */
ndrs_cwt 0:41a622cdd86d 87 /**************************************************************************/
ndrs_cwt 0:41a622cdd86d 88 bool Adafruit_SGP30::IAQinit(void) {
ndrs_cwt 0:41a622cdd86d 89 uint8_t command[2];
ndrs_cwt 0:41a622cdd86d 90 command[0] = 0x20;
ndrs_cwt 0:41a622cdd86d 91 command[1] = 0x03;
ndrs_cwt 0:41a622cdd86d 92 return readWordFromCommand(command, 2, 10);
ndrs_cwt 0:41a622cdd86d 93 }
ndrs_cwt 0:41a622cdd86d 94
ndrs_cwt 0:41a622cdd86d 95 /**************************************************************************/
ndrs_cwt 0:41a622cdd86d 96 /*!
ndrs_cwt 0:41a622cdd86d 97 @brief Commands the sensor to take a single eCO2/VOC measurement. Places results in {@link TVOC} and {@link eCO2}
ndrs_cwt 0:41a622cdd86d 98 @returns True if command completed successfully, false if something went wrong!
ndrs_cwt 0:41a622cdd86d 99 */
ndrs_cwt 0:41a622cdd86d 100 /**************************************************************************/
ndrs_cwt 0:41a622cdd86d 101 bool Adafruit_SGP30::IAQmeasure(void) {
ndrs_cwt 0:41a622cdd86d 102 uint8_t command[2];
ndrs_cwt 0:41a622cdd86d 103 command[0] = 0x20;
ndrs_cwt 0:41a622cdd86d 104 command[1] = 0x08;
ndrs_cwt 0:41a622cdd86d 105 uint16_t reply[2];
ndrs_cwt 0:41a622cdd86d 106 if (! readWordFromCommand(command, 2, 12, reply, 2))
ndrs_cwt 0:41a622cdd86d 107 return false;
ndrs_cwt 0:41a622cdd86d 108 TVOC = reply[1];
ndrs_cwt 0:41a622cdd86d 109 eCO2 = reply[0];
ndrs_cwt 0:41a622cdd86d 110 return true;
ndrs_cwt 0:41a622cdd86d 111 }
ndrs_cwt 0:41a622cdd86d 112
ndrs_cwt 0:41a622cdd86d 113 /**************************************************************************/
ndrs_cwt 0:41a622cdd86d 114 /*!
ndrs_cwt 0:41a622cdd86d 115 @brief Request baseline calibration values for both CO2 and TVOC IAQ calculations. Places results in parameter memory locaitons.
ndrs_cwt 0:41a622cdd86d 116 @param eco2_base A pointer to a uint16_t which we will save the calibration value to
ndrs_cwt 0:41a622cdd86d 117 @param tvoc_base A pointer to a uint16_t which we will save the calibration value to
ndrs_cwt 0:41a622cdd86d 118 @returns True if command completed successfully, false if something went wrong!
ndrs_cwt 0:41a622cdd86d 119 */
ndrs_cwt 0:41a622cdd86d 120 /**************************************************************************/
ndrs_cwt 0:41a622cdd86d 121 bool Adafruit_SGP30::getIAQBaseline(uint16_t *eco2_base, uint16_t *tvoc_base) {
ndrs_cwt 0:41a622cdd86d 122 uint8_t command[2];
ndrs_cwt 0:41a622cdd86d 123 command[0] = 0x20;
ndrs_cwt 0:41a622cdd86d 124 command[1] = 0x15;
ndrs_cwt 0:41a622cdd86d 125 uint16_t reply[2];
ndrs_cwt 0:41a622cdd86d 126 if (! readWordFromCommand(command, 2, 10, reply, 2))
ndrs_cwt 0:41a622cdd86d 127 return false;
ndrs_cwt 0:41a622cdd86d 128 *eco2_base = reply[0];
ndrs_cwt 0:41a622cdd86d 129 *tvoc_base = reply[1];
ndrs_cwt 0:41a622cdd86d 130 return true;
ndrs_cwt 0:41a622cdd86d 131 }
ndrs_cwt 0:41a622cdd86d 132
ndrs_cwt 0:41a622cdd86d 133 bool Adafruit_SGP30::getIAQRaw(uint16_t *H2_raw, uint16_t *Eth_raw) {
ndrs_cwt 0:41a622cdd86d 134 uint8_t command[2];
ndrs_cwt 0:41a622cdd86d 135 command[0] = 0x20;
ndrs_cwt 0:41a622cdd86d 136 command[1] = 0x50;
ndrs_cwt 0:41a622cdd86d 137 uint16_t reply[2];
ndrs_cwt 0:41a622cdd86d 138 if (! readWordFromCommand(command, 2, 40, reply, 2))
ndrs_cwt 0:41a622cdd86d 139 return false;
ndrs_cwt 0:41a622cdd86d 140 *H2_raw = reply[0];
ndrs_cwt 0:41a622cdd86d 141 *Eth_raw = reply[1];
ndrs_cwt 0:41a622cdd86d 142 return true;
ndrs_cwt 0:41a622cdd86d 143 }
ndrs_cwt 0:41a622cdd86d 144
ndrs_cwt 0:41a622cdd86d 145 /**************************************************************************/
ndrs_cwt 0:41a622cdd86d 146 /*!
ndrs_cwt 0:41a622cdd86d 147 @brief Assign baseline calibration values for both CO2 and TVOC IAQ calculations.
ndrs_cwt 0:41a622cdd86d 148 @param eco2_base A uint16_t which we will save the calibration value from
ndrs_cwt 0:41a622cdd86d 149 @param tvoc_base A uint16_t which we will save the calibration value from
ndrs_cwt 0:41a622cdd86d 150 @returns True if command completed successfully, false if something went wrong!
ndrs_cwt 0:41a622cdd86d 151 */
ndrs_cwt 0:41a622cdd86d 152 /**************************************************************************/
ndrs_cwt 0:41a622cdd86d 153 bool Adafruit_SGP30::setIAQBaseline(uint16_t eco2_base, uint16_t tvoc_base) {
ndrs_cwt 0:41a622cdd86d 154 uint8_t command[8];
ndrs_cwt 0:41a622cdd86d 155 command[0] = 0x20;
ndrs_cwt 0:41a622cdd86d 156 command[1] = 0x1e;
ndrs_cwt 0:41a622cdd86d 157 command[2] = tvoc_base >> 8;
ndrs_cwt 0:41a622cdd86d 158 command[3] = tvoc_base & 0xFF;
ndrs_cwt 0:41a622cdd86d 159 command[4] = generateCRC(command+2, 2);
ndrs_cwt 0:41a622cdd86d 160 command[5] = eco2_base >> 8;
ndrs_cwt 0:41a622cdd86d 161 command[6] = eco2_base & 0xFF;
ndrs_cwt 0:41a622cdd86d 162 command[7] = generateCRC(command+5, 2);
ndrs_cwt 0:41a622cdd86d 163
ndrs_cwt 0:41a622cdd86d 164 return readWordFromCommand(command, 8, 10);
ndrs_cwt 0:41a622cdd86d 165 }
ndrs_cwt 0:41a622cdd86d 166
ndrs_cwt 0:41a622cdd86d 167 /**************************************************************************/
ndrs_cwt 0:41a622cdd86d 168 /*!
ndrs_cwt 0:41a622cdd86d 169 @brief I2C low level interfacing
ndrs_cwt 0:41a622cdd86d 170 */
ndrs_cwt 0:41a622cdd86d 171 /**************************************************************************/
ndrs_cwt 0:41a622cdd86d 172
ndrs_cwt 0:41a622cdd86d 173
ndrs_cwt 0:41a622cdd86d 174 bool Adafruit_SGP30::readWordFromCommand(uint8_t command[], uint8_t commandLength, uint16_t delayms, uint16_t *readdata, uint8_t readlen)
ndrs_cwt 0:41a622cdd86d 175 {
ndrs_cwt 0:41a622cdd86d 176 uint8_t retval;
ndrs_cwt 0:41a622cdd86d 177
ndrs_cwt 0:41a622cdd86d 178
ndrs_cwt 0:41a622cdd86d 179 #ifdef I2C_DEBUG
ndrs_cwt 0:41a622cdd86d 180 printf("\t\t-> ");
ndrs_cwt 0:41a622cdd86d 181 #endif
ndrs_cwt 0:41a622cdd86d 182
ndrs_cwt 0:41a622cdd86d 183 retval = _i2c.write((int)_i2caddr, (const char*)command, (int)commandLength);
ndrs_cwt 0:41a622cdd86d 184 //0=OK, 1=Fail https://os.mbed.com/docs/v5.9/reference/i2c.html
ndrs_cwt 0:41a622cdd86d 185 if ( retval != 0)
ndrs_cwt 0:41a622cdd86d 186 return false;
ndrs_cwt 0:41a622cdd86d 187
ndrs_cwt 0:41a622cdd86d 188 #ifdef I2C_DEBUG
ndrs_cwt 0:41a622cdd86d 189 for (uint8_t i=0; i<commandLength; i++) {
ndrs_cwt 0:41a622cdd86d 190 printf("0x");
ndrs_cwt 0:41a622cdd86d 191 printf("%x", command[i]);
ndrs_cwt 0:41a622cdd86d 192 printf(", ");
ndrs_cwt 0:41a622cdd86d 193 }
ndrs_cwt 0:41a622cdd86d 194 #endif
ndrs_cwt 0:41a622cdd86d 195
ndrs_cwt 0:41a622cdd86d 196 #ifdef I2C_DEBUG
ndrs_cwt 0:41a622cdd86d 197 printf("\n");
ndrs_cwt 0:41a622cdd86d 198 #endif
ndrs_cwt 0:41a622cdd86d 199
ndrs_cwt 0:41a622cdd86d 200 wait_ms(delayms);
ndrs_cwt 0:41a622cdd86d 201
ndrs_cwt 0:41a622cdd86d 202
ndrs_cwt 0:41a622cdd86d 203
ndrs_cwt 0:41a622cdd86d 204 if (readlen == 0)
ndrs_cwt 0:41a622cdd86d 205 return true;
ndrs_cwt 0:41a622cdd86d 206
ndrs_cwt 0:41a622cdd86d 207 uint8_t replylen = readlen * (SGP30_WORD_LEN +1);
ndrs_cwt 0:41a622cdd86d 208 uint8_t replybuffer[replylen];
ndrs_cwt 0:41a622cdd86d 209
ndrs_cwt 0:41a622cdd86d 210 retval = _i2c.read((int)_i2caddr, (char*)replybuffer, (int)replylen);
ndrs_cwt 0:41a622cdd86d 211
ndrs_cwt 0:41a622cdd86d 212 //0=OK, 1=Fail https://os.mbed.com/docs/v5.9/reference/i2c.html
ndrs_cwt 0:41a622cdd86d 213 if ( retval != 0)
ndrs_cwt 0:41a622cdd86d 214 return false;
ndrs_cwt 0:41a622cdd86d 215
ndrs_cwt 0:41a622cdd86d 216 #ifdef I2C_DEBUG
ndrs_cwt 0:41a622cdd86d 217 printf("\t\t<- ");
ndrs_cwt 0:41a622cdd86d 218 for (uint8_t i=0; i<replylen; i++) {
ndrs_cwt 0:41a622cdd86d 219 printf("0x");
ndrs_cwt 0:41a622cdd86d 220 printf("%x", replybuffer[i]);
ndrs_cwt 0:41a622cdd86d 221 printf(", ");
ndrs_cwt 0:41a622cdd86d 222 }
ndrs_cwt 0:41a622cdd86d 223 #endif
ndrs_cwt 0:41a622cdd86d 224
ndrs_cwt 0:41a622cdd86d 225
ndrs_cwt 0:41a622cdd86d 226 #ifdef I2C_DEBUG
ndrs_cwt 0:41a622cdd86d 227 printf("\n");
ndrs_cwt 0:41a622cdd86d 228 #endif
ndrs_cwt 0:41a622cdd86d 229
ndrs_cwt 0:41a622cdd86d 230 for (uint8_t i=0; i<readlen; i++) {
ndrs_cwt 0:41a622cdd86d 231 uint8_t crc = generateCRC(replybuffer+i*3, 2);
ndrs_cwt 0:41a622cdd86d 232 #ifdef I2C_DEBUG
ndrs_cwt 0:41a622cdd86d 233 printf("\t\tCRC calced: 0x");
ndrs_cwt 0:41a622cdd86d 234 printf("%x", crc);
ndrs_cwt 0:41a622cdd86d 235 printf(" vs. 0x");
ndrs_cwt 0:41a622cdd86d 236 printf("%x\n" ,replybuffer[i * 3 + 2];
ndrs_cwt 0:41a622cdd86d 237 #endif
ndrs_cwt 0:41a622cdd86d 238 if (crc != replybuffer[i * 3 + 2])
ndrs_cwt 0:41a622cdd86d 239 return false;
ndrs_cwt 0:41a622cdd86d 240 // success! store it
ndrs_cwt 0:41a622cdd86d 241 readdata[i] = replybuffer[i*3];
ndrs_cwt 0:41a622cdd86d 242 readdata[i] <<= 8;
ndrs_cwt 0:41a622cdd86d 243 readdata[i] |= replybuffer[i*3 + 1];
ndrs_cwt 0:41a622cdd86d 244 #ifdef I2C_DEBUG
ndrs_cwt 0:41a622cdd86d 245 printf("\t\tRead: 0x");
ndrs_cwt 0:41a622cdd86d 246 printf("%x\n", readdata[i]);
ndrs_cwt 0:41a622cdd86d 247 #endif
ndrs_cwt 0:41a622cdd86d 248 }
ndrs_cwt 0:41a622cdd86d 249 return true;
ndrs_cwt 0:41a622cdd86d 250 }
ndrs_cwt 0:41a622cdd86d 251
ndrs_cwt 0:41a622cdd86d 252 uint8_t Adafruit_SGP30::generateCRC(uint8_t *data, uint8_t datalen) {
ndrs_cwt 0:41a622cdd86d 253 // calculates 8-Bit checksum with given polynomial
ndrs_cwt 0:41a622cdd86d 254 uint8_t crc = SGP30_CRC8_INIT;
ndrs_cwt 0:41a622cdd86d 255
ndrs_cwt 0:41a622cdd86d 256 for (uint8_t i=0; i<datalen; i++) {
ndrs_cwt 0:41a622cdd86d 257 crc ^= data[i];
ndrs_cwt 0:41a622cdd86d 258 for (uint8_t b=0; b<8; b++) {
ndrs_cwt 0:41a622cdd86d 259 if (crc & 0x80)
ndrs_cwt 0:41a622cdd86d 260 crc = (crc << 1) ^ SGP30_CRC8_POLYNOMIAL;
ndrs_cwt 0:41a622cdd86d 261 else
ndrs_cwt 0:41a622cdd86d 262 crc <<= 1;
ndrs_cwt 0:41a622cdd86d 263 }
ndrs_cwt 0:41a622cdd86d 264 }
ndrs_cwt 0:41a622cdd86d 265 return crc;
ndrs_cwt 0:41a622cdd86d 266 }