Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 2 of 2

Thread: HTU21D negative humidity!

  1. #1

    HTU21D negative humidity!

    Good morning all.

    I am working with a HTU21D humidity and temperature sensor, the same as SparkFun URL

    I am using the i2C communication path and there are no other devices/sensors connected to my Teensy 3.2. I am using Windows 10, Arduino 1.6.8 and TeensyLoader 1.28. I really don't know what to make of this.

    Here is what the code below outputs to the serial window: Temperature: -44.2 C Relative Humidity: -6.0 %

    I have checked and redone wiring several times.

    The only difference between the unit as shown by SparkFun, is that in their image the pull up resistors' solder bridge is shown soldered, on mine they are not yet soldered. However, I have 4.7K pull up resistors on my pcb/Teensy board.

    Here is my code (from SparkFun GitHub):
     HTU21D Humidity Sensor Example Code
     By: Nathan Seidle
     SparkFun Electronics
     Date: September 15th, 2013
     License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).
     Get humidity and temperature from the HTU21D sensor.
     Hardware Connections (Breakoutboard to Arduino):
     -VCC = 3.3V
     -GND = GND
     -SDA = A4
     -SCL = A5
     Serial.print it out at 9600 baud to serial monitor.
    #include <Wire.h>
    #define HTDU21D_ADDRESS 0x40  //Unshifted 7-bit I2C address for the sensor
    #define WRITE_USER_REG  0xE6
    #define READ_USER_REG  0xE7
    #define SOFT_RESET  0xFE
    byte sensorStatus;
    void setup()
      Serial.println("HTU21D Example!");
    void loop()
      unsigned int rawHumidity = htdu21d_readHumidity();
      unsigned int rawTemperature = htdu21d_readTemp();
      float temperature = calc_temp(rawTemperature);
      float relativeHumidity = calc_humidity(rawHumidity); //Turn the humidity signal into actual humidity
      Serial.print("Temperature: ");
      Serial.print(temperature, 1); //Print float with one decimal
      Serial.print(" C");
      Serial.print(" Relative Humidity: ");
      Serial.print(relativeHumidity, 1);
      Serial.print(" %");
    //Read the uncompensated temperature value
    unsigned int htdu21d_readTemp()
      //Request the temperature
      //Wait for sensor to complete measurement
      delay(60); //44-50 ms max - we could also poll the sensor
      //Comes back in three bytes, data(MSB) / data(LSB) / CRC
      Wire.requestFrom(HTDU21D_ADDRESS, 3);
      //Wait for data to become available
      int counter = 0;
      while(Wire.available() < 3)
        if(counter > 100) return 998; //Error out
      unsigned char msb, lsb, crc;
      msb =;
      lsb =;
      crc =; //We don't do anything with CRC for now
      unsigned int temperature = ((unsigned int)msb << 8) | lsb;
      temperature &= 0xFFFC; //Zero out the status bits but keep them in place
      return temperature;
    //Read the humidity
    unsigned int htdu21d_readHumidity()
      byte msb, lsb, checksum;
      //Request a humidity reading
      Wire.write(TRIGGER_HUMD_MEASURE_NOHOLD); //Measure humidity with no bus holding
      //Hang out while measurement is taken. 50mS max, page 4 of datasheet.
      //Read result
      Wire.requestFrom(HTDU21D_ADDRESS, 3);
      //Wait for data to become available
      int counter = 0;
      while(Wire.available() < 3)
        if(counter > 100) return 0; //Error out
      msb =;
      lsb =;
      checksum =;
      unsigned int rawHumidity = ((unsigned int) msb << 8) | (unsigned int) lsb;
      rawHumidity &= 0xFFFC; //Zero out the status bits but keep them in place
    //Given the raw temperature data, calculate the actual temperature
    float calc_temp(int SigTemp)
      float tempSigTemp = SigTemp / (float)65536; //2^16 = 65536
      float realTemperature = -46.85 + (175.72 * tempSigTemp); //From page 14
    //Given the raw humidity data, calculate the actual relative humidity
    float calc_humidity(int SigRH)
      float tempSigRH = SigRH / (float)65536; //2^16 = 65536
      float rh = -6 + (125 * tempSigRH); //From page 14
    //Read the user register
    byte read_user_register(void)
      byte userRegister;
      //Request the user register
      Wire.write(READ_USER_REG); //Read the user register
      //Read result
      Wire.requestFrom(HTDU21D_ADDRESS, 1);
      userRegister =;
    //Write to the user register
    //NOTE: We disable all bits except for measurement resolution
    //Bit 7 & 0 = Measurement resolution
    //Bit 6 = Status of battery
    //Bit 5/4/3 = Reserved
    //Bit 2 = Enable on-board heater
    //Bit 1 = Disable OTP reload
    void write_user_register(byte thing_to_write)
      byte userRegister = read_user_register(); //Go get the current register state
      userRegister &= 0b01111110; //Turn off the resolution bits
      thing_to_write &= 0b10000001; //Turn off all other bits but resolution bits
      userRegister |= thing_to_write; //Mask in the requested resolution bits
      //Request a write to user register
      Wire.write(WRITE_USER_REG); //Write to the user register
      Wire.write(userRegister); //Write to the data
    //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
    //POLYNOMIAL = 0x0131 = x^8 + x^5 + x^4 + 1 :
    #define SHIFTED_DIVISOR 0x988000 //This is the 0x0131 polynomial shifted to farthest left of three bytes
    unsigned int check_crc(uint16_t message_from_sensor, uint8_t check_value_from_sensor)
      //Test cases from datasheet:
      //message = 0xDC, result is 0x79
      //message = 0x683A, result is 0x7C
      //message = 0x4E85, result is 0x6B
      uint32_t remainder = (uint32_t)message_from_sensor << 8; //Pad with 8 bits because we have to add in the result/check value
      remainder |= check_value_from_sensor; //Add on the check value
      uint32_t divsor = (uint32_t)SHIFTED_DIVISOR;
      for (int i = 0 ; i < 16 ; i++) //Operate on only 16 positions of max 24. The remaining 8 are our remainder and should be zero when we're done.
        //Serial.print("remainder:  ");
        //Serial.println(remainder, BIN);
        //Serial.print("divsor:     ");
        //Serial.println(divsor, BIN);
        if( remainder & (uint32_t)1<<(23 - i) ) //Check if there is a one in the left position
          remainder ^= divsor;
        divsor >>= 1; //Rotate the divsor max 16 times so that we have 8 bits left of a remainder
      return remainder;

  2. #2
    Hello the list.

    My bad. An accidental brush of the mini USB connection resulted in normal function of the sensor and correct seeming temp and Rh readings. It appears that the usb connector on my Teensy has become worn and the mechanical/electrical connection is sometimes faulty. A slight downward pressure on the USB male connector and the readings are correct.

    Oh well, better late than never.

    Thank you

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts