HTU21D Humidity/Temperature Sensor



  • Hi,

    I've tried the new humidity/temperature sensor HTU21D from sparkfun and really like this little breakout board.
    It is a much better replacement for the slow und sometimes unreliable DHTxx sensors. Because of the I2C interface wiring and programming is very easy.

    Here is my adapted version of the MySensors humidity sketch (you need the HTU21D library from sparkfun):

    #include <SPI.h>                                                                                                                                                            
    #include <MySensor.h>                                                                                                                                                       
    #include <Wire.h>                                                                                                                                                           
    #include <HTU21D.h>                                                                                                                                                         
    
    #define CHILD_ID_HUM 0                                                                                                                                                      
    #define CHILD_ID_TEMP 1                                                                                                                                                     
    unsigned long SLEEP_TIME = 60000; // Sleep time between reads (in milliseconds)                                                                                             
                                                                                                                                                                            
    MySensor gw;                                                                                                                                                                
                                                                                                                                                                            
    //Create an instance of the object                                                                                                                                          
    HTU21D myHumidity;                                                                                                                                                          
                                                                                                                                                                            
    boolean metric = true;                                                                                                                                                      
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);                                                                                                                                      
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);                                                                                                                                   
                                                                                                                                                                            
    void setup()                                                                                                                                                                
    {                                                                                                                                                                           
      gw.begin();                                                                                                                                                               
                                                                                                                                                                            
      // Send the Sketch Version Information to the Gateway                                                                                                                     
      gw.sendSketchInfo("Humidity", "2.0");                                                                                                                                     
                                                                                                                                                                            
      // Register all sensors to gw (they will be created as child devices)                                                                                                     
      gw.present(CHILD_ID_HUM, S_HUM);                                                                                                                                          
      gw.present(CHILD_ID_TEMP, S_TEMP);                                                                                                                                        
    
      metric = gw.getConfig().isMetric;                                                                                                                                         
      myHumidity.begin();                                                                                                                                                       
    }                                                                                                                                                                           
    void loop()                                                                                                                                                                 
    {                                                                                                                                                                           
      float temperature = myHumidity.readTemperature();                                                                                                                         
      if (!metric) {                                                                                                                                                            
          temperature = (temperature * 1.8) + 32.0;                                                                                                                             
      }                                                                                                                                                                         
      gw.send(msgTemp.set(temperature, 1));                                                                                                                                     
    
      float humidity = myHumidity.readHumidity();                                                                                                                               
      gw.send(msgHum.set(humidity, 1));                                                                                                                                         
                                                                                                                                                                            
      gw.sleep(SLEEP_TIME); //sleep a bit                                                                                                                                       
    }
    

    cheers


  • Mod

    @Talisker This is a cheaper version of the Sensirion temp/humidity sensors.
    I have very good experience with Sensirion devices -- I have one measuring temp/humidity levels outside for over a year now so I find them very reliable.

    You could also have a look at silicon labs SI702x devices. They're also compatible.


  • Admin

    @Talisker

    Welcome, and thanks for the sketch!



  • I know this is an old topic, but having recently purchased HTU21D i2c sensor, I have taken the sensebender code and adapted it for this sensor. It is less versatile than Si7021.
    The code reports temperature, humidity and battery voltage.

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - Henrik Ekblad
     * Version 1.1 - Alexander Shestakovsky adopted for HTU21D
    *
     * DESCRIPTION
     * Temperature and humidity HTU21D sensor module  
     * http://www.mysensors.org/build/pressure
     *
     */
     
    #include <SPI.h>
    #include <MySensor.h>  
    #include <Wire.h>
    #include <HTU21D.h>
    #include <avr/power.h>
    
    #define NODE_ADDRESS   5
    #define RELEASE "1.1"
    
    
    #define CHILD_ID_TEMP 0
    #define CHILD_ID_HUM 1
    #define BATT_SENSOR 2 
    
    // Sleep time between reads (in seconds). 
    #define MEASURE_INTERVAL 60000 
    #define FORCE_TRANSMIT_INTERVAL 30
    
    #define HUMI_TRANSMIT_THRESHOLD 0.3
    #define TEMP_TRANSMIT_THRESHOLD 0.3
    
    MySensor gw;
    
    HTU21D humiditySensor;
    
    // Sensor messages
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgBatt(BATT_SENSOR, V_VOLTAGE);
    
    
    // Pins
    #define LED_PIN 8
    
    
    // Global settings
    int measureCount = 0;
    int sendBattery = 0;
    boolean isMetric = true;
    boolean highfreq = true;
    
    // Storage of old measurements
    float lastTemperature = -100;
    float lastHumidity = -100;
    long lastBattery = -100;
    
    
    
    void setup() 
    {
      pinMode(LED_PIN, OUTPUT);
      digitalWrite(LED_PIN, LOW);
    
      Serial.begin(115200);
      Serial.print(F("HTU21D Sensor"));
      Serial.print(RELEASE);
      Serial.flush();
    
      digitalWrite(LED_PIN, HIGH); 
      
      gw.begin(NULL, NODE_ADDRESS, false);
    
      
      humiditySensor.begin();
    
      digitalWrite(LED_PIN, LOW);
      
      // Send the sketch version information to the gateway and Controller
      gw.sendSketchInfo("Temp/Hum Sensor - HTU21D", RELEASE);
      Serial.flush();
      Serial.println(F(" - Online!"));  
      // Register sensors to gw (they will be created as child devices)
      gw.present(CHILD_ID_TEMP, S_TEMP);
      gw.present(CHILD_ID_HUM, S_HUM);
      gw.present(BATT_SENSOR, S_POWER);
      
      isMetric = gw.getConfig().isMetric;
      Serial.print(F("isMetric: ")); Serial.println(isMetric);
      sendTempHumidityMeasurements(false);
      sendBattLevel(false);
    }
    
    void loop() {
      measureCount ++;
      sendBattery ++;
      bool forceTransmit = false;
      
      if ((measureCount == 5) && highfreq) 
      {
        clock_prescale_set(clock_div_8); // Switch to 1Mhz for the reminder of the sketch, save power.
        highfreq = false;
      } 
      
      if (measureCount > FORCE_TRANSMIT_INTERVAL) { // force a transmission
        forceTransmit = true; 
        measureCount = 0;
      }
        
      gw.process();
    
      sendTempHumidityMeasurements(forceTransmit);
      digitalWrite(LED_PIN, HIGH);
      delay(50); 
      digitalWrite(LED_PIN, LOW); 
    
      if (sendBattery > 60) 
      {
         sendBattLevel(forceTransmit); // Not needed to send battery info that often
         sendBattery = 0;
      }
      
      gw.sleep(MEASURE_INTERVAL);  
    }
    
    
    /*********************************************
     *
     * Sends temperature and humidity from Si7021 sensor
     *
     * Parameters
     * - force : Forces transmission of a value (even if it's the same as previous measurement)
     *
     *********************************************/
    void sendTempHumidityMeasurements(bool force)
    {
      bool tx = force;
      
    float temperature = humiditySensor.readTemperature();
    float humidity = humiditySensor.readHumidity();
     
     float diffTemp = abs(lastTemperature - temperature);
     float diffHum = abs(lastHumidity - humidity);
    
      Serial.print(F("TempDiff :"));Serial.println(diffTemp);
      Serial.print(F("HumDiff  :"));Serial.println(diffHum);   
       
    
      if (diffTemp > TEMP_TRANSMIT_THRESHOLD) tx = true;
      if (diffHum >= HUMI_TRANSMIT_THRESHOLD) tx = true;
    
      if (tx) {
        measureCount = 0;
        
        Serial.print("T: ");Serial.println(temperature);
        Serial.print("H: ");Serial.println(humidity);
        
        gw.send(msgTemp.set(temperature,1));
        gw.send(msgHum.set(humidity,1));
        lastTemperature = temperature;
        lastHumidity = humidity;
      }
    }
    
    /********************************************
     *
     * Sends battery information (battery percentage)
     *
     * Parameters
     * - force : Forces transmission of a value
     *
     *******************************************/
    void sendBattLevel(bool force)
    {
      if (force) lastBattery = -1;
      long vcc = readVcc();
      if (vcc != lastBattery) {
        lastBattery = vcc;
    
    #ifdef BATT_SENSOR
        float Volt = vcc / 1000.0;
        gw.send(msgBatt.set(Volt,2));
    #endif
    
        // Calculate percentage
    
        vcc = vcc - 1800; // subtract 1.9V from vcc, as this is the lowest voltage we will operate at
        
        long percent = vcc / 14.0;
        gw.sendBatteryLevel(percent);
      }
    }
    
    /*******************************************
     *
     * Internal battery ADC measuring 
     *
     *******************************************/
    long readVcc() {
      // Read 1.1V reference against AVcc
      // set the reference to Vcc and the measurement to the internal 1.1V reference
      #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
        ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
      #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
        ADMUX = _BV(MUX5) | _BV(MUX0);
      #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
        ADcdMUX = _BV(MUX3) | _BV(MUX2);
      #else
        ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
      #endif  
     
      delay(2); // Wait for Vref to settle
      ADCSRA |= _BV(ADSC); // Start conversion
      while (bit_is_set(ADCSRA,ADSC)); // measuring
     
      uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH  
      uint8_t high = ADCH; // unlocks both
     
      long result = (high<<8) | low;
     
      result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
      return result; // Vcc in millivolts
    }
    

  • Hardware Contributor

    We did just do the same here.



  • @LastSamurai Damn! I should have done a better search on the forum. Anyway, thanks for bringing it up. HTU21D is a good inexpensive sensor so I wonder why we have not had anything done with it before


Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.