├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── githubci.yml ├── Adafruit_CCS811.cpp ├── Adafruit_CCS811.h ├── LICENSE ├── README.md ├── code-of-conduct.md ├── examples ├── CCS811_OLED_Demo │ └── CCS811_OLED_Demo.ino └── CCS811_test │ └── CCS811_test.ino ├── library.properties └── license.txt /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for opening an issue on an Adafruit Arduino library repository. To 2 | improve the speed of resolution please review the following guidelines and 3 | common troubleshooting steps below before creating the issue: 4 | 5 | - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use 6 | the forums at http://forums.adafruit.com to ask questions and troubleshoot why 7 | something isn't working as expected. In many cases the problem is a common issue 8 | that you will more quickly receive help from the forum community. GitHub issues 9 | are meant for known defects in the code. If you don't know if there is a defect 10 | in the code then start with troubleshooting on the forum first. 11 | 12 | - **If following a tutorial or guide be sure you didn't miss a step.** Carefully 13 | check all of the steps and commands to run have been followed. Consult the 14 | forum if you're unsure or have questions about steps in a guide/tutorial. 15 | 16 | - **For Arduino projects check these very common issues to ensure they don't apply**: 17 | 18 | - For uploading sketches or communicating with the board make sure you're using 19 | a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes 20 | very hard to tell the difference between a data and charge cable! Try using the 21 | cable with other devices or swapping to another cable to confirm it is not 22 | the problem. 23 | 24 | - **Be sure you are supplying adequate power to the board.** Check the specs of 25 | your board and plug in an external power supply. In many cases just 26 | plugging a board into your computer is not enough to power it and other 27 | peripherals. 28 | 29 | - **Double check all soldering joints and connections.** Flakey connections 30 | cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. 31 | 32 | - **Ensure you are using an official Arduino or Adafruit board.** We can't 33 | guarantee a clone board will have the same functionality and work as expected 34 | with this code and don't support them. 35 | 36 | If you're sure this issue is a defect in the code and checked the steps above 37 | please fill in the following fields to provide enough troubleshooting information. 38 | You may delete the guideline and text above to just leave the following details: 39 | 40 | - Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE** 41 | 42 | - Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO 43 | VERSION HERE** 44 | 45 | - List the steps to reproduce the problem below (if possible attach a sketch or 46 | copy the sketch code in too): **LIST REPRO STEPS BELOW** 47 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for creating a pull request to contribute to Adafruit's GitHub code! 2 | Before you open the request please review the following guidelines and tips to 3 | help it be more easily integrated: 4 | 5 | - **Describe the scope of your change--i.e. what the change does and what parts 6 | of the code were modified.** This will help us understand any risks of integrating 7 | the code. 8 | 9 | - **Describe any known limitations with your change.** For example if the change 10 | doesn't apply to a supported platform of the library please mention it. 11 | 12 | - **Please run any tests or examples that can exercise your modified code.** We 13 | strive to not break users of the code and running tests/examples helps with this 14 | process. 15 | 16 | Thank you again for contributing! We will try to test and integrate the change 17 | as soon as we can, but be aware we have many GitHub repositories to manage and 18 | can't immediately respond to every request. There is no need to bump or check in 19 | on a pull request (it will clutter the discussion of the request). 20 | 21 | Also don't be worried if the request is closed or not integrated--sometimes the 22 | priorities of Adafruit's GitHub code (education, ease of use) might not match the 23 | priorities of the pull request. Don't fret, the open source community thrives on 24 | forks and GitHub makes it easy to keep your changes in a forked repo. 25 | 26 | After reviewing the guidelines above you can delete this text from the pull request. 27 | -------------------------------------------------------------------------------- /.github/workflows/githubci.yml: -------------------------------------------------------------------------------- 1 | name: Arduino Library CI 2 | 3 | on: [pull_request, push, repository_dispatch] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/setup-python@v4 11 | with: 12 | python-version: '3.x' 13 | - uses: actions/checkout@v3 14 | - uses: actions/checkout@v3 15 | with: 16 | repository: adafruit/ci-arduino 17 | path: ci 18 | 19 | - name: pre-install 20 | run: bash ci/actions_install.sh 21 | 22 | - name: test platforms 23 | run: python3 ci/build_platform.py main_platforms 24 | 25 | - name: clang 26 | run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r . 27 | 28 | - name: doxygen 29 | env: 30 | GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }} 31 | PRETTYNAME : "Adafruit CCS811 Arduino Library" 32 | run: bash ci/doxy_gen_and_deploy.sh 33 | -------------------------------------------------------------------------------- /Adafruit_CCS811.cpp: -------------------------------------------------------------------------------- 1 | #include "Adafruit_CCS811.h" 2 | 3 | Adafruit_CCS811::~Adafruit_CCS811(void) { 4 | if (i2c_dev) 5 | delete i2c_dev; 6 | } 7 | 8 | /**************************************************************************/ 9 | /*! 10 | @brief Setups the I2C interface and hardware and checks for communication. 11 | @param addr Optional I2C address the sensor can be found on. Default is 12 | 0x5A 13 | @param theWire Optional pointer to I2C interface, &Wire is used by default 14 | @returns True if device is set up, false on any failure 15 | */ 16 | /**************************************************************************/ 17 | bool Adafruit_CCS811::begin(uint8_t addr, TwoWire *theWire) { 18 | if (i2c_dev) 19 | delete i2c_dev; 20 | i2c_dev = new Adafruit_I2CDevice(addr, theWire); 21 | if (!i2c_dev->begin()) { 22 | return false; 23 | } 24 | #ifdef ESP8266 25 | theWire->setClockStretchLimit(500); 26 | #endif 27 | 28 | SWReset(); 29 | delay(100); 30 | 31 | // check that the HW id is correct 32 | if (this->read8(CCS811_HW_ID) != CCS811_HW_ID_CODE) 33 | return false; 34 | 35 | // try to start the app 36 | this->write(CCS811_BOOTLOADER_APP_START, NULL, 0); 37 | delay(100); 38 | 39 | // make sure there are no errors and we have entered application mode 40 | if (checkError()) 41 | return false; 42 | if (!_status.FW_MODE) 43 | return false; 44 | 45 | disableInterrupt(); 46 | 47 | // default to read every second 48 | setDriveMode(CCS811_DRIVE_MODE_1SEC); 49 | 50 | return true; 51 | } 52 | 53 | /**************************************************************************/ 54 | /*! 55 | @brief sample rate of the sensor. 56 | @param mode one of CCS811_DRIVE_MODE_IDLE, CCS811_DRIVE_MODE_1SEC, 57 | CCS811_DRIVE_MODE_10SEC, CCS811_DRIVE_MODE_60SEC, CCS811_DRIVE_MODE_250MS. 58 | */ 59 | void Adafruit_CCS811::setDriveMode(uint8_t mode) { 60 | _meas_mode.DRIVE_MODE = mode; 61 | this->write8(CCS811_MEAS_MODE, _meas_mode.get()); 62 | } 63 | 64 | /**************************************************************************/ 65 | /*! 66 | @brief enable the data ready interrupt pin on the device. 67 | */ 68 | /**************************************************************************/ 69 | void Adafruit_CCS811::enableInterrupt() { 70 | _meas_mode.INT_DATARDY = 1; 71 | this->write8(CCS811_MEAS_MODE, _meas_mode.get()); 72 | } 73 | 74 | /**************************************************************************/ 75 | /*! 76 | @brief disable the data ready interrupt pin on the device 77 | */ 78 | /**************************************************************************/ 79 | void Adafruit_CCS811::disableInterrupt() { 80 | _meas_mode.INT_DATARDY = 0; 81 | this->write8(CCS811_MEAS_MODE, _meas_mode.get()); 82 | } 83 | 84 | /**************************************************************************/ 85 | /*! 86 | @brief checks if data is available to be read. 87 | @returns True if data is ready, false otherwise. 88 | */ 89 | /**************************************************************************/ 90 | bool Adafruit_CCS811::available() { 91 | _status.set(read8(CCS811_STATUS)); 92 | if (!_status.DATA_READY) 93 | return false; 94 | else 95 | return true; 96 | } 97 | 98 | /**************************************************************************/ 99 | /*! 100 | @brief read and store the sensor data. This data can be accessed with 101 | getTVOC(), geteCO2(), getCurrentSelected() and getRawADCreading() 102 | @returns 0 if no error, error code otherwise. 103 | */ 104 | /**************************************************************************/ 105 | uint8_t Adafruit_CCS811::readData() { 106 | if (!available()) 107 | return false; 108 | else { 109 | uint8_t buf[8]; 110 | this->read(CCS811_ALG_RESULT_DATA, buf, 8); 111 | 112 | _eCO2 = ((uint16_t)buf[0] << 8) | ((uint16_t)buf[1]); 113 | _TVOC = ((uint16_t)buf[2] << 8) | ((uint16_t)buf[3]); 114 | _currentSelected = ((uint16_t)buf[6] >> 2); 115 | _rawADCreading = ((uint16_t)(buf[6] & 3) << 8) | ((uint16_t)buf[7]); 116 | 117 | if (_status.ERROR) 118 | return buf[5]; 119 | 120 | else 121 | return 0; 122 | } 123 | } 124 | 125 | /**************************************************************************/ 126 | /*! 127 | @brief set the humidity and temperature compensation for the sensor. 128 | @param humidity the humidity data as a percentage. For 55.5% humidity, pass 129 | in 55.5 130 | @param temperature the temperature in degrees C as a decimal number. 131 | For 25.5 degrees C, pass in 25.5 132 | */ 133 | /**************************************************************************/ 134 | void Adafruit_CCS811::setEnvironmentalData(float humidity, float temperature) { 135 | /* Humidity is stored as an unsigned 16 bits in 1/512%RH. The 136 | default value is 50% = 0x64, 0x00. As an example 48.5% 137 | humidity would be 0x61, 0x00.*/ 138 | 139 | /* Temperature is stored as an unsigned 16 bits integer in 1/512 140 | degrees; there is an offset: 0 maps to -25°C. The default value is 141 | 25°C = 0x64, 0x00. As an example 23.5% temperature would be 142 | 0x61, 0x00. 143 | The internal algorithm uses these values (or default values if 144 | not set by the application) to compensate for changes in 145 | relative humidity and ambient temperature.*/ 146 | 147 | uint16_t hum_conv = humidity * 512.0f + 0.5f; 148 | uint16_t temp_conv = (temperature + 25.0f) * 512.0f + 0.5f; 149 | 150 | uint8_t buf[] = { 151 | (uint8_t)((hum_conv >> 8) & 0xFF), (uint8_t)(hum_conv & 0xFF), 152 | (uint8_t)((temp_conv >> 8) & 0xFF), (uint8_t)(temp_conv & 0xFF)}; 153 | 154 | this->write(CCS811_ENV_DATA, buf, 4); 155 | } 156 | 157 | /**************************************************************************/ 158 | /*! 159 | @brief get the current baseline from the sensor. 160 | @returns the baseline as 16 bit integer. This value is not human readable. 161 | */ 162 | /**************************************************************************/ 163 | uint16_t Adafruit_CCS811::getBaseline() { 164 | /* baseline is not in a human readable format, the two bytes are assembled 165 | to an uint16_t for easy handling/passing around */ 166 | 167 | uint8_t buf[2]; 168 | 169 | this->read(CCS811_BASELINE, buf, 2); 170 | 171 | return ((uint16_t)buf[0] << 8) | ((uint16_t)buf[1]); 172 | } 173 | 174 | /**************************************************************************/ 175 | /*! 176 | @brief set the baseline for the sensor. 177 | @param baseline the baseline to be set. Has to be a value retrieved by 178 | getBaseline(). 179 | */ 180 | /**************************************************************************/ 181 | void Adafruit_CCS811::setBaseline(uint16_t baseline) { 182 | /* baseline is not in a human readable format, byte ordering matches 183 | getBaseline() */ 184 | 185 | uint8_t buf[] = {(uint8_t)((baseline >> 8) & 0xFF), 186 | (uint8_t)(baseline & 0xFF)}; 187 | 188 | this->write(CCS811_BASELINE, buf, 2); 189 | } 190 | 191 | /**************************************************************************/ 192 | /*! 193 | @deprecated hardware support removed by vendor 194 | @brief calculate the temperature using the onboard NTC resistor. 195 | @returns temperature as a double. 196 | */ 197 | /**************************************************************************/ 198 | double Adafruit_CCS811::calculateTemperature() { 199 | uint8_t buf[4]; 200 | this->read(CCS811_NTC, buf, 4); 201 | 202 | uint32_t vref = ((uint32_t)buf[0] << 8) | buf[1]; 203 | uint32_t vntc = ((uint32_t)buf[2] << 8) | buf[3]; 204 | 205 | // from ams ccs811 app note 206 | uint32_t rntc = vntc * CCS811_REF_RESISTOR / vref; 207 | 208 | double ntc_temp; 209 | ntc_temp = log((double)rntc / CCS811_REF_RESISTOR); // 1 210 | ntc_temp /= 3380; // 2 211 | ntc_temp += 1.0 / (25 + 273.15); // 3 212 | ntc_temp = 1.0 / ntc_temp; // 4 213 | ntc_temp -= 273.15; // 5 214 | return ntc_temp - _tempOffset; 215 | } 216 | 217 | /**************************************************************************/ 218 | /*! 219 | @brief set interrupt thresholds 220 | @param low_med the level below which an interrupt will be triggered. 221 | @param med_high the level above which the interrupt will ge triggered. 222 | @param hysteresis optional histeresis level. Defaults to 50 223 | */ 224 | /**************************************************************************/ 225 | void Adafruit_CCS811::setThresholds(uint16_t low_med, uint16_t med_high, 226 | uint8_t hysteresis) { 227 | uint8_t buf[] = {(uint8_t)((low_med >> 8) & 0xF), (uint8_t)(low_med & 0xF), 228 | (uint8_t)((med_high >> 8) & 0xF), (uint8_t)(med_high & 0xF), 229 | hysteresis}; 230 | 231 | this->write(CCS811_THRESHOLDS, buf, 5); 232 | } 233 | 234 | /**************************************************************************/ 235 | /*! 236 | @brief trigger a software reset of the device 237 | */ 238 | /**************************************************************************/ 239 | void Adafruit_CCS811::SWReset() { 240 | // reset sequence from the datasheet 241 | uint8_t seq[] = {0x11, 0xE5, 0x72, 0x8A}; 242 | this->write(CCS811_SW_RESET, seq, 4); 243 | } 244 | 245 | /**************************************************************************/ 246 | /*! 247 | @brief read the status register and store any errors. 248 | @returns the error bits from the status register of the device. 249 | */ 250 | /**************************************************************************/ 251 | bool Adafruit_CCS811::checkError() { 252 | _status.set(read8(CCS811_STATUS)); 253 | return _status.ERROR; 254 | } 255 | 256 | /**************************************************************************/ 257 | /*! 258 | @brief write one byte of data to the specified register 259 | @param reg the register to write to 260 | @param value the value to write 261 | */ 262 | /**************************************************************************/ 263 | void Adafruit_CCS811::write8(byte reg, byte value) { 264 | this->write(reg, &value, 1); 265 | } 266 | 267 | /**************************************************************************/ 268 | /*! 269 | @brief read one byte of data from the specified register 270 | @param reg the register to read 271 | @returns one byte of register data 272 | */ 273 | /**************************************************************************/ 274 | uint8_t Adafruit_CCS811::read8(byte reg) { 275 | uint8_t ret; 276 | this->read(reg, &ret, 1); 277 | 278 | return ret; 279 | } 280 | 281 | void Adafruit_CCS811::read(uint8_t reg, uint8_t *buf, uint8_t num) { 282 | uint8_t buffer[1] = {reg}; 283 | i2c_dev->write_then_read(buffer, 1, buf, num); 284 | } 285 | 286 | void Adafruit_CCS811::write(uint8_t reg, uint8_t *buf, uint8_t num) { 287 | uint8_t prefix[1] = {reg}; 288 | i2c_dev->write(buf, num, true, prefix, 1); 289 | } 290 | -------------------------------------------------------------------------------- /Adafruit_CCS811.h: -------------------------------------------------------------------------------- 1 | #ifndef LIB_ADAFRUIT_CCS811_H 2 | #define LIB_ADAFRUIT_CCS811_H 3 | 4 | #if (ARDUINO >= 100) 5 | #include "Arduino.h" 6 | #else 7 | #include "WProgram.h" 8 | #endif 9 | 10 | #include 11 | 12 | /*========================================================================= 13 | I2C ADDRESS/BITS 14 | -----------------------------------------------------------------------*/ 15 | #define CCS811_ADDRESS (0x5A) 16 | /*=========================================================================*/ 17 | 18 | /*========================================================================= 19 | REGISTERS 20 | -----------------------------------------------------------------------*/ 21 | enum { 22 | CCS811_STATUS = 0x00, 23 | CCS811_MEAS_MODE = 0x01, 24 | CCS811_ALG_RESULT_DATA = 0x02, 25 | CCS811_RAW_DATA = 0x03, 26 | CCS811_ENV_DATA = 0x05, 27 | CCS811_NTC = 0x06, 28 | CCS811_THRESHOLDS = 0x10, 29 | CCS811_BASELINE = 0x11, 30 | CCS811_HW_ID = 0x20, 31 | CCS811_HW_VERSION = 0x21, 32 | CCS811_FW_BOOT_VERSION = 0x23, 33 | CCS811_FW_APP_VERSION = 0x24, 34 | CCS811_ERROR_ID = 0xE0, 35 | CCS811_SW_RESET = 0xFF, 36 | }; 37 | 38 | // bootloader registers 39 | enum { 40 | CCS811_BOOTLOADER_APP_ERASE = 0xF1, 41 | CCS811_BOOTLOADER_APP_DATA = 0xF2, 42 | CCS811_BOOTLOADER_APP_VERIFY = 0xF3, 43 | CCS811_BOOTLOADER_APP_START = 0xF4 44 | }; 45 | 46 | enum { 47 | CCS811_DRIVE_MODE_IDLE = 0x00, 48 | CCS811_DRIVE_MODE_1SEC = 0x01, 49 | CCS811_DRIVE_MODE_10SEC = 0x02, 50 | CCS811_DRIVE_MODE_60SEC = 0x03, 51 | CCS811_DRIVE_MODE_250MS = 0x04, 52 | }; 53 | 54 | /*=========================================================================*/ 55 | 56 | #define CCS811_HW_ID_CODE 0x81 57 | 58 | #define CCS811_REF_RESISTOR 100000 59 | 60 | /**************************************************************************/ 61 | /*! 62 | @brief Class that stores state and functions for interacting with CCS811 63 | gas sensor chips 64 | */ 65 | /**************************************************************************/ 66 | class Adafruit_CCS811 { 67 | public: 68 | // constructors 69 | Adafruit_CCS811(void){}; 70 | ~Adafruit_CCS811(void); 71 | 72 | bool begin(uint8_t addr = CCS811_ADDRESS, TwoWire *theWire = &Wire); 73 | 74 | void setEnvironmentalData(float humidity, float temperature); 75 | 76 | uint16_t getBaseline(); 77 | void setBaseline(uint16_t baseline); 78 | 79 | // calculate temperature based on the NTC register 80 | double calculateTemperature(); 81 | 82 | void setThresholds(uint16_t low_med, uint16_t med_high, 83 | uint8_t hysteresis = 50); 84 | 85 | void SWReset(); 86 | 87 | void setDriveMode(uint8_t mode); 88 | void enableInterrupt(); 89 | void disableInterrupt(); 90 | 91 | /**************************************************************************/ 92 | /*! 93 | @brief returns the stored total volatile organic compounds measurement. 94 | This does does not read the sensor. To do so, call readData() 95 | @returns TVOC measurement as 16 bit integer 96 | */ 97 | /**************************************************************************/ 98 | uint16_t getTVOC() { return _TVOC; } 99 | 100 | /**************************************************************************/ 101 | /*! 102 | @brief returns the stored estimated carbon dioxide measurement. This does 103 | does not read the sensor. To do so, call readData() 104 | @returns eCO2 measurement as 16 bit integer 105 | */ 106 | /**************************************************************************/ 107 | uint16_t geteCO2() { return _eCO2; } 108 | 109 | /**************************************************************************/ 110 | /*! 111 | @brief returns the "Current Selected" in uA. 112 | This does does not read the sensor. To do so, call readData() 113 | @returns "Current Selected" in uA as 16 bit integer 114 | */ 115 | /**************************************************************************/ 116 | uint16_t getCurrentSelected() { return _currentSelected; } 117 | 118 | /**************************************************************************/ 119 | /*! 120 | @brief returns the raw ADC reading. This does 121 | does not read the sensor. To do so, call readData() 122 | @returns raw ADC reading as 16 bit integer 123 | */ 124 | /**************************************************************************/ 125 | uint16_t getRawADCreading() { return _rawADCreading; } 126 | 127 | /**************************************************************************/ 128 | /*! 129 | @brief set the temperature compensation offset for the device. This is 130 | needed to offset errors in NTC measurements. 131 | @param offset the offset to be added to temperature measurements. 132 | */ 133 | /**************************************************************************/ 134 | void setTempOffset(float offset) { _tempOffset = offset; } 135 | 136 | // check if data is available to be read 137 | bool available(); 138 | uint8_t readData(); 139 | 140 | bool checkError(); 141 | 142 | private: 143 | Adafruit_I2CDevice *i2c_dev = NULL; ///< Pointer to I2C bus interface 144 | float _tempOffset; 145 | 146 | uint16_t _TVOC; 147 | uint16_t _eCO2; 148 | 149 | uint16_t _currentSelected; 150 | uint16_t _rawADCreading; 151 | 152 | void write8(byte reg, byte value); 153 | void write16(byte reg, uint16_t value); 154 | uint8_t read8(byte reg); 155 | 156 | void read(uint8_t reg, uint8_t *buf, uint8_t num); 157 | void write(uint8_t reg, uint8_t *buf, uint8_t num); 158 | 159 | /*========================================================================= 160 | REGISTER BITFIELDS 161 | -----------------------------------------------------------------------*/ 162 | // The status register 163 | struct status { 164 | 165 | /* 0: no error 166 | * 1: error has occurred 167 | */ 168 | uint8_t ERROR : 1; 169 | 170 | // reserved : 2 171 | 172 | /* 0: no samples are ready 173 | * 1: samples are ready 174 | */ 175 | uint8_t DATA_READY : 1; 176 | uint8_t APP_VALID : 1; 177 | 178 | // reserved : 2 179 | 180 | /* 0: boot mode, new firmware can be loaded 181 | * 1: application mode, can take measurements 182 | */ 183 | uint8_t FW_MODE : 1; 184 | 185 | void set(uint8_t data) { 186 | ERROR = data & 0x01; 187 | DATA_READY = (data >> 3) & 0x01; 188 | APP_VALID = (data >> 4) & 0x01; 189 | FW_MODE = (data >> 7) & 0x01; 190 | } 191 | }; 192 | status _status; 193 | 194 | // measurement and conditions register 195 | struct meas_mode { 196 | // reserved : 2 197 | 198 | /* 0: interrupt mode operates normally 199 | * 1: Interrupt mode (if enabled) only asserts the nINT signal (driven low) if 200 | the new ALG_RESULT_DATA crosses one of the thresholds set in the THRESHOLDS 201 | register by more than the hysteresis value (also in the THRESHOLDS register) 202 | */ 203 | uint8_t INT_THRESH : 1; 204 | 205 | /* 0: int disabled 206 | * 1: The nINT signal is asserted (driven low) when a new sample is ready in 207 | ALG_RESULT_DATA. The nINT signal will stop being driven low 208 | when ALG_RESULT_DATA is read on the I²C interface. 209 | */ 210 | uint8_t INT_DATARDY : 1; 211 | 212 | uint8_t DRIVE_MODE : 3; 213 | 214 | uint8_t get() { 215 | return (INT_THRESH << 2) | (INT_DATARDY << 3) | (DRIVE_MODE << 4); 216 | } 217 | }; 218 | meas_mode _meas_mode; 219 | 220 | struct error_id { 221 | /* The CCS811 received an I²C write request addressed to this station but 222 | with invalid register address ID */ 223 | uint8_t WRITE_REG_INVALID : 1; 224 | 225 | /* The CCS811 received an I²C read request to a mailbox ID that is invalid 226 | */ 227 | uint8_t READ_REG_INVALID : 1; 228 | 229 | /* The CCS811 received an I²C request to write an unsupported mode to 230 | MEAS_MODE */ 231 | uint8_t MEASMODE_INVALID : 1; 232 | 233 | /* The sensor resistance measurement has reached or exceeded the maximum 234 | range */ 235 | uint8_t MAX_RESISTANCE : 1; 236 | 237 | /* The Heater current in the CCS811 is not in range */ 238 | uint8_t HEATER_FAULT : 1; 239 | 240 | /* The Heater voltage is not being applied correctly */ 241 | uint8_t HEATER_SUPPLY : 1; 242 | 243 | void set(uint8_t data) { 244 | WRITE_REG_INVALID = data & 0x01; 245 | READ_REG_INVALID = (data & 0x02) >> 1; 246 | MEASMODE_INVALID = (data & 0x04) >> 2; 247 | MAX_RESISTANCE = (data & 0x08) >> 3; 248 | HEATER_FAULT = (data & 0x10) >> 4; 249 | HEATER_SUPPLY = (data & 0x20) >> 5; 250 | } 251 | }; 252 | error_id _error_id; 253 | 254 | /*=========================================================================*/ 255 | }; 256 | 257 | #endif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Adafruit Industries 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Adafruit CCS811 [![Build Status](https://github.com/adafruit/Adafruit_CCS811/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_CCS811/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit_CCS811/html/index.html) 2 | 3 | 4 | 5 | 6 | This is a library for the Adafruit CCS811 gas sensor breakout board: 7 | * https://www.adafruit.com/product/3566 8 | 9 | Check out the [product guide on the Adafruit Learning System](https://learn.adafruit.com/adafruit-ccs811-air-quality-sensor) for our tutorials and wiring diagrams. 10 | This chip uses **I2C** to communicate 11 | 12 | Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! 13 | # Dependencies 14 | * [Adafruit SSD1306](https://github.com/adafruit/Adafruit SSD1306) 15 | * [Adafruit GFX Library](https://github.com/adafruit/Adafruit-GFX-Library) 16 | 17 | # Contributing 18 | 19 | Contributions are welcome! Please read our [Code of Conduct](https://github.com/adafruit/Adafruit_CCS811/blob/master/CODE_OF_CONDUCT.md>) 20 | before contributing to help this project stay welcoming. 21 | 22 | ## Documentation and doxygen 23 | Documentation is produced by doxygen. Contributions should include documentation for any new code added. 24 | 25 | Some examples of how to use doxygen can be found in these guide pages: 26 | 27 | https://learn.adafruit.com/the-well-automated-arduino-library/doxygen 28 | 29 | https://learn.adafruit.com/the-well-automated-arduino-library/doxygen-tips 30 | 31 | 32 | Written by Dean Miller for Adafruit Industries. 33 | MIT license, all text above must be included in any redistribution. See license.txt for more information 34 | All text above must be included in any redistribution 35 | 36 | To install, use the Arduino Library Manager and search for "Adafruit CCS811" and install the library. 37 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Adafruit Community Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and leaders pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level or type of 9 | experience, education, socio-economic status, nationality, personal appearance, 10 | race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | We are committed to providing a friendly, safe and welcoming environment for 15 | all. 16 | 17 | Examples of behavior that contributes to creating a positive environment 18 | include: 19 | 20 | * Be kind and courteous to others 21 | * Using welcoming and inclusive language 22 | * Being respectful of differing viewpoints and experiences 23 | * Collaborating with other community members 24 | * Gracefully accepting constructive criticism 25 | * Focusing on what is best for the community 26 | * Showing empathy towards other community members 27 | 28 | Examples of unacceptable behavior by participants include: 29 | 30 | * The use of sexualized language or imagery and sexual attention or advances 31 | * The use of inappropriate images, including in a community member's avatar 32 | * The use of inappropriate language, including in a community member's nickname 33 | * Any spamming, flaming, baiting or other attention-stealing behavior 34 | * Excessive or unwelcome helping; answering outside the scope of the question 35 | asked 36 | * Trolling, insulting/derogatory comments, and personal or political attacks 37 | * Public or private harassment 38 | * Publishing others' private information, such as a physical or electronic 39 | address, without explicit permission 40 | * Other conduct which could reasonably be considered inappropriate 41 | 42 | The goal of the standards and moderation guidelines outlined here is to build 43 | and maintain a respectful community. We ask that you don’t just aim to be 44 | "technically unimpeachable", but rather try to be your best self. 45 | 46 | We value many things beyond technical expertise, including collaboration and 47 | supporting others within our community. Providing a positive experience for 48 | other community members can have a much more significant impact than simply 49 | providing the correct answer. 50 | 51 | ## Our Responsibilities 52 | 53 | Project leaders are responsible for clarifying the standards of acceptable 54 | behavior and are expected to take appropriate and fair corrective action in 55 | response to any instances of unacceptable behavior. 56 | 57 | Project leaders have the right and responsibility to remove, edit, or 58 | reject messages, comments, commits, code, issues, and other contributions 59 | that are not aligned to this Code of Conduct, or to ban temporarily or 60 | permanently any community member for other behaviors that they deem 61 | inappropriate, threatening, offensive, or harmful. 62 | 63 | ## Moderation 64 | 65 | Instances of behaviors that violate the Adafruit Community Code of Conduct 66 | may be reported by any member of the community. Community members are 67 | encouraged to report these situations, including situations they witness 68 | involving other community members. 69 | 70 | You may report in the following ways: 71 | 72 | In any situation, you may send an email to . 73 | 74 | On the Adafruit Discord, you may send an open message from any channel 75 | to all Community Helpers by tagging @community helpers. You may also send an 76 | open message from any channel, or a direct message to @kattni#1507, 77 | @tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or 78 | @Andon#8175. 79 | 80 | Email and direct message reports will be kept confidential. 81 | 82 | In situations on Discord where the issue is particularly egregious, possibly 83 | illegal, requires immediate action, or violates the Discord terms of service, 84 | you should also report the message directly to Discord. 85 | 86 | These are the steps for upholding our community’s standards of conduct. 87 | 88 | 1. Any member of the community may report any situation that violates the 89 | Adafruit Community Code of Conduct. All reports will be reviewed and 90 | investigated. 91 | 2. If the behavior is an egregious violation, the community member who 92 | committed the violation may be banned immediately, without warning. 93 | 3. Otherwise, moderators will first respond to such behavior with a warning. 94 | 4. Moderators follow a soft "three strikes" policy - the community member may 95 | be given another chance, if they are receptive to the warning and change their 96 | behavior. 97 | 5. If the community member is unreceptive or unreasonable when warned by a 98 | moderator, or the warning goes unheeded, they may be banned for a first or 99 | second offense. Repeated offenses will result in the community member being 100 | banned. 101 | 102 | ## Scope 103 | 104 | This Code of Conduct and the enforcement policies listed above apply to all 105 | Adafruit Community venues. This includes but is not limited to any community 106 | spaces (both public and private), the entire Adafruit Discord server, and 107 | Adafruit GitHub repositories. Examples of Adafruit Community spaces include 108 | but are not limited to meet-ups, audio chats on the Adafruit Discord, or 109 | interaction at a conference. 110 | 111 | This Code of Conduct applies both within project spaces and in public spaces 112 | when an individual is representing the project or its community. As a community 113 | member, you are representing our community, and are expected to behave 114 | accordingly. 115 | 116 | ## Attribution 117 | 118 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 119 | version 1.4, available at 120 | , 121 | and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html). 122 | 123 | For other projects adopting the Adafruit Community Code of 124 | Conduct, please contact the maintainers of those projects for enforcement. 125 | If you wish to use this code of conduct for your own project, consider 126 | explicitly mentioning your moderation policy or making a copy with your 127 | own moderation policy so as to avoid confusion. 128 | -------------------------------------------------------------------------------- /examples/CCS811_OLED_Demo/CCS811_OLED_Demo.ino: -------------------------------------------------------------------------------- 1 | /* This demo shows how to display the CCS811 readings on an Adafruit I2C OLED. 2 | * (We used a Feather + OLED FeatherWing) 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include "Adafruit_CCS811.h" 11 | 12 | Adafruit_CCS811 ccs; 13 | Adafruit_SSD1306 display = Adafruit_SSD1306(); 14 | 15 | void setup() { 16 | Serial.begin(115200); 17 | 18 | if(!ccs.begin()){ 19 | Serial.println("Failed to start sensor! Please check your wiring."); 20 | while(1); 21 | } 22 | 23 | // by default, we'll generate the high voltage from the 3.3v line internally! (neat!) 24 | display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32) 25 | 26 | // Show image buffer on the display hardware. 27 | // Since the buffer is intialized with an Adafruit splashscreen 28 | // internally, this will display the splashscreen. 29 | display.display(); 30 | delay(500); 31 | 32 | // Clear the buffer. 33 | display.clearDisplay(); 34 | display.display(); 35 | 36 | //calibrate temperature sensor 37 | while(!ccs.available()); 38 | float temp = ccs.calculateTemperature(); 39 | ccs.setTempOffset(temp - 25.0); 40 | 41 | Serial.println("IO test"); 42 | 43 | // text display tests 44 | display.setTextSize(1); 45 | display.setTextColor(WHITE); 46 | } 47 | 48 | 49 | void loop() { 50 | display.setCursor(0,0); 51 | if(ccs.available()){ 52 | display.clearDisplay(); 53 | float temp = ccs.calculateTemperature(); 54 | if(!ccs.readData()){ 55 | display.print("eCO2: "); 56 | Serial.print("eCO2: "); 57 | float eCO2 = ccs.geteCO2(); 58 | display.print(eCO2); 59 | Serial.print(eCO2); 60 | 61 | display.print(" ppm\nTVOC: "); 62 | Serial.print(" ppm, TVOC: "); 63 | float TVOC = ccs.getTVOC(); 64 | display.print(TVOC); 65 | Serial.print(TVOC); 66 | 67 | Serial.print(" ppb Temp:"); 68 | display.print(" ppb\nTemp: "); 69 | Serial.println(temp); 70 | display.println(temp); 71 | display.display(); 72 | } 73 | else{ 74 | Serial.println("ERROR!"); 75 | while(1); 76 | } 77 | } 78 | delay(500); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /examples/CCS811_test/CCS811_test.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | This is a library for the CCS811 air 3 | 4 | This sketch reads the sensor 5 | 6 | Designed specifically to work with the Adafruit CCS811 breakout 7 | ----> http://www.adafruit.com/products/3566 8 | 9 | These sensors use I2C to communicate. The device's I2C address is 0x5A 10 | 11 | Adafruit invests time and resources providing this open source code, 12 | please support Adafruit andopen-source hardware by purchasing products 13 | from Adafruit! 14 | 15 | Written by Dean Miller for Adafruit Industries. 16 | BSD license, all text above must be included in any redistribution 17 | ***************************************************************************/ 18 | 19 | #include "Adafruit_CCS811.h" 20 | 21 | Adafruit_CCS811 ccs; 22 | 23 | void setup() { 24 | Serial.begin(9600); 25 | 26 | Serial.println("CCS811 test"); 27 | 28 | if(!ccs.begin()){ 29 | Serial.println("Failed to start sensor! Please check your wiring."); 30 | while(1); 31 | } 32 | 33 | // Wait for the sensor to be ready 34 | while(!ccs.available()); 35 | } 36 | 37 | void loop() { 38 | if(ccs.available()){ 39 | if(!ccs.readData()){ 40 | Serial.print("CO2: "); 41 | Serial.print(ccs.geteCO2()); 42 | Serial.print("ppm, TVOC: "); 43 | Serial.println(ccs.getTVOC()); 44 | } 45 | else{ 46 | Serial.println("ERROR!"); 47 | while(1); 48 | } 49 | } 50 | delay(500); 51 | } 52 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Adafruit CCS811 Library 2 | version=1.1.3 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=This is a library for the Adafruit CCS811 I2C gas sensor breakout. 6 | paragraph=CCS811 is a gas sensor that can detect a wide range of Volatile Organic Compounds (VOCs) and is intended for indoor air quality monitoring. 7 | category=Sensors 8 | url=https://github.com/adafruit/Adafruit_CCS811 9 | architectures=* 10 | depends=Adafruit SSD1306, Adafruit GFX Library, Adafruit BusIO 11 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 Dean Miller for Adafruit Industries 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 19 | OR OTHER DEALINGS IN THE SOFTWARE. 20 | --------------------------------------------------------------------------------