HDC1080 Try
AGCB
Posts: 327
in Propeller 1
I've been trying to get some simple data from a new chip I got. The temp data never changes and I'm doing something wrong with the math. I've attached a picture of the TV screen and code.
Thanks for looking.
[img][/img]
Thanks for looking.
CON _clkmode = xtal1 + pll16x '80 MHz system clock _xinfreq = 5_000_000 'I2C pins scl = 20 sda = 21 Bitrate = 10000 'I2C @ 50Khz for longish cables HDC = $40 'I2C 7 bit address Config_reg = $02 'config register address trigger = $00 'Trigger byte & temperature output register Hum_out = $01 'humidity output register Config_params = %1001_0000_0000_0000 'see pg 15 OBJ TV : "TV_TEXT" I2C : "I2C PASM driver v1.8OD" VAR byte data[4] '0 & 1 temp output, 2 & 3 hum output word temper, humid ,RH long temp_C PUB main TV.start(0) WaitMS(100) I2C.start(SCL,SDA,bitrate) WaitMS(100) I2C.writeWordB(HDC,Config_reg,Config_params) 'configure device WaitMS(100) repeat I2C.command(HDC,trigger) 'start a temp, hum measurement WaitMS(100) 'allow time for measurement tv.home temper := (I2C.ReadByte(HDC,$00) << 8) temper |= I2C.ReadNext(HDC) temper := temper <<= 2 humid := (I2C.ReadByte(HDC,$01) << 8) humid |= I2C.ReadNext(HDC) humid := humid <<= 2 tv.cr tv.str(string ("temp in bin = ")) tv.bin(temper,14) tv.cr tv.dec(temper) tv.cr tv.str(string("hum in bin = ")) tv.bin(humid,14) tv.cr tv.dec(humid) waitms(1000) temp_C := (((temper/65536)*165)-40) RH:=((humid/65536)*100) tv.cr tv.str(string("temp in c = ")) tv.dec(temp_c) tv.cr tv.str(string("RH = ")) tv.dec(RH) WaitMS(1000) PUB WaitMS(millisec) |time time := clkfreq/1000 * millisec waitcnt(time + cnt)
[img][/img]
Comments
temp_C := ((temper*165)/65536)-40)
But the temper value looks way too large. 65028 will be 123.72°C ???
Bean
Bean is correct that dividing a 14-bit number by 2^16 results in loss of all digits, but even with multiplying before dividing you still lose fractional digits.
The temperature ranges from -40 to +125, a span of 165. With 14-bit resolution, each lsb equals 0.0107 degrees. The operation temper := temper >> 2 - 4000 gets you degrees x 100; 1 = -3999, 16383 = 12383.
If you don't need that resolution, keep temper and humid at 16-bits and use; temper := temper * 165 / 65536 - 40 and humid := humid * 100 / 65536.
If I'm reading the datasheet properly, the measurements are triggered with a write to register $00. Then after waiting for the HDC1080 to complete, the measurements are read from $00 and $01.
A possible problem that I see here is re-addressing the register for the read begins another sample. If it's not a problem, then the i2c method readWordB can be used instead of the readByte and readNexts with shifting and or'ing. I also don't know if the readNext method even works with this device, as the HDC1080 returns 16 bits from a single register address; I've never seen that before.
I included an arbitrary method for non-standard devices, to use: i2c.arbitrary(@local_long,1,@local_long,4). You'll have to declare local_long and load local_long := HDC << 1 | 1 into it before executing, the temperature will be in bits[31:18] and humidity in bits[15:02] afterward.
Lastly, the PASM version of that I2C driver is intended for high speeds. The Spin version of that driver runs at about 20Kbps and uses the same methods without consuming a cog.
Edited because I forgot how my own code works
I'll make some mods and have another go of it
BUT, although the 32 bit value from the HDC keeps updating every 3 seconds as it should. everything else stays the same and the temper and humid BIN read nothing. I've tried other ways of masking but I think BITWISE AND(&) is the right way.
I tried converting the returned binary value into temp and humidity and discovered another problem in that the i2c.arbitrary method reads little-endian.
The easiest/laziest fix is: Looks like it's about 19c and 43% RH there.
For some reason I didn't see your reply. I've been busy and not programming.
That took care of the problem and it now works. I get mixed up with that @ operator. Still no handle on it.
I'll try to clean up the code and add it to my weather station.
Thanks very much Chris!
Aaron
Chris
Could not the value just be reversed with >< to get big-endian? I'm less than novice!
Aaron