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.
Dependents: ECE4180FinalProjectFall22
ens160_i2c.cpp
00001 #include "ens160_i2c.h" 00002 00003 ENS160::ENS160(PinName sda, PinName scl, uint8_t i2c_device_address) 00004 :i2c(sda, scl) 00005 { 00006 this->i2c_address = i2c_device_address; 00007 } 00008 00009 int32_t ENS160::readRegisterRegion(uint8_t reg, char *data) 00010 { 00011 uint8_t retVal; 00012 char temp[1] = {reg}; 00013 char tempVal[1] = {0xFF}; 00014 this->i2c.write(this->i2c_address, temp, 1); 00015 wait(0.01); 00016 retVal = this->i2c.read(this->i2c_address, tempVal, 1); 00017 wait(0.01); 00018 data[0] = tempVal[0]; 00019 if (retVal != 0) 00020 return -1; 00021 return 0; 00022 } 00023 00024 int32_t ENS160::readRegisterRegion(uint8_t reg, char *data, uint8_t length) 00025 { 00026 int i; 00027 int32_t retVal; 00028 char temp_dest[length]; 00029 for (i=0; i < length; i++) 00030 { 00031 temp_dest[i] = 0xFF; 00032 } 00033 char temp[1] = {reg}; 00034 this->i2c.write(this->i2c_address, temp, 1); 00035 wait(0.01); 00036 retVal = this->i2c.read(this->i2c_address, temp_dest, length); 00037 wait(0.01); 00038 for (i=0; i < length; i++) 00039 { 00040 data[i] = temp_dest[i]; 00041 } 00042 if (retVal !=0) 00043 return -1; 00044 return 0; 00045 } 00046 00047 int32_t ENS160::writeRegisterRegion(char *data, uint8_t length) 00048 { 00049 int32_t retVal; 00050 retVal = this->i2c.write(this->i2c_address, data, length); 00051 wait(0.01); 00052 if(retVal !=0) 00053 return -1; 00054 return 0; 00055 } 00056 00057 int32_t ENS160::writeRegisterRegion(uint8_t reg, char data) 00058 { 00059 int32_t retVal; 00060 char temp_data[2] = {reg, data}; 00061 retVal = this->i2c.write(this->i2c_address, temp_data, 2); 00062 wait(0.01); 00063 if (retVal != 0) 00064 return -1; 00065 return 0; 00066 } 00067 00068 ////////////////////////////////////////////////////////////////////////////// 00069 // getUniqueID() 00070 // Gets the device's unique ID 00071 uint16_t ENS160::getUniqueID() 00072 { 00073 int32_t retVal; 00074 char tempVal[2] = {0}; 00075 uint16_t id; 00076 00077 retVal = this->readRegisterRegion(SFE_ENS160_PART_ID, tempVal, 2); 00078 00079 id = tempVal[0]; 00080 id |= tempVal[1] << 8; 00081 00082 if( retVal != 0 ) 00083 return 0; 00084 00085 return id; 00086 } 00087 00088 /////////////////////////////////////////////////////////////////////// 00089 // isConnected() 00090 // Parameter Description 00091 // --------- ----------------------------- 00092 // retVal true if device is connected, false if not connected 00093 00094 bool ENS160::isConnected() 00095 { 00096 uint16_t uniqueID; 00097 uniqueID = getUniqueID(); 00098 if( uniqueID != ENS160_DEVICE_ID ) 00099 return false; 00100 return true; 00101 } 00102 00103 bool ENS160::init() 00104 { 00105 return this->isConnected(); 00106 } 00107 00108 ////////////////////////////////////////////////////////////////////////////// 00109 // setOperatingMode() 00110 // Sets the operating mode: Deep Sleep (0x00), Idle (0x01), Standard (0x02), Reset (0xF0) 00111 // 00112 // Parameter Description 00113 // --------- ----------------------------- 00114 // val The desired operating mode to set. 00115 bool ENS160::setOperatingMode(uint8_t val) 00116 { 00117 int32_t retVal; 00118 00119 if( val > SFE_ENS160_RESET ) 00120 return false; 00121 00122 retVal = this->writeRegisterRegion(SFE_ENS160_OP_MODE, val); 00123 00124 if( retVal != 0 ) 00125 return false; 00126 00127 return true; 00128 } 00129 00130 ////////////////////////////////////////////////////////////////////////////// 00131 // getOperatingMode() 00132 // 00133 // Gets the current operating mode: Deep Sleep (0x00), Idle (0x01), Standard (0x02), Reset (0xF0) 00134 00135 int8_t ENS160::getOperatingMode() 00136 { 00137 int32_t retVal; 00138 char tempVal[1] = {0x00}; 00139 00140 retVal = this->readRegisterRegion(SFE_ENS160_OP_MODE, tempVal); 00141 00142 if( retVal != 0 ) 00143 return -1; 00144 00145 return tempVal[0]; 00146 } 00147 00148 ////////////////////////////////////////////////////////////////////////////// 00149 // configureInterrupt() 00150 // 00151 // Changes all of the settings within the interrupt configuration register. 00152 // 00153 // Parameter Description 00154 // --------- ----------------------------- 00155 // val The desired configuration settings. 00156 00157 bool ENS160::configureInterrupt(uint8_t val) 00158 { 00159 int32_t retVal; 00160 00161 retVal = this->writeRegisterRegion(SFE_ENS160_CONFIG, val); 00162 00163 if( retVal != 0 ) 00164 return false; 00165 00166 return true; 00167 } 00168 00169 00170 ////////////////////////////////////////////////////////////////////////////// 00171 // setInterrupt() 00172 // 00173 // Enables the interrupt. 00174 // 00175 // Parameter Description 00176 // --------- ----------------------------- 00177 // enable Turns on or off the interrupt. 00178 00179 bool ENS160::enableInterrupt(bool enable) 00180 { 00181 int32_t retVal; 00182 char tempVal[1] = {0x00}; 00183 00184 retVal = this->readRegisterRegion(SFE_ENS160_CONFIG, tempVal); 00185 00186 if( retVal != 0 ) 00187 return false; 00188 00189 tempVal[0] = (tempVal[0] | (uint8_t)enable); 00190 00191 retVal = this->writeRegisterRegion(SFE_ENS160_CONFIG, tempVal[0]); 00192 00193 if( retVal != 0 ) 00194 return false; 00195 00196 return true; 00197 } 00198 00199 ////////////////////////////////////////////////////////////////////////////// 00200 // setInterruptPolarity() 00201 // 00202 // Changes the polarity of the interrupt: active high or active low. By default 00203 // this value is set to zero or active low. 00204 // 00205 // Parameter Description 00206 // --------- ----------------------------- 00207 // activeHigh Changes active state of interrupt from high to low. 00208 00209 bool ENS160::setInterruptPolarity(bool activeHigh) 00210 { 00211 int32_t retVal; 00212 char tempVal[1] = {0x00}; 00213 00214 retVal = this->readRegisterRegion(SFE_ENS160_CONFIG, tempVal); 00215 00216 if( retVal != 0 ) 00217 return false; 00218 00219 tempVal[0] = (tempVal[0] | (activeHigh << 6)); 00220 00221 retVal = this->writeRegisterRegion(SFE_ENS160_CONFIG, tempVal[0]); 00222 00223 if( retVal != 0 ) 00224 return false; 00225 00226 return true; 00227 } 00228 00229 ////////////////////////////////////////////////////////////////////////////// 00230 // getInterruptPolarity() 00231 // 00232 // Retrieves the polarity of the physical interrupt. 00233 00234 int8_t ENS160::getInterruptPolarity() 00235 { 00236 int32_t retVal; 00237 char tempVal[1] = {0x00}; 00238 00239 retVal = this->readRegisterRegion(SFE_ENS160_CONFIG, tempVal); 00240 00241 if( retVal != 0 ) 00242 return -1; 00243 00244 tempVal[0] &= 0x40; 00245 00246 return (tempVal[0] >> 6); 00247 } 00248 00249 ////////////////////////////////////////////////////////////////////////////// 00250 // setInterruptDrive() 00251 // 00252 // Changes the pin drive of the interrupt: open drain (default) to push/pull 00253 // 00254 // Parameter Description 00255 // --------- ----------------------------- 00256 // pushPull Changes the drive of the pin. 00257 00258 bool ENS160::setInterruptDrive(bool pushPull) 00259 { 00260 int32_t retVal; 00261 char tempVal[1] = {0x00}; 00262 00263 retVal = this->readRegisterRegion(SFE_ENS160_CONFIG, tempVal); 00264 00265 if( retVal != 0 ) 00266 return false; 00267 00268 tempVal[0] = (tempVal[0] | (uint8_t)(pushPull << 5)); 00269 00270 retVal = this->writeRegisterRegion(SFE_ENS160_CONFIG, tempVal[0]); 00271 00272 if( retVal != 0 ) 00273 return false; 00274 00275 return true; 00276 } 00277 00278 00279 ////////////////////////////////////////////////////////////////////////////// 00280 // setDataInterrupt() 00281 // 00282 // Routes the data ready signal to the interrupt pin. 00283 // 00284 // Parameter Description 00285 // --------- ----------------------------- 00286 // enable Self-explanatory: enables or disables data ready on interrupt. 00287 00288 bool ENS160::setDataInterrupt(bool enable) 00289 { 00290 int32_t retVal; 00291 char tempVal[1] = {0x00}; 00292 00293 retVal = this->readRegisterRegion(SFE_ENS160_CONFIG, tempVal); 00294 00295 if( retVal != 0 ) 00296 return false; 00297 00298 tempVal[0] = (tempVal[0] | (uint8_t)(enable << 1)); 00299 00300 retVal = this->writeRegisterRegion(SFE_ENS160_CONFIG, tempVal[0]); 00301 00302 if( retVal != 0 ) 00303 return false; 00304 00305 return true; 00306 } 00307 00308 00309 ////////////////////////////////////////////////////////////////////////////// 00310 // setGPRInterrupt() 00311 // 00312 // Routes the general purporse read register signal to the interrupt pin. 00313 // 00314 // Parameter Description 00315 // --------- ----------------------------- 00316 // enable Self-explanatory: enables or disables general purpos read interrupt. 00317 00318 bool ENS160::setGPRInterrupt(bool enable) 00319 { 00320 int32_t retVal; 00321 char tempVal[1] = {0x00}; 00322 00323 retVal = this->readRegisterRegion(SFE_ENS160_CONFIG, tempVal); 00324 00325 if( retVal != 0 ) 00326 return false; 00327 00328 tempVal[0] = (tempVal[0] | (uint8_t)(enable << 3)); 00329 00330 retVal = this->writeRegisterRegion(SFE_ENS160_CONFIG, tempVal[0]); 00331 00332 if( retVal != 0 ) 00333 return false; 00334 00335 return true; 00336 } 00337 00338 00339 ////////////////////////////////////////////////////////////////////////////// 00340 // getAppVer() 00341 // 00342 // Retrieves the 24 bit application version of the device. 00343 00344 uint32_t ENS160::getAppVer() 00345 { 00346 int32_t retVal; 00347 char tempVal[3] = {0}; 00348 uint32_t version; 00349 00350 retVal = this->readRegisterRegion(SFE_ENS160_GPR_READ4, tempVal, 3); 00351 00352 if( retVal != 0 ) 00353 return 0; 00354 00355 version = tempVal[0]; 00356 version |= tempVal[1] << 8; 00357 version |= tempVal[2] << 16; 00358 00359 return version; 00360 } 00361 00362 ////////////////////////////////////////////////////////////////////////////// 00363 // setTempCompensation() 00364 // 00365 // The ENS160 can use temperature data to help give more accurate sensor data. 00366 // 00367 // Parameter Description 00368 // --------- ----------------------------- 00369 // kelvinConversion The given temperature in Kelvin 00370 00371 bool ENS160::setTempCompensation(float tempKelvin) 00372 { 00373 int32_t retVal; 00374 char tempVal[3] = {0}; 00375 uint16_t kelvinConversion = tempKelvin; 00376 00377 kelvinConversion = kelvinConversion * 64; // convert value - fixed equation pg. 29 of datasheet 00378 tempVal[0] = SFE_ENS160_TEMP_IN; 00379 tempVal[1] = (kelvinConversion & 0x00FF); 00380 tempVal[2] = (kelvinConversion & 0xFF00) >> 8; 00381 00382 retVal = this->writeRegisterRegion(tempVal, 3); 00383 00384 if( retVal != 0 ) 00385 return false; 00386 00387 return true; 00388 } 00389 00390 00391 ////////////////////////////////////////////////////////////////////////////// 00392 // setTempCompensationCelsius() 00393 // 00394 // The ENS160 can use temperature data to help give more accurate sensor data. 00395 // 00396 // Parameter Description 00397 // --------- ----------------------------- 00398 // tempCelsius The given temperature in Celsius 00399 00400 bool ENS160::setTempCompensationCelsius(float tempCelsius) 00401 { 00402 float kelvinConversion = tempCelsius + 273.15; 00403 00404 if( setTempCompensation(kelvinConversion) ) 00405 return true; 00406 00407 return false; 00408 } 00409 00410 00411 ////////////////////////////////////////////////////////////////////////////// 00412 // setRHCompensation() 00413 // 00414 // The ENS160 can use relative Humidiy data to help give more accurate sensor data. 00415 // 00416 // Parameter Description 00417 // --------- ----------------------------- 00418 // humidity The given relative humidity. 00419 00420 bool ENS160::setRHCompensation(uint16_t humidity) 00421 { 00422 int32_t retVal; 00423 char tempVal[3] = {0}; 00424 00425 humidity = humidity * 512; // convert value - fixed equation pg. 29 in datasheet. 00426 tempVal[0] = SFE_ENS160_RH_IN; 00427 tempVal[1] = (humidity & 0x00FF); 00428 tempVal[2] = (humidity & 0xFF00) >> 8; 00429 00430 retVal = this->writeRegisterRegion(tempVal, 3); 00431 00432 if( retVal != 0 ) 00433 return false; 00434 00435 return true; 00436 } 00437 00438 ////////////////////////////////////////////////////////////////////////////// 00439 // setRHCompensationFloat() 00440 // 00441 // The ENS160 can use relative Humidiy data to help give more accurate sensor data. 00442 // 00443 // Parameter Description 00444 // --------- ----------------------------- 00445 // humidity The given relative humidity. 00446 00447 bool ENS160::setRHCompensationFloat(float humidity) 00448 { 00449 uint16_t humidityConversion = (uint16_t)humidity; 00450 00451 if( setRHCompensation(humidityConversion) ) 00452 return false; 00453 00454 return true; 00455 } 00456 00457 ////////////////////////////////////////////////////////////////////////////// 00458 // checkDataStatus() 00459 // 00460 // This checks the if the NEWDAT bit is high indicating that new data is ready to be read. 00461 // The bit is cleared when data has been read from their registers. 00462 00463 bool ENS160::checkDataStatus() 00464 { 00465 int32_t retVal; 00466 char tempVal[1] = {0x00}; 00467 00468 retVal = this->readRegisterRegion(SFE_ENS160_DEVICE_STATUS, tempVal); 00469 00470 if( retVal != 0 ) 00471 return false; 00472 00473 tempVal[0] &= 0x02; 00474 00475 if( tempVal[0] == 0x02 ) 00476 return true; 00477 00478 return false; 00479 } 00480 00481 00482 ////////////////////////////////////////////////////////////////////////////// 00483 // checkGPRStatus() 00484 // 00485 // This checks the if the NEWGPR bit is high indicating that there is data in the 00486 // general purpose read registers. The bit is cleared the relevant registers have been 00487 // read. 00488 00489 bool ENS160::checkGPRStatus() 00490 { 00491 int32_t retVal; 00492 char tempVal[1] = {0x00}; 00493 00494 retVal = this->readRegisterRegion(SFE_ENS160_DEVICE_STATUS, tempVal); 00495 00496 if( retVal != 0 ) 00497 return false; 00498 00499 tempVal[0] &= 0x01; 00500 00501 if( tempVal[0] == 0x01 ) 00502 return true; 00503 00504 return false; 00505 } 00506 00507 00508 ////////////////////////////////////////////////////////////////////////////// 00509 // getFlags() 00510 // 00511 // This checks the status "flags" of the device (0-3). 00512 00513 uint8_t ENS160::getFlags() 00514 { 00515 int32_t retVal; 00516 char tempVal[1] = {0x00}; 00517 00518 retVal = this->readRegisterRegion(SFE_ENS160_DEVICE_STATUS, tempVal); 00519 00520 if( retVal != 0 ) 00521 return 0xFF; // Change to general error 00522 00523 tempVal[0] = (tempVal[0] & 0x0C) >> 2; 00524 00525 switch( tempVal[0] ) 00526 { 00527 case 0: // Normal operation 00528 return 0; 00529 case 1: // Warm-up phase 00530 return 1; 00531 case 2: // Initial Start-Up Phase 00532 return 2; 00533 case 3: // Invalid Output 00534 return 3; 00535 default: 00536 return 0xFF; 00537 } 00538 } 00539 00540 00541 00542 ////////////////////////////////////////////////////////////////////////////// 00543 // checkOperationStatus() 00544 // 00545 // Checks the bit that indicates if an operation mode is running i.e. the device is not off. 00546 00547 bool ENS160::checkOperationStatus() 00548 { 00549 int32_t retVal; 00550 char tempVal[1] = {0x00}; 00551 00552 retVal = this->readRegisterRegion(SFE_ENS160_DEVICE_STATUS, tempVal); 00553 00554 if( retVal != 0 ) 00555 return false; 00556 00557 tempVal[0] &= 0x80; 00558 00559 if( tempVal[0] == 0x80 ) 00560 return true; 00561 00562 return false; 00563 } 00564 00565 00566 ////////////////////////////////////////////////////////////////////////////// 00567 // getOperationError() 00568 // 00569 // Checks the bit that indicates if an invalid operating mode has been selected. 00570 00571 bool ENS160::getOperationError() 00572 { 00573 int32_t retVal; 00574 char tempVal[1] = {0x00}; 00575 00576 retVal = this->readRegisterRegion(SFE_ENS160_DEVICE_STATUS, tempVal); 00577 00578 if( retVal != 0 ) 00579 return false; 00580 00581 tempVal[0] &= 0x40; 00582 00583 if( tempVal[0] == 0x40 ) 00584 return true; 00585 00586 return false; 00587 } 00588 00589 00590 00591 ////////////////////////////////////////////////////////////////////////////// 00592 // getAQI() 00593 // 00594 // This reports the calculated Air Quality Index according to UBA which is a value between 1-5. 00595 // The AQI-UBA is a guideline developed by the German Federal Environmental Agency and is widely 00596 // referenced and adopted by many countries and organizations. 00597 // 00598 // 1 - Excellent, 2 - Good, 3 - Moderate, 4 - Poor, 5 - Unhealthy. 00599 00600 uint8_t ENS160::getAQI() 00601 { 00602 int32_t retVal; 00603 char tempVal[1] = {0x00}; 00604 00605 retVal = this->readRegisterRegion(SFE_ENS160_DATA_AQI, tempVal); 00606 00607 if( retVal != 0 ) 00608 return 0; 00609 00610 tempVal[0] = (tempVal[0] & 0x03); 00611 00612 return tempVal[0]; 00613 } 00614 00615 ////////////////////////////////////////////////////////////////////////////// 00616 // getTVOC() 00617 // 00618 // This reports the Total Volatile Organic Compounds in ppb (parts per billion) 00619 00620 uint16_t ENS160::getTVOC() 00621 { 00622 int32_t retVal; 00623 uint16_t tvoc; 00624 char tempVal[2] = {0}; 00625 00626 retVal = this->readRegisterRegion(SFE_ENS160_DATA_TVOC, tempVal, 2); 00627 00628 if( retVal != 0 ) 00629 return 0; 00630 00631 tvoc = tempVal[0]; 00632 tvoc |= tempVal[1] << 8; 00633 00634 return tvoc; 00635 } 00636 00637 00638 00639 ////////////////////////////////////////////////////////////////////////////// 00640 // getETOH() 00641 // 00642 // This reports the ehtanol concentration in ppb (parts per billion). According to 00643 // the datasheet this is a "virtual mirror" of the ethanol-calibrated TVOC register, 00644 // which is why they share the same register. 00645 00646 uint16_t ENS160::getETOH() 00647 { 00648 int32_t retVal; 00649 uint16_t ethanol; 00650 char tempVal[2] = {0}; 00651 00652 retVal = this->readRegisterRegion(SFE_ENS160_DATA_ETOH, tempVal, 2); 00653 00654 if( retVal != 0 ) 00655 return 0; 00656 00657 ethanol = tempVal[0]; 00658 ethanol |= tempVal[1] << 8; 00659 00660 return ethanol; 00661 } 00662 00663 00664 ////////////////////////////////////////////////////////////////////////////// 00665 // getECO2() 00666 // 00667 // This reports the CO2 concentration in ppm (parts per million) based on the detected VOCs and hydrogen. 00668 00669 uint16_t ENS160::getECO2() 00670 { 00671 int32_t retVal; 00672 uint16_t eco; 00673 char tempVal[2] = {0}; 00674 00675 retVal = this->readRegisterRegion(SFE_ENS160_DATA_ECO2, tempVal, 2); 00676 00677 if( retVal != 0 ) 00678 return 0; 00679 00680 eco = tempVal[0]; 00681 eco |= tempVal[1] << 8; 00682 00683 return eco; 00684 } 00685 00686 00687 ////////////////////////////////////////////////////////////////////////////// 00688 // getTempKelvin() 00689 // 00690 // This reports the temperature compensation value given to the sensor in Kelvin. 00691 00692 float ENS160::getTempKelvin() 00693 { 00694 int32_t retVal; 00695 float temperature; 00696 int16_t tempConversion; 00697 char tempVal[2] = {0}; 00698 00699 retVal = this->readRegisterRegion(SFE_ENS160_DATA_T, tempVal, 2); 00700 00701 if( retVal != 0 ) 00702 return -1.0; 00703 00704 tempConversion = tempVal[0]; 00705 tempConversion |= (tempVal[1] << 8); 00706 temperature = (float)tempConversion; 00707 00708 temperature = temperature/64; // Formula as described on pg. 32 of datasheet. 00709 00710 return temperature; 00711 } 00712 00713 00714 ////////////////////////////////////////////////////////////////////////////// 00715 // getTempCelsius() 00716 // 00717 // This reports the temperature compensation value given to the sensor in Celsius. 00718 00719 float ENS160::getTempCelsius() 00720 { 00721 float temperature; 00722 00723 temperature = getTempKelvin(); 00724 00725 return (temperature - 273.15); 00726 } 00727 00728 00729 ////////////////////////////////////////////////////////////////////////////// 00730 // getRH() 00731 // 00732 // This reports the relative humidity compensation value given to the sensor. 00733 00734 float ENS160::getRH() 00735 { 00736 int32_t retVal; 00737 uint16_t rh; 00738 char tempVal[2] = {0}; 00739 00740 retVal = this->readRegisterRegion(SFE_ENS160_DATA_RH, tempVal, 2); 00741 00742 if( retVal != 0 ) 00743 return -1.0; 00744 00745 rh = tempVal[0]; 00746 rh |= tempVal[1] << 8; 00747 00748 rh = rh/512; // Formula as described on pg. 33 of datasheet. 00749 00750 return rh; 00751 }
Generated on Thu Dec 8 2022 16:51:02 by
1.7.2