Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: AMS_CCS811_gas_sensor/AMS_CCS811.h
- Revision:
- 10:525bcf8907fc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/AMS_CCS811_gas_sensor/AMS_CCS811.h Wed Jan 09 07:39:41 2019 +0000
@@ -0,0 +1,440 @@
+/**
+* @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 */
\ No newline at end of file