246 lines
5.4 KiB
C++
246 lines
5.4 KiB
C++
/*!
|
|
* @file Adafruit_SHT31.cpp
|
|
*
|
|
* @mainpage Adafruit SHT31 Digital Humidity & Temp Sensor
|
|
*
|
|
* @section intro_sec Introduction
|
|
*
|
|
* This is a library for the SHT31 Digital Humidity & Temp Sensor
|
|
*
|
|
* Designed specifically to work with the SHT31 Digital sensor from Adafruit
|
|
*
|
|
* Pick one up today in the adafruit shop!
|
|
* ------> https://www.adafruit.com/product/2857
|
|
*
|
|
* These sensors use I2C to communicate, 2 pins are required to interface
|
|
*
|
|
* Adafruit invests time and resources providing this open source code,
|
|
* please support Adafruit andopen-source hardware by purchasing products
|
|
* from Adafruit!
|
|
*
|
|
* @section author Author
|
|
*
|
|
* Limor Fried/Ladyada (Adafruit Industries).
|
|
*
|
|
* @section license License
|
|
*
|
|
* BSD license, all text above must be included in any redistribution
|
|
*/
|
|
|
|
#include "Adafruit_SHT31.h"
|
|
|
|
/*!
|
|
* @brief SHT31 constructor using i2c
|
|
* @param *theWire
|
|
* optional wire
|
|
*/
|
|
Adafruit_SHT31::Adafruit_SHT31(TwoWire *theWire) {
|
|
_wire = theWire;
|
|
|
|
humidity = NAN;
|
|
temp = NAN;
|
|
}
|
|
|
|
/**
|
|
* Destructor to free memory in use.
|
|
*/
|
|
Adafruit_SHT31::~Adafruit_SHT31() {
|
|
if (i2c_dev) {
|
|
delete i2c_dev; // remove old interface
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialises the I2C bus, and assigns the I2C address to us.
|
|
*
|
|
* @param i2caddr The I2C address to use for the sensor.
|
|
*
|
|
* @return True if initialisation was successful, otherwise False.
|
|
*/
|
|
bool Adafruit_SHT31::begin(uint8_t i2caddr) {
|
|
if (i2c_dev) {
|
|
delete i2c_dev; // remove old interface
|
|
}
|
|
|
|
i2c_dev = new Adafruit_I2CDevice(i2caddr, _wire);
|
|
|
|
if (!i2c_dev->begin()) {
|
|
return false;
|
|
}
|
|
|
|
reset();
|
|
return readStatus() != 0xFFFF;
|
|
}
|
|
|
|
/**
|
|
* Gets the current status register contents.
|
|
*
|
|
* @return The 16-bit status register.
|
|
*/
|
|
uint16_t Adafruit_SHT31::readStatus(void) {
|
|
writeCommand(SHT31_READSTATUS);
|
|
|
|
uint8_t data[3];
|
|
i2c_dev->read(data, 3);
|
|
|
|
uint16_t stat = data[0];
|
|
stat <<= 8;
|
|
stat |= data[1];
|
|
// Serial.println(stat, HEX);
|
|
return stat;
|
|
}
|
|
|
|
/**
|
|
* Performs a reset of the sensor to put it into a known state.
|
|
*/
|
|
void Adafruit_SHT31::reset(void) {
|
|
writeCommand(SHT31_SOFTRESET);
|
|
delay(10);
|
|
}
|
|
|
|
/**
|
|
* Enables or disabled the heating element.
|
|
*
|
|
* @param h True to enable the heater, False to disable it.
|
|
*/
|
|
void Adafruit_SHT31::heater(bool h) {
|
|
if (h)
|
|
writeCommand(SHT31_HEATEREN);
|
|
else
|
|
writeCommand(SHT31_HEATERDIS);
|
|
delay(1);
|
|
}
|
|
|
|
/*!
|
|
* @brief Return sensor heater state
|
|
* @return heater state (TRUE = enabled, FALSE = disabled)
|
|
*/
|
|
bool Adafruit_SHT31::isHeaterEnabled() {
|
|
uint16_t regValue = readStatus();
|
|
return (bool)bitRead(regValue, SHT31_REG_HEATER_BIT);
|
|
}
|
|
|
|
/**
|
|
* Gets a single temperature reading from the sensor.
|
|
*
|
|
* @return A float value indicating the temperature.
|
|
*/
|
|
float Adafruit_SHT31::readTemperature(void) {
|
|
if (!readTempHum())
|
|
return NAN;
|
|
|
|
return temp;
|
|
}
|
|
|
|
/**
|
|
* Gets a single relative humidity reading from the sensor.
|
|
*
|
|
* @return A float value representing relative humidity.
|
|
*/
|
|
float Adafruit_SHT31::readHumidity(void) {
|
|
if (!readTempHum())
|
|
return NAN;
|
|
|
|
return humidity;
|
|
}
|
|
|
|
/**
|
|
* Gets a reading of both temperature and relative humidity from the sensor.
|
|
*
|
|
* @param temperature_out Where to write the temperature float.
|
|
* @param humidity_out Where to write the relative humidity float.
|
|
* @return True if the read was successful, false otherwise
|
|
*/
|
|
bool Adafruit_SHT31::readBoth(float *temperature_out, float *humidity_out) {
|
|
if (!readTempHum()) {
|
|
*temperature_out = *humidity_out = NAN;
|
|
return false;
|
|
}
|
|
|
|
*temperature_out = temp;
|
|
*humidity_out = humidity;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Performs a CRC8 calculation on the supplied values.
|
|
*
|
|
* @param data Pointer to the data to use when calculating the CRC8.
|
|
* @param len The number of bytes in 'data'.
|
|
*
|
|
* @return The computed CRC8 value.
|
|
*/
|
|
static uint8_t crc8(const uint8_t *data, int len) {
|
|
/*
|
|
*
|
|
* CRC-8 formula from page 14 of SHT spec pdf
|
|
*
|
|
* Test data 0xBE, 0xEF should yield 0x92
|
|
*
|
|
* Initialization data 0xFF
|
|
* Polynomial 0x31 (x8 + x5 +x4 +1)
|
|
* Final XOR 0x00
|
|
*/
|
|
|
|
const uint8_t POLYNOMIAL(0x31);
|
|
uint8_t crc(0xFF);
|
|
|
|
for (int j = len; j; --j) {
|
|
crc ^= *data++;
|
|
|
|
for (int i = 8; i; --i) {
|
|
crc = (crc & 0x80) ? (crc << 1) ^ POLYNOMIAL : (crc << 1);
|
|
}
|
|
}
|
|
return crc;
|
|
}
|
|
|
|
/**
|
|
* Internal function to perform a temp + humidity read.
|
|
*
|
|
* @return True if successful, otherwise false.
|
|
*/
|
|
bool Adafruit_SHT31::readTempHum(void) {
|
|
uint8_t readbuffer[6];
|
|
|
|
if (!writeCommand(SHT31_MEAS_HIGHREP))
|
|
return false;
|
|
|
|
delay(20);
|
|
|
|
if (!i2c_dev->read(readbuffer, sizeof(readbuffer)))
|
|
return false;
|
|
|
|
if (readbuffer[2] != crc8(readbuffer, 2) ||
|
|
readbuffer[5] != crc8(readbuffer + 3, 2))
|
|
return false;
|
|
|
|
int32_t stemp = (int32_t)(((uint32_t)readbuffer[0] << 8) | readbuffer[1]);
|
|
// simplified (65536 instead of 65535) integer version of:
|
|
// temp = (stemp * 175.0f) / 65535.0f - 45.0f;
|
|
stemp = ((4375 * stemp) >> 14) - 4500;
|
|
temp = (float)stemp / 100.0f;
|
|
|
|
uint32_t shum = ((uint32_t)readbuffer[3] << 8) | readbuffer[4];
|
|
// simplified (65536 instead of 65535) integer version of:
|
|
// humidity = (shum * 100.0f) / 65535.0f;
|
|
shum = (625 * shum) >> 12;
|
|
humidity = (float)shum / 100.0f;
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Internal function to perform and I2C write.
|
|
*
|
|
* @param cmd The 16-bit command ID to send.
|
|
*/
|
|
bool Adafruit_SHT31::writeCommand(uint16_t command) {
|
|
uint8_t cmd[2];
|
|
|
|
cmd[0] = command >> 8;
|
|
cmd[1] = command & 0xFF;
|
|
|
|
return i2c_dev->write(cmd, 2);
|
|
}
|