Venkata Siva Krishna Madala / ENS160_Library

Dependents:   ECE4180FinalProjectFall22

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ens160_i2c.cpp Source File

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 }