Library for the AMS CC811 digitial gas sensor
Dependencies: AMS_ENS210_temp_humid_sensor
AMS_CCS811.h
00001 /** 00002 * @author Marcus Lee 00003 * 00004 * @section DESCRIPTION 00005 * A library for the AMS CCS811 digital gas sensor. 00006 * 00007 */ 00008 #ifndef AMS_CCS811_H 00009 #define AMS_CCS811_H 00010 00011 #include "mbed.h" 00012 #include "AMS_ENS210.h" 00013 00014 /* Library defaults */ 00015 #define CONFIG_OP_MODE TEN_SECOND // Every 10 seconds 00016 #define CONFIG_INTR 0 // Interupt off 00017 #define CONFIG_ADDR_DIR 0 // ADDR n_wake_pin pulled low 00018 #define CONFIG_ENS210_POLL 3000 // ENS210 is polled every 3 seconds 00019 00020 /* Library Constants */ 00021 #define CCS811_SLAVE_ADDR_RAW_H 0x5B 00022 #define CCS811_SLAVE_ADDR_RAW_L 0x5A 00023 #define CCS811_SLAVE_ADDR_RAW _slave_addr 00024 #define CCS811_SLAVE_ADDR CCS811_SLAVE_ADDR_RAW << 1 00025 #define CCS811_SLAVE_ADDR_W CCS811_SLAVE_ADDR 00026 #define CCS811_SLAVE_ADDR_R CCS811_SLAVE_ADDR | 1 00027 00028 #define MEAS_MODE 0x01 00029 #define STATUS 0x00 00030 00031 #define ALG_RESULT_DATA 0x02 00032 #define RAW_DATA 0x03 00033 #define ENV_DATA 0x05 00034 #define ERROR_ID 0xE0 00035 00036 #define APP_START 0xF4 00037 00038 #define CCS811_T_AWAKE 55 // us - time taken for sensor I2C to become active 00039 #define CCS811_T_DWAKE 25 // us - time taken for sensor I2C to become inactive 00040 00041 #define CCS811_MAX_HUMID 127.998046875 // maxmium value that can be represented in the register 00042 #define CCS811_MAX_TEMP 102.998046875 // maxmium value that can be represented in the register 00043 00044 /* Error Codes */ 00045 #define CCS811_NO_ERROR "No Error"; 00046 /* Sensor Errors */ 00047 #define CCS811_ERR_NUM 8 00048 #define CCS811_WRITE_REG_INVALID "The CCS811 received an I2C write request addressed to this station but with invalid register address ID" 00049 #define CCS811_READ_REG_INVALID "The CCS811 received an I2C read request to a mailbox ID that is invalid" 00050 #define CCS811_MEASMODE_INVALID "The CCS811 received an I2C request to write an unsupported mode to MEAS_MODE" 00051 #define CCS811_MAX_RESISTANCE "The sensor resistance measurement has reached or exceeded the maximum range" 00052 #define CCS811_HEATER_FAULT "The Heater current in the CCS811 is not in range" 00053 #define CCS811_HEATER_SUPPLY "The Heater voltage is not being applied correctly" 00054 #define CCS811_RESERVED "Reserved for Future Use" 00055 /* Library Errors */ 00056 #define CCS811_LIB_ERR_NUM 9 00057 #define CCS811_LIB_N_WAKE_ID 0 00058 #define CCS811_LIB_N_WAKE "nWAKE pin not set" 00059 #define CCS811_LIB_I2C_ID 1 00060 #define CCS811_LIB_I2C "I2C interface is NULL" 00061 #define CCS811_LIB_SLAVE_W_ID 2 00062 #define CCS811_LIB_SLAVE_W "Failed to write slave write address" 00063 #define CCS811_LIB_REG_ADDR_ID 3 00064 #define CCS811_LIB_REG_ADDR "Failed to write register address" 00065 #define CCS811_LIB_I2CWRITE_ID 4 00066 #define CCS811_LIB_I2CWRITE "Failed to write byte" 00067 #define CCS811_LIB_SLAVE_R_ID 5 00068 #define CCS811_LIB_SLAVE_R "Failed to write slave read address" 00069 #define CCS811_LIB_INV_MODE_ID 6 00070 #define CCS811_LIB_INV_MODE "Invalid operation mode" 00071 #define CCS811_LIB_ENS210_INIT_ID 7 00072 #define CCS811_LIB_ENS210_INIT "Failed to create new AMS_ENS210 object" 00073 #define CCS811_LIB_ENS210_POLL_ID 7 00074 #define CCS811_LIB_ENS210_POLL "AMS_ENS210 poll error" 00075 00076 #define CCS811_TOTAL_ERR_NUM CCS811_ERR_NUM+CCS811_LIB_ERR_NUM 00077 00078 00079 /** The AMS CCS811 class 00080 */ 00081 class AMS_CCS811 00082 { 00083 public: 00084 /** Sensor operation modes. 00085 * 00086 */ 00087 enum OP_MODES { 00088 IDLE, /**< Measurements disabled */ 00089 SECOND, /**< Measurement every second */ 00090 TEN_SECOND, /**< Measurement every 10 seconds */ 00091 SIXTY_SECOND, /**< Measurement every 60 seconds */ 00092 CONSTANT, /**< Measurement every 250ms - Only raw data available */ 00093 INVALID /**< Invalid bit configuration/Error Occured */ 00094 }; 00095 00096 /** Holds error information. 00097 * 00098 */ 00099 struct ccs811_errors { 00100 int count; /**< Number of total errors */ 00101 int codes[CCS811_TOTAL_ERR_NUM]; /**< Array of active error codes */ 00102 00103 ccs811_errors() : count(0) {} 00104 }; 00105 00106 /** Create an AMS_CCS811 instance 00107 * 00108 * @param i2c The I2C interface to use for communication 00109 * @param n_wake_pin Pin nWAKE is attached to 00110 */ 00111 AMS_CCS811(I2C * i2c, PinName n_wake_pin); 00112 00113 /** Create an AMS_CCS811 instance 00114 * 00115 * @param i2c The I2C interface to use for communication 00116 * @param n_wake_pin Pin nWAKE is attached to 00117 * @param ens210_i2c The I2C interface for an attached AMS_ENS210 00118 */ 00119 AMS_CCS811(I2C * i2c, PinName n_wake_pin, I2C * ens210_i2c); 00120 00121 /** Destroy the AMS_CCS811 instance 00122 */ 00123 ~AMS_CCS811(); 00124 00125 /** Initalise the sensor 00126 * 00127 * @return Intalisation success 00128 */ 00129 bool init(); 00130 00131 /** Set the I2C interface 00132 * 00133 * @param i2c The I2C interface to use for communication 00134 * 00135 */ 00136 void i2c_interface(I2C * i2c); 00137 00138 /** Set the ENS210 I2C interface 00139 * 00140 * @param i2c The I2C interface for an attached AMS_ENS210 00141 * 00142 * @return Success 00143 */ 00144 bool ens210_i2c_interface(I2C * i2c); 00145 00146 /** Set whether the attached AMS_ENS210 is enabled. 00147 * If an I2C interface is not set for the ENS210, calling this method will have no effect. 00148 * 00149 * @param enabled True for enabled, false for disabled 00150 * 00151 * @return enabled True for enabled, false for disabled 00152 */ 00153 bool enable_ens210(bool enable); 00154 00155 /** Get whether the attached AMS_ENS210 is enabled. 00156 * 00157 * @return enabled True for enabled, false for disabled 00158 * 00159 */ 00160 bool ens210_is_enabled(); 00161 00162 /** Set the AMS_ENS210 poll interval 00163 * 00164 * @param poll_ms Poll interval in ms 00165 * 00166 */ 00167 void ens210_poll_interval(int poll_ms); 00168 00169 /** Get the AMS_ENS210 poll interval 00170 * 00171 * @return The poll interval in ms 00172 */ 00173 int ens210_poll_interval(); 00174 00175 /** Get the current firmware mode 00176 * 00177 * @return 1 application mode, 0 for boot mode, -1 for error 00178 */ 00179 int firmware_mode(); 00180 00181 /** Set the operation mode \n 00182 * Notes: \n 1.\ When a sensor operating mode is changed to a new mode with\n 00183 * a lower sample rate (e.g.\ from SECOND to SIXTY_SECOND), it should be\n 00184 * placed in IDLE for at least 10 minutes before enabling the new mode.\ \n 00185 * When a sensor operating mode is changed to a new mode with a higher\n 00186 * sample rate (e.g.\ from SIXTY_SECOND to SECOND), there is no requirement\n 00187 * to wait before enabling the new mode.\ \n 00188 * 2.\ If this method fails, the state of the config register cannot be guaranteed.\ \n 00189 * Check errors and ensure all config settings are as expected. 00190 * 00191 * @param mode OP_MODES mode to set 00192 * 00193 * @return Write success 00194 */ 00195 bool mode(OP_MODES mode); 00196 00197 /** Get the current power mode 00198 * 00199 * @return The current OP_MODES mode 00200 */ 00201 AMS_CCS811::OP_MODES mode(); 00202 00203 /** Set the ADDR mode \n 00204 * 00205 * @param high True sets to high, false to low 00206 * 00207 * @return Write success 00208 */ 00209 bool addr_mode(bool high); 00210 00211 /** Get the the ADDR mode 00212 * 00213 * @return The current ADDR mode, true for high, false for low 00214 */ 00215 bool addr_mode(); 00216 00217 /** Set the ADDR pin 00218 * 00219 * @param pin Pin ADDR is attached to 00220 * 00221 * @return Write success 00222 */ 00223 bool addr_pin(PinName pin); 00224 00225 /** Get the the ADDR pin 00226 * 00227 * @return The addr pin 00228 */ 00229 PinName addr_pin(); 00230 00231 /** Set the nWAKE pin 00232 * 00233 * @param pin Pin nWAKE is attached to 00234 * 00235 * @return Write success 00236 */ 00237 bool n_wake_pin(PinName pin); 00238 00239 /** Get the the nWAKE pin 00240 * 00241 * @return The nWAKE pin 00242 */ 00243 PinName n_wake_pin(); 00244 00245 /** Set the relative humidity (%) and temperature (C).\ \n 00246 * Use when AMS ENS210 is not linked.\ \n 00247 * Humidity values are clipped between 0 and CCS811_MAX_HUMID.\ \n 00248 * Temperature values are clipped between -25 and CCS811_MAX_TEMP. 00249 * 00250 * @return Write success 00251 */ 00252 bool env_data(float humid, float temp); 00253 00254 /** Get the sensor collection state 00255 * Use when interrupts are disabled. 00256 * 00257 * @return Current collection state, 1 for new data ready, 0 for data not ready and -1 for error 00258 */ 00259 int has_new_data(); 00260 00261 /** Get the most recent CO2 measurement.\ \n 00262 * Must call has_new_data() first when when interupts are disabled otherwise the same data will be returned 00263 * 00264 * @return Most recent eCO2 measurement in ppm 00265 */ 00266 uint16_t co2_read(); 00267 00268 /** Get the most recent TVOC measurement.\ \n 00269 * Must call has_new_data() first when when interupts are disabled otherwise the same data will be returned 00270 * 00271 * @return Most recent TVOC measurement in ppb 00272 */ 00273 uint16_t tvoc_read(); 00274 00275 /** Get the most recent RAW data.\ \n 00276 * Must call has_new_data() first when NOT in CONSTANT mode and interupts are disabled otherwise the same data will be returned.\ \n 00277 * When in CONSTANT mode only this read method will return anything other than 0 or NULL.\ If 0 is returned, check for errors. 00278 * 00279 * @return Most recent RAW data 00280 */ 00281 uint16_t raw_read(); 00282 00283 /** Get the most recent Tempurature(C) measurement from the ENS210 (if attached and enabled).\ \n 00284 * Will be at most as old as the ENS210 poll time 00285 * 00286 * @return Most recent Tempurature(C) measurement from the ENS210 00287 */ 00288 float temp_read(); 00289 00290 /** Get the most recent Relative Humidity(%) measurement from the ENS210 (if attached and enabled).\ \n 00291 * Will be at most as old as the ENS210 poll time 00292 * 00293 * @return Most recent Relative Humidity(%) measurement from the ENS210 00294 */ 00295 float humid_read(); 00296 00297 /** Get current error status 00298 * 00299 * @return True when error has occured, false when no error has occured 00300 */ 00301 bool error_status(); 00302 00303 /** Get the latest errors. 00304 * 00305 * @return Latest errors. 00306 */ 00307 ccs811_errors errors(); 00308 00309 /** Get the error string. 00310 * 00311 * @param err_code Error code to be translated 00312 * 00313 * @return Error String. 00314 */ 00315 const char * error_string(int err_code); 00316 00317 /** Attach a function to be called when data is ready. 00318 * Calling this method enables interupts 00319 * 00320 * @param func_ptr A pointer to the function to be called 00321 * @param pin Pin attached to nINT 00322 * 00323 * @return Attach success 00324 */ 00325 bool attach(void (*func_ptr)(void), PinName pin) { 00326 _isr_data_fp.attach(func_ptr); 00327 interrupt_pin(pin); 00328 return enable_interupt(true); 00329 } 00330 00331 /** Attach a member function to be called when data is ready. 00332 * Calling this method enables interupts 00333 * 00334 * @param type_ptr A pointer to the instance of the class 00335 * @param mem_ptr A pointer to the member function 00336 * @param pin Pin attached to nINT 00337 * 00338 * @return Attach success 00339 */ 00340 template<typename T> 00341 bool attach(T *type_ptr, void (T::*mem_ptr)(void), PinName pin) { 00342 _isr_data_fp.attach(callback(type_ptr, mem_ptr)); 00343 interrupt_pin(pin); 00344 return enable_interupt(true); 00345 } 00346 00347 /** Set whether the data ready interupt is enabled.\ \n 00348 * Note: If this method fails, the state of the config register cannot be guaranteed.\ \n 00349 * Check errors and ensure all config settings are as expected. 00350 * 00351 * @param enabled True for enabled, false for disabled 00352 * 00353 * @return Write success 00354 */ 00355 bool enable_interupt(bool enable); 00356 00357 /** Get whether the data ready interupt is enabled. 00358 * 00359 * 00360 * @return 1 for enabled, 0 for disabled, -1 for error 00361 */ 00362 int interupt_enabled(); 00363 00364 /** Set the nINT pin 00365 * 00366 * @param pin Pin nINT is attached to 00367 * 00368 * @return Write success 00369 */ 00370 bool interrupt_pin(PinName pin); 00371 00372 /** Get the the nINT pin 00373 * 00374 * @return The nINT pin 00375 */ 00376 PinName interrupt_pin(); 00377 00378 00379 00380 00381 private: 00382 I2C* _i2c; 00383 00384 bool _addr_dir; 00385 int _slave_addr; 00386 void update_slave_addr(); 00387 00388 AMS_ENS210 *_ens210; 00389 bool _ens210_enabled; 00390 int _ens210_poll_split; 00391 void update_ens210_timer(); 00392 Ticker _ens210_poll_t; 00393 void ens210_isr(); 00394 float temp_reading; 00395 float humid_reading; 00396 00397 float fractions[9]; 00398 void _init_fractions(); 00399 void float_to_short(float in, char * output); 00400 00401 OP_MODES _mode; 00402 00403 void set_defaults(); 00404 00405 bool _errors[CCS811_LIB_ERR_NUM]; 00406 int _error_count; 00407 char _error_strings[CCS811_TOTAL_ERR_NUM][255]; 00408 void _init_errors(); 00409 void clear_errors(); 00410 void new_error(int error_id); 00411 00412 DigitalOut *_n_wake_out; 00413 DigitalOut *_addr_out; 00414 00415 char _alg_result_data[8]; 00416 00417 FunctionPointer _isr_data_fp; 00418 bool _int_data_enabled; 00419 InterruptIn *_int_data; 00420 void _isr_data(); 00421 00422 bool write_config(); 00423 00424 struct read_byte_result { 00425 bool success; 00426 uint8_t byte; 00427 read_byte_result() : success(false), byte(0) {} 00428 }; 00429 read_byte_result read_config(); 00430 read_byte_result read_status(); 00431 00432 bool boot_app_start(); 00433 00434 int i2c_read(char reg_addr, char* output, int len); 00435 int i2c_write(char reg_addr, char* input, int len); 00436 00437 }; 00438 00439 00440 #endif /* AMS_CCS811_H */
Generated on Wed Jul 13 2022 07:08:22 by
![doxygen](doxygen.png)