Sensor HYT 221 with I2C and 20x2

woschx

New Member
Hi,

ffor a project I must measure the temperature and the air humidity.
For it I have got myself the HYT 221.

https://www.ist-usadivision.com/objects/media/data-sheets/product/humidity-module/HYT-221.pdf

With an Arduino and this programme I can select the values / register
Code:
#include <Wire.h>
void setup() {
#define HYT_ADDR 0x28 // I2C address of the HYT 221, 271, 371 and most likely the rest of the family
Wire.begin(); // Join I2c Bus as master
pinMode(13, OUTPUT); // Set pin 13 to output for status LED
// I2C Pins on the Arduino Uno are A4 for SDA and A5 for SCL
Serial.begin(9600); // Start serial communication for serial console output
}

void loop() {
double humidity;
double temperature;

Wire.beginTransmission(HYT_ADDR); // Begin transmission with given device on I2C bus
Wire.requestFrom(HYT_ADDR, 4); // Request 4 bytes

// Read the bytes if they are available
// The first two bytes are humidity the last two are temperature
if(Wire.available() == 4) {
int b1 = Wire.read();
int b2 = Wire.read();
int b3 = Wire.read();
int b4 = Wire.read();

Wire.endTransmission(); // End transmission and release I2C bus

// combine humidity bytes and calculate humidity
int rawHumidity = b1 << 8 | b2;
// compound bitwise to get 14 bit measurement first two bits
// are status/stall bit (see intro text)
rawHumidity = (rawHumidity &= 0x3FFF);
humidity = 100.0 / pow(2,14) * rawHumidity;

// combine temperature bytes and calculate temperature
b4 = (b4 >> 2); // Mask away 2 least significant bits see HYT 221 doc
int rawTemperature = b3 << 6 | b4;
temperature = 165.0 / pow(2,14) * rawTemperature - 40;

Serial.print(humidity);
Serial.print("% - Temperature: ");
Serial.println(temperature);
}
else {
Serial.println("Not enough bytes available on wire.");
}
blinkWait();
}

void blinkWait() {
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
}

Now I try to select in vain the sensor with 20x2 about I2C and get no reasonable values.
Byte 0 is 29 and the following three bytes 255.
I have pulled SDA and SCL with 4K7 on 5 V. Has developed the opposition also sometimes. It Changing to itself, however, nothing.
SCL on B.7
SDA on B.5

So in the kind I have tested it:
Code:
start:
let b8 = 4
hi2csetup i2cmaster, $28, i2cslow, i2cbyte
; i2cslave $28,i2cfast, i2cbyte
writei2c 0,(b8)
pause 10
readi2c 0,(b0,b1,b2,b3)
debug
goto start

Can somebody help me there?

Wolfgang
 

AllyCat

Senior Member
Hi Wolfgang,

Welcome to the forum.

You pbobably need to use Slave address $50 (not $28) as shown in the data sheet page 15, when using a PICaxe. I2C uses the LSB as a Read/Write flag, so the "address" starts at bit 1 (not bit 0).

Cheers, Alan.
 

woschx

New Member
Many thanks for the info!
Now I get useful register values.
Now by the conversion of the register values in the measuring values I have this here:
------------------------
start:
i2cslave $50,i2cfast, i2cbyte
pause 100
readi2c 0,(b1,b0,b3,b2)
let b1 = b1 and %00111111

let w2 = w0 / 164 ; humidity

let w1 = w1 / 4 ; temperature
let w3 = w1 / 99
let w3 = w3 -40
debug
goto start
------------------------

I have determined the factors 164 and 99, because descendant's calculations are not possible.

Small inaccuracies thereby arise of course in the result!
Is there still a better calculation possibility?

Wolfgang
 

AllyCat

Senior Member
Hi Wolfgang,

Yes, if you are entering calibration factors directly into the Progam, the ** operator can be very useful. It multiplies by the subsequent number and then divides by 65536.

So, instead of dividing by 4 and then 99, you can ** 165.4949.... (because 65536 / (99 * 4) = 165.4949..) . That's a rather "unfortunate" number, so in this particular case you might ** 331 / 2 . Thus the calculation could be done as a "one liner" : w3 = w1 ** 331 / 2 - 40 .

But perhaps better to work in tenths of a degree with something like (not tested) :
Code:
w3 = w1 ** 1655 - 400
w1 = w3 // 10              ; Remainder = Tenths
w3 = w3 / 10               ; Integer degrees
sertxd("Temperature= ",#w3,".",#w1," degrees C")
Cheers, Alan.
 

marks

Senior Member
Hi derschutzhund,
like Allycat has already suggested you can reuse the same variable

also try for temp. w1=w1 *4 **16502 -4000 'ie 6162 =2206 (22.06)
and humidity. w0=w0 ** 4001 ' ie 8045 =491 (49.1%RH)

using the recommended 2.2k pullup should make received data more reliable
 

woschx

New Member
Thus the ready programme looks!
humidity and temperature are given with two postcomma places.
-----------------------------
start:
i2cslave $50,i2cfast, i2cbyte
pause 100
readi2c 0,(b1,b0,b3,b2)
let b1 = b1 and %00111111

w2 = w0 ** 40001
w0 = w2 // 100
w2 = w2 / 100

w3 = w1 ** 16500 - 4000
w1 = w3 // 100 ; Remainder = Tenths
w3 = w3 / 100 ; Integer degrees

sertxd("Feuchte= ",#w2,".",#w0," %"," Temp.= ",#w3,".",#w1," C",13,10)

goto start
-----------------------------
Many thanks for your help!

Wolfgang
 
Top