User avatar
Davespice
Forum Moderator
Forum Moderator
Posts: 1665
Joined: Fri Oct 14, 2011 8:06 pm
Location: The Netherlands

Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu May 08, 2014 1:06 pm

Hey folks, I can't talk too much about what this is for but I could really use some help here.
I'm almost to the point of...
Image
...so any help would be gratefully received.

This is the product in question.
https://www.sparkfun.com/products/12064 (has a link to the datasheet)

I've got a working C program for it here which uses GordonDrogon's wiringPi library;

Code: Select all

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#include "wiringPi.h"
#include "wiringPiI2C.h"

#define	ADDR	0x40

// cTemp:
//	Convert sensor reading into temperature.
//	See page 14 of the datasheet

double cTemp (int sensorTemp)
{
  double tSensorTemp = sensorTemp / 65536.0 ;
  return -46.85 + (175.72 * tSensorTemp) ;
}

// cHumid:
//	Convert sensor reading into humidity.
//	See page 15 of the datasheet

double cHumid (int sensorHumid)
{
  double tSensorHumid = sensorHumid / 65536.0 ;
  return -6.0 + (125.0 * tSensorHumid) ;
}

int main (void)
{
  int fd ;
  unsigned int x ;
  unsigned char buf [4] ;
  unsigned int temp, humid ;

  wiringPiSetup () ;

  if ((fd = wiringPiI2CSetup (ADDR)) < 0)
  {
    fprintf (stderr, "Unable to open I2C device: %s\n", strerror (errno)) ;
    exit (-1) ;
  }

// Temperature

  wiringPiI2CWrite (fd, 0xF3) ;
  delay (100) ;
  x = read (fd, buf, 3) ;

  if (x != 3)
    printf ("%d: %02X %02X %02X\n", x, buf[0], buf[1], buf[2]) ;

  temp = (buf [0] << 8 | buf [1]) & 0xFFFC ;

  printf ("%4d %5.1fC\n", temp, cTemp (temp)) ;

// Yoomidity

  wiringPiI2CWrite (fd, 0xF5) ;
  delay (100) ;
  x = read (fd, buf, 3) ;

  if (x != 3)
    printf ("%d: %02X %02X %02X\n", x, buf[0], buf[1], buf[2]) ;

  humid = (buf [0] << 8 | buf [1]) & 0xFFFC ;

  printf ("%4d %5.2f %%rh\n", humid, cHumid (humid)) ;

  return 0 ;
}
However I'm trying to write the same program in Python but am running into problems. I need it in the python language for consistency across the rest of the project since the code will be used for educational resources.
This is what I have so far;

Code: Select all

#!/usr/bin/python
import time
import smbus

msleep = lambda x: time.sleep(x/1000.0)

ADDR = 0x40

i2c = smbus.SMBus(1)

CMD_READ_TEMP_HOLD = 0xe3
CMD_READ_HUM_HOLD = 0xe5
CMD_READ_TEMP_NOHOLD = 0xf3
CMD_READ_HUM_NOHOLD = 0xf5
CMD_WRITE_USER_REG = 0xe6
CMD_READ_USER_REG = 0xe7
CMD_SOFT_RESET= 0xfe

i2c.write_byte(ADDR, CMD_SOFT_RESET)
msleep(100)

i2c.write_byte(ADDR, CMD_READ_TEMP_NOHOLD)
msleep(100)

data = i2c.read_i2c_block_data(ADDR, CMD_READ_TEMP_NOHOLD, 3)
msleep(100)
No matter what I try the read_i2c_block_data line throws IOError: [Errno 5] Input/output error

I am aware of some existing libraries for this sensor, but they all exhibit this same issue for me. These include;
https://github.com/jwineinger/quick2wir ... /htu21d.py
https://github.com/randymxj/Adafruit-Ra ... _HTU21D.py

Can anyone see what is going wrong with the python code?

simplesi
Posts: 2327
Joined: Fri Feb 24, 2012 6:19 pm
Location: Euxton, Lancashire, UK

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu May 08, 2014 1:12 pm

JFI - I find that once I get an Python I2C error 5 - I have to power cycle before re-running any program as the PI seems to "remember" the errored state and you can end up applying a fix but not know that it would have worked had you just power cycled

Pain in the neck but I can fix I2C bugs quicker nowadays that way

Simon
Seeking help with Scratch and I/O stuff for Primary age children
http://cymplecy.wordpress.com/ @cymplecy on twitter

User avatar
Davespice
Forum Moderator
Forum Moderator
Posts: 1665
Joined: Fri Oct 14, 2011 8:06 pm
Location: The Netherlands

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu May 08, 2014 1:18 pm

Okay cool, I don't think its that though because I can run the c binary directly after getting the error 5 and that works okay.

simplesi
Posts: 2327
Joined: Fri Feb 24, 2012 6:19 pm
Location: Euxton, Lancashire, UK

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu May 08, 2014 1:29 pm

I think its am SMBUS python module bug - its certainly pops up in my ScratchGPIO developement and it took a while before I relasied what was going on so now I correct what I think gives the error - re-save - reboot and then retry :(

Slow but its faster than not doing it I find :)

Simon
Seeking help with Scratch and I/O stuff for Primary age children
http://cymplecy.wordpress.com/ @cymplecy on twitter

User avatar
joan
Posts: 16247
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu May 08, 2014 2:07 pm

You could bypass the smbus module and just use the raw device.

I have some code which demonstrates the principle.

Code: Select all

#!/usr/bin/env python

import io
import fcntl

I2C_SLAVE=0x0703

class i2c:

   def __init__(self, device, bus):

      self.fr = io.open("/dev/i2c-"+str(bus), "rb", buffering=0)
      self.fw = io.open("/dev/i2c-"+str(bus), "wb", buffering=0)

      # set device address

      fcntl.ioctl(self.fr, I2C_SLAVE, device)
      fcntl.ioctl(self.fw, I2C_SLAVE, device)

   def write(self, bytes):
      self.fw.write(bytes)

   def read(self, bytes):
      return self.fr.read(bytes)

   def close(self):
      self.fw.close()
      self.fr.close()

if __name__ == "__main__":

   import time
   import struct

   import i2c

   dev = i2c.i2c(0x53, 1) # device 0x53, bus 1

   dev.write("\x2D\x00") # POWER_CTL reset
   dev.write("\x2D\x08") # POWER_CTL measure
   dev.write("\x31\x00") # DATA_FORMAT reset
   dev.write("\x31\x0B") # DATA_FORMAT full res +/- 16g

   num_samples=5000

   sample=[(0,0,0)]*num_samples

   start1 = time.time()

   for s in xrange(num_samples):

      dev.write("\x32")
      sample[s] = struct.unpack('3h', dev.read(6))
      print("x={} y={} z={}".format(sample[s][0], sample[s][1], sample[s][2]))

   end1 = time.time()

   print(end1-start1)

   dev.close()
i2c.py

User avatar
Davespice
Forum Moderator
Forum Moderator
Posts: 1665
Joined: Fri Oct 14, 2011 8:06 pm
Location: The Netherlands

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu May 08, 2014 2:16 pm

Hi simplesi, I did try your suggestion but to no avail. Joan, I am going to try this approach, thanks for that I think it might work.

User avatar
Davespice
Forum Moderator
Forum Moderator
Posts: 1665
Joined: Fri Oct 14, 2011 8:06 pm
Location: The Netherlands

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu May 08, 2014 3:36 pm

Go it working! Woohoo, thanks to Joan.

Code: Select all

#!/usr/bin/python
import struct, array, time, io, fcntl

I2C_SLAVE=0x0703
HTU21D_ADDR = 0x40
CMD_READ_TEMP_HOLD = "\xE3"
CMD_READ_HUM_HOLD = "\xE5"
CMD_READ_TEMP_NOHOLD = "\xF3"
CMD_READ_HUM_NOHOLD = "\xF5"
CMD_WRITE_USER_REG = "\xE6"
CMD_READ_USER_REG = "\xE7"
CMD_SOFT_RESET= "\xFE"

class i2c(object):
   def __init__(self, device, bus):

      self.fr = io.open("/dev/i2c-"+str(bus), "rb", buffering=0)
      self.fw = io.open("/dev/i2c-"+str(bus), "wb", buffering=0)

      # set device address

      fcntl.ioctl(self.fr, I2C_SLAVE, device)
      fcntl.ioctl(self.fw, I2C_SLAVE, device)

   def write(self, bytes):
      self.fw.write(bytes)

   def read(self, bytes):
      return self.fr.read(bytes)

   def close(self):
      self.fw.close()
      self.fr.close()

class HTU21D(object):
	def __init__(self):
		self.dev = i2c(HTU21D_ADDR, 1) #HTU21D 0x40, bus 1
		self.dev.write(CMD_SOFT_RESET) #soft reset
		time.sleep(.1)

	def ctemp(self, sensorTemp):
		tSensorTemp = sensorTemp / 65536.0
		return -46.85 + (175.72 * tSensorTemp)

	def chumid(self, sensorHumid):
		tSensorHumid = sensorHumid / 65536.0
		return -6.0 + (125.0 * tSensorHumid)

	def crc8check(self, value):
		# Ported from Sparkfun Arduino HTU21D Library: https://github.com/sparkfun/HTU21D_Breakout
		remainder = ( ( value[0] << 8 ) + value[1] ) << 8
		remainder |= value[2]
		
		# POLYNOMIAL = 0x0131 = x^8 + x^5 + x^4 + 1
		# divsor = 0x988000 is the 0x0131 polynomial shifted to farthest left of three bytes
		divsor = 0x988000
		
		for i in range(0, 16):
			if( remainder & 1 << (23 - i) ):
				remainder ^= divsor
			divsor = divsor >> 1
		
		if remainder == 0:
			return True
		else:
			return False
	
	def read_tmperature(self):
		self.dev.write(CMD_READ_TEMP_NOHOLD) #measure temp
		time.sleep(.1)

		data = self.dev.read(3)
		buf = array.array('B', data)

		if self.crc8check(buf):
			temp = (buf[0] << 8 | buf [1]) & 0xFFFC
			return self.ctemp(temp)
		else:
			return -255
			
	def read_humidity(self):
		self.dev.write(CMD_READ_HUM_NOHOLD) #measure humidity
		time.sleep(.1)

		data = self.dev.read(3)
		buf = array.array('B', data)
		
		if self.crc8check(buf):
			humid = (buf[0] << 8 | buf [1]) & 0xFFFC
			return self.chumid(humid)
		else:
			return -255
			
if __name__ == "__main__":
	obj = HTU21D()
	print "Temp:", obj.read_tmperature(), "C"
	print "Humid:", obj.read_humidity(), "% rH"
Image

simplesi
Posts: 2327
Joined: Fri Feb 24, 2012 6:19 pm
Location: Euxton, Lancashire, UK

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu May 08, 2014 6:26 pm

Does this mean the SMBus module is broken then?

Because a lot of Pi-oneers are going to want to use it so its got to be worth getting it fixed rather than just bypassing it I'd thought

Simon
Seeking help with Scratch and I/O stuff for Primary age children
http://cymplecy.wordpress.com/ @cymplecy on twitter

User avatar
joan
Posts: 16247
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu May 08, 2014 6:52 pm

simplesi wrote:Does this mean the SMBus module is broken then?

Because a lot of Pi-oneers are going to want to use it so its got to be worth getting it fixed rather than just bypassing it I'd thought

Simon
Perhaps the problem is that smbus != I2C.

I don't think Read I2C Block Data is part of the smbus standard. I'm not sure there is an agreed definition of what it is meant to do.

simplesi
Posts: 2327
Joined: Fri Feb 24, 2012 6:19 pm
Location: Euxton, Lancashire, UK

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu May 08, 2014 8:55 pm

Aah I see :)

I'm not (usually anyway - I did used to be able to write 6502 machine code when I was a lad) a low-level programmer so I don't know these things :)

Maybe what's needed is an I2C Python module then.

Sounds like a good thing for Foundation to fund?

Simon
Seeking help with Scratch and I/O stuff for Primary age children
http://cymplecy.wordpress.com/ @cymplecy on twitter

User avatar
joan
Posts: 16247
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu May 08, 2014 9:06 pm

I really don't know how much of a problem this is in practice. Perhaps another combination of smbus commands could work with the HTU21D sensor.

Just googled to find this http://www.ti.com/lit/an/sloa132/sloa132.pdf which gives a short overview.

simplesi
Posts: 2327
Joined: Fri Feb 24, 2012 6:19 pm
Location: Euxton, Lancashire, UK

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu May 08, 2014 9:38 pm

really don't know how much of a problem this is in practice
Well - Dave can't get it to work in practice :)

Simon
Seeking help with Scratch and I/O stuff for Primary age children
http://cymplecy.wordpress.com/ @cymplecy on twitter

User avatar
joan
Posts: 16247
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu May 08, 2014 9:44 pm

simplesi wrote:
really don't know how much of a problem this is in practice
Well - Dave can't get it to work in practice :)

Simon
If he was working to a deadline he may not have had the luxury of exploring alternative solutions.

richlane
Posts: 9
Joined: Thu Mar 13, 2014 9:37 pm

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Tue Dec 30, 2014 5:22 pm

Thank you for this post, this gave me a huge boost getting my own humidity and temperature project working. I have included my own code below which takes the original code and adds a loop which logs to a CSV file on a network share every 5 minutes. The output file is flushed every time it is written and the format works well with excel using a scatter chart.

Code: Select all

#!/usr/bin/python
import sys, struct, array, time, io, os, fcntl, datetime

I2C_SLAVE=0x0703
HTU21D_ADDR = 0x40
CMD_READ_TEMP_HOLD = "\xE3"
CMD_READ_HUM_HOLD = "\xE5"
CMD_READ_TEMP_NOHOLD = "\xF3"
CMD_READ_HUM_NOHOLD = "\xF5"
CMD_WRITE_USER_REG = "\xE6"
CMD_READ_USER_REG = "\xE7"
CMD_SOFT_RESET= "\xFE"

class i2c(object):
   def __init__(self, device, bus):

      self.fr = io.open("/dev/i2c-"+str(bus), "rb", buffering=0)
      self.fw = io.open("/dev/i2c-"+str(bus), "wb", buffering=0)

      # set device address

      fcntl.ioctl(self.fr, I2C_SLAVE, device)
      fcntl.ioctl(self.fw, I2C_SLAVE, device)

   def write(self, bytes):
      self.fw.write(bytes)

   def read(self, bytes):
      return self.fr.read(bytes)

   def close(self):
      self.fw.close()
      self.fr.close()

class HTU21D(object):
   def __init__(self):
      self.dev = i2c(HTU21D_ADDR, 1) #HTU21D 0x40, bus 1
      self.dev.write(CMD_SOFT_RESET) #soft reset
      time.sleep(.1)

   def ctemp(self, sensorTemp):
      tSensorTemp = sensorTemp / 65536.0
      return -46.85 + (175.72 * tSensorTemp)

   def chumid(self, sensorHumid):
      tSensorHumid = sensorHumid / 65536.0
      return -6.0 + (125.0 * tSensorHumid)

   def crc8check(self, value):
      # Ported from Sparkfun Arduino HTU21D Library: https://github.com/sparkfun/HTU21D_Breakout
      remainder = ( ( value[0] << 8 ) + value[1] ) << 8
      remainder |= value[2]
      
      # POLYNOMIAL = 0x0131 = x^8 + x^5 + x^4 + 1
      # divsor = 0x988000 is the 0x0131 polynomial shifted to farthest left of three bytes
      divsor = 0x988000
      
      for i in range(0, 16):
         if( remainder & 1 << (23 - i) ):
            remainder ^= divsor
         divsor = divsor >> 1
      
      if remainder == 0:
         return True
      else:
         return False
   
   def read_tmperature(self):
      self.dev.write(CMD_READ_TEMP_NOHOLD) #measure temp
      time.sleep(.1)

      data = self.dev.read(3)
      buf = array.array('B', data)

      if self.crc8check(buf):
         temp = (buf[0] << 8 | buf [1]) & 0xFFFC
         return self.ctemp(temp)
      else:
         return -255
         
   def read_humidity(self):
      self.dev.write(CMD_READ_HUM_NOHOLD) #measure humidity
      time.sleep(.1)

      data = self.dev.read(3)
      buf = array.array('B', data)
      
      if self.crc8check(buf):
         humid = (buf[0] << 8 | buf [1]) & 0xFFFC
         return self.chumid(humid)
      else:
         return -255

if __name__ == "__main__":
   # Open logging file
   if len(sys.argv) != 2:
      print 'Usage: python ', sys.argv[0], '<logfile.csv>'
   filename = '/mnt/share/htu21d_logs/' + sys.argv[1]
   try:
      file = open(filename, 'a')
   except IOError:
      print "Could not open:", filename
      exit(1)
   print "Opened in append mode:", filename
   # Create humdity sensor object
   obj = HTU21D()
   base_date = datetime.datetime(1970,1,1)
   now = datetime.datetime.now()
   target = int((now-base_date).total_seconds())
   # Round up to next 5 minute boundary
   target = ((target + 299) / 300) * 300
   while True:
      # Get current datetime
      now = datetime.datetime.now()
      now_seconds = int((now-base_date).total_seconds())
      if now_seconds >= target:
         # Read temp and humidity and log to file
         temp = obj.read_tmperature()
         humid = obj.read_humidity()
         out_string = "%d-%02d-%02d %02d:%02d,%.1f,%.1f" % (now.year, now.month, now.day, now.hour, now.minute, temp, humid)
         print out_string
         print >>file, out_string
         file.flush()
         os.fsync(file)
         target += 300 # Advance target by 5 minutes
      time.sleep(30)
Attachments
htu21d.PNG
Screenshot of humidity and temperature plots in excel.
htu21d.PNG (18.17 KiB) Viewed 18670 times

pumatrax
Posts: 4
Joined: Thu Dec 24, 2015 6:09 am

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu Dec 24, 2015 6:16 am

Hey Dave,

Nice work here, it works with an ebay senor I just picked up. By any chance would you happen to know the correct math to output the temperature in Fahrenheit?

Thanks!
class HTU21D(object):
def __init__(self):
self.dev = i2c(HTU21D_ADDR, 1) #HTU21D 0x40, bus 1
self.dev.write(CMD_SOFT_RESET) #soft reset
time.sleep(.1)

def ctemp(self, sensorTemp):
tSensorTemp = sensorTemp / 65536.0
return -46.85 + (175.72 * tSensorTemp)

def chumid(self, sensorHumid):
tSensorHumid = sensorHumid / 65536.0
return -6.0 + (125.0 * tSensorHumid)

Alexandrekx
Posts: 1
Joined: Mon Jul 04, 2016 10:00 am

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Mon Jul 04, 2016 10:22 am

It´s necessary to download the library of the sensor or i just need to put the code that you posted?
If the library is necessary pls post the link, ty.

edwardsnick
Posts: 8
Joined: Sat Sep 19, 2015 12:15 am

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Thu Oct 13, 2016 1:53 am

WOW, what is going on here? I've been miserably trying to use the SMBUS library to interface a CO2 sensor which was never going to work then resorted to installing the PIGPIO library and having to slow the clock speed right down as it wouldn't pause to a delayed clock cycle - a terrible mess although I got it to work.
Is this 'io' and 'fcntl' a software implementation? Sorry I'm learning, if this seems like a basic question but I haven't found any other example like it and SMBus often doesn't work for I2C devices. I nearly abandoned my project and started again using a Arduino to interface the sensors as I was getting so frustrated with the SMBus protocol.

Davespice wrote:Go it working! Woohoo, thanks to Joan.

Code: Select all

#!/usr/bin/python
import struct, array, time, io, fcntl

I2C_SLAVE=0x0703
HTU21D_ADDR = 0x40
CMD_READ_TEMP_HOLD = "\xE3"
CMD_READ_HUM_HOLD = "\xE5"
CMD_READ_TEMP_NOHOLD = "\xF3"
CMD_READ_HUM_NOHOLD = "\xF5"
CMD_WRITE_USER_REG = "\xE6"
CMD_READ_USER_REG = "\xE7"
CMD_SOFT_RESET= "\xFE"

class i2c(object):
   def __init__(self, device, bus):

      self.fr = io.open("/dev/i2c-"+str(bus), "rb", buffering=0)
      self.fw = io.open("/dev/i2c-"+str(bus), "wb", buffering=0)

      # set device address

      fcntl.ioctl(self.fr, I2C_SLAVE, device)
      fcntl.ioctl(self.fw, I2C_SLAVE, device)

   def write(self, bytes):
      self.fw.write(bytes)

   def read(self, bytes):
      return self.fr.read(bytes)

   def close(self):
      self.fw.close()
      self.fr.close()

class HTU21D(object):
	def __init__(self):
		self.dev = i2c(HTU21D_ADDR, 1) #HTU21D 0x40, bus 1
		self.dev.write(CMD_SOFT_RESET) #soft reset
		time.sleep(.1)

	def ctemp(self, sensorTemp):
		tSensorTemp = sensorTemp / 65536.0
		return -46.85 + (175.72 * tSensorTemp)

	def chumid(self, sensorHumid):
		tSensorHumid = sensorHumid / 65536.0
		return -6.0 + (125.0 * tSensorHumid)

	def crc8check(self, value):
		# Ported from Sparkfun Arduino HTU21D Library: https://github.com/sparkfun/HTU21D_Breakout
		remainder = ( ( value[0] << 8 ) + value[1] ) << 8
		remainder |= value[2]
		
		# POLYNOMIAL = 0x0131 = x^8 + x^5 + x^4 + 1
		# divsor = 0x988000 is the 0x0131 polynomial shifted to farthest left of three bytes
		divsor = 0x988000
		
		for i in range(0, 16):
			if( remainder & 1 << (23 - i) ):
				remainder ^= divsor
			divsor = divsor >> 1
		
		if remainder == 0:
			return True
		else:
			return False
	
	def read_tmperature(self):
		self.dev.write(CMD_READ_TEMP_NOHOLD) #measure temp
		time.sleep(.1)

		data = self.dev.read(3)
		buf = array.array('B', data)

		if self.crc8check(buf):
			temp = (buf[0] << 8 | buf [1]) & 0xFFFC
			return self.ctemp(temp)
		else:
			return -255
			
	def read_humidity(self):
		self.dev.write(CMD_READ_HUM_NOHOLD) #measure humidity
		time.sleep(.1)

		data = self.dev.read(3)
		buf = array.array('B', data)
		
		if self.crc8check(buf):
			humid = (buf[0] << 8 | buf [1]) & 0xFFFC
			return self.chumid(humid)
		else:
			return -255
			
if __name__ == "__main__":
	obj = HTU21D()
	print "Temp:", obj.read_tmperature(), "C"
	print "Humid:", obj.read_humidity(), "% rH"
Image

jofrefo
Posts: 3
Joined: Thu Jan 14, 2016 10:18 am

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Tue Sep 05, 2017 8:23 pm

This is kind of an old thread, however, searching the internet today for scripts using smbus and the HTU21D shows no results. Then, I believe posting here the working script may help many others as the script using smbus is very simple, in fact, Dave almost made it! It is just a question of using the hold option.

Code: Select all

#!/usr/bin/python
import time
import smbus

msleep = lambda x: time.sleep(x/1000.0)

ADDR = 0x40

i2c = smbus.SMBus(1)

CMD_READ_TEMP_HOLD = 0xe3
CMD_READ_HUM_HOLD = 0xe5
CMD_READ_TEMP_NOHOLD = 0xf3
CMD_READ_HUM_NOHOLD = 0xf5
CMD_WRITE_USER_REG = 0xe6
CMD_READ_USER_REG = 0xe7
CMD_SOFT_RESET= 0xfe

i2c.write_byte(ADDR, CMD_SOFT_RESET)
msleep(100)

i2c.write_byte(ADDR, CMD_READ_TEMP_HOLD)
msleep(100)


data = i2c.read_i2c_block_data(ADDR, CMD_READ_TEMP_HOLD, 3)
msleep(100)

t1 = 256*data[0] + data[1]

temp = (t1/65536.0) * 175.72 - 46.85

print 'Temperature:' + str(temp)
The hold option is that the sensor will hold the clock low while measuring which means the master must wait for it. Also the sensor ACKs the first read command while the NO_HOLD option uses a NACK that seems to confuse the smbus and produce the error.

Above code is not using the checksum byte ( which is available at data[2]). But if you are not interested on the checksum at all, you can do the block read just changing the number of expected bytes to 2 as shown below.

Code: Select all

data = i2c.read_i2c_block_data(ADDR, CMD_READ_TEMP_HOLD, 2)

Pyrce
Posts: 1
Joined: Mon Nov 27, 2017 8:04 am

Re: Need help with HTU21D Humidity Sensor (for RPi outreach)

Mon Nov 27, 2017 8:29 am

A bit late, but I ran into a lot of frustration with controlling the HTU21D sensor. So I made a repository which wraps the whole thing up cleanly: https://github.com/MSeal/htu21df_sensor, or from pip htu21df. I found the NACK, or firmware issues in Pi I2C implementation, to constantly cause problems or prevent block reads from (consistently) returning without error. It uses non-holding commands with a direct io connection to the i2c file and sleeps at the maximum sampling interval times. It also checks the checksum based on the reference above to the arduino library's implementation.

Hopefully this simplifies working through this for the next person to stumble into the thread.

Return to “Interfacing (DSI, CSI, I2C, etc.)”