0.2.0 SHT2x

This commit is contained in:
rob tillaart 2022-07-13 15:46:33 +02:00
parent 69ac9d5f25
commit 02d63b3beb
7 changed files with 261 additions and 42 deletions

View File

@ -64,7 +64,7 @@ for platforms with multiple I2C buses. **begin()** calls **reset()** which can t
- **bool read()** Reads both the temperature and humidity.
Initial release has a blocking delay.
- **bool isConnected()** check if sensor is reachable over I2C. Returns false if not connected.
- **uint16_t getStatus()** returns a 2 bit status. See below.
- **uint16_t getStatus()** returns a 2 bit status. See Status fields below.
- **uint32_t lastRead()** in milliSeconds since start of program.
- **bool reset()** resets the sensor, soft reset, no hard reset supported.
- **float getHumidity()** computes the relative humidity in % based off the latest raw reading, and returns it.
@ -76,6 +76,8 @@ Note that the temperature and humidity values are recalculated on every call to
If you're worried about the extra cycles, you should make sure to cache these values or only request them
after you've performed a new **read()**.
Note: The raw temperature and raw humidity are ideal to minimize storage or to minimize communication.
### Error interface
@ -125,9 +127,11 @@ Returns false if fails, setting error to **SHT2x_ERR_HEATER_OFF**.
### Electronic ID
- **uint32_t getEIDA()** not tested yet.
- **uint32_t getEIDB()** not tested yet.
- **uint8_t getFirmwareVersion()** not tested yet.
To be tested.
- **uint32_t getEIDA()** returns unique ID part A.
- **uint32_t getEIDB()** returns unique ID part B.
- **uint8_t getFirmwareVersion()** returns firmware version.
### Status fields
@ -142,29 +146,70 @@ From HTU20 datasheet
| 11 | 3 | closed circuit |
## Operation
### Resolution
See examples
**Warning experimental**
- needs more testing as results are not in line with the datasheet.
- only tested on a HTUxx sensor.
- tested with **SHT2X_resolution.ino**
- **void setResolution(uint8_t res)** res = 0..3, other values return false.
- **uint8_t getResolution()** returns resolution set 0..3.
Datasheet SHT20 Table 8: (resolution)
| RES | Humidity | Temperature |
|:-----:|:---------:|:-----------:|
| 0 | 12 bit | 14 bit |
| 1 | 08 bit | 12 bit |
| 2 | 10 bit | 13 bit |
| 3 | 11 bit | 11 bit |
Datasheet SHT20 Table 7: (timing) and results of real measurements.
( https://github.com/RobTillaart/SHT2x/pull/11 )
| RES | HUM | TEMP | TOTAL | REAL |
|:-----:|:-----:|:------:|:-------:|:------:|
| 0 | 29 | 85 | 114 | 116 |
| 1 | 4 | 22 | 26 | 113 |
| 2 | 9 | 43 | 52 | 084 |
| 3 | 15 | 11 | 26 | 102 |
Timing in milliseconds.
### Battery
- **bool batteryOK()** returns true if VCC > 2.5 Volts.
## Future
- test
- test test test
- get hardware
- investigate resolution anomalies
- improve documentation
- add **getSerialNumber()**
**getEIDA()** and **getEIDB()** covers this
- fix TODO in code (.cpp and .h)
- add examples
- test resolutions
- performance different resolutions
- test battery
- update unit tests
#### 0.3.0
- add crc8 check (need sensor)
- improve error handling (all code paths)
- investigate blocking delay() in read
- optimize... Q: need async interface?
- add crc8 check
- fix TODO in code (4 in CPP)
- **ASYNC** NO HOLD call to read T or H
- **void requestTemperature()** ==> **void readTemperature()**
- **void requestHumidity()** ==> **void readHumidity()**
#### wont
### 0.2.0
- add **getSerialNumber()**
**getEIDA()** and **getEIDB()** covers this
- add **setResolution()** and **getResolution()**
- write user register E6
- read user register R7
(note table 8 + FIgure 16 code)
- add **getBatteryStatus()**

View File

@ -1,7 +1,7 @@
//
// FILE: SHT2x.cpp
// AUTHOR: Rob Tillaart, Viktor Balint
// VERSION: 0.1.4
// VERSION: 0.2.0
// DATE: 2021-09-25
// PURPOSE: Arduino library for the SHT2x temperature and humidity sensor
// URL: https://github.com/RobTillaart/SHT2x
@ -17,6 +17,12 @@
// 0.1.3 2021-12-28 update library.json, license, minor edits
// 0.1.4 2022-06-21 Fix #9 ESP32 wire.begin()
// Fix getEIDB() bug.
//
// 0.2.0 2022-07-10 Fix #11 RawTemp + rawHum (kudos to theandy94)
// add experimental getResolution() + setResolution()
// adjust read delay
// add experimental batteryOK()
// add CRC in read() - no fail.
#include "SHT2x.h"
@ -34,6 +40,11 @@
#define SHT2x_ADDRESS 0x40
#define SHT2x_USRREG_RESOLUTION 0x81
#define SHT2x_USRREG_BATTERY 0x20
#define SHT2x_USRREG_HEATER 0x04
SHT2x::SHT2x()
{
_lastRead = 0;
@ -45,6 +56,7 @@ SHT2x::SHT2x()
_heaterOn = false;
_error = SHT2x_OK;
_status = 0;
_resolution = 0;
}
@ -86,20 +98,28 @@ bool SHT2x::read()
// TEMPERATURE
writeCmd(SHT2x_GET_TEMPERATURE_NO_HOLD);
delay(70);
// table 7
if (_resolution == 3) delay(11); // 11 bit
else if (_resolution == 1) delay(22); // 12 bit
else if (_resolution == 2) delay(43); // 13 bit
else delay(85); // 14 bit
if (readBytes(3, (uint8_t*) &buffer[0], 90) == false)
{
_error = SHT2x_ERR_READBYTES;
return false;
}
// TODO CRC8 check
// error = SHT2x_ERR_CRC_TEMP;
_rawTemperature = buffer[0] << 8;
if (crc8(buffer, 2) != buffer[2])
{
_error = SHT2x_ERR_CRC_TEMP;
// return false; // do not fail yet
}
_rawTemperature = buffer[0] << 8;
_rawTemperature += buffer[1];
_rawTemperature &= 0xFFFC;
_status = buffer[1] & 0x0003;
if (_status == 0xFF) // TODO != 0x01
if (_status == 0xFF) // TODO != 0x01 (need HW to test)
{
_error = SHT2x_ERR_READBYTES;
return false;
@ -107,19 +127,27 @@ bool SHT2x::read()
// HUMIDITY
writeCmd(SHT2x_GET_HUMIDITY_NO_HOLD);
delay(30);
// table 7
if (_resolution == 1) delay(4); // 8 bit
else if (_resolution == 2) delay(9); // 10 bit
else if (_resolution == 3) delay(15); // 11 bit
else delay(29); // 12 bit
if (readBytes(3, (uint8_t*) &buffer[0], 30) == false)
{
return false;
}
// TODO CRC8 check
// _error = SHT2x_ERR_CRC_HUM;
_rawHumidity = buffer[0] << 8;
if (crc8(buffer, 2) != buffer[2])
{
_error = SHT2x_ERR_CRC_HUM;
// return false; // do not fail yet
}
_rawHumidity = buffer[0] << 8;
_rawHumidity += buffer[1];
_rawHumidity &= 0xFFFC;
_rawHumidity &= 0xFFFC; // TODO is this mask OK? as humidity is max 12 bit..
_status = buffer[1] & 0x0003;
if (_status == 0xFF) // TODO != 0x02
if (_status == 0xFF) // TODO != 0x02 (need HW to test)
{
_error = SHT2x_ERR_READBYTES;
return false;
@ -148,8 +176,7 @@ float SHT2x::getHumidity()
bool SHT2x::reset()
{
bool b = writeCmd(SHT2x_SOFT_RESET);
if (b == false) return false;
return true;
return b;
}
@ -184,7 +211,9 @@ bool SHT2x::heatOn()
_error = SHT2x_ERR_READBYTES;
return false;
}
userReg |= 0x04; // HEAT BIT ON
// HEAT BIT ON
userReg |= SHT2x_USRREG_HEATER;
if (writeCmd(SHT2x_READ_USER_REGISTER, userReg) == false)
{
@ -206,7 +235,10 @@ bool SHT2x::heatOff()
_error = SHT2x_ERR_READBYTES;
return false;
}
userReg &= ~0x04; // HEAT BIT OFF
// HEAT BIT OFF
userReg &= ~SHT2x_USRREG_HEATER;
if (writeCmd(SHT2x_READ_USER_REGISTER, userReg) == false)
{
_error = SHT2x_ERR_HEATER_OFF; // can be serious!
@ -338,6 +370,55 @@ uint8_t SHT2x::getFirmwareVersion()
}
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);
if (writeCmd(SHT2x_READ_USER_REGISTER, userReg) == false)
{
_error = SHT2x_ERR_RESOLUTION;
return false;
}
_resolution = res;
return true;
}
uint8_t SHT2x::getResolution()
{
return _resolution;
};
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;
}
//////////////////////////////////////////////////////////
//
// PRIVATE
@ -345,8 +426,9 @@ uint8_t SHT2x::getFirmwareVersion()
uint8_t SHT2x::crc8(const uint8_t *data, uint8_t len)
{
// CRC-8 formula from page 14 of SHT spec pdf
const uint8_t POLY(0x31);
uint8_t crc(0xFF);
// Sensirion_Humidity_Sensors_SHT2x_CRC_Calculation.pdf
const uint8_t POLY = 0x31;
uint8_t crc = 0x00;
for (uint8_t j = len; j; --j)
{

View File

@ -2,7 +2,7 @@
//
// FILE: SHT2x.h
// AUTHOR: Rob Tillaart, Viktor Balint
// VERSION: 0.1.4
// VERSION: 0.2.0
// DATE: 2021-09-25
// PURPOSE: Arduino library for the SHT2x temperature and humidity sensor
// URL: https://github.com/RobTillaart/SHT2x
@ -13,7 +13,7 @@
#include "Wire.h"
#define SHT2x_LIB_VERSION (F("0.1.4"))
#define SHT2x_LIB_VERSION (F("0.2.0"))
// fields getStatus
@ -35,6 +35,9 @@
#define SHT2x_ERR_CRC_STATUS 0x87 // not used
#define SHT2x_ERR_HEATER_COOLDOWN 0x88
#define SHT2x_ERR_HEATER_ON 0x89
// 0.2.0
#define SHT2x_ERR_RESOLUTION 0x8A
class SHT2x
@ -55,8 +58,8 @@ public:
float getTemperature();
float getHumidity();
uint16_t getRawTemperature() { return _rawHumidity; };
uint16_t getRawHumidity() { return _rawTemperature; };
uint16_t getRawTemperature() { return _rawTemperature; };
uint16_t getRawHumidity() { return _rawHumidity; };
// might take up to 15 milliseconds.
bool reset();
@ -98,6 +101,24 @@ public:
uint32_t getEIDB();
uint8_t getFirmwareVersion();
// experimental 0.2.0 - needs testing.
// table 8 SHT20 datasheet
// table 7 shows different timing per resolution
// every level is roughly factor 2 in time.
// RES HUM TEMP
// 0 12 bit 14 bit
// 1 08 bit 12 bit
// 2 10 bit 13 bit
// 3 11 bit 11 bit
// 4..255 returns false
bool setResolution(uint8_t res = 0);
// returns RES set (cached value)
uint8_t getResolution();
bool batteryOK();
private:
uint8_t crc8(const uint8_t *data, uint8_t len);
@ -119,6 +140,7 @@ private:
uint8_t _status;
uint8_t _error;
uint8_t _resolution;
};

View File

@ -0,0 +1,67 @@
//
// FILE: SHT2x_resolution.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo resolution and battery
// URL: https://github.com/RobTillaart/SHT2x
#include "Wire.h"
#include "SHT2x.h"
uint32_t start;
uint32_t stop;
SHT2x sht;
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("SHT2x_LIB_VERSION: \t");
Serial.println(SHT2x_LIB_VERSION);
sht.begin();
uint8_t stat = sht.getStatus();
Serial.print("STAT:\t");
Serial.print(stat, HEX);
Serial.println();
Serial.print("BATT:\t");
Serial.print(sht.batteryOK() ? "OK" : "FAIL");
Serial.println();
for (uint8_t res = 0; res < 4; res++)
{
for (uint8_t times = 0; times < 5; times++)
{
sht.setResolution(res);
Serial.print("RES:\t");
Serial.print(sht.getResolution());
delay(100);
start = micros();
sht.read();
stop = micros();
Serial.print("\t");
Serial.print(stop - start);
Serial.print("\t");
Serial.print(sht.getTemperature(), 3);
Serial.print("\t");
Serial.println(sht.getHumidity(), 3);
delay(3000);
}
}
Serial.println("\ndone...");
}
void loop()
{
}
// -- END OF FILE --

View File

@ -18,7 +18,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/SHT2x.git"
},
"version": "0.1.4",
"version": "0.2.0",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",

View File

@ -1,5 +1,5 @@
name=SHT2x
version=0.1.4
version=0.2.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for the I2C SHT20 SHT21 SHT25 series temperature and humidity sensor.

View File

@ -30,6 +30,7 @@
It appears that Wire.write does not fail without sensor...
*/
#include <ArduinoUnitTests.h>
#include "Arduino.h"
@ -39,6 +40,7 @@ int expect; // TODO needed as there seems a problem with 8 bit comparisons (cha
uint32_t start, stop;
unittest_setup()
{
fprintf(stderr, "SHT2x_LIB_VERSION: %s \n", (char *) SHT2x_LIB_VERSION);
@ -73,6 +75,7 @@ unittest(test_constants_2)
assertEqual(SHT2x_ERR_CRC_STATUS , 0x87);
assertEqual(SHT2x_ERR_HEATER_COOLDOWN, 0x88);
assertEqual(SHT2x_ERR_HEATER_ON , 0x89);
assertEqual(SHT2x_ERR_RESOLUTION , 0x8A);
}