Humidity and Temperature Sensor Driver HIH6130 I2C - Project Showcase - Netduino Forums
   
Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Humidity and Temperature Sensor Driver HIH6130 I2C

I2C Humidity Temperature Sensor Driver HIH6130

  • Please log in to reply
13 replies to this topic

#1 ShVerni

ShVerni

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationNew York, New York

Posted 05 July 2013 - 10:58 PM

Hello all,
 
So a little while ago I picked up this nifty little digital humidity and temperature sensor (HIH6130):
 
https://www.sparkfun.../products/11295
 
This was my excuse to learn more about I2C and bitwise operations on the Netduino. To that end, this is my first attempt at a driver for the HIH6130 sensor. Not only will this driver give you accurate temperature and humidity readings, but can also give you the calculated heat index!
 
Further, if you optionally connect the VDD to a digital pin, the driver is capable of putting the sensor into command mode for reading and writing to the EEPROM and configuring the sensor settings. The sensor also provides optional high and low humidity alarm pins, which are fully configurable through the driver, and use event handlers to trigger whenever the alarm state changes.
 
Here's an example how the driver is used:

public class Program
    {
        private static HIH6130 sensor;
        public static void Main()
        {
            //Create the sensor           
            sensor = new HIH6130(0x27, power: Pins.GPIO_PIN_D0, AL_H: Pins.GPIO_PIN_D1);
            //Enter command mode            
            sensor.enterCommandMode();
            //Read the current sensor configuration            
            byte[] config = new byte[3];
            sensor.readEEPROM(HIH6130.EEPROM.Cust_Config, config);
            //Write some random data to the custom storage EEPROM            
            byte[] data = new byte[] { 0x20, 0x2F };
            sensor.writeCustomROM(data, 2);
            //Read the custom data            
            byte[] custom = new byte[3];
            sensor.readEEPROM(HIH6130.EEPROM.Cust_ID2, custom);
            //Set the high humidity alarm            
            sensor.setAlarmHigh(80, 75);
            //Exit command mode            
            sensor.exitCommandMode(true);
            //Attach a high alarm event            
            sensor.highAlarmEvent += sensor_highAlarmEvent;
            while (true)
            {
                //Take a measurement. Note: The alarm will only trigger after a measurement, so we need to keep taking measurements
                sensor.takeMeasurement();
                Debug.Print("Temperature: " + sensor.tempC.ToString("f") + "\nHumidity: " + sensor.hum.ToString("f") + "%\nHeat index: " + sensor.heatIndexC.ToString("f"));
                Thread.Sleep(60000);
            }
        }

        static void sensor_highAlarmEvent(object sender, HIH6130.AlarmArgs e)
        {
            Debug.Print("The alarm temperature is: " + e.TempC.ToString("f") + "\nThe alarm humidity is: " + e.hum.ToString("f") + "\nThe alarm pin state is: " + e.state.ToString());
        }
    }

Anyway, the driver is attached below, any suggestions are more than welcome. If you have any questions, let me know, and enjoy!
Attached File  HIH6130.cs   20.31KB   43 downloads



#2 iced98lx

iced98lx

    Advanced Member

  • Members
  • PipPipPip
  • 134 posts
  • LocationSouth Dakota

Posted 06 August 2013 - 03:06 PM

Bookmarking this one, I do not love the current DHT based options, the i2c option you've shown here looks great.



#3 NooM

NooM

    Advanced Member

  • Members
  • PipPipPip
  • 490 posts
  • LocationAustria

Posted 06 August 2013 - 04:17 PM

wow 30$

 

a dht22 is like 3$

yeah iced is right, the support of dht for netduino is uncool, but still possible.

 

 

suggestion:

remove the sensor.enterCommandMode(); and sensor.exitCommandMode(true); for the user.

make it automatically if you call the functions that wants command mode.



#4 iced98lx

iced98lx

    Advanced Member

  • Members
  • PipPipPip
  • 134 posts
  • LocationSouth Dakota

Posted 06 August 2013 - 09:08 PM

I think the support is tricky enough that I chose specifically not to try to use one, and have been looking for something else. While I think $30 is a lot I'll likely get one, as it's SO much less code/load on the board to get R/H. 

 

Also, I took a peak, nice commenting within and good explanation of everything, it's much appreciated by the community!!



#5 ShVerni

ShVerni

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationNew York, New York

Posted 07 August 2013 - 12:08 AM

Thanks for the feedback!
 

suggestion:
remove the sensor.enterCommandMode(); and sensor.exitCommandMode(true); for the user.
make it automatically if you call the functions that wants command mode.

 

That's an interesting suggestion. The only reason I would hesitate is that the sensor needs to reboot upon leaving command mode or before entering command mode, so if you wanted to pass several commands one after another (say, to set the high and low alarms and write some custom data to the EEPROM) the sensor would powercycle between each command twice (once to enter command mode, once to leave command mode after the first command, again to enter command mode for the second command, etc…). Doing that seems a bit inefficient, and would require some code to make sure the sensor has powered back on before doing anything. A simple Thread.Sleep(250) would probably work, but would slow things down. I should point out the reason I make it optional to reboot when leaving command mode is that the reboot is only necessary to make changes to the EEPROM take effect, so you could leave command mode and enter normal operation without rebooting, and then reboot later to have the changes take effect.

 

I think the support is tricky enough that I chose specifically not to try to use one, and have been looking for something else. While I think $30 is a lot I'll likely get one, as it's SO much less code/load on the board to get R/H.

 
Those were my thoughts exactly. Looking through the DHT thread made it seem very complicated and unreliable, having to implement tweaks like:
 

Due to the resolution of Netduino system timer which is not enough to precisely measure duration of sensor pulses, it may happen that the sensor readout fails due to invalid checksum, usually for specific values of RH or temperature. You could either ignore that or try tuning BitThreshold value in DhtSensor.cs

 
I needed something very reliable and simple, as I was using it to control appliances in my home, and could rack up quite the electricity bill if something went wrong. Also, I2C easily allows for multiple sensors, and of course has all the extra features like EEPROM storage and programmable humidity alarms.
 
Overall, while the HIH is significantly more expensive (though very much less so if purchased from someplace other than SparkFun without the breakout board), I felt it was much easier to implement, and much more reliable than other, non serial sensors.
 

Also, I took a peak, nice commenting within and good explanation of everything, it's much appreciated by the community!!

 

Thank you! I'm always happy to contribute to a community as awesome and helpful as this one is. Let me know if you find any typos :P.



#6 TheBrian

TheBrian

    New Member

  • Members
  • Pip
  • 6 posts

Posted 24 October 2013 - 08:57 PM

Hi ShVerni,

 

Thanks a bunch for posting HIH6130.cs. I would have gotten nowhere without it.

 

As a disclaimer, I have no formal programming experience and still can't fully explain the bit shifting stuff. However, please correct me if I am wrong, but in the function takeMeasurement() shouldn't line:

 

 _hum = (readBuffer[0] << 6 | readBuffer[1]) * 0.006104260774;

 

read:

 

 _hum = (readBuffer[0] << 8 | readBuffer[1]) * 0.006104260774;

 

The difference being a left shift of 8 rather than 6. If I shift 6, the RH is only in the mid teens. If I shift 8 similar to the arduino code out there, I get a more reasonable RH = 60 for my region.

 

I am using the SparkFun breakout board and tested it with an arduino as well. I also sliced up your code and some arduino code so I could see everything at a glance for testing...

public class Program    {        static I2CDevice sensor;        static Double hum;        static Double temp;        static String status;        public static void Main()        {            //0x27 is the default address of the HIH6130.            sensor = new I2CDevice(new I2CDevice.Configuration((Byte)0x27, 300));            while (true)            {                takeMeasurements();                Debug.Print("Device state:   " + status);                Debug.Print("Temperature = " + temp.ToString());                Debug.Print("Relative humidity = " + hum.ToString());                Debug.Print(string.Empty);                Thread.Sleep(3000);            }        }        public static void takeMeasurements()        {            //Byte buffer to hold device output.            byte[] readBuffer = new byte[4];            //Send temp/hum request to HIH6130.            sensor.Execute(new I2CDevice.I2CTransaction[] { I2CDevice.CreateWriteTransaction(new byte[] { (byte)0x00 }) }, 1000);            //Give it a moment to record reading in device.            Thread.Sleep(100);            //Read device reading.            sensor.Execute(new I2CDevice.I2CTransaction[] { I2CDevice.CreateReadTransaction(readBuffer) }, 1000);            //http://www.phanderson.com/arduino/I2CCommunications.pdf (see fig. 4)            byte hhigh = readBuffer[0];            byte hlow = readBuffer[1];            byte thigh = readBuffer[2];            byte tlow = readBuffer[3];            //// Slice of state bytes            byte state = (Byte)((hhigh >> 6) & (Byte)0x03);            // Clean up remaining humidity bytes            hhigh = (Byte)(hhigh & (Byte)0x3f);            // Shift humidity bytes into a value            // Convert value to humidity per data sheet             float hdata = (((uint)hhigh) << 8) | hlow;            hdata = (float)(hdata * 6.10e-3);            // Shift temperature bytes into a value            // Convert value to temperature per data sheet            float tdata = (((uint)thigh) << 8) | tlow;            tdata = tdata / 4;            tdata = (float)(tdata * 1.007e-2 - 40.0);            //Set variables for debug in Main.            switch (state)            {                case 0: status = "normal";                    break;                case 1: status = "stale data";                    break;                case 2: status = "command mode";                    break;                default: status = "diagnostic";                    break;            }            temp = ((tdata * 9) / 5 + 32);            hum = hdata;        }    }

Honestly, I've had a tough time getting my head around bit shifting in conjunction with the "|" operator and am just posting the code in case you see that I'm doing something wrong...

 

Thanks,

Brian



#7 TheBrian

TheBrian

    New Member

  • Members
  • Pip
  • 6 posts

Posted 04 November 2013 - 07:28 PM

Hi ShVerni,

 

In your HIH6130.cs class the method takeMeasurement calculates humidity as:

 

 _hum = (readBuffer[0] << 6 | readBuffer[1]) * 0.006104260774;

 

But, in my tests the bit shift of 6 generates a relative humidity in the teens. If I shift it 8 then I get a more realistic measurement of around 60. A couple of Arduino examples for this sensor also shift 8 bits. Is there something I'm missing?

 

Thanks,

Brian 



#8 TheBrian

TheBrian

    New Member

  • Members
  • Pip
  • 6 posts

Posted 10 November 2013 - 07:28 PM

Hi ShVerni,
 
Thanks for posting the HIH6130.cs. I couldn't have gotten my sensor to work without this code. I do have one question though. In the takeMeasurement method you have:
 
_hum = (readBuffer[0] << 6 | readBuffer[1]) * 0.006104260774;
 
Shouldn't it be a left bit shift of 8, not 6? I'm still getting my head around bit shifts. I am basing my question off of arduino code I've seen for this sensor and the fact that if I use a shift of 6 my RH value is in the teens, but if I use 8 I get a more reasonable value.
 
Thanks,
Brian


#9 ShVerni

ShVerni

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationNew York, New York

Posted 11 November 2013 - 12:38 AM

Hello Brian,

 

I'm glad you found my code useful, and I think you're perfectly right that there is an error with that line. It seems like I, rather absentmindedly, used the same shift for the humidity as for the temperature (d'oh!). The line should read:

_hum = ((readBuffer[0] & 0x3f) << 8  | readBuffer[1]) * 0.006104260774;

I'm pretty new to bit shifts myself, so I'd be happy to go over in more detail what each operation is doing with the sensor data if you'd like. As is evident here, a second pair of eyes really helps to find mistakes.

 

In any case, I've updated the driver with the correct line and reattached it to my first post. I admit, I don't have a separate humidity meter so I can't double check the values, but this should work, though I'd love for someone to verify that with a a proper humidity meter.

 

Thanks for your help catching that mistake, and I'd love to know about the project you're working on!



#10 FourT2

FourT2

    Advanced Member

  • Members
  • PipPipPip
  • 63 posts
  • LocationSeattle, WA

Posted 26 September 2014 - 04:34 PM

Hey ShVerni, thanks for sharing your code, this looks like exactly what I need. I tried DHT11 and could not get this to work at all, though it works perfectly on my Arduinos, and the whole approach seems very unreliable. I will probably pick up the sensor to play with. 



#11 ShVerni

ShVerni

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationNew York, New York

Posted 26 September 2014 - 10:07 PM

You're very welcome! Good luck with your project and let us know what you do!



#12 FourT2

FourT2

    Advanced Member

  • Members
  • PipPipPip
  • 63 posts
  • LocationSeattle, WA

Posted 27 September 2014 - 09:23 AM

ShVerni, can you describe how you wired your sensor to your N2+? I want to make sure I follow the same steps as you when I get my sensor.



#13 ShVerni

ShVerni

    Advanced Member

  • Members
  • PipPipPip
  • 138 posts
  • LocationNew York, New York

Posted 27 September 2014 - 06:39 PM

Hello,

 

So the basic hookup I use is as follows:

 

Sensor      Netduino 2

SDA   --->  SDA

SCL   --->  SCL

VDD  --->   D0

GND  --->  GND

 

A couple of notes:

 

You don't need to connect VDD to a digital output pin, and could instead connect directly to 3.3V on the Neduino, however doing so would preclude you from entering command mode on the sensor. You can also use any GPIO you want for VDD, of course, not just D0.

 

You will also need pull-up resistors on the SDA and SCL lines. I use two 1.6k resistors, but anything between 1k-3k would probably work.



#14 FourT2

FourT2

    Advanced Member

  • Members
  • PipPipPip
  • 63 posts
  • LocationSeattle, WA

Posted 27 September 2014 - 09:39 PM

Thanks, I will try this out when my sensor comes in!







Also tagged with one or more of these keywords: I2C, Humidity, Temperature, Sensor, Driver, HIH6130

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.