Library for the AMS CC811 digitial gas sensor
Dependencies: AMS_ENS210_temp_humid_sensor
AMS_CCS811.h
- Committer:
- UHSLMarcus
- Date:
- 2017-01-24
- Revision:
- 13:a74306788df7
- Parent:
- 8:58a36d9218be
File content as of revision 13:a74306788df7:
/** * @author Marcus Lee * * @section DESCRIPTION * A library for the AMS CCS811 digital gas sensor. * */ #ifndef AMS_CCS811_H #define AMS_CCS811_H #include "mbed.h" #include "AMS_ENS210.h" /* Library defaults */ #define CONFIG_OP_MODE TEN_SECOND // Every 10 seconds #define CONFIG_INTR 0 // Interupt off #define CONFIG_ADDR_DIR 0 // ADDR n_wake_pin pulled low #define CONFIG_ENS210_POLL 3000 // ENS210 is polled every 3 seconds /* Library Constants */ #define CCS811_SLAVE_ADDR_RAW_H 0x5B #define CCS811_SLAVE_ADDR_RAW_L 0x5A #define CCS811_SLAVE_ADDR_RAW _slave_addr #define CCS811_SLAVE_ADDR CCS811_SLAVE_ADDR_RAW << 1 #define CCS811_SLAVE_ADDR_W CCS811_SLAVE_ADDR #define CCS811_SLAVE_ADDR_R CCS811_SLAVE_ADDR | 1 #define MEAS_MODE 0x01 #define STATUS 0x00 #define ALG_RESULT_DATA 0x02 #define RAW_DATA 0x03 #define ENV_DATA 0x05 #define ERROR_ID 0xE0 #define APP_START 0xF4 #define CCS811_T_AWAKE 55 // us - time taken for sensor I2C to become active #define CCS811_T_DWAKE 25 // us - time taken for sensor I2C to become inactive #define CCS811_MAX_HUMID 127.998046875 // maxmium value that can be represented in the register #define CCS811_MAX_TEMP 102.998046875 // maxmium value that can be represented in the register /* Error Codes */ #define CCS811_NO_ERROR "No Error"; /* Sensor Errors */ #define CCS811_ERR_NUM 8 #define CCS811_WRITE_REG_INVALID "The CCS811 received an I2C write request addressed to this station but with invalid register address ID" #define CCS811_READ_REG_INVALID "The CCS811 received an I2C read request to a mailbox ID that is invalid" #define CCS811_MEASMODE_INVALID "The CCS811 received an I2C request to write an unsupported mode to MEAS_MODE" #define CCS811_MAX_RESISTANCE "The sensor resistance measurement has reached or exceeded the maximum range" #define CCS811_HEATER_FAULT "The Heater current in the CCS811 is not in range" #define CCS811_HEATER_SUPPLY "The Heater voltage is not being applied correctly" #define CCS811_RESERVED "Reserved for Future Use" /* Library Errors */ #define CCS811_LIB_ERR_NUM 9 #define CCS811_LIB_N_WAKE_ID 0 #define CCS811_LIB_N_WAKE "nWAKE pin not set" #define CCS811_LIB_I2C_ID 1 #define CCS811_LIB_I2C "I2C interface is NULL" #define CCS811_LIB_SLAVE_W_ID 2 #define CCS811_LIB_SLAVE_W "Failed to write slave write address" #define CCS811_LIB_REG_ADDR_ID 3 #define CCS811_LIB_REG_ADDR "Failed to write register address" #define CCS811_LIB_I2CWRITE_ID 4 #define CCS811_LIB_I2CWRITE "Failed to write byte" #define CCS811_LIB_SLAVE_R_ID 5 #define CCS811_LIB_SLAVE_R "Failed to write slave read address" #define CCS811_LIB_INV_MODE_ID 6 #define CCS811_LIB_INV_MODE "Invalid operation mode" #define CCS811_LIB_ENS210_INIT_ID 7 #define CCS811_LIB_ENS210_INIT "Failed to create new AMS_ENS210 object" #define CCS811_LIB_ENS210_POLL_ID 7 #define CCS811_LIB_ENS210_POLL "AMS_ENS210 poll error" #define CCS811_TOTAL_ERR_NUM CCS811_ERR_NUM+CCS811_LIB_ERR_NUM /** The AMS CCS811 class */ class AMS_CCS811 { public: /** Sensor operation modes. * */ enum OP_MODES { IDLE, /**< Measurements disabled */ SECOND, /**< Measurement every second */ TEN_SECOND, /**< Measurement every 10 seconds */ SIXTY_SECOND, /**< Measurement every 60 seconds */ CONSTANT, /**< Measurement every 250ms - Only raw data available */ INVALID /**< Invalid bit configuration/Error Occured */ }; /** Holds error information. * */ struct ccs811_errors { int count; /**< Number of total errors */ int codes[CCS811_TOTAL_ERR_NUM]; /**< Array of active error codes */ ccs811_errors() : count(0) {} }; /** Create an AMS_CCS811 instance * * @param i2c The I2C interface to use for communication * @param n_wake_pin Pin nWAKE is attached to */ AMS_CCS811(I2C * i2c, PinName n_wake_pin); /** Create an AMS_CCS811 instance * * @param i2c The I2C interface to use for communication * @param n_wake_pin Pin nWAKE is attached to * @param ens210_i2c The I2C interface for an attached AMS_ENS210 */ AMS_CCS811(I2C * i2c, PinName n_wake_pin, I2C * ens210_i2c); /** Destroy the AMS_CCS811 instance */ ~AMS_CCS811(); /** Initalise the sensor * * @return Intalisation success */ bool init(); /** Set the I2C interface * * @param i2c The I2C interface to use for communication * */ void i2c_interface(I2C * i2c); /** Set the ENS210 I2C interface * * @param i2c The I2C interface for an attached AMS_ENS210 * * @return Success */ bool ens210_i2c_interface(I2C * i2c); /** Set whether the attached AMS_ENS210 is enabled. * If an I2C interface is not set for the ENS210, calling this method will have no effect. * * @param enabled True for enabled, false for disabled * * @return enabled True for enabled, false for disabled */ bool enable_ens210(bool enable); /** Get whether the attached AMS_ENS210 is enabled. * * @return enabled True for enabled, false for disabled * */ bool ens210_is_enabled(); /** Set the AMS_ENS210 poll interval * * @param poll_ms Poll interval in ms * */ void ens210_poll_interval(int poll_ms); /** Get the AMS_ENS210 poll interval * * @return The poll interval in ms */ int ens210_poll_interval(); /** Get the current firmware mode * * @return 1 application mode, 0 for boot mode, -1 for error */ int firmware_mode(); /** Set the operation mode \n * Notes: \n 1.\ When a sensor operating mode is changed to a new mode with\n * a lower sample rate (e.g.\ from SECOND to SIXTY_SECOND), it should be\n * placed in IDLE for at least 10 minutes before enabling the new mode.\ \n * When a sensor operating mode is changed to a new mode with a higher\n * sample rate (e.g.\ from SIXTY_SECOND to SECOND), there is no requirement\n * to wait before enabling the new mode.\ \n * 2.\ If this method fails, the state of the config register cannot be guaranteed.\ \n * Check errors and ensure all config settings are as expected. * * @param mode OP_MODES mode to set * * @return Write success */ bool mode(OP_MODES mode); /** Get the current power mode * * @return The current OP_MODES mode */ AMS_CCS811::OP_MODES mode(); /** Set the ADDR mode \n * * @param high True sets to high, false to low * * @return Write success */ bool addr_mode(bool high); /** Get the the ADDR mode * * @return The current ADDR mode, true for high, false for low */ bool addr_mode(); /** Set the ADDR pin * * @param pin Pin ADDR is attached to * * @return Write success */ bool addr_pin(PinName pin); /** Get the the ADDR pin * * @return The addr pin */ PinName addr_pin(); /** Set the nWAKE pin * * @param pin Pin nWAKE is attached to * * @return Write success */ bool n_wake_pin(PinName pin); /** Get the the nWAKE pin * * @return The nWAKE pin */ PinName n_wake_pin(); /** Set the relative humidity (%) and temperature (C).\ \n * Use when AMS ENS210 is not linked.\ \n * Humidity values are clipped between 0 and CCS811_MAX_HUMID.\ \n * Temperature values are clipped between -25 and CCS811_MAX_TEMP. * * @return Write success */ bool env_data(float humid, float temp); /** Get the sensor collection state * Use when interrupts are disabled. * * @return Current collection state, 1 for new data ready, 0 for data not ready and -1 for error */ int has_new_data(); /** Get the most recent CO2 measurement.\ \n * Must call has_new_data() first when when interupts are disabled otherwise the same data will be returned * * @return Most recent eCO2 measurement in ppm */ uint16_t co2_read(); /** Get the most recent TVOC measurement.\ \n * Must call has_new_data() first when when interupts are disabled otherwise the same data will be returned * * @return Most recent TVOC measurement in ppb */ uint16_t tvoc_read(); /** Get the most recent RAW data.\ \n * Must call has_new_data() first when NOT in CONSTANT mode and interupts are disabled otherwise the same data will be returned.\ \n * When in CONSTANT mode only this read method will return anything other than 0 or NULL.\ If 0 is returned, check for errors. * * @return Most recent RAW data */ uint16_t raw_read(); /** Get the most recent Tempurature(C) measurement from the ENS210 (if attached and enabled).\ \n * Will be at most as old as the ENS210 poll time * * @return Most recent Tempurature(C) measurement from the ENS210 */ float temp_read(); /** Get the most recent Relative Humidity(%) measurement from the ENS210 (if attached and enabled).\ \n * Will be at most as old as the ENS210 poll time * * @return Most recent Relative Humidity(%) measurement from the ENS210 */ float humid_read(); /** Get current error status * * @return True when error has occured, false when no error has occured */ bool error_status(); /** Get the latest errors. * * @return Latest errors. */ ccs811_errors errors(); /** Get the error string. * * @param err_code Error code to be translated * * @return Error String. */ const char * error_string(int err_code); /** Attach a function to be called when data is ready. * Calling this method enables interupts * * @param func_ptr A pointer to the function to be called * @param pin Pin attached to nINT * * @return Attach success */ bool attach(void (*func_ptr)(void), PinName pin) { _isr_data_fp.attach(func_ptr); interrupt_pin(pin); return enable_interupt(true); } /** Attach a member function to be called when data is ready. * Calling this method enables interupts * * @param type_ptr A pointer to the instance of the class * @param mem_ptr A pointer to the member function * @param pin Pin attached to nINT * * @return Attach success */ template<typename T> bool attach(T *type_ptr, void (T::*mem_ptr)(void), PinName pin) { _isr_data_fp.attach(callback(type_ptr, mem_ptr)); interrupt_pin(pin); return enable_interupt(true); } /** Set whether the data ready interupt is enabled.\ \n * Note: If this method fails, the state of the config register cannot be guaranteed.\ \n * Check errors and ensure all config settings are as expected. * * @param enabled True for enabled, false for disabled * * @return Write success */ bool enable_interupt(bool enable); /** Get whether the data ready interupt is enabled. * * * @return 1 for enabled, 0 for disabled, -1 for error */ int interupt_enabled(); /** Set the nINT pin * * @param pin Pin nINT is attached to * * @return Write success */ bool interrupt_pin(PinName pin); /** Get the the nINT pin * * @return The nINT pin */ PinName interrupt_pin(); private: I2C* _i2c; bool _addr_dir; int _slave_addr; void update_slave_addr(); AMS_ENS210 *_ens210; bool _ens210_enabled; int _ens210_poll_split; void update_ens210_timer(); Ticker _ens210_poll_t; void ens210_isr(); float temp_reading; float humid_reading; float fractions[9]; void _init_fractions(); void float_to_short(float in, char * output); OP_MODES _mode; void set_defaults(); bool _errors[CCS811_LIB_ERR_NUM]; int _error_count; char _error_strings[CCS811_TOTAL_ERR_NUM][255]; void _init_errors(); void clear_errors(); void new_error(int error_id); DigitalOut *_n_wake_out; DigitalOut *_addr_out; char _alg_result_data[8]; FunctionPointer _isr_data_fp; bool _int_data_enabled; InterruptIn *_int_data; void _isr_data(); bool write_config(); struct read_byte_result { bool success; uint8_t byte; read_byte_result() : success(false), byte(0) {} }; read_byte_result read_config(); read_byte_result read_status(); bool boot_app_start(); int i2c_read(char reg_addr, char* output, int len); int i2c_write(char reg_addr, char* input, int len); }; #endif /* AMS_CCS811_H */