/* * Driver for AMS CCS811 digital gas sensor connected to I2C. * * This driver is for the usage with the ESP8266 and FreeRTOS (esp-open-rtos) * [https://github.com/SuperHouse/esp-open-rtos]. It is also working with ESP32 * and ESP-IDF [https://github.com/espressif/esp-idf.git] as well as Linux * based systems using a wrapper library for ESP8266 functions. * * --------------------------------------------------------------------------- * * The BSD License (3-clause license) * * Copyright (c) 2017 Gunar Schorcht (https://github.com/gschorcht) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef CCS811_DRV_H_ #define CCS811_DRV_H_ // Uncomment one of the following defines to enable debug output // #define CCS811_DEBUG_LEVEL_1 // only error messages // #define CCS811_DEBUG_LEVEL_2 // debug and error messages #include "stdint.h" #include "stdbool.h" #include "ccs811_platform.h" // CCS811 I2C addresses #define CCS811_I2C_ADDRESS_1 0x5A // default #define CCS811_I2C_ADDRESS_2 0x5B // CCS811 clock streching counter #define CCS811_I2C_CLOCK_STRETCH 200 // Definition of error codes #define CCS811_OK 0 #define CCS811_NOK -1 #define CCS811_INT_ERROR_MASK 0x000f #define CCS811_DRV_ERROR_MASK 0xfff0 // Error codes for the I2C interface ORed with CCS811 driver error codes #define CCS811_I2C_READ_FAILED 1 #define CCS811_I2C_WRITE_FAILED 2 #define CCS811_I2C_BUSY 3 // CCS811 driver error codes ORed with error codes for I2C the interface #define CCS811_DRV_BOOT_MODE (1 << 8) // firmware is in boot mode #define CCS811_DRV_NO_APP (2 << 8) // no application firmware loaded #define CCS811_DRV_NO_NEW_DATA (3 << 8) // no new data samples are ready #define CCS811_DRV_NO_IAQ_DATA (4 << 8) // no new data samples are ready #define CCS811_DRV_HW_ID (5 << 8) // wrong hardware ID #define CCS811_DRV_INV_SENS (6 << 8) // invalid sensor ID #define CCS811_DRV_WR_REG_INV (7 << 8) // invalid register addr on write #define CCS811_DRV_RD_REG_INV (8 << 8) // invalid register addr on read #define CCS811_DRV_MM_INV (9 << 8) // invalid measurement mode #define CCS811_DRV_MAX_RESIST (10 << 8) // max sensor resistance reached #define CCS811_DRV_HEAT_FAULT (11 << 8) // heater current not in range #define CCS811_DRV_HEAT_SUPPLY (12 << 8) // heater voltage not correct #define CCS811_DRV_WRONG_MODE (13 << 8) // wrong measurement mode #define CCS811_DRV_RD_STAT_FAILED (14 << 8) // read status register failed #define CCS811_DRV_RD_DATA_FAILED (15 << 8) // read sensor data failed #define CCS811_DRV_APP_START_FAIL (16 << 8) // sensor app start failure #define CCS811_DRV_WRONG_PARAMS (17 << 8) // wrong parameters used // ranges #define CCS_ECO2_RANGE_MIN 400 #define CCS_ECO2_RANGE_MAX 8192 #define CCS_TVOC_RANGE_MIN 0 #define CCS_TVOC_RANGE_MAX 1187 #ifdef __cplusplus extern "C" { #endif /** * @brief CCS811 operation modes */ typedef enum { ccs811_mode_idle = 0, // Idle, low current mode ccs811_mode_1s = 1, // Constant Power mode, IAQ values every 1 s ccs811_mode_10s = 2, // Pulse Heating mode, IAQ values every 10 s ccs811_mode_60s = 3, // Low Power Pulse Heating, IAQ values every 60 s ccs811_mode_250ms = 4 // Constant Power mode, RAW data every 250 ms } ccs811_mode_t; /** * @brief CCS811 sensor device data structure */ typedef struct { int error_code; // contains the error code of last operation uint8_t bus; // I2C bus uint8_t addr; // I2C slave address ccs811_mode_t mode; // operation mode } ccs811_sensor_t; /** * @brief Initialize a CCS811 sensor * * The function initializes the CCS811 sensor and checks its availability. * * @param bus I2C bus at which CCS811 sensor is connected * @param addr I2C slave address of the CCS811 sensor * * @return pointer to sensor data structure, or NULL on error */ ccs811_sensor_t* ccs811_init_sensor (uint8_t bus, uint8_t addr); /** * @brief Set the operation mode of the sensor * * The function sets the operating mode of the sensor. If the parameter * *mode* is either *ccs811_mode_1s*, *ccs811_mode_10s*, *ccs811_mode_60s* * or *ccs811_mode_250ms*, the sensor starts a periodic measurement with * the specified period. Function *ccs811_get_results* can then be used at * the same rate to get the results. * * In *ccs811_mode_1s*, *ccs811_mode_10s* and *ccs811_mode_60s*, raw sensor * data as well as IAQ values calculated by the sensor values are available. * In *ccs811_mode_250ms*, only raw data are available. * * In case, parameter mode is *ccs811_mode_idle*, the sensor does not perform * any measurements. * * Please note: Mode timings are subject to typical 2% tolerance due * to accuracy of internal sensor clock. * * Please note: After setting the sensor mode, the sensor needs up to * 20 minutes, before accurate readings are generated. * * Please note: When a sensor operating mode is changed to a new mode with * a lower sample rate, e.g., from *ccs811_mode_60s* to *ccs811_mode_1s, it * should be placed in *mode_idle* for at least 10 minutes before enabling * the new mode. * * @param sensor pointer to the sensor device data structure * @param period measurement period in ms (default 1000 ms) * * @return true on success, false on error */ bool ccs811_set_mode (ccs811_sensor_t* sensor, ccs811_mode_t mode); /** * @brief Get latest IAQ sensor values and/or RAW sensor data * * The function reads the IAQ sensor values (TVOC and eCO2) and/or the raw * sensor data. If some of the results are not needed, the corresponding * pointer parameters can be set to NULL. * * Please note: If the function is called and no new data are available, * e.g., due to the sensor mode time tolerance of 2%, the function still * returns successfully. In this case, the results of the last measurement * are returned and the error code CCS811_DRV_NO_NEW_DATA is set. * * Please note: In *ccs811_mode_250ms*, only RAW data are available. In * that case, the function fails with error_code CCS811_DRV_NO_IAQ_DATA * if parameters *iaq_tvoc* and *iaq_eco2* are not NULL. * @param sensor pointer to the sensor device data structure * @param iaq_tvoc TVOC total volatile organic compound (0 - 1187 ppb) * @param iaq_eco2 eCO2 equivalent CO2 (400 - 8192 ppm) * @param raw_i current through the sensor used for measuring (0 - 63 uA) * @param raw_v voltage across the sensor measured (0 - 1023 = 1.65 V) * * @return true on success, false on error */ bool ccs811_get_results (ccs811_sensor_t* sensor, uint16_t* iaq_tvoc, uint16_t* iaq_eco2, uint8_t* raw_i, uint16_t* raw_v); /** * brief Get the resistance of connected NTC thermistor * * CCS811 supports an external interface for connecting a negative thermal * coefficient thermistor (R_NTC) to provide a cost effective and power * efficient means of calculating the local ambient temperature. The sensor * measures the voltage V_NTC across the R_NTC as well as the voltage V_REF * across a connected reference resistor (R_REF). * * The function returns the current resistance of R_NTC using the equation * * R_NTC = R_REF / V_REF * V_NTC * * Using the data sheet of the NTC, the ambient temperature can be calculated. * * @param sensor pointer to the sensor device data structure * @param reference resistance of R_REF in Ohm * @return resistance of R_NTC in Ohm, or 0 on error */ uint32_t ccs811_get_ntc_resistance (ccs811_sensor_t* sensor, uint32_t r_ref); /* * @brief Set environmental data * * If information about the environment are available from another sensor, * they can be used by CCS811 to compensate gas readings due to * temperature and humidity changes. * * @param sensor pointer to the sensor device data structure * @param temperature measured temperature in degree Celsius * @param humidity measured relative humidity in percent * * @return true on success, false on error */ bool ccs811_set_environmental_data (ccs811_sensor_t* sensor, float temperature, float humidity); /** * @brief Enable or disable data ready interrupt signal *nINT* * * At the end of each measurement cycle (250ms, 1s, 10s, 60s), CCS811 can * optionally trigger an interrupt. The signal *nINT* is driven low as soon * as new sensor values are ready to read. It will stop being driven low * when sensor data are read with function *ccs811_get_results*. * * The interrupt is disabled by default. * * @param sensor pointer to the sensor device data structure * @param enabled if true, the interrupt is enabled, or disabled otherwise * * @return true on success, false on error */ bool ccs811_enable_interrupt (ccs811_sensor_t* sensor, bool enabled); /* * @brief Set eCO2 threshold mode for data ready interrupts * * The user task can choose that the data ready interrupt is not generated * every time when new sensor values become ready but only if the eCO2 value * moves from the current range (LOW, MEDIUM, or HIGH) into another range by * more than a hysteresis value. Hysteresis is used to prevent multiple * interrupts close to a threshold. * * LOW below parameter value *low* * MEDIUM between parameter values *low* and *high* * HIGH above parameter value *high* is range HIGH. * * If all parameters have valid values, the function sets the thresholds and * enables the data ready interrupt. Using 0 for all parameters disables the * interrupt. * * The interrupt is disabled by default. * * @param sensor pointer to the sensor device data structure * @param low threshold LOW to MEDIUM (> 400, default 1500) * @param high threshold MEDIUM to HIGH (< 8192, default 2500) * @param hysteresis hysteresis value (default 50) * * @return true on success, false on error */ bool ccs811_set_eco2_thresholds (ccs811_sensor_t* sensor, uint16_t low, uint16_t high, uint8_t hysteresis); /* * @brief Get the current baseline value from sensor * * The sensor supports automatic baseline correction over a minimum time of * 24 hours. Using this function, the current baseline value can be saved * before the sensor is powered down. This baseline can then be restored after * sensor is powered up again to continue the automatic baseline process. * * @param sensor pointer to the sensor device data structure * @return current baseline value on success, or 0 on error */ uint16_t ccs811_get_baseline (ccs811_sensor_t* sensor); /* * @brief Write a previously stored baseline value to the sensor * * The sensor supports automatic baseline correction over a minimum time of * 24 hours. Using this function, a previously saved baseline value be * restored after the sensor is powered up to continue the automatic baseline * process. * * Please note: The baseline must be written after the conditioning period * of 20 min after power up. * * @param sensor pointer to the sensor device data structure * @param basline baseline to be set * @return true on success, false on error */ bool ccs811_set_baseline (ccs811_sensor_t* sensor, uint16_t baseline); #ifdef __cplusplus } #endif /* End of CPP guard */ #endif /* CCS811_DRV_H_ */