GY-63_MS5611/libraries/SHT2x/SHT2x.cpp

697 lines
12 KiB
C++
Raw Normal View History

2021-09-27 14:51:23 -04:00
//
// FILE: SHT2x.cpp
2023-11-27 03:44:42 -05:00
// AUTHOR: Rob Tillaart, Viktor Balint, JensB
2023-12-07 11:29:13 -05:00
// VERSION: 0.5.0
2023-11-27 03:44:42 -05:00
// DATE: 2023-11-25
2021-09-27 14:51:23 -04:00
// PURPOSE: Arduino library for the SHT2x temperature and humidity sensor
// URL: https://github.com/RobTillaart/SHT2x
#include "SHT2x.h"
// SUPPORTED COMMANDS
2023-11-27 03:44:42 -05:00
#define SHT2x_GET_TEMPERATURE_NO_HOLD 0xF3
2023-12-04 05:37:43 -05:00
#define SHT2x_GET_TEMPERATURE_FOR_HUMIDITY 0xE0
2023-11-27 03:44:42 -05:00
#define SHT2x_GET_HUMIDITY_NO_HOLD 0xF5
#define SHT2x_SOFT_RESET 0xFE
#define SHT2x_WRITE_USER_REGISTER 0xE6
#define SHT2x_READ_USER_REGISTER 0xE7
2021-09-27 14:51:23 -04:00
2023-11-27 03:44:42 -05:00
#define SHT2x_HEATER_TIMEOUT 180000UL // milliseconds
2021-09-27 14:51:23 -04:00
2023-11-27 03:44:42 -05:00
#define SHT2x_ADDRESS 0x40
2021-09-27 14:51:23 -04:00
2023-11-27 03:44:42 -05:00
#define SHT2x_USRREG_RESOLUTION 0x81
#define SHT2x_USRREG_BATTERY 0x20
#define SHT2x_USRREG_HEATER 0x04
2022-07-13 09:46:33 -04:00
2022-12-18 04:41:37 -05:00
//////////////////////////////////////////////////////////////
//
// PUBLIC
//
2023-09-21 10:37:38 -04:00
SHT2x::SHT2x(TwoWire *wire)
2021-09-27 14:51:23 -04:00
{
2023-09-21 10:37:38 -04:00
_wire = wire;
2021-09-27 14:51:23 -04:00
_lastRead = 0;
2022-12-18 04:41:37 -05:00
_lastRequest = 0;
2023-09-11 04:13:31 -04:00
_requestType = SHT2x_REQ_NONE;
2021-09-27 14:51:23 -04:00
_rawTemperature = 0;
_rawHumidity = 0;
_heatTimeout = 0;
_heaterStart = 0;
_heaterStop = 0;
_heaterOn = false;
_error = SHT2x_OK;
_status = 0;
2022-07-13 09:46:33 -04:00
_resolution = 0;
2021-09-27 14:51:23 -04:00
}
2023-09-21 10:37:38 -04:00
bool SHT2x::begin()
2021-09-27 14:51:23 -04:00
{
2023-12-07 11:29:13 -05:00
if (! isConnected()) return false;
2021-09-27 14:51:23 -04:00
return reset();
}
bool SHT2x::isConnected()
{
_wire->beginTransmission(SHT2x_ADDRESS);
int rv = _wire->endTransmission();
if (rv != 0) _error = SHT2x_ERR_NOT_CONNECT;
return (rv == 0);
}
2022-12-18 04:41:37 -05:00
/////////////////////////////////////////////////////////
//
// SYNCHRONOUS INTERFACE
//
2021-09-27 14:51:23 -04:00
bool SHT2x::read()
{
// TEMPERATURE
2022-12-18 04:41:37 -05:00
if (requestTemperature() == false) return false;
while (reqTempReady() == false)
{
yield();
};
if (readTemperature() == false) return false;
// HUMIDITY
if (requestHumidity() == false) return false;
while (reqHumReady() == false)
{
yield();
};
if (readHumidity() == false) return false;
return true;
}
/////////////////////////////////////////////////////////
//
// ASYNCHRONOUS INTERFACE
//
bool SHT2x::requestTemperature()
{
2021-09-27 14:51:23 -04:00
writeCmd(SHT2x_GET_TEMPERATURE_NO_HOLD);
2022-12-18 04:41:37 -05:00
_lastRequest = millis();
_requestType = SHT2x_REQ_TEMPERATURE;
return true;
}
bool SHT2x::requestHumidity()
{
writeCmd(SHT2x_GET_HUMIDITY_NO_HOLD);
_lastRequest = millis();
_requestType = SHT2x_REQ_HUMIDITY;
return true;
}
bool SHT2x::reqTempReady()
{
if (_requestType != SHT2x_REQ_TEMPERATURE) return false;
uint32_t waiting = millis() - _lastRequest;
// table 7
if (waiting < 11) return false;
if (_resolution == 3) return true;
if (waiting < 22) return false;
if (_resolution == 1) return true;
if (waiting < 43) return false;
if (_resolution == 2) return true;
if (waiting < 85) return false;
return true;
}
bool SHT2x::reqHumReady()
{
if (_requestType != SHT2x_REQ_HUMIDITY) return false;
uint32_t waiting = millis() - _lastRequest;
// table 7
if (waiting < 4) return false;
if (_resolution == 1) return true; // 8 bit
if (waiting < 9) return false;
if (_resolution == 2) return true; // 10 bit
if (waiting < 15) return false;
if (_resolution == 3) return true; // 11 bit
if (waiting < 29) return false;
return true; // 12 bit
}
2023-09-11 04:13:31 -04:00
bool SHT2x::requestReady()
{
return (reqTempReady() || reqHumReady());
}
2022-12-18 04:41:37 -05:00
bool SHT2x::readTemperature()
{
uint8_t buffer[3];
2022-07-13 09:46:33 -04:00
2021-09-27 14:51:23 -04:00
if (readBytes(3, (uint8_t*) &buffer[0], 90) == false)
{
_error = SHT2x_ERR_READBYTES;
return false;
}
2022-07-13 09:46:33 -04:00
if (crc8(buffer, 2) != buffer[2])
{
_error = SHT2x_ERR_CRC_TEMP;
2023-09-11 04:13:31 -04:00
// return false; // do not fail yet
2022-07-13 09:46:33 -04:00
}
_rawTemperature = buffer[0] << 8;
2021-09-27 14:51:23 -04:00
_rawTemperature += buffer[1];
_rawTemperature &= 0xFFFC;
2022-12-18 04:41:37 -05:00
// clear requestType
_requestType = SHT2x_REQ_NONE;
2023-12-07 11:29:13 -05:00
_status = buffer[1] & 0x03;
if (_status == 0xFF) // TODO != 0x01 (need HW to test)
2021-09-27 14:51:23 -04:00
{
_error = SHT2x_ERR_READBYTES;
return false;
}
2022-12-18 04:41:37 -05:00
return true;
}
2021-09-27 14:51:23 -04:00
2022-12-18 04:41:37 -05:00
bool SHT2x::readHumidity()
{
uint8_t buffer[3];
2022-07-13 09:46:33 -04:00
2021-09-27 14:51:23 -04:00
if (readBytes(3, (uint8_t*) &buffer[0], 30) == false)
{
return false;
}
2022-07-13 09:46:33 -04:00
if (crc8(buffer, 2) != buffer[2])
{
_error = SHT2x_ERR_CRC_HUM;
2023-09-11 04:13:31 -04:00
// return false; // do not fail yet
2022-07-13 09:46:33 -04:00
}
_rawHumidity = buffer[0] << 8;
2021-09-27 14:51:23 -04:00
_rawHumidity += buffer[1];
2023-12-07 11:29:13 -05:00
_rawHumidity &= 0xFFFC;
2021-09-27 14:51:23 -04:00
2022-12-18 04:41:37 -05:00
// clear requestType
_requestType = SHT2x_REQ_NONE;
2023-12-07 11:29:13 -05:00
_status = buffer[1] & 0x03;
2022-07-13 09:46:33 -04:00
if (_status == 0xFF) // TODO != 0x02 (need HW to test)
2021-09-27 14:51:23 -04:00
{
_error = SHT2x_ERR_READBYTES;
return false;
}
_error = SHT2x_OK;
_lastRead = millis();
return true;
}
2023-12-04 05:37:43 -05:00
bool SHT2x::readCachedTemperature()
{
if (_error == SHT2x_OK)
{
writeCmd(SHT2x_GET_TEMPERATURE_FOR_HUMIDITY);
uint8_t buffer[2];
if (readBytes(2, (uint8_t*) &buffer[0], 10) == false)
{
_error = SHT2x_ERR_READBYTES;
return false;
}
_rawTemperature = buffer[0] << 8;
_rawTemperature += buffer[1];
_rawTemperature &= 0xFFFC;
return true;
}
else
{
return false;
}
}
2022-12-18 04:41:37 -05:00
uint32_t SHT2x::lastRequest()
{
return _lastRequest;
}
2023-09-11 04:13:31 -04:00
uint8_t SHT2x::getRequestType()
{
return _requestType;
}
2022-12-18 04:41:37 -05:00
/////////////////////////////////////////////////////////
//
// TEMPERATURE AND HUMIDTY
//
2021-09-27 14:51:23 -04:00
float SHT2x::getTemperature()
{
2023-09-11 04:13:31 -04:00
// par 6.2
2021-09-27 14:51:23 -04:00
return -46.85 + (175.72 / 65536.0) * _rawTemperature;
}
float SHT2x::getHumidity()
{
2023-09-11 04:13:31 -04:00
// par 6.1
2021-09-27 14:51:23 -04:00
return -6.0 + (125.0 / 65536.0) * _rawHumidity;
}
2023-03-26 16:08:27 -04:00
uint16_t SHT2x::getRawTemperature()
{
return _rawTemperature;
}
uint16_t SHT2x::getRawHumidity()
{
return _rawHumidity;
}
2021-09-27 14:51:23 -04:00
bool SHT2x::reset()
{
2023-11-27 03:44:42 -05:00
bool success = writeCmd(SHT2x_SOFT_RESET);
if (success)
{
_resolution = 0;
_heaterOn = false;
_error = SHT2x_OK;
}
return success;
2021-09-27 14:51:23 -04:00
}
uint8_t SHT2x::getStatus()
{
2021-11-17 12:59:50 -05:00
return _status;
2021-09-27 14:51:23 -04:00
}
2023-03-26 16:08:27 -04:00
uint32_t SHT2x::lastRead()
{
return _lastRead;
}
2022-12-18 04:41:37 -05:00
/////////////////////////////////////////////////////////
//
2021-11-17 12:59:50 -05:00
// HEATER
2022-12-18 04:41:37 -05:00
//
2021-09-27 14:51:23 -04:00
void SHT2x::setHeatTimeout(uint8_t seconds)
{
_heatTimeout = seconds;
if (_heatTimeout > 180) _heatTimeout = 180;
}
2023-03-26 16:08:27 -04:00
uint8_t SHT2x::getHeatTimeout()
{
return _heatTimeout;
}
2021-09-27 14:51:23 -04:00
bool SHT2x::heatOn()
{
if (isHeaterOn()) return true;
if ((_heaterStop > 0) && (millis() - _heaterStop < SHT2x_HEATER_TIMEOUT))
{
_error = SHT2x_ERR_HEATER_COOLDOWN;
return false;
}
uint8_t userReg = 0x00;
writeCmd(SHT2x_READ_USER_REGISTER);
if (readBytes(1, (uint8_t *) &userReg, 5) == false)
{
_error = SHT2x_ERR_READBYTES;
return false;
}
2022-07-13 09:46:33 -04:00
// HEAT BIT ON
userReg |= SHT2x_USRREG_HEATER;
2021-09-27 14:51:23 -04:00
2023-03-26 16:08:27 -04:00
if (writeCmd(SHT2x_WRITE_USER_REGISTER, userReg) == false)
2021-09-27 14:51:23 -04:00
{
_error = SHT2x_ERR_HEATER_ON;
return false;
}
_heaterStart = millis();
_heaterOn = true;
return true;
}
bool SHT2x::heatOff()
{
uint8_t userReg = 0x00;
writeCmd(SHT2x_READ_USER_REGISTER);
if (readBytes(1, (uint8_t *) &userReg, 5) == false)
{
_error = SHT2x_ERR_READBYTES;
return false;
}
2022-07-13 09:46:33 -04:00
// HEAT BIT OFF
userReg &= ~SHT2x_USRREG_HEATER;
2023-03-26 16:08:27 -04:00
if (writeCmd(SHT2x_WRITE_USER_REGISTER, userReg) == false)
2021-09-27 14:51:23 -04:00
{
2023-09-11 04:13:31 -04:00
_error = SHT2x_ERR_HEATER_OFF; // can be serious!
2021-09-27 14:51:23 -04:00
return false;
}
_heaterStop = millis();
_heaterOn = false;
return true;
}
bool SHT2x::isHeaterOn()
{
if (_heaterOn == false)
{
return false;
}
2023-09-11 04:13:31 -04:00
// did not exceed time out
2021-09-27 14:51:23 -04:00
if (millis() - _heaterStart < (_heatTimeout * 1000UL))
{
return true;
}
heatOff();
return false;
}
2021-11-17 12:59:50 -05:00
bool SHT2x::setHeaterLevel(uint8_t level)
{
if (level > 15)
{
return false;
}
uint8_t heaterReg = 0;
2023-09-11 04:13:31 -04:00
writeCmd(0x11); // Read Heater Control Register
2021-11-17 12:59:50 -05:00
if (readBytes(1, (uint8_t *) &heaterReg, 5) == false)
{
_error = SHT2x_ERR_READBYTES;
return false;
}
heaterReg &= 0xF0;
heaterReg |= level;
if (writeCmd(0x51, heaterReg) == false)
{
_error = -1;
return false;
}
return true;
}
bool SHT2x::getHeaterLevel(uint8_t & level)
{
uint8_t heaterReg = 0;
2023-09-11 04:13:31 -04:00
writeCmd(0x11); // Read Heater Control Register
2021-11-17 12:59:50 -05:00
if (readBytes(1, (uint8_t *) &heaterReg, 5) == false)
{
_error = SHT2x_ERR_READBYTES;
return false;
}
level = heaterReg & 0x0F;
return true;
}
2021-09-27 14:51:23 -04:00
int SHT2x::getError()
{
int rv = _error;
_error = SHT2x_OK;
return rv;
}
2022-12-18 04:41:37 -05:00
/////////////////////////////////////////////////////////
//
// Electronic Identification Code
//
2022-06-23 09:15:32 -04:00
// Sensirion_Humidity_SHT2x_Electronic_Identification_Code_V1.1.pdf
2021-11-17 12:59:50 -05:00
uint32_t SHT2x::getEIDA()
{
uint32_t id = 0;
uint8_t buffer[8];
writeCmd(0xFA, 0x0F);
if (readBytes(8, (uint8_t *) buffer, 10) == false)
{
_error = SHT2x_ERR_READBYTES;
return false;
}
2022-06-23 09:15:32 -04:00
// skip CRC's
2021-11-17 12:59:50 -05:00
for (uint8_t i = 0; i < 4; i++)
{
id <<= 8;
id |= buffer[i*2];
}
return id;
}
2022-06-23 09:15:32 -04:00
// Sensirion_Humidity_SHT2x_Electronic_Identification_Code_V1.1.pdf
2021-11-17 12:59:50 -05:00
uint32_t SHT2x::getEIDB()
{
uint32_t id = 0;
uint8_t buffer[8];
writeCmd(0xFC, 0xC9);
if (readBytes(8, (uint8_t *) buffer, 10) == false)
{
_error = SHT2x_ERR_READBYTES;
return false;
}
2022-06-23 09:15:32 -04:00
// skip CRC's
id = buffer[0]; // SNC_1
id <<= 8;
id |= buffer[1]; // SNC_0
id <<= 8;
id |= buffer[3]; // SNA_1
id <<= 8;
id |= buffer[4]; // SNA_0
2021-11-17 12:59:50 -05:00
return id;
}
uint8_t SHT2x::getFirmwareVersion()
{
uint8_t version = 0;
writeCmd(0x84, 0xB8);
if (readBytes(1, (uint8_t *) &version, 10) == false)
{
_error = SHT2x_ERR_READBYTES;
return false;
}
return version;
}
2022-12-18 04:41:37 -05:00
/////////////////////////////////////////////////////////
//
// RESOLUTION
//
2022-07-13 09:46:33 -04:00
bool SHT2x::setResolution(uint8_t res)
{
if (res > 3) return false;
uint8_t userReg = 0x00;
writeCmd(SHT2x_READ_USER_REGISTER);
if (readBytes(1, (uint8_t *) &userReg, 5) == false)
{
_error = SHT2x_ERR_READBYTES;
return false;
}
// clear old resolution and set new
userReg &= ~SHT2x_USRREG_RESOLUTION;
// resolution is bit 7 and bit 0.
userReg |= ((res & 0x02) << 6);
userReg |= (res & 0x01);
2023-03-26 16:08:27 -04:00
if (writeCmd(SHT2x_WRITE_USER_REGISTER, userReg) == false)
2022-07-13 09:46:33 -04:00
{
_error = SHT2x_ERR_RESOLUTION;
return false;
}
_resolution = res;
return true;
}
uint8_t SHT2x::getResolution()
{
return _resolution;
};
2022-12-18 04:41:37 -05:00
/////////////////////////////////////////////////////////
//
// OTHER
//
2022-07-13 09:46:33 -04:00
bool SHT2x::batteryOK()
{
uint8_t userReg = 0x00;
writeCmd(SHT2x_READ_USER_REGISTER);
if (readBytes(1, (uint8_t *) &userReg, 5) == false)
{
_error = SHT2x_ERR_READBYTES;
return false;
}
return (userReg & SHT2x_USRREG_BATTERY) == 0;
}
2021-09-27 14:51:23 -04:00
//////////////////////////////////////////////////////////
//
2022-12-18 04:41:37 -05:00
// PROTECTED
2021-09-27 14:51:23 -04:00
//
2021-11-17 12:59:50 -05:00
uint8_t SHT2x::crc8(const uint8_t *data, uint8_t len)
2021-09-27 14:51:23 -04:00
{
2023-09-11 04:13:31 -04:00
// CRC-8 formula from page 14 of SHT spec pdf
// Sensirion_Humidity_Sensors_SHT2x_CRC_Calculation.pdf
2022-07-13 09:46:33 -04:00
const uint8_t POLY = 0x31;
uint8_t crc = 0x00;
2021-09-27 14:51:23 -04:00
2021-11-17 12:59:50 -05:00
for (uint8_t j = len; j; --j)
2021-09-27 14:51:23 -04:00
{
crc ^= *data++;
2021-11-17 12:59:50 -05:00
for (uint8_t i = 8; i; --i)
2021-09-27 14:51:23 -04:00
{
crc = (crc & 0x80) ? (crc << 1) ^ POLY : (crc << 1);
}
}
return crc;
}
bool SHT2x::writeCmd(uint8_t cmd)
{
_wire->beginTransmission(SHT2x_ADDRESS);
_wire->write(cmd);
if (_wire->endTransmission() != 0)
{
_error = SHT2x_ERR_WRITECMD;
return false;
}
return true;
}
bool SHT2x::writeCmd(uint8_t cmd, uint8_t value)
{
_wire->beginTransmission(SHT2x_ADDRESS);
_wire->write(cmd);
_wire->write(value);
if (_wire->endTransmission() != 0)
{
_error = SHT2x_ERR_WRITECMD;
return false;
}
return true;
}
bool SHT2x::readBytes(uint8_t n, uint8_t *val, uint8_t maxDuration)
{
_wire->requestFrom((uint8_t)SHT2x_ADDRESS, (uint8_t) n);
uint32_t start = millis();
while (_wire->available() < n)
{
2021-11-17 12:59:50 -05:00
if (millis() - start > maxDuration)
2021-09-27 14:51:23 -04:00
{
_error = SHT2x_ERR_READBYTES;
return false;
}
yield();
}
for (uint8_t i = 0; i < n; i++)
{
val[i] = _wire->read();
}
_error = SHT2x_OK;
return true;
}
////////////////////////////////////////////////////////
//
2021-11-17 12:59:50 -05:00
// DERIVED SHT
2021-09-27 14:51:23 -04:00
//
2023-09-21 10:37:38 -04:00
SHT20::SHT20(TwoWire *wire) : SHT2x(wire)
2021-09-27 14:51:23 -04:00
{
2023-03-26 16:08:27 -04:00
}
2021-09-27 14:51:23 -04:00
2023-09-21 10:37:38 -04:00
SHT21::SHT21(TwoWire *wire) : SHT2x(wire)
2021-09-27 14:51:23 -04:00
{
2023-03-26 16:08:27 -04:00
}
2021-09-27 14:51:23 -04:00
2023-09-21 10:37:38 -04:00
SHT25::SHT25(TwoWire *wire) : SHT2x(wire)
2021-09-27 14:51:23 -04:00
{
2023-03-26 16:08:27 -04:00
}
2021-09-27 14:51:23 -04:00
2021-09-29 07:21:17 -04:00
////////////////////////////////////////////////////////
//
// DERIVED HTU
//
2023-09-21 10:37:38 -04:00
HTU20::HTU20(TwoWire *wire) : SHT2x(wire)
2021-09-29 07:21:17 -04:00
{
2023-03-26 16:08:27 -04:00
}
2021-09-29 07:21:17 -04:00
2023-09-21 10:37:38 -04:00
HTU21::HTU21(TwoWire *wire) : SHT2x(wire)
2021-09-29 07:21:17 -04:00
{
2023-03-26 16:08:27 -04:00
}
2021-09-29 07:21:17 -04:00
2021-09-27 14:51:23 -04:00
2021-11-17 12:59:50 -05:00
////////////////////////////////////////////////////////
//
// DERIVED Si70xx
//
2023-09-21 10:37:38 -04:00
Si7013::Si7013(TwoWire *wire) : SHT2x(wire)
2021-11-17 12:59:50 -05:00
{
2023-03-26 16:08:27 -04:00
}
2021-11-17 12:59:50 -05:00
2023-09-21 10:37:38 -04:00
Si7020::Si7020(TwoWire *wire) : SHT2x(wire)
2021-11-17 12:59:50 -05:00
{
2023-03-26 16:08:27 -04:00
}
2021-11-17 12:59:50 -05:00
2023-09-21 10:37:38 -04:00
Si7021::Si7021(TwoWire *wire) : SHT2x(wire)
2021-11-17 12:59:50 -05:00
{
2023-03-26 16:08:27 -04:00
}
////////////////////////////////////////////////////////
//
// DERIVED Si70xx
//
2023-09-21 10:37:38 -04:00
GY21::GY21(TwoWire *wire) : SHT2x(wire)
2023-03-26 16:08:27 -04:00
{
}
2021-11-17 12:59:50 -05:00
2023-03-26 16:08:27 -04:00
// -- END OF FILE --
2021-11-17 12:59:50 -05:00