2

I'm trying to get an Adafruit HDC1008 Temperature and Humidity breakout working on the Raspberry Pi. I have had some success using the 'raw' code shown at the bottom of the Interfacing HDC1008 Temperature/Humidity thread from Raspberry Pi Dot Org but would like to get the smbus version working.

Currently my code looks like:

bus = smbus.SMBus(1)
ADDR = 0x40

myBytes = [0x10,0x00]
bus.write_i2c_block_data(ADDR,0x02,myBytes)

tempRaw = bus.read_i2c_block_data(ADDR,0x00)
print(tempRaw)

However this is resulting in an IOError with the read block line. Having looked at the HDC1008 datasheet page 12 suggests that I should set the address pointer and then read:

    1. Trigger the measurement by executing a pointer write transaction. Refer to Figure 12. – Set the address pointer to 0x00 for a temperature measurement. – Set the address pointer to 0x01 for a humidity measurement.
    1. Wait for the measurement to complete, based on the conversion time ...
    1. Read the output data: Retrieve the completed measurement result from register address 0x00 or 0x01, as appropriate ...

So my question is: Does the read_i2c_block set the address for me? Or if not how do I set the address before reading.

Thanks

**** UPDATE ****

So I'm pass the IOError by setting the address but don't appear to be reading the data correctly. Whether this is because I'm not setting the address correctly or not reading it I don't know. I'm still looking at this.

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

bus = smbus.SMBus(1)    
HDC1008_ADDR = 0x40

#Set configuration with two bytes written to 0x02
myBytes = [0x10, 0x00]
bus.write_i2c_block_data(HDC1008_ADDR,0x02,myBytes)
time.sleep(0.0635)

#Set Pointer to 0x00 and sleep
bus.write_byte(HDC1008_ADDR,0x00)
time.sleep(0.0635)

#Read temp as two bytes from 0x00
data = bus.read_byte_data(HDC1008_ADDR,2)
print(data)
  • I don't think you need a sleep in between setting the configuration register and triggering the conversion -- you just need one after the latter. I would try experimenting with longer sleeps also (10-20ms). – goldilocks Jun 29 '16 at 13:17
  • I have commented out the sleep as suggested and increased the second sleep to 20ms. At the moment I'm always getting 16 as an answer. The alternative script returns 22.851868 from the same sensor. – Davies-Barnard Jun 29 '16 at 13:26
  • Currently looking at stackoverflow.com/questions/32656722/… which seems to help. – Davies-Barnard Jun 29 '16 at 13:55
  • I.e., reading one byte, then one byte instead of two bytes? This might make sense as it is not clear what it really does on a signal level (e.g., there should be an "ack from master" bit between each byte read); I've noticed this kind of issue w/ the C API this wraps. You could try also try polling the DRDYn line to see what goes on with that (n is "negated" so this will actually go from high to low when data is ready and according to the datasheet stays there until a new request is made), maybe using a separate concurrent process. – goldilocks Jun 29 '16 at 13:58
  • Ok. stackoverflow.com/questions/32656722/… is basically a working solution so this is kind of a duplicate answer from the update onwards. – Davies-Barnard Jun 29 '16 at 14:23
1

I don't use python for this stuff but hopefully that doesn't matter much.

By my reading of 8.5.1, "I2C Serial Bus Address Configuration" you have the two address pins connected to other (non-I2C) GPIOs and their state determines the bus address; they should remain in the same consistent state. Judging by your use of 0x40 = 0b1000000 you have both those lines low.

Beware this means they must actually be outputs set low. Not connecting them, or connecting them to inputs, is not the same. I think you should then see address 0x40 occupied in i2cdetect. I presume you've confirmed this.

It refers to using that seven bit address with an eight bit either high or low to indicate read or write; those timing diagrams show a "7 bit serial address bus byte" but if you look it is an actual 8-bit byte; the least significant bit is either 0 or 1. However, I believe this is standard and the nature of the read vs. write methods deal with this so you should be sticking with the 0x40 address (the python interface is a little confusing to me this way; with C API you open a handle to the I2C node, /dev/i2c-1, then use an ioctl() to set the specific 7-bit device address, and thereafter the handle always refers to that specific device and no address is used, but you are always either reading or writing; I'm presuming your use of the python smbus API is correct).

Then the first thing you should do is then write 16-bits in two bytes, MSB first, to register 0x02. Presuming you want 14 bit resolution for both temp and humidity, following 1) a-b-c on pg. 11 this means the value here should be 0x1000. Note I think Figure 10 at the top of that page ("Writing Frame (Configuration Register)") involves a misprint when it says for frame 3 & 4 "Data MSB/LSB from SLAVE" -- that should either be "from MASTER" or "to SLAVE" (if you look at the ACK bits those are all "by Slave").

"0x1000" because to read temp and humidity together, you want to set the 12th bit counting from 0, i.e., 0b0001 0000 0000 0000 (so the MSB is 16, 0x10). This is also the "reset value" from table 2, pg 14.

If there's a write_word method I would use that, not write_block.

Then you "trigger the measurements by executing a pointer write transaction with the address pointer set to 0x00".

Thus far that seems to be what you are doing, but it is then not clear whether you are either waiting for either the "conversion time" to pass (pg. 5) or until the DRDYn line goes low (connected to a regular GPIO as input). Doing the latter is probably more of a hassle as it requires a poll or callback and takes up another pin, but it also seems like the most unequivocal method.

The conversion time is 6.5 ms for both temp and humidity; I would guess those are concurrent but you could try both 7 and 14 ms waits (I don't think the resolution will always be that precise, and while you should get at least what you ask for you might experiment with ranges from 10-20 ms).

Then you read two bytes from register 0x00 (temp) and two bytes from register 0x01 (humidity).

  • Thanks Goldilocks. You seem to have a pretty good grasp of what is required and what I have/am doing. I will update my question to show progress. – Davies-Barnard Jun 29 '16 at 13:06
  • Upvoted this answer because it gives an detailed explanation of the original question. – Davies-Barnard Jun 29 '16 at 14:24
0

Once past the initial question regarding setting address pointer for the Adafruit HDC1008 Temperature and Humidity breakout I ran into a second issue - reading two bytes at once. This led me to find a complete solution on Python: Can I read two bytes in one transaction with the smbus module?, which works once the correct address is given for the I2C_BUS. Shame the smbus module for python is not better documented.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.