esp-open-rtos/extras/ccs811/ccs811.h
Gunar Schorcht f0425e7abd - small corrections
- changes to use the same source code with ESP8266 (esp-open-rtos) and
  ESP32 (ESP-IDF)
2017-12-21 19:00:16 +01:00

336 lines
13 KiB
C

/*
* 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_ */