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

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?)

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

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.

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