simple CCS811 driver
Dependencies: AMS_ENS210_temp_humid_sensor
Dependents: TBSense2_Sensor_Demo
Fork of AMS_CCS811_gas_sensor by
AMS_CCS811.h
- Committer:
- UHSLMarcus
- Date:
- 2017-01-20
- Revision:
- 5:41e97348e9e7
- Parent:
- 4:a6b8881eae87
- Child:
- 6:22c0a7f2ece2
File content as of revision 5:41e97348e9e7:
/** * @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 "serialBuffer.h" using utils::SerialBuffer; extern SerialBuffer USBserialComms; /* 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 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 /* 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 6 #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 "Invaid 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 "Invaid slave read address" #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 * * @return Write success */ void i2c_interface(I2C * i2c); /** Set the ENS210 I2C interface * * @param i2c The I2C interface for an attached AMS_ENS210 * * @return Write success */ void 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 * Note: \n 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. * * @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) * Use when AMS ENS210 is not linked * * @return Write success */ bool env_data(float humid, float temp); /** Get the sensor collection state * Use when interupts 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. * 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. * 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. * 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 raw_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. * * @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; I2C* _ens210_i2c; bool _addr_dir; int _slave_addr; void update_slave_addr(); bool _ens210_enabled; int _ens210_poll_split; void update_ens210_timer(); Ticker _ens210_poll_t; void ens210_isr(); 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 */