123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- /*
- SHT2x - Humidity Library for Arduino.
- Get humidity and temperature from the HTU21D/SHT2x sensors.
-
- Hardware Setup:
- Attach the SDA pin to A4, SCL to A5.
-
- Software:
- Call SHT2x.Begin() in setup.
- SHT2x.ReadHumidity() will return a float containing the humidity. Ex: 54.7
- SHT2x.ReadTemperature() will return a float containing the temperature in Celsius. Ex: 24.1
- SHT2x.SetResolution(byte: 0b.76543210) sets the resolution of the readings.
-
- Copyright (C) 2015 Nuno Chaveiro nchaveiro[at]gmail.com Lisbon, Portugal
- Copyright (C) 2020 Thomas Buck <thomas@xythobuz.de>
- */
-
- #include <Wire.h>
- #include "SHT2x.h"
-
- SHT2x::SHT2x(uint8_t _addr, TwoWire* _wire) {
- addr = _addr;
- wire = _wire;
- }
-
- void SHT2x::begin(void) {
- wire->begin();
- }
-
- bool SHT2x::GetAlive(void) {
- uint16_t r = readSensor(TRIGGER_TEMP_MEASURE_HOLD);
- if ((r == ERROR_TIMEOUT) || (r == ERROR_CRC)) {
- return false;
- }
- return true;
- }
-
- /**********************************************************
- * GetHumidity
- * Gets the current humidity from the sensor.
- *
- * @return float - The relative humidity in %RH
- **********************************************************/
- float SHT2x::GetHumidity(void) {
- return (-6.0 + 125.0 / 65536.0 * (float)(readSensor(TRIGGER_HUMD_MEASURE_HOLD)));
- }
-
- /**********************************************************
- * GetTemperature
- * Gets the current temperature from the sensor.
- *
- * @return float - The temperature in Deg C
- **********************************************************/
- float SHT2x::GetTemperature(void) {
- return (-46.85 + 175.72 / 65536.0 * (float)(readSensor(TRIGGER_TEMP_MEASURE_HOLD)));
- }
-
- /**********************************************************
- * Sets the sensor resolution to one of four levels:
- * 0/0 = 12bit RH, 14bit Temp
- * 0/1 = 8bit RH, 12bit Temp
- * 1/0 = 10bit RH, 13bit Temp
- * 1/1 = 11bit RH, 11bit Temp
- * Power on default is 0/0
- **********************************************************/
- void SHT2x::setResolution(uint8_t resolution) {
- uint8_t userRegister = read_user_register(); //Go get the current register state
- userRegister &= B01111110; //Turn off the resolution bits
- resolution &= B10000001; //Turn off all other bits but resolution bits
- userRegister |= resolution; //Mask in the requested resolution bits
-
- //Request a write to user register
- wire->beginTransmission(addr);
- wire->write(WRITE_USER_REG); //Write to the user register
- wire->write(userRegister); //Write the new resolution bits
- wire->endTransmission();
- }
-
- uint8_t SHT2x::read_user_register(void) {
- uint8_t userRegister;
-
- //Request the user register
- wire->beginTransmission(addr);
- wire->write(READ_USER_REG); //Read the user register
- wire->endTransmission();
-
- //Read result
- wire->requestFrom(addr, 1);
-
- userRegister = wire->read();
-
- return userRegister;
- }
-
- uint16_t SHT2x::readSensor(uint8_t command) {
- uint16_t result;
-
- wire->beginTransmission(addr); //begin
- wire->write(command); //send the pointer location
- wire->endTransmission(); //end
-
- //Hang out while measurement is taken. 50mS max, page 4 of datasheet.
- delay(55);
-
- //Comes back in three bytes, data(MSB) / data(LSB) / Checksum
- wire->requestFrom(addr, 3);
-
- //Wait for data to become available
- int counter = 0;
- while (wire->available() < 3) {
- counter++;
- delay(1);
- if(counter > 100) return ERROR_TIMEOUT; //Error timout
- }
-
- //Store the result
- result = ((wire->read()) << 8);
- result |= wire->read();
- //Check validity
- uint8_t checksum = wire->read();
- if(check_crc(result, checksum) != 0) return(ERROR_CRC); //Error checksum
- //sensorStatus = rawTemperature & 0x0003; //get status bits
- result &= ~0x0003; // clear two low bits (status bits)
- return result;
- }
-
- //Give this function the 2 byte message (measurement) and the check_value byte from the HTU21D
- //If it returns 0, then the transmission was good
- //If it returns something other than 0, then the communication was corrupted
- //From: http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html
- //POLYNOMIAL = 0x0131 = x^8 + x^5 + x^4 + 1 : http://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks
- #define SHIFTED_DIVISOR 0x988000 // This is the 0x0131 polynomial shifted to farthest left of three bytes
-
- uint8_t SHT2x::check_crc(uint16_t message_from_sensor, uint8_t check_value_from_sensor) {
- // Pad with 8 bits because we have to add in the check value
- uint32_t remainder = (uint32_t)message_from_sensor << 8;
-
- // Add on the check value
- remainder |= check_value_from_sensor;
- uint32_t divsor = (uint32_t)SHIFTED_DIVISOR;
-
- // Operate on only 16 positions of max 24.
- // The remaining 8 are our remainder and should be zero when we're done.
- for (int i = 0; i < 16; i++) {
- // Check if there is a one in the left position
- if (remainder & ((uint32_t)1 << (23 - i))) {
- remainder ^= divsor;
- }
-
- // Rotate the divsor max 16 times so that we have 8 bits left of a remainder
- divsor >>= 1;
- }
-
- return (uint8_t)remainder;
- }
|