HDC1000 temp & humidity sensor (works, but in C)


#1

I got the temp and humidity sensor HDC1000 working, which was a pain since the i2c on it is somewhat hairier than normal.

I have it working in C:

#include <sys/ioctl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>

unsigned short i2c_read_16(int fd,
                           unsigned char addr,
                           unsigned char reg)
{

  static struct i2c_msg msgs[1];
  int r;

  struct i2c_rdwr_ioctl_data msgset =
  {
    msgs, sizeof(msgs) / sizeof(*msgs)
  };
  unsigned char buf[2];

  buf[0] = reg;
  msgs[0].addr = addr;
  msgs[0].flags = 0;
  msgs[0].buf = (void *)buf;
  msgs[0].len = 1;

  r = ioctl(fd, I2C_RDWR, &msgset);
  if (r<0) { perror("ioctl"); exit(1); }

  usleep(10000);

  msgs[0].addr = addr;
  msgs[0].flags = I2C_M_RD;
  msgs[0].buf = (void *)buf;
  msgs[0].len = 2;

  r = ioctl(fd, I2C_RDWR, &msgset);
  if (r<0) { perror("ioctl"); exit(1); }

  return buf[0]*256 + buf[1];
}

int main(int argc, char *argv[])
{
  int fd = open("/dev/i2c-1", O_RDWR);

  unsigned short temp = i2c_read_16(fd,0x40,0);
  unsigned short hum  = i2c_read_16(fd,0x40,1);

  printf("temperature: %.3f C\n",  temp * (160.0/65536.0) - 40);
  printf("humidity:    %.3f %%RH\n",hum  * (100.0/65536.0));

    return 0;
}

$ gcc -Wall i2c.c -o i2c && ./i2c
temperature: 22.596 C
humidity:    60.040 %RH

but I don’t know how to access those ioctls in python to put it into grovepi.py.

The problem is the delay between the write-the-read-address and the actual read. The SMBUS interface doesn’t support that.

(Can the grovepi itself run as i2c master for this?)


#2

Hey,
From your code, it looks like all the sensor needs is to write the register address to it then wait for 10ms and then read the 2 bytes coming back. We have a couple of sensors with direct I2C interface working with python. We use the smbus library and use write_byte_data() to write the register address and read_i2c_block_data() to read the values back. You can pretty much modify this https://github.com/DexterInd/GrovePi/blob/master/Software/Python/grove_i2c_adc/grove_i2c_adc.py to get it working with HDC1000. There are a couple of other I2C examples in the Python folder so you can have a look at them for more details.

Do let us know if it helps and do send a pull request for the code too once you get it working.

-karan


#3

i2c_smbus_read_block_data() restarts the transmission, so that doesn’t work,
reading https://www.kernel.org/doc/Documentation/i2c/smbus-protocol :

I2C Block Read:  i2c_smbus_read_i2c_block_data()
================================================

This command reads a block of bytes from a device, from a 
designated register that is specified through the Comm byte.

S Addr Wr [A] Comm [A] 
           S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P


For this, it needs to do

S Addr Wr [A] Comm [A] 
delay 10ms
S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P

The byte reads doesn’t work either, you get repeats of the first byte only because of the stop condition after reading the byte.

…but anyway, I’m relatively happy with my C code. I thought I’d toss this in this direction if anyone here or any visitor is interested in getting the HDC1000 to work.


#4

Hey Mirar,
Thanks for looking into this. We’ll be getting the sensor in a bit and will try to get it working with Python. Will keep you updated about it.

-Karan