Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:41a622cdd86d, committed 2018-07-23
- Comitter:
- ndrs_cwt
- Date:
- Mon Jul 23 09:51:43 2018 +0000
- Child:
- 1:ba856ab1ea97
- Commit message:
- Port from Adafruit_SGP30 arduino lib(https://github.com/adafruit/Adafruit_SGP30) to use Mbed API
Changed in this revision
| Adafruit_SGP30.cpp | Show annotated file Show diff for this revision Revisions of this file |
| Adafruit_SGP30.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Adafruit_SGP30.cpp Mon Jul 23 09:51:43 2018 +0000
@@ -0,0 +1,258 @@
+/*!
+ * @file Adafruit_SGP30.cpp
+ *
+ * @mainpage Adafruit SGP30 gas sensor driver
+ *
+ * @section intro_sec Introduction
+ *
+ * This is the documentation for Adafruit's SGP30 driver for the
+ * Arduino platform. It is designed specifically to work with the
+ * Adafruit SGP30 breakout: http://www.adafruit.com/products/3709
+ *
+ * These sensors use I2C to communicate, 2 pins (SCL+SDA) are required
+ * to interface with the breakout.
+ *
+ * Adafruit invests time and resources providing this open source code,
+ * please support Adafruit and open-source hardware by purchasing
+ * products from Adafruit!
+ *
+ *
+ * @section author Author
+ * Written by Ladyada for Adafruit Industries.
+ *
+ * @section license License
+ * BSD license, all text here must be included in any redistribution.
+ *
+ */
+
+#include "mbed.h"
+#include "Adafruit_SGP30.h"
+
+//#define I2C_DEBUG
+
+/**************************************************************************/
+/*!
+ @brief Instantiates a new SGP30 class
+*/
+/**************************************************************************/
+Adafruit_SGP30::Adafruit_SGP30(PinName sda, PinName scl) : _i2c(sda, scl) {
+}
+
+/**************************************************************************/
+/*!
+ @brief Setups the hardware and detects a valid SGP30. Initializes I2C
+ then reads the serialnumber and checks that we are talking to an SGP30
+ @param theWire Optional pointer to I2C interface, otherwise use Wire
+ @returns True if SGP30 found on I2C, False if something went wrong!
+*/
+/**************************************************************************/
+bool Adafruit_SGP30::begin() {
+ //Mbed use 8bit addr
+ _i2caddr = SGP30_I2CADDR_DEFAULT << 1;
+
+ uint8_t command[3];
+ command[0] = 0x36;
+ command[1] = 0x82;
+ command[2] = 0x0;
+ if (! readWordFromCommand(command, 2, 5, serialnumber, 3))
+ return false;
+
+ uint16_t featureset;
+ command[0] = 0x20;
+ command[1] = 0x2F;
+ if (! readWordFromCommand(command, 2, 10, &featureset, 1))
+ return false;
+ //Serial.print("Featureset 0x"); Serial.println(featureset, HEX);
+ if (featureset != SGP30_FEATURESET)
+ return false;
+ if (! IAQinit())
+ return false;
+
+ return true;
+}
+
+/**************************************************************************/
+/*!
+ @brief Commands the sensor to begin the IAQ algorithm. Must be called after startup.
+ @returns True if command completed successfully, false if something went wrong!
+*/
+/**************************************************************************/
+bool Adafruit_SGP30::IAQinit(void) {
+ uint8_t command[2];
+ command[0] = 0x20;
+ command[1] = 0x03;
+ return readWordFromCommand(command, 2, 10);
+}
+
+/**************************************************************************/
+/*!
+ @brief Commands the sensor to take a single eCO2/VOC measurement. Places results in {@link TVOC} and {@link eCO2}
+ @returns True if command completed successfully, false if something went wrong!
+*/
+/**************************************************************************/
+bool Adafruit_SGP30::IAQmeasure(void) {
+ uint8_t command[2];
+ command[0] = 0x20;
+ command[1] = 0x08;
+ uint16_t reply[2];
+ if (! readWordFromCommand(command, 2, 12, reply, 2))
+ return false;
+ TVOC = reply[1];
+ eCO2 = reply[0];
+ return true;
+}
+
+/**************************************************************************/
+/*!
+ @brief Request baseline calibration values for both CO2 and TVOC IAQ calculations. Places results in parameter memory locaitons.
+ @param eco2_base A pointer to a uint16_t which we will save the calibration value to
+ @param tvoc_base A pointer to a uint16_t which we will save the calibration value to
+ @returns True if command completed successfully, false if something went wrong!
+*/
+/**************************************************************************/
+bool Adafruit_SGP30::getIAQBaseline(uint16_t *eco2_base, uint16_t *tvoc_base) {
+ uint8_t command[2];
+ command[0] = 0x20;
+ command[1] = 0x15;
+ uint16_t reply[2];
+ if (! readWordFromCommand(command, 2, 10, reply, 2))
+ return false;
+ *eco2_base = reply[0];
+ *tvoc_base = reply[1];
+ return true;
+}
+
+bool Adafruit_SGP30::getIAQRaw(uint16_t *H2_raw, uint16_t *Eth_raw) {
+ uint8_t command[2];
+ command[0] = 0x20;
+ command[1] = 0x50;
+ uint16_t reply[2];
+ if (! readWordFromCommand(command, 2, 40, reply, 2))
+ return false;
+ *H2_raw = reply[0];
+ *Eth_raw = reply[1];
+ return true;
+}
+
+/**************************************************************************/
+/*!
+ @brief Assign baseline calibration values for both CO2 and TVOC IAQ calculations.
+ @param eco2_base A uint16_t which we will save the calibration value from
+ @param tvoc_base A uint16_t which we will save the calibration value from
+ @returns True if command completed successfully, false if something went wrong!
+*/
+/**************************************************************************/
+bool Adafruit_SGP30::setIAQBaseline(uint16_t eco2_base, uint16_t tvoc_base) {
+ uint8_t command[8];
+ command[0] = 0x20;
+ command[1] = 0x1e;
+ command[2] = tvoc_base >> 8;
+ command[3] = tvoc_base & 0xFF;
+ command[4] = generateCRC(command+2, 2);
+ command[5] = eco2_base >> 8;
+ command[6] = eco2_base & 0xFF;
+ command[7] = generateCRC(command+5, 2);
+
+ return readWordFromCommand(command, 8, 10);
+}
+
+/**************************************************************************/
+/*!
+ @brief I2C low level interfacing
+*/
+/**************************************************************************/
+
+
+bool Adafruit_SGP30::readWordFromCommand(uint8_t command[], uint8_t commandLength, uint16_t delayms, uint16_t *readdata, uint8_t readlen)
+{
+ uint8_t retval;
+
+
+#ifdef I2C_DEBUG
+ printf("\t\t-> ");
+#endif
+
+ retval = _i2c.write((int)_i2caddr, (const char*)command, (int)commandLength);
+ //0=OK, 1=Fail https://os.mbed.com/docs/v5.9/reference/i2c.html
+ if ( retval != 0)
+ return false;
+
+#ifdef I2C_DEBUG
+ for (uint8_t i=0; i<commandLength; i++) {
+ printf("0x");
+ printf("%x", command[i]);
+ printf(", ");
+ }
+#endif
+
+#ifdef I2C_DEBUG
+ printf("\n");
+#endif
+
+ wait_ms(delayms);
+
+
+
+ if (readlen == 0)
+ return true;
+
+ uint8_t replylen = readlen * (SGP30_WORD_LEN +1);
+ uint8_t replybuffer[replylen];
+
+ retval = _i2c.read((int)_i2caddr, (char*)replybuffer, (int)replylen);
+
+ //0=OK, 1=Fail https://os.mbed.com/docs/v5.9/reference/i2c.html
+ if ( retval != 0)
+ return false;
+
+#ifdef I2C_DEBUG
+ printf("\t\t<- ");
+ for (uint8_t i=0; i<replylen; i++) {
+ printf("0x");
+ printf("%x", replybuffer[i]);
+ printf(", ");
+ }
+#endif
+
+
+#ifdef I2C_DEBUG
+ printf("\n");
+#endif
+
+ for (uint8_t i=0; i<readlen; i++) {
+ uint8_t crc = generateCRC(replybuffer+i*3, 2);
+#ifdef I2C_DEBUG
+ printf("\t\tCRC calced: 0x");
+ printf("%x", crc);
+ printf(" vs. 0x");
+ printf("%x\n" ,replybuffer[i * 3 + 2];
+#endif
+ if (crc != replybuffer[i * 3 + 2])
+ return false;
+ // success! store it
+ readdata[i] = replybuffer[i*3];
+ readdata[i] <<= 8;
+ readdata[i] |= replybuffer[i*3 + 1];
+#ifdef I2C_DEBUG
+ printf("\t\tRead: 0x");
+ printf("%x\n", readdata[i]);
+#endif
+ }
+ return true;
+}
+
+uint8_t Adafruit_SGP30::generateCRC(uint8_t *data, uint8_t datalen) {
+ // calculates 8-Bit checksum with given polynomial
+ uint8_t crc = SGP30_CRC8_INIT;
+
+ for (uint8_t i=0; i<datalen; i++) {
+ crc ^= data[i];
+ for (uint8_t b=0; b<8; b++) {
+ if (crc & 0x80)
+ crc = (crc << 1) ^ SGP30_CRC8_POLYNOMIAL;
+ else
+ crc <<= 1;
+ }
+ }
+ return crc;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Adafruit_SGP30.h Mon Jul 23 09:51:43 2018 +0000
@@ -0,0 +1,68 @@
+/*!
+ * @file Adafruit_SGP30.h
+ *
+ * This is the documentation for Adafruit's SGP30 driver for the
+ * Arduino platform. It is designed specifically to work with the
+ * Adafruit SGP30 breakout: http://www.adafruit.com/products/3709
+ *
+ * These sensors use I2C to communicate, 2 pins (SCL+SDA) are required
+ * to interface with the breakout.
+ *
+ * Adafruit invests time and resources providing this open source code,
+ * please support Adafruit and open-source hardware by purchasing
+ * products from Adafruit!
+ *
+ * Written by Ladyada for Adafruit Industries.
+ *
+ * BSD license, all text here must be included in any redistribution.
+ *
+*/
+
+#include "mbed.h"
+
+// the i2c address
+#define SGP30_I2CADDR_DEFAULT 0x58 ///< SGP30 has only one I2C address
+
+// commands and constants
+#define SGP30_FEATURESET 0x0020 ///< The required set for this library
+#define SGP30_CRC8_POLYNOMIAL 0x31 ///< Seed for SGP30's CRC polynomial
+#define SGP30_CRC8_INIT 0xFF ///< Init value for CRC
+#define SGP30_WORD_LEN 2 ///< 2 bytes per word
+
+/**************************************************************************/
+/*! Class that stores state and functions for interacting with SGP30 Gas Sensor */
+/**************************************************************************/
+class Adafruit_SGP30 {
+ public:
+ Adafruit_SGP30(PinName sda, PinName scl);
+ bool begin();
+ bool IAQinit(void);
+ bool IAQmeasure(void);
+
+ bool getIAQBaseline(uint16_t *eco2_base, uint16_t *tvoc_base);
+ bool setIAQBaseline(uint16_t eco2_base, uint16_t tvoc_base);
+ bool getIAQRaw(uint16_t *H2_raw, uint16_t *Eth_raw);
+
+ /**
+ * The last measurement of the IAQ-calculated Total Volatile Organic Compounds in ppb. This value is set when you call {@link IAQmeasure()}
+ */
+ uint16_t TVOC;
+
+ /**
+ * The last measurement of the IAQ-calculated equivalent CO2 in ppm. This value is set when you call {@link IAQmeasure()}
+ */
+ uint16_t eCO2;
+
+ /**
+ * The 48-bit serial number, this value is set when you call {@link begin()}
+ */
+ uint16_t serialnumber[3];
+ private:
+ I2C _i2c;
+ int _i2caddr;
+
+ void write(uint8_t address, uint8_t *data, uint8_t n);
+ void read(uint8_t address, uint8_t *data, uint8_t n);
+ bool readWordFromCommand(uint8_t command[], uint8_t commandLength, uint16_t delay, uint16_t *readdata = NULL, uint8_t readlen = 0);
+ uint8_t generateCRC(uint8_t data[], uint8_t datalen);
+};