simple CCS811 driver

Dependencies:   AMS_ENS210_temp_humid_sensor

Dependents:   TBSense2_Sensor_Demo

Fork of AMS_CCS811_gas_sensor by Marcus Lee

Committer:
UHSLMarcus
Date:
Tue Jan 24 11:21:43 2017 +0000
Revision:
8:58a36d9218be
Parent:
7:5c95614a61ee
Child:
9:3f0733792717
added facility to query the current temp and humid measurement from an attached ENS210

Who changed what in which revision?

UserRevisionLine numberNew contents of line
UHSLMarcus 0:5edbf3550350 1
UHSLMarcus 2:e394671ef5f6 2 #include "AMS_CCS811.h"
UHSLMarcus 0:5edbf3550350 3
UHSLMarcus 0:5edbf3550350 4 AMS_CCS811::AMS_CCS811(I2C * i2c, PinName n_wake_pin) {
UHSLMarcus 5:41e97348e9e7 5 _n_wake_out = new (std::nothrow) DigitalOut(n_wake_pin, 1);
UHSLMarcus 4:a6b8881eae87 6 _i2c = i2c;
UHSLMarcus 0:5edbf3550350 7 }
UHSLMarcus 0:5edbf3550350 8
UHSLMarcus 0:5edbf3550350 9 AMS_CCS811::AMS_CCS811(I2C * i2c, PinName n_wake_pin, I2C * ens210_i2c) {
UHSLMarcus 5:41e97348e9e7 10 _n_wake_out = new (std::nothrow) DigitalOut(n_wake_pin, 1);
UHSLMarcus 0:5edbf3550350 11 _i2c = i2c;
UHSLMarcus 7:5c95614a61ee 12 ens210_i2c_interface(ens210_i2c);
UHSLMarcus 0:5edbf3550350 13 }
UHSLMarcus 0:5edbf3550350 14
UHSLMarcus 1:acfca1d3256d 15 AMS_CCS811::~AMS_CCS811() {
UHSLMarcus 1:acfca1d3256d 16 delete _n_wake_out;
UHSLMarcus 1:acfca1d3256d 17 delete _addr_out;
UHSLMarcus 1:acfca1d3256d 18 delete _int_data;
UHSLMarcus 7:5c95614a61ee 19 delete _ens210;
UHSLMarcus 1:acfca1d3256d 20 }
UHSLMarcus 1:acfca1d3256d 21
UHSLMarcus 1:acfca1d3256d 22 bool AMS_CCS811::init() {
UHSLMarcus 5:41e97348e9e7 23
UHSLMarcus 5:41e97348e9e7 24 bool success = false;
UHSLMarcus 5:41e97348e9e7 25
UHSLMarcus 5:41e97348e9e7 26 _init_errors();
UHSLMarcus 7:5c95614a61ee 27 _init_fractions();
UHSLMarcus 5:41e97348e9e7 28 set_defaults();
UHSLMarcus 5:41e97348e9e7 29
UHSLMarcus 8:58a36d9218be 30 temp_reading = 0;
UHSLMarcus 8:58a36d9218be 31 humid_reading = 0;
UHSLMarcus 8:58a36d9218be 32
UHSLMarcus 5:41e97348e9e7 33 if (_n_wake_out) {
UHSLMarcus 5:41e97348e9e7 34
UHSLMarcus 5:41e97348e9e7 35 int fw_mode = firmware_mode();
UHSLMarcus 5:41e97348e9e7 36
UHSLMarcus 5:41e97348e9e7 37 if (fw_mode == 1) {
UHSLMarcus 5:41e97348e9e7 38 enable_ens210(true);
UHSLMarcus 5:41e97348e9e7 39 success = write_config();
UHSLMarcus 5:41e97348e9e7 40
UHSLMarcus 5:41e97348e9e7 41 } else if (fw_mode == 0) { // is in boot mode, needs to be loaded into app mode
UHSLMarcus 5:41e97348e9e7 42 if (boot_app_start()) // if succesfully writes to app_start, retry init
UHSLMarcus 5:41e97348e9e7 43 init();
UHSLMarcus 5:41e97348e9e7 44 }
UHSLMarcus 5:41e97348e9e7 45 }
UHSLMarcus 5:41e97348e9e7 46 return success;
UHSLMarcus 4:a6b8881eae87 47 }
UHSLMarcus 4:a6b8881eae87 48
UHSLMarcus 4:a6b8881eae87 49 void AMS_CCS811::i2c_interface(I2C * i2c) {
UHSLMarcus 4:a6b8881eae87 50 _i2c = i2c;
UHSLMarcus 4:a6b8881eae87 51 }
UHSLMarcus 4:a6b8881eae87 52
UHSLMarcus 7:5c95614a61ee 53 bool AMS_CCS811::ens210_i2c_interface(I2C * i2c) {
UHSLMarcus 7:5c95614a61ee 54 bool success;
UHSLMarcus 7:5c95614a61ee 55 if (_ens210 == NULL) {
UHSLMarcus 7:5c95614a61ee 56 _ens210 = new (std::nothrow) AMS_ENS210(i2c, true, true);
UHSLMarcus 7:5c95614a61ee 57 if (_ens210 != NULL) {
UHSLMarcus 7:5c95614a61ee 58 if (_ens210->init()) {
UHSLMarcus 7:5c95614a61ee 59 success = _ens210->start();
UHSLMarcus 7:5c95614a61ee 60 }
UHSLMarcus 7:5c95614a61ee 61 }
UHSLMarcus 7:5c95614a61ee 62 } else {
UHSLMarcus 7:5c95614a61ee 63 _ens210->i2c_interface(i2c);
UHSLMarcus 7:5c95614a61ee 64 success = true;
UHSLMarcus 7:5c95614a61ee 65 }
UHSLMarcus 7:5c95614a61ee 66
UHSLMarcus 7:5c95614a61ee 67 if (!success) new_error(CCS811_LIB_ENS210_INIT_ID);
UHSLMarcus 7:5c95614a61ee 68
UHSLMarcus 7:5c95614a61ee 69 return success;
UHSLMarcus 4:a6b8881eae87 70 }
UHSLMarcus 4:a6b8881eae87 71
UHSLMarcus 4:a6b8881eae87 72 bool AMS_CCS811::enable_ens210(bool enable) {
UHSLMarcus 4:a6b8881eae87 73
UHSLMarcus 4:a6b8881eae87 74 _ens210_enabled = false;
UHSLMarcus 7:5c95614a61ee 75 if (_ens210 != NULL) {
UHSLMarcus 7:5c95614a61ee 76 if (_ens210->i2c_interface() != NULL) _ens210_enabled = enable;
UHSLMarcus 7:5c95614a61ee 77 }
UHSLMarcus 4:a6b8881eae87 78 update_ens210_timer();
UHSLMarcus 4:a6b8881eae87 79 return _ens210_enabled;
UHSLMarcus 4:a6b8881eae87 80 }
UHSLMarcus 4:a6b8881eae87 81
UHSLMarcus 4:a6b8881eae87 82 bool AMS_CCS811::ens210_is_enabled() {
UHSLMarcus 7:5c95614a61ee 83 enable_ens210(_ens210_enabled); // Make sure the state is representive
UHSLMarcus 4:a6b8881eae87 84 return _ens210_enabled;
UHSLMarcus 4:a6b8881eae87 85 }
UHSLMarcus 4:a6b8881eae87 86
UHSLMarcus 4:a6b8881eae87 87 void AMS_CCS811::ens210_poll_interval(int poll_ms) {
UHSLMarcus 4:a6b8881eae87 88 _ens210_poll_split = poll_ms;
UHSLMarcus 7:5c95614a61ee 89 enable_ens210(_ens210_enabled); // makes sure the state is representive, and will also update the timer
UHSLMarcus 4:a6b8881eae87 90 }
UHSLMarcus 4:a6b8881eae87 91
UHSLMarcus 4:a6b8881eae87 92 int AMS_CCS811::ens210_poll_interval() {
UHSLMarcus 4:a6b8881eae87 93 return _ens210_poll_split;
UHSLMarcus 1:acfca1d3256d 94 }
UHSLMarcus 1:acfca1d3256d 95
UHSLMarcus 5:41e97348e9e7 96 int AMS_CCS811::firmware_mode() {
UHSLMarcus 5:41e97348e9e7 97 int firmware_result = -1;
UHSLMarcus 5:41e97348e9e7 98
UHSLMarcus 6:22c0a7f2ece2 99 clear_errors();
UHSLMarcus 6:22c0a7f2ece2 100
UHSLMarcus 5:41e97348e9e7 101 read_byte_result read_result = read_status();
UHSLMarcus 5:41e97348e9e7 102 if (read_result.success) {
UHSLMarcus 5:41e97348e9e7 103 firmware_result = (read_result.byte >> 7) & 1;
UHSLMarcus 6:22c0a7f2ece2 104 }
UHSLMarcus 5:41e97348e9e7 105
UHSLMarcus 5:41e97348e9e7 106 return firmware_result;
UHSLMarcus 5:41e97348e9e7 107 }
UHSLMarcus 5:41e97348e9e7 108
UHSLMarcus 1:acfca1d3256d 109 bool AMS_CCS811::mode(OP_MODES mode) {
UHSLMarcus 6:22c0a7f2ece2 110 clear_errors();
UHSLMarcus 6:22c0a7f2ece2 111
UHSLMarcus 1:acfca1d3256d 112 OP_MODES old = _mode; // incase the write fails, to roll back
UHSLMarcus 1:acfca1d3256d 113 _mode = mode;
UHSLMarcus 1:acfca1d3256d 114
UHSLMarcus 1:acfca1d3256d 115 bool success = write_config();
UHSLMarcus 1:acfca1d3256d 116 if (!success)
UHSLMarcus 1:acfca1d3256d 117 _mode = old;
UHSLMarcus 1:acfca1d3256d 118
UHSLMarcus 1:acfca1d3256d 119 return success;
UHSLMarcus 1:acfca1d3256d 120 }
UHSLMarcus 1:acfca1d3256d 121
UHSLMarcus 1:acfca1d3256d 122 AMS_CCS811::OP_MODES AMS_CCS811::mode() {
UHSLMarcus 6:22c0a7f2ece2 123 clear_errors();
UHSLMarcus 6:22c0a7f2ece2 124
UHSLMarcus 5:41e97348e9e7 125 OP_MODES result = INVALID;
UHSLMarcus 1:acfca1d3256d 126
UHSLMarcus 5:41e97348e9e7 127 read_byte_result read_result = read_config();
UHSLMarcus 1:acfca1d3256d 128 if (read_result.success) {
UHSLMarcus 1:acfca1d3256d 129 int mode = (read_result.byte >> 4) & 0b111;
UHSLMarcus 2:e394671ef5f6 130 result = mode > 4 ? INVALID : (OP_MODES)mode;
UHSLMarcus 6:22c0a7f2ece2 131 }
UHSLMarcus 1:acfca1d3256d 132
UHSLMarcus 2:e394671ef5f6 133 return result;
UHSLMarcus 1:acfca1d3256d 134 }
UHSLMarcus 1:acfca1d3256d 135
UHSLMarcus 1:acfca1d3256d 136 bool AMS_CCS811::addr_mode(bool high) {
UHSLMarcus 1:acfca1d3256d 137 _addr_dir = high;
UHSLMarcus 5:41e97348e9e7 138 if (_addr_out != NULL) _addr_out->write(_addr_dir);
UHSLMarcus 1:acfca1d3256d 139
UHSLMarcus 2:e394671ef5f6 140 update_slave_addr();
UHSLMarcus 2:e394671ef5f6 141
UHSLMarcus 1:acfca1d3256d 142 return addr_mode() == high;
UHSLMarcus 1:acfca1d3256d 143 }
UHSLMarcus 1:acfca1d3256d 144
UHSLMarcus 1:acfca1d3256d 145 bool AMS_CCS811::addr_mode() {
UHSLMarcus 1:acfca1d3256d 146 if (_addr_out != NULL) {
UHSLMarcus 5:41e97348e9e7 147 _addr_dir = _addr_out->read();
UHSLMarcus 1:acfca1d3256d 148 }
UHSLMarcus 1:acfca1d3256d 149
UHSLMarcus 1:acfca1d3256d 150 return _addr_dir;
UHSLMarcus 1:acfca1d3256d 151 }
UHSLMarcus 1:acfca1d3256d 152
UHSLMarcus 1:acfca1d3256d 153 bool AMS_CCS811::addr_pin(PinName pin) {
UHSLMarcus 1:acfca1d3256d 154 _addr_out = _addr_out == NULL ? new (std::nothrow) DigitalOut(pin) : new (_addr_out) DigitalOut(pin);
UHSLMarcus 1:acfca1d3256d 155 addr_mode(_addr_dir);
UHSLMarcus 1:acfca1d3256d 156
UHSLMarcus 1:acfca1d3256d 157 return _addr_out != NULL;
UHSLMarcus 1:acfca1d3256d 158 }
UHSLMarcus 1:acfca1d3256d 159
UHSLMarcus 1:acfca1d3256d 160 bool AMS_CCS811::n_wake_pin(PinName pin) {
UHSLMarcus 1:acfca1d3256d 161 _n_wake_out = _n_wake_out == NULL ? new (std::nothrow) DigitalOut(pin) : new (_n_wake_out) DigitalOut(pin);
UHSLMarcus 1:acfca1d3256d 162 return _n_wake_out != NULL;
UHSLMarcus 1:acfca1d3256d 163 }
UHSLMarcus 1:acfca1d3256d 164
UHSLMarcus 2:e394671ef5f6 165 bool AMS_CCS811::env_data(float humid, float temp) {
UHSLMarcus 7:5c95614a61ee 166 char bytes[4];
UHSLMarcus 7:5c95614a61ee 167 if (humid > CCS811_MAX_HUMID) humid = CCS811_MAX_HUMID;
UHSLMarcus 7:5c95614a61ee 168 if (humid < 0) humid = 0;
UHSLMarcus 7:5c95614a61ee 169
UHSLMarcus 7:5c95614a61ee 170 temp += 25;
UHSLMarcus 7:5c95614a61ee 171 if (temp > CCS811_MAX_TEMP) humid = CCS811_MAX_TEMP;
UHSLMarcus 7:5c95614a61ee 172 if (temp < 0) temp = 0;
UHSLMarcus 7:5c95614a61ee 173
UHSLMarcus 7:5c95614a61ee 174 float_to_short(humid, bytes);
UHSLMarcus 7:5c95614a61ee 175 float_to_short(temp, bytes+2);
UHSLMarcus 7:5c95614a61ee 176
UHSLMarcus 7:5c95614a61ee 177 USBserialComms.printf("humid byte0: %s ", byte_to_binary(bytes[0]));
UHSLMarcus 7:5c95614a61ee 178 USBserialComms.printf("humid byte1: %s\r", byte_to_binary(bytes[1]));
UHSLMarcus 7:5c95614a61ee 179 USBserialComms.printf("temp byte0: %s ", byte_to_binary(bytes[2]));
UHSLMarcus 7:5c95614a61ee 180 USBserialComms.printf("temp byte1: %s\r", byte_to_binary(bytes[3]));
UHSLMarcus 7:5c95614a61ee 181
UHSLMarcus 7:5c95614a61ee 182 return i2c_write(ENV_DATA, bytes, 4) == 4;
UHSLMarcus 1:acfca1d3256d 183 }
UHSLMarcus 1:acfca1d3256d 184
UHSLMarcus 1:acfca1d3256d 185
UHSLMarcus 5:41e97348e9e7 186 int AMS_CCS811::has_new_data() {
UHSLMarcus 6:22c0a7f2ece2 187
UHSLMarcus 6:22c0a7f2ece2 188 clear_errors();
UHSLMarcus 6:22c0a7f2ece2 189
UHSLMarcus 5:41e97348e9e7 190 int result = -1;
UHSLMarcus 5:41e97348e9e7 191
UHSLMarcus 6:22c0a7f2ece2 192 char meas_mode[1];
UHSLMarcus 6:22c0a7f2ece2 193 if(i2c_read(MEAS_MODE, meas_mode, 1) == 1) { // one read here is quicker than calling read_config() twice
UHSLMarcus 6:22c0a7f2ece2 194
UHSLMarcus 6:22c0a7f2ece2 195 int curr_mode = (meas_mode[0] >> 4) & 0b111;
UHSLMarcus 6:22c0a7f2ece2 196 if (curr_mode < 5) {
UHSLMarcus 6:22c0a7f2ece2 197 if (curr_mode > 0) { // check for all valid modes other than idle
UHSLMarcus 6:22c0a7f2ece2 198 if (((meas_mode[0] >> 3) & 1) == 0) { // check if interrupts are disabled
UHSLMarcus 6:22c0a7f2ece2 199 char status[1];
UHSLMarcus 6:22c0a7f2ece2 200 if (i2c_read(STATUS, status, 1) == 1) // for some reason the status register in ALG_RESULT_DATA is not updated after reading data, however the STATUS register is
UHSLMarcus 6:22c0a7f2ece2 201 result = (status[0] >> 3) & 1;
UHSLMarcus 6:22c0a7f2ece2 202
UHSLMarcus 6:22c0a7f2ece2 203 } else result = 1;
UHSLMarcus 6:22c0a7f2ece2 204
UHSLMarcus 6:22c0a7f2ece2 205 if (result == 1)
UHSLMarcus 6:22c0a7f2ece2 206 if (i2c_read(ALG_RESULT_DATA, _alg_result_data, 8) != 8) result = -1;
UHSLMarcus 6:22c0a7f2ece2 207
UHSLMarcus 6:22c0a7f2ece2 208
UHSLMarcus 6:22c0a7f2ece2 209 } else result = 0; // return 0 when in idle
UHSLMarcus 6:22c0a7f2ece2 210 } else new_error(CCS811_LIB_INV_MODE_ID);
UHSLMarcus 5:41e97348e9e7 211 }
UHSLMarcus 5:41e97348e9e7 212
UHSLMarcus 5:41e97348e9e7 213 return result;
UHSLMarcus 1:acfca1d3256d 214 }
UHSLMarcus 1:acfca1d3256d 215
UHSLMarcus 1:acfca1d3256d 216 uint16_t AMS_CCS811::co2_read() {
UHSLMarcus 6:22c0a7f2ece2 217 return 0 | (_alg_result_data[0] << 8) | _alg_result_data[1];
UHSLMarcus 2:e394671ef5f6 218 }
UHSLMarcus 1:acfca1d3256d 219
UHSLMarcus 1:acfca1d3256d 220 uint16_t AMS_CCS811::tvoc_read() {
UHSLMarcus 6:22c0a7f2ece2 221 return 0 | (_alg_result_data[2] << 8) | _alg_result_data[3];
UHSLMarcus 1:acfca1d3256d 222 }
UHSLMarcus 1:acfca1d3256d 223
UHSLMarcus 1:acfca1d3256d 224 uint16_t AMS_CCS811::raw_read() {
UHSLMarcus 6:22c0a7f2ece2 225 return 0 | (_alg_result_data[6] << 8) | _alg_result_data[7];
UHSLMarcus 1:acfca1d3256d 226 }
UHSLMarcus 1:acfca1d3256d 227
UHSLMarcus 8:58a36d9218be 228 float AMS_CCS811::temp_read() {
UHSLMarcus 8:58a36d9218be 229 return temp_reading;
UHSLMarcus 8:58a36d9218be 230 }
UHSLMarcus 8:58a36d9218be 231
UHSLMarcus 8:58a36d9218be 232 float AMS_CCS811::humid_read() {
UHSLMarcus 8:58a36d9218be 233 return humid_reading;
UHSLMarcus 8:58a36d9218be 234 }
UHSLMarcus 8:58a36d9218be 235
UHSLMarcus 5:41e97348e9e7 236 bool AMS_CCS811::error_status() {
UHSLMarcus 5:41e97348e9e7 237 bool result = false;
UHSLMarcus 5:41e97348e9e7 238
UHSLMarcus 5:41e97348e9e7 239 read_byte_result read_result = read_status();
UHSLMarcus 5:41e97348e9e7 240 if (read_result.success) {
UHSLMarcus 5:41e97348e9e7 241 result = read_result.byte & 1;
UHSLMarcus 5:41e97348e9e7 242 }
UHSLMarcus 5:41e97348e9e7 243
UHSLMarcus 5:41e97348e9e7 244 result = result || (_error_count > 0);
UHSLMarcus 5:41e97348e9e7 245
UHSLMarcus 5:41e97348e9e7 246 return result;
UHSLMarcus 5:41e97348e9e7 247 }
UHSLMarcus 5:41e97348e9e7 248
UHSLMarcus 5:41e97348e9e7 249 AMS_CCS811::ccs811_errors AMS_CCS811::errors() {
UHSLMarcus 5:41e97348e9e7 250 ccs811_errors error_result;
UHSLMarcus 5:41e97348e9e7 251
UHSLMarcus 5:41e97348e9e7 252 char byte[1];
UHSLMarcus 5:41e97348e9e7 253 if (i2c_read(ERROR_ID, byte, 1) == 1) {
UHSLMarcus 5:41e97348e9e7 254 for(int i = 0; i < CCS811_ERR_NUM; i++) {
UHSLMarcus 5:41e97348e9e7 255 if ((byte[0] << i) & 1) {
UHSLMarcus 5:41e97348e9e7 256 error_result.codes[error_result.count++] = i;
UHSLMarcus 5:41e97348e9e7 257 }
UHSLMarcus 5:41e97348e9e7 258 }
UHSLMarcus 5:41e97348e9e7 259 }
UHSLMarcus 5:41e97348e9e7 260 for(int i = 0; i < CCS811_LIB_ERR_NUM; i++) {
UHSLMarcus 5:41e97348e9e7 261 if (_errors[i]) {
UHSLMarcus 5:41e97348e9e7 262 error_result.codes[error_result.count++] = i + CCS811_ERR_NUM;
UHSLMarcus 5:41e97348e9e7 263 }
UHSLMarcus 5:41e97348e9e7 264 }
UHSLMarcus 5:41e97348e9e7 265
UHSLMarcus 5:41e97348e9e7 266 return error_result;
UHSLMarcus 5:41e97348e9e7 267
UHSLMarcus 5:41e97348e9e7 268 }
UHSLMarcus 5:41e97348e9e7 269
UHSLMarcus 5:41e97348e9e7 270 const char * AMS_CCS811::error_string(int err_code){
UHSLMarcus 5:41e97348e9e7 271 static char result[255];
UHSLMarcus 5:41e97348e9e7 272 result[0] = 0;
UHSLMarcus 5:41e97348e9e7 273 if (err_code < CCS811_TOTAL_ERR_NUM && err_code > -1)
UHSLMarcus 5:41e97348e9e7 274 strcpy(result, _error_strings[err_code]);
UHSLMarcus 5:41e97348e9e7 275 else
UHSLMarcus 5:41e97348e9e7 276 sprintf(result, "Invalid Code: %d is out of range (0 - %d)", err_code, CCS811_TOTAL_ERR_NUM-1);
UHSLMarcus 5:41e97348e9e7 277
UHSLMarcus 5:41e97348e9e7 278 return result;
UHSLMarcus 1:acfca1d3256d 279 }
UHSLMarcus 1:acfca1d3256d 280
UHSLMarcus 1:acfca1d3256d 281 bool AMS_CCS811::enable_interupt(bool enable) {
UHSLMarcus 1:acfca1d3256d 282 bool old = _int_data_enabled; // incase the write fails, to roll back
UHSLMarcus 1:acfca1d3256d 283 _int_data_enabled = enable;
UHSLMarcus 1:acfca1d3256d 284
UHSLMarcus 1:acfca1d3256d 285 bool success = write_config();
UHSLMarcus 1:acfca1d3256d 286 if (!success)
UHSLMarcus 1:acfca1d3256d 287 _int_data_enabled = old;
UHSLMarcus 1:acfca1d3256d 288
UHSLMarcus 1:acfca1d3256d 289 return success;
UHSLMarcus 1:acfca1d3256d 290
UHSLMarcus 1:acfca1d3256d 291 }
UHSLMarcus 1:acfca1d3256d 292
UHSLMarcus 5:41e97348e9e7 293 int AMS_CCS811::interupt_enabled() {
UHSLMarcus 5:41e97348e9e7 294 int enabled = -1;
UHSLMarcus 1:acfca1d3256d 295
UHSLMarcus 5:41e97348e9e7 296 read_byte_result read_result = read_config();
UHSLMarcus 1:acfca1d3256d 297 if (read_result.success) {
UHSLMarcus 1:acfca1d3256d 298 enabled = (read_result.byte >> 3) & 1;
UHSLMarcus 6:22c0a7f2ece2 299 }
UHSLMarcus 1:acfca1d3256d 300
UHSLMarcus 2:e394671ef5f6 301 return enabled;
UHSLMarcus 1:acfca1d3256d 302 }
UHSLMarcus 1:acfca1d3256d 303
UHSLMarcus 1:acfca1d3256d 304 bool AMS_CCS811::interrupt_pin(PinName pin) {
UHSLMarcus 1:acfca1d3256d 305 bool success = false;
UHSLMarcus 1:acfca1d3256d 306
UHSLMarcus 2:e394671ef5f6 307 _int_data = _int_data == NULL ? new (std::nothrow) InterruptIn(pin) : new (_int_data) InterruptIn(pin);
UHSLMarcus 1:acfca1d3256d 308 if (_int_data != NULL) {
UHSLMarcus 2:e394671ef5f6 309 _int_data->fall(callback(this, &AMS_CCS811::_isr_data));
UHSLMarcus 1:acfca1d3256d 310 success = true;
UHSLMarcus 1:acfca1d3256d 311 }
UHSLMarcus 1:acfca1d3256d 312
UHSLMarcus 1:acfca1d3256d 313 return success;
UHSLMarcus 1:acfca1d3256d 314 }
UHSLMarcus 0:5edbf3550350 315
UHSLMarcus 0:5edbf3550350 316
UHSLMarcus 0:5edbf3550350 317
UHSLMarcus 1:acfca1d3256d 318
UHSLMarcus 1:acfca1d3256d 319 /** Private **/
UHSLMarcus 1:acfca1d3256d 320
UHSLMarcus 5:41e97348e9e7 321 void AMS_CCS811::set_defaults() {
UHSLMarcus 1:acfca1d3256d 322 if (_mode == NULL)
UHSLMarcus 1:acfca1d3256d 323 _mode = CONFIG_OP_MODE;
UHSLMarcus 1:acfca1d3256d 324 if (_addr_dir == NULL)
UHSLMarcus 1:acfca1d3256d 325 _addr_dir = CONFIG_ADDR_DIR;
UHSLMarcus 1:acfca1d3256d 326 if (_int_data_enabled == NULL)
UHSLMarcus 1:acfca1d3256d 327 _int_data_enabled = CONFIG_INTR;
UHSLMarcus 2:e394671ef5f6 328 if (_ens210_poll_split == NULL)
UHSLMarcus 2:e394671ef5f6 329 _ens210_poll_split = CONFIG_ENS210_POLL;
UHSLMarcus 2:e394671ef5f6 330
UHSLMarcus 5:41e97348e9e7 331 update_slave_addr();
UHSLMarcus 5:41e97348e9e7 332 }
UHSLMarcus 5:41e97348e9e7 333
UHSLMarcus 5:41e97348e9e7 334 void AMS_CCS811::_init_errors() {
UHSLMarcus 5:41e97348e9e7 335 clear_errors();
UHSLMarcus 5:41e97348e9e7 336 /* Sensor errors */
UHSLMarcus 5:41e97348e9e7 337 strcpy(_error_strings[0], CCS811_WRITE_REG_INVALID);
UHSLMarcus 5:41e97348e9e7 338 strcpy(_error_strings[1], CCS811_READ_REG_INVALID);
UHSLMarcus 5:41e97348e9e7 339 strcpy(_error_strings[2], CCS811_MEASMODE_INVALID);
UHSLMarcus 5:41e97348e9e7 340 strcpy(_error_strings[3], CCS811_MAX_RESISTANCE);
UHSLMarcus 5:41e97348e9e7 341 strcpy(_error_strings[4], CCS811_HEATER_FAULT);
UHSLMarcus 5:41e97348e9e7 342 strcpy(_error_strings[5], CCS811_HEATER_SUPPLY);
UHSLMarcus 5:41e97348e9e7 343 strcpy(_error_strings[6], CCS811_RESERVED);
UHSLMarcus 5:41e97348e9e7 344 strcpy(_error_strings[7], CCS811_RESERVED);
UHSLMarcus 5:41e97348e9e7 345 /* Library errors */
UHSLMarcus 5:41e97348e9e7 346 strcpy(_error_strings[CCS811_LIB_N_WAKE_ID+CCS811_ERR_NUM], CCS811_LIB_N_WAKE);
UHSLMarcus 5:41e97348e9e7 347 strcpy(_error_strings[CCS811_LIB_I2C_ID+CCS811_ERR_NUM], CCS811_LIB_I2C);
UHSLMarcus 5:41e97348e9e7 348 strcpy(_error_strings[CCS811_LIB_SLAVE_W_ID+CCS811_ERR_NUM], CCS811_LIB_SLAVE_W);
UHSLMarcus 5:41e97348e9e7 349 strcpy(_error_strings[CCS811_LIB_REG_ADDR_ID+CCS811_ERR_NUM], CCS811_LIB_REG_ADDR);
UHSLMarcus 5:41e97348e9e7 350 strcpy(_error_strings[CCS811_LIB_I2CWRITE_ID+CCS811_ERR_NUM], CCS811_LIB_I2CWRITE);
UHSLMarcus 5:41e97348e9e7 351 strcpy(_error_strings[CCS811_LIB_SLAVE_R_ID+CCS811_ERR_NUM], CCS811_LIB_SLAVE_R);
UHSLMarcus 6:22c0a7f2ece2 352 strcpy(_error_strings[CCS811_LIB_INV_MODE_ID+CCS811_ERR_NUM], CCS811_LIB_INV_MODE);
UHSLMarcus 7:5c95614a61ee 353 strcpy(_error_strings[CCS811_LIB_ENS210_INIT_ID+CCS811_ERR_NUM], CCS811_LIB_ENS210_INIT);
UHSLMarcus 5:41e97348e9e7 354 }
UHSLMarcus 5:41e97348e9e7 355
UHSLMarcus 5:41e97348e9e7 356 void AMS_CCS811::clear_errors() {
UHSLMarcus 5:41e97348e9e7 357 _error_count = 0;
UHSLMarcus 5:41e97348e9e7 358 for (int i = 0; i < CCS811_LIB_ERR_NUM; i++) {
UHSLMarcus 5:41e97348e9e7 359 _errors[i] = false;
UHSLMarcus 5:41e97348e9e7 360 }
UHSLMarcus 5:41e97348e9e7 361 }
UHSLMarcus 5:41e97348e9e7 362
UHSLMarcus 5:41e97348e9e7 363 void AMS_CCS811::new_error(int error_id) {
UHSLMarcus 5:41e97348e9e7 364 if (!_errors[error_id]) {
UHSLMarcus 5:41e97348e9e7 365 _errors[error_id] = true;
UHSLMarcus 5:41e97348e9e7 366 _error_count++;
UHSLMarcus 5:41e97348e9e7 367 }
UHSLMarcus 1:acfca1d3256d 368 }
UHSLMarcus 2:e394671ef5f6 369
UHSLMarcus 4:a6b8881eae87 370 void AMS_CCS811::update_ens210_timer() {
UHSLMarcus 4:a6b8881eae87 371 _ens210_poll_t.detach();
UHSLMarcus 4:a6b8881eae87 372 if (_ens210_enabled)
UHSLMarcus 4:a6b8881eae87 373 _ens210_poll_t.attach_us(callback(this, &AMS_CCS811::ens210_isr), _ens210_poll_split*1000);
UHSLMarcus 4:a6b8881eae87 374 }
UHSLMarcus 4:a6b8881eae87 375
UHSLMarcus 4:a6b8881eae87 376 void AMS_CCS811::ens210_isr() {
UHSLMarcus 8:58a36d9218be 377 temp_reading = ((float)_ens210->temp_read() / 64) - - 273.15;
UHSLMarcus 8:58a36d9218be 378 humid_reading = (float)_ens210->humid_read()/512;
UHSLMarcus 8:58a36d9218be 379 env_data(humid_reading, temp_reading);
UHSLMarcus 7:5c95614a61ee 380 }
UHSLMarcus 7:5c95614a61ee 381
UHSLMarcus 7:5c95614a61ee 382 void AMS_CCS811::_init_fractions() {
UHSLMarcus 7:5c95614a61ee 383
UHSLMarcus 7:5c95614a61ee 384 fractions[0] = 0.5;
UHSLMarcus 7:5c95614a61ee 385 fractions[1] = 0.25;
UHSLMarcus 7:5c95614a61ee 386 fractions[2] = 0.125;
UHSLMarcus 7:5c95614a61ee 387 fractions[3] = 0.0625;
UHSLMarcus 7:5c95614a61ee 388 fractions[4] = 0.03125;
UHSLMarcus 7:5c95614a61ee 389 fractions[5] = 0.015625;
UHSLMarcus 7:5c95614a61ee 390 fractions[6] = 0.0078125;
UHSLMarcus 7:5c95614a61ee 391 fractions[7] = 0.00390625;
UHSLMarcus 7:5c95614a61ee 392 fractions[8] = 0.001953125;
UHSLMarcus 7:5c95614a61ee 393
UHSLMarcus 7:5c95614a61ee 394 }
UHSLMarcus 7:5c95614a61ee 395
UHSLMarcus 7:5c95614a61ee 396 void AMS_CCS811::float_to_short(float in, char * output) {
UHSLMarcus 7:5c95614a61ee 397
UHSLMarcus 7:5c95614a61ee 398 uint8_t int_part = (uint8_t)in;
UHSLMarcus 7:5c95614a61ee 399 float dec_part = in - int_part;
UHSLMarcus 7:5c95614a61ee 400
UHSLMarcus 7:5c95614a61ee 401 uint16_t _short = 0;
UHSLMarcus 7:5c95614a61ee 402 for (int i = 0; i < 9; i++) {
UHSLMarcus 7:5c95614a61ee 403 if (dec_part == 0) break;
UHSLMarcus 7:5c95614a61ee 404 if (dec_part >= fractions[i]) {
UHSLMarcus 7:5c95614a61ee 405 dec_part -= fractions[i];
UHSLMarcus 7:5c95614a61ee 406 _short |= 256 >> i;
UHSLMarcus 7:5c95614a61ee 407 } else USBserialComms.printf("no\r");
UHSLMarcus 7:5c95614a61ee 408 }
UHSLMarcus 7:5c95614a61ee 409
UHSLMarcus 7:5c95614a61ee 410 _short |= int_part << 9;
UHSLMarcus 7:5c95614a61ee 411
UHSLMarcus 7:5c95614a61ee 412 output[0] = _short >> 8;
UHSLMarcus 7:5c95614a61ee 413 output[1] = _short;
UHSLMarcus 4:a6b8881eae87 414 }
UHSLMarcus 4:a6b8881eae87 415
UHSLMarcus 3:782a719f47a5 416 void AMS_CCS811::update_slave_addr() {
UHSLMarcus 5:41e97348e9e7 417 _slave_addr = addr_mode() ? CCS811_SLAVE_ADDR_RAW_H : CCS811_SLAVE_ADDR_RAW_L;
UHSLMarcus 2:e394671ef5f6 418 }
UHSLMarcus 1:acfca1d3256d 419
UHSLMarcus 1:acfca1d3256d 420 void AMS_CCS811::_isr_data() {
UHSLMarcus 6:22c0a7f2ece2 421 has_new_data(); // populate the data array
UHSLMarcus 3:782a719f47a5 422 _isr_data_fp.call();
UHSLMarcus 1:acfca1d3256d 423 }
UHSLMarcus 1:acfca1d3256d 424
UHSLMarcus 1:acfca1d3256d 425 bool AMS_CCS811::write_config() {
UHSLMarcus 3:782a719f47a5 426 char cmd[1] = {0 | (_int_data_enabled << 3) | (_mode << 4)};
UHSLMarcus 5:41e97348e9e7 427 return i2c_write(MEAS_MODE, cmd, 1) == 1;
UHSLMarcus 5:41e97348e9e7 428 }
UHSLMarcus 5:41e97348e9e7 429
UHSLMarcus 5:41e97348e9e7 430 AMS_CCS811::read_byte_result AMS_CCS811::read_config() {
UHSLMarcus 5:41e97348e9e7 431 read_byte_result result;
UHSLMarcus 5:41e97348e9e7 432 char byte[1];
UHSLMarcus 5:41e97348e9e7 433 if (i2c_read(MEAS_MODE, byte, 1) == 1) {
UHSLMarcus 5:41e97348e9e7 434 result.success = true;
UHSLMarcus 5:41e97348e9e7 435 result.byte = byte[0];
UHSLMarcus 5:41e97348e9e7 436 }
UHSLMarcus 5:41e97348e9e7 437 return result;
UHSLMarcus 1:acfca1d3256d 438 }
UHSLMarcus 1:acfca1d3256d 439
UHSLMarcus 5:41e97348e9e7 440 AMS_CCS811::read_byte_result AMS_CCS811::read_status() {
UHSLMarcus 5:41e97348e9e7 441 read_byte_result result;
UHSLMarcus 2:e394671ef5f6 442 char byte[1];
UHSLMarcus 5:41e97348e9e7 443 if (i2c_read(STATUS, byte, 1) == 1) {
UHSLMarcus 2:e394671ef5f6 444 result.success = true;
UHSLMarcus 5:41e97348e9e7 445 result.byte = byte[0];
UHSLMarcus 5:41e97348e9e7 446 }
UHSLMarcus 6:22c0a7f2ece2 447
UHSLMarcus 5:41e97348e9e7 448 return result;
UHSLMarcus 5:41e97348e9e7 449 }
UHSLMarcus 5:41e97348e9e7 450
UHSLMarcus 5:41e97348e9e7 451 bool AMS_CCS811::boot_app_start() {
UHSLMarcus 5:41e97348e9e7 452 bool success = false;
UHSLMarcus 5:41e97348e9e7 453
UHSLMarcus 5:41e97348e9e7 454 if (i2c_write(APP_START, NULL, 0) == 0) {
UHSLMarcus 5:41e97348e9e7 455 wait_ms(70);
UHSLMarcus 5:41e97348e9e7 456 success = true;
UHSLMarcus 2:e394671ef5f6 457 }
UHSLMarcus 2:e394671ef5f6 458
UHSLMarcus 5:41e97348e9e7 459 return success;
UHSLMarcus 2:e394671ef5f6 460 }
UHSLMarcus 2:e394671ef5f6 461
UHSLMarcus 2:e394671ef5f6 462 int AMS_CCS811::i2c_read(char reg_addr, char* output, int len) {
UHSLMarcus 2:e394671ef5f6 463
UHSLMarcus 2:e394671ef5f6 464 int read_count = 0;
UHSLMarcus 2:e394671ef5f6 465 if (_n_wake_out != NULL) { // check nWAKE pin is set
UHSLMarcus 5:41e97348e9e7 466 _n_wake_out->write(0); // Hold low
UHSLMarcus 5:41e97348e9e7 467 wait_us(CCS811_T_AWAKE); // tAWAKE time to allow sensor I2C to wake up
UHSLMarcus 2:e394671ef5f6 468 if (_i2c != NULL) { // check I2C interface is set
UHSLMarcus 2:e394671ef5f6 469 _i2c->start(); // send start condition for write
UHSLMarcus 5:41e97348e9e7 470 if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) { // write slave address with write bit
UHSLMarcus 2:e394671ef5f6 471 if(_i2c->write(reg_addr) == 1) { // write register address
UHSLMarcus 2:e394671ef5f6 472 _i2c->start(); // send another start condition for read
UHSLMarcus 5:41e97348e9e7 473 if(_i2c->write(CCS811_SLAVE_ADDR_R) == 1) { // write slave address with read bit
UHSLMarcus 2:e394671ef5f6 474 for (int i = 0; i < len; i++) { // read len bytes
UHSLMarcus 2:e394671ef5f6 475 output[i] = _i2c->read(i < len-1 ? 1 : 0); // ack all reads aside from the final one (i == len-1)
UHSLMarcus 2:e394671ef5f6 476 read_count++;
UHSLMarcus 2:e394671ef5f6 477 }
UHSLMarcus 5:41e97348e9e7 478 } else new_error(CCS811_LIB_SLAVE_R_ID);
UHSLMarcus 5:41e97348e9e7 479 } else new_error(CCS811_LIB_REG_ADDR_ID);
UHSLMarcus 5:41e97348e9e7 480 } else new_error(CCS811_LIB_SLAVE_W_ID);
UHSLMarcus 2:e394671ef5f6 481 _i2c->stop(); // send stop condition
UHSLMarcus 5:41e97348e9e7 482 } else new_error(CCS811_LIB_I2C_ID);
UHSLMarcus 5:41e97348e9e7 483 _n_wake_out->write(1); // Set back to high
UHSLMarcus 5:41e97348e9e7 484 wait_us(CCS811_T_DWAKE); // tDWAKE time to allow sensor I2C to sleep
UHSLMarcus 5:41e97348e9e7 485 } else new_error(CCS811_LIB_N_WAKE_ID);
UHSLMarcus 2:e394671ef5f6 486
UHSLMarcus 2:e394671ef5f6 487 return read_count;
UHSLMarcus 2:e394671ef5f6 488 }
UHSLMarcus 2:e394671ef5f6 489
UHSLMarcus 5:41e97348e9e7 490 int AMS_CCS811::i2c_write(char reg_addr, char* input, int len) {
UHSLMarcus 2:e394671ef5f6 491
UHSLMarcus 5:41e97348e9e7 492 int write_count = -1;
UHSLMarcus 2:e394671ef5f6 493 if (_n_wake_out != NULL) { // check nWAKE pin is set
UHSLMarcus 5:41e97348e9e7 494 _n_wake_out->write(0); // Hold low
UHSLMarcus 5:41e97348e9e7 495 wait_us(CCS811_T_AWAKE); // tAWAKE time to allow sensor I2C to wake up
UHSLMarcus 2:e394671ef5f6 496 if (_i2c != NULL) { // check I2C interface is set
UHSLMarcus 2:e394671ef5f6 497 _i2c->start(); // send start condition for write
UHSLMarcus 5:41e97348e9e7 498 if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) { // write slave address
UHSLMarcus 2:e394671ef5f6 499 if(_i2c->write(reg_addr) == 1) { // write register address
UHSLMarcus 5:41e97348e9e7 500 write_count = 0;
UHSLMarcus 2:e394671ef5f6 501 for (int i = 0; i < len; i++) { // write len bytes
UHSLMarcus 2:e394671ef5f6 502 if(_i2c->write(input[i]) == 1) write_count++; // write each byte, if successful increment count
UHSLMarcus 5:41e97348e9e7 503 else new_error(CCS811_LIB_I2CWRITE_ID);
UHSLMarcus 2:e394671ef5f6 504 }
UHSLMarcus 5:41e97348e9e7 505 } else new_error(CCS811_LIB_REG_ADDR_ID);
UHSLMarcus 5:41e97348e9e7 506 } else new_error(CCS811_LIB_SLAVE_W_ID);
UHSLMarcus 2:e394671ef5f6 507 _i2c->stop(); // send stop condition
UHSLMarcus 5:41e97348e9e7 508 } else new_error(CCS811_LIB_I2C_ID);
UHSLMarcus 5:41e97348e9e7 509 _n_wake_out->write(1); // set back to high
UHSLMarcus 5:41e97348e9e7 510 wait_us(CCS811_T_DWAKE); // tDWAKE time to allow sensor I2C to sleep
UHSLMarcus 5:41e97348e9e7 511 }else new_error(CCS811_LIB_N_WAKE_ID);
UHSLMarcus 2:e394671ef5f6 512
UHSLMarcus 2:e394671ef5f6 513 return write_count;
UHSLMarcus 1:acfca1d3256d 514 }