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
- Committer:
- krishnamvs
- Date:
- 2022-12-06
- Revision:
- 3:63ff52373e71
- Child:
- 4:cb50c2f7e2b2
File content as of revision 3:63ff52373e71:
#include "ens160_i2c.h"
ENS160::ENS160(PinName sda, PinName scl, uint8_t i2c_device_address)
:i2c(sda, scl)
{
this->i2c_address = i2c_device_address;
}
bool ENS160::ping(uint8_t address)
{
int ret;
char rxdata;
ret = i2c.read(this->i2c_address, &rxdata, 1);
if (ret)
return true;
return false;
}
uint8_t ENS160::readRegisterRegion(uint8_t reg, uint8_t *data, uint8_t length)
{
int i;
char temp_dest[length];
char temp[1] = {reg};
i2c.write(this->i2c_address, temp, 1);
i2c.read(this->i2c_address, temp_dest, length);
for (i=0; i < length; i++)
{
data[i] = temp_dest[i];
}
return length;
}
int32_t ENS160::writeRegisterRegion(uint8_t *data, uint8_t length)
{
char temp_dest[length];
for (int i = 0; i < length; i++)
{
temp_dest[i] = *(data + i);
}
return i2c.write(this->i2c_address, temp_dest, length);
}
int32_t ENS160::writeRegisterRegion(uint8_t reg, uint8_t data)
{
char temp_data[2] = {reg, data};
return i2c.write(this->i2c_address, temp_data, 2);
}
//////////////////////////////////////////////////////////////////////////////
// getUniqueID()
// Gets the device's unique ID
uint16_t ENS160::getUniqueID()
{
int32_t retVal;
uint8_t tempVal[2] = {0};
uint16_t id;
retVal = readRegisterRegion(SFE_ENS160_PART_ID, tempVal, 2);
id = tempVal[0];
id |= tempVal[1] << 8;
if( retVal != 0 )
return 0;
return id;
}
///////////////////////////////////////////////////////////////////////
// isConnected()
// Parameter Description
// --------- -----------------------------
// retVal true if device is connected, false if not connected
bool ENS160::isConnected()
{
uint16_t uniqueID;
uniqueID = getUniqueID();
if( uniqueID != ENS160_DEVICE_ID )
return false;
return true;
}
bool ENS160::init()
{
if(!this->ping(this->i2c_address))
return false;
return this->isConnected();
}
//////////////////////////////////////////////////////////////////////////////
// setOperatingMode()
// Sets the operating mode: Deep Sleep (0x00), Idle (0x01), Standard (0x02), Reset (0xF0)
//
// Parameter Description
// --------- -----------------------------
// val The desired operating mode to set.
bool ENS160::setOperatingMode(uint8_t val)
{
int32_t retVal;
if( val > SFE_ENS160_RESET )
return false;
retVal = this->writeRegisterRegion(SFE_ENS160_OP_MODE, val);
if( retVal != 0 )
return false;
return true;
}
//////////////////////////////////////////////////////////////////////////////
// getOperatingMode()
//
// Gets the current operating mode: Deep Sleep (0x00), Idle (0x01), Standard (0x02), Reset (0xF0)
int8_t ENS160::getOperatingMode()
{
int32_t retVal;
uint8_t tempVal;
retVal = readRegisterRegion(SFE_ENS160_OP_MODE, &tempVal, 1);
if( retVal != 0 )
return -1;
return tempVal;
}
//////////////////////////////////////////////////////////////////////////////
// configureInterrupt()
//
// Changes all of the settings within the interrupt configuration register.
//
// Parameter Description
// --------- -----------------------------
// val The desired configuration settings.
bool ENS160::configureInterrupt(uint8_t val)
{
int32_t retVal;
retVal = writeRegisterRegion(SFE_ENS160_CONFIG, val);
if( retVal != 0 )
return false;
return true;
}
//////////////////////////////////////////////////////////////////////////////
// setInterrupt()
//
// Enables the interrupt.
//
// Parameter Description
// --------- -----------------------------
// enable Turns on or off the interrupt.
bool ENS160::enableInterrupt(bool enable)
{
int32_t retVal;
uint8_t tempVal;
retVal = readRegisterRegion(SFE_ENS160_CONFIG, &tempVal, 1);
if( retVal != 0 )
return false;
tempVal = (tempVal | (uint8_t)enable);
retVal = writeRegisterRegion(SFE_ENS160_CONFIG, tempVal);
if( retVal != 0 )
return false;
return true;
}
//////////////////////////////////////////////////////////////////////////////
// setInterruptPolarity()
//
// Changes the polarity of the interrupt: active high or active low. By default
// this value is set to zero or active low.
//
// Parameter Description
// --------- -----------------------------
// activeHigh Changes active state of interrupt from high to low.
bool ENS160::setInterruptPolarity(bool activeHigh)
{
int32_t retVal;
uint8_t tempVal;
retVal = readRegisterRegion(SFE_ENS160_CONFIG, &tempVal, 1);
if( retVal != 0 )
return false;
tempVal = (tempVal | (activeHigh << 6));
retVal = writeRegisterRegion(SFE_ENS160_CONFIG, tempVal);
if( retVal != 0 )
return false;
return true;
}
//////////////////////////////////////////////////////////////////////////////
// getInterruptPolarity()
//
// Retrieves the polarity of the physical interrupt.
int8_t ENS160::getInterruptPolarity()
{
int32_t retVal;
uint8_t tempVal;
retVal = readRegisterRegion(SFE_ENS160_CONFIG, &tempVal, 1);
if( retVal != 0 )
return -1;
tempVal &= 0x40;
return (tempVal >> 6);
}
//////////////////////////////////////////////////////////////////////////////
// setInterruptDrive()
//
// Changes the pin drive of the interrupt: open drain (default) to push/pull
//
// Parameter Description
// --------- -----------------------------
// pushPull Changes the drive of the pin.
bool ENS160::setInterruptDrive(bool pushPull)
{
int32_t retVal;
uint8_t tempVal;
retVal = readRegisterRegion(SFE_ENS160_CONFIG, &tempVal, 1);
if( retVal != 0 )
return false;
tempVal = (tempVal | (uint8_t)(pushPull << 5));
retVal = writeRegisterRegion(SFE_ENS160_CONFIG, tempVal);
if( retVal != 0 )
return false;
return true;
}
//////////////////////////////////////////////////////////////////////////////
// setDataInterrupt()
//
// Routes the data ready signal to the interrupt pin.
//
// Parameter Description
// --------- -----------------------------
// enable Self-explanatory: enables or disables data ready on interrupt.
bool ENS160::setDataInterrupt(bool enable)
{
int32_t retVal;
uint8_t tempVal;
retVal = readRegisterRegion(SFE_ENS160_CONFIG, &tempVal, 1);
if( retVal != 0 )
return false;
tempVal = (tempVal | (uint8_t)(enable << 1));
retVal = writeRegisterRegion(SFE_ENS160_CONFIG, tempVal);
if( retVal != 0 )
return false;
return true;
}
//////////////////////////////////////////////////////////////////////////////
// setGPRInterrupt()
//
// Routes the general purporse read register signal to the interrupt pin.
//
// Parameter Description
// --------- -----------------------------
// enable Self-explanatory: enables or disables general purpos read interrupt.
bool ENS160::setGPRInterrupt(bool enable)
{
int32_t retVal;
uint8_t tempVal;
retVal = readRegisterRegion(SFE_ENS160_CONFIG, &tempVal, 1);
if( retVal != 0 )
return false;
tempVal = (tempVal | (uint8_t)(enable << 3));
retVal = writeRegisterRegion(SFE_ENS160_CONFIG, tempVal);
if( retVal != 0 )
return false;
return true;
}
//////////////////////////////////////////////////////////////////////////////
// getAppVer()
//
// Retrieves the 24 bit application version of the device.
uint32_t ENS160::getAppVer()
{
int32_t retVal;
uint8_t tempVal[3] = {0};
uint32_t version;
retVal = readRegisterRegion(SFE_ENS160_GPR_READ4, tempVal, 3);
if( retVal != 0 )
return 0;
version = tempVal[0];
version |= tempVal[1] << 8;
version |= tempVal[2] << 16;
return version;
}
//////////////////////////////////////////////////////////////////////////////
// setTempCompensation()
//
// The ENS160 can use temperature data to help give more accurate sensor data.
//
// Parameter Description
// --------- -----------------------------
// kelvinConversion The given temperature in Kelvin
bool ENS160::setTempCompensation(float tempKelvin)
{
int32_t retVal;
uint8_t tempVal[3] = {0};
uint16_t kelvinConversion = tempKelvin;
kelvinConversion = kelvinConversion * 64; // convert value - fixed equation pg. 29 of datasheet
tempVal[0] = SFE_ENS160_TEMP_IN;
tempVal[1] = (kelvinConversion & 0x00FF);
tempVal[2] = (kelvinConversion & 0xFF00) >> 8;
retVal = writeRegisterRegion(tempVal, 2);
if( retVal != 0 )
return false;
return true;
}
//////////////////////////////////////////////////////////////////////////////
// setTempCompensationCelsius()
//
// The ENS160 can use temperature data to help give more accurate sensor data.
//
// Parameter Description
// --------- -----------------------------
// tempCelsius The given temperature in Celsius
bool ENS160::setTempCompensationCelsius(float tempCelsius)
{
float kelvinConversion = tempCelsius + 273.15;
if( setTempCompensation(kelvinConversion) )
return true;
return false;
}
//////////////////////////////////////////////////////////////////////////////
// setRHCompensation()
//
// The ENS160 can use relative Humidiy data to help give more accurate sensor data.
//
// Parameter Description
// --------- -----------------------------
// humidity The given relative humidity.
bool ENS160::setRHCompensation(uint16_t humidity)
{
int32_t retVal;
uint8_t tempVal[3] = {0};
humidity = humidity * 512; // convert value - fixed equation pg. 29 in datasheet.
tempVal[0] = SFE_ENS160_RH_IN;
tempVal[1] = (humidity & 0x00FF);
tempVal[2] = (humidity & 0xFF00) >> 8;
retVal = writeRegisterRegion(tempVal, 2);
if( retVal != 0 )
return false;
return true;
}
//////////////////////////////////////////////////////////////////////////////
// setRHCompensationFloat()
//
// The ENS160 can use relative Humidiy data to help give more accurate sensor data.
//
// Parameter Description
// --------- -----------------------------
// humidity The given relative humidity.
bool ENS160::setRHCompensationFloat(float humidity)
{
uint16_t humidityConversion = (uint16_t)humidity;
if( setRHCompensation(humidityConversion) )
return false;
return true;
}
//////////////////////////////////////////////////////////////////////////////
// checkDataStatus()
//
// This checks the if the NEWDAT bit is high indicating that new data is ready to be read.
// The bit is cleared when data has been read from their registers.
bool ENS160::checkDataStatus()
{
int32_t retVal;
uint8_t tempVal;
retVal = readRegisterRegion(SFE_ENS160_DEVICE_STATUS, &tempVal, 1);
if( retVal != 0 )
return false;
tempVal &= 0x02;
if( tempVal == 0x02 )
return true;
return false;
}
//////////////////////////////////////////////////////////////////////////////
// checkGPRStatus()
//
// This checks the if the NEWGPR bit is high indicating that there is data in the
// general purpose read registers. The bit is cleared the relevant registers have been
// read.
bool ENS160::checkGPRStatus()
{
int32_t retVal;
uint8_t tempVal;
retVal = readRegisterRegion(SFE_ENS160_DEVICE_STATUS, &tempVal, 1);
if( retVal != 0 )
return false;
tempVal &= 0x01;
if( tempVal == 0x01 )
return true;
return false;
}
//////////////////////////////////////////////////////////////////////////////
// getFlags()
//
// This checks the status "flags" of the device (0-3).
uint8_t ENS160::getFlags()
{
int32_t retVal;
uint8_t tempVal;
retVal = readRegisterRegion(SFE_ENS160_DEVICE_STATUS, &tempVal, 1);
if( retVal != 0 )
return 0xFF; // Change to general error
tempVal = (tempVal & 0x0C) >> 2;
switch( tempVal )
{
case 0: // Normal operation
return 0;
break;
case 1: // Warm-up phase
return 1;
break;
case 2: // Initial Start-Up Phase
return 2;
break;
case 3: // Invalid Output
return 3;
break;
default:
return 0xFF;
}
}
//////////////////////////////////////////////////////////////////////////////
// checkOperationStatus()
//
// Checks the bit that indicates if an operation mode is running i.e. the device is not off.
bool ENS160::checkOperationStatus()
{
int32_t retVal;
uint8_t tempVal;
retVal = readRegisterRegion(SFE_ENS160_DEVICE_STATUS, &tempVal, 1);
if( retVal != 0 )
return false;
tempVal &= 0x80;
if( tempVal == 0x80 )
return true;
return false;
}
//////////////////////////////////////////////////////////////////////////////
// getOperationError()
//
// Checks the bit that indicates if an invalid operating mode has been selected.
bool ENS160::getOperationError()
{
int32_t retVal;
uint8_t tempVal;
retVal = readRegisterRegion(SFE_ENS160_DEVICE_STATUS, &tempVal, 1);
if( retVal != 0 )
return false;
tempVal &= 0x40;
if( tempVal == 0x40 )
return true;
return false;
}
//////////////////////////////////////////////////////////////////////////////
// getAQI()
//
// This reports the calculated Air Quality Index according to UBA which is a value between 1-5.
// The AQI-UBA is a guideline developed by the German Federal Environmental Agency and is widely
// referenced and adopted by many countries and organizations.
//
// 1 - Excellent, 2 - Good, 3 - Moderate, 4 - Poor, 5 - Unhealthy.
uint8_t ENS160::getAQI()
{
int32_t retVal;
uint8_t tempVal;
retVal = readRegisterRegion(SFE_ENS160_DATA_AQI, &tempVal, 1);
if( retVal != 0 )
return 0;
tempVal = (tempVal & 0x03);
return tempVal;
}
//////////////////////////////////////////////////////////////////////////////
// getTVOC()
//
// This reports the Total Volatile Organic Compounds in ppb (parts per billion)
uint16_t ENS160::getTVOC()
{
int32_t retVal;
uint16_t tvoc;
uint8_t tempVal[2] = {0};
retVal = readRegisterRegion(SFE_ENS160_DATA_TVOC, tempVal, 2);
if( retVal != 0 )
return 0;
tvoc = tempVal[0];
tvoc |= tempVal[1] << 8;
return tvoc;
}
//////////////////////////////////////////////////////////////////////////////
// getETOH()
//
// This reports the ehtanol concentration in ppb (parts per billion). According to
// the datasheet this is a "virtual mirror" of the ethanol-calibrated TVOC register,
// which is why they share the same register.
uint16_t ENS160::getETOH()
{
int32_t retVal;
uint16_t ethanol;
uint8_t tempVal[2] = {0};
retVal = readRegisterRegion(SFE_ENS160_DATA_ETOH, tempVal, 2);
if( retVal != 0 )
return 0;
ethanol = tempVal[0];
ethanol |= tempVal[1] << 8;
return ethanol;
}
//////////////////////////////////////////////////////////////////////////////
// getECO2()
//
// This reports the CO2 concentration in ppm (parts per million) based on the detected VOCs and hydrogen.
uint16_t ENS160::getECO2()
{
int32_t retVal;
uint16_t eco;
uint8_t tempVal[2] = {0};
retVal = readRegisterRegion(SFE_ENS160_DATA_ECO2, tempVal, 2);
if( retVal != 0 )
return 0;
eco = tempVal[0];
eco |= tempVal[1] << 8;
return eco;
}
//////////////////////////////////////////////////////////////////////////////
// getTempKelvin()
//
// This reports the temperature compensation value given to the sensor in Kelvin.
float ENS160::getTempKelvin()
{
int32_t retVal;
float temperature;
int16_t tempConversion;
uint8_t tempVal[2] = {0};
retVal = readRegisterRegion(SFE_ENS160_DATA_T, tempVal, 2);
if( retVal != 0 )
return 0;
tempConversion = tempVal[0];
tempConversion |= (tempVal[1] << 8);
temperature = (float)tempConversion;
temperature = temperature/64; // Formula as described on pg. 32 of datasheet.
return temperature;
}
//////////////////////////////////////////////////////////////////////////////
// getTempCelsius()
//
// This reports the temperature compensation value given to the sensor in Celsius.
float ENS160::getTempCelsius()
{
float temperature;
temperature = getTempKelvin();
return (temperature - 273.15);
}
//////////////////////////////////////////////////////////////////////////////
// getRH()
//
// This reports the relative humidity compensation value given to the sensor.
float ENS160::getRH()
{
int32_t retVal;
uint16_t rh;
uint8_t tempVal[2] = {0};
retVal = readRegisterRegion(SFE_ENS160_DATA_RH, tempVal, 2);
if( retVal != 0 )
return 0;
rh = tempVal[0];
rh |= tempVal[1] << 8;
rh = rh/512; // Formula as described on pg. 33 of datasheet.
return rh;
}
