HYT 939(HYTxxx) Accurate temperature and humidity I2C sensor

Discussion about Z-Uno product. Visit http://z-uno.z-wave.me for more details.
mdietinger@gmail.com
Posts: 39
Joined: 12 Aug 2016 12:08

HYT 939(HYTxxx) Accurate temperature and humidity I2C sensor

Post by mdietinger@gmail.com » 07 Nov 2016 11:08

All, Poltos,

did some further testing with HYT 939 temp/hum I2C sensor.
I think it is better to post HYT939 sensor code rather than HYT221 in the examples section.
Main reason is that HYT939 easily fits into a breadboard and is physically more robust (HYT221 Pins don't fit the 2.54mm standard)
Attached example allows two HYT939 sensors to be connected via I2C.
To allow both of them being operated, for one the default I2C address needs to be changed. (2nd script)
Every 30" temperature and humidity are reported to serial monitor.
The values are reported to Z_Wave controller based on the defined polling time. (in my case every 300 sec or 5 minutes)
I believe I managed to cover as well temperatures bellow 0° by using unsigned integer.
Was only able to simulate the temperature and that worked fine.
Installed Fritzing, but had issues to modify a TO39 component to show the correct location of notch/nose.

I am happy if this code is posted in examples, but would need some help to get the right component for Fritzing.

Code: Select all

// demo sketch for connecting HYT221 humidity and temperature sensor to Z-Uno

// add library
#include <Wire.h>  
#include <math.h>   

unsigned int humidity; // here we will store the humidity
unsigned int temperature; // here we will store the temperature

unsigned int humidity2; // here we will store the humidity
unsigned int temperature2; // here we will store the temperature

// set up channels
ZUNO_SETUP_CHANNELS(
     ZUNO_SENSOR_MULTILEVEL(ZUNO_SENSOR_MULTILEVEL_TYPE_TEMPERATURE, 
                          SENSOR_MULTILEVEL_SCALE_CELSIUS, 
                          SENSOR_MULTILEVEL_SIZE_TWO_BYTES, 
                          SENSOR_MULTILEVEL_PRECISION_ONE_DECIMAL,
                          getterTemperature),
     ZUNO_SENSOR_MULTILEVEL_HUMIDITY(getterHumidity),
     ZUNO_SENSOR_MULTILEVEL(ZUNO_SENSOR_MULTILEVEL_TYPE_TEMPERATURE, 
                          SENSOR_MULTILEVEL_SCALE_CELSIUS, 
                          SENSOR_MULTILEVEL_SIZE_TWO_BYTES, 
                          SENSOR_MULTILEVEL_PRECISION_ONE_DECIMAL,
                          getterTemperature2),
     ZUNO_SENSOR_MULTILEVEL_HUMIDITY(getterHumidity2)
);

void setup() {
  #define HYT_ADDR  0x28     // I2C address of the HYT 221, 271, 939 and most likely the rest of the family
  #define HYT_ADDR2 0x50     // I2C address of the HYT 221, 271, 939 and most likely the rest of the family
  Wire.begin();             // Join I2c Bus as master
  Serial.begin(9600);       // Start serial communication for serial console output
  pinMode(13, OUTPUT);
}




void loop() {
  readHYT(); 
  readHYT2(); 
  delay(30000);
  }

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

void readHYT () {
  int iData[4];
 Wire.beginTransmission(HYT_ADDR);
  Wire.write(0);    // initiate measurement
  Wire.endTransmission(); 
blinkWait();
  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) {                   
           iData[1] = Wire.read();
           iData[2] = Wire.read();
           iData[3] = Wire.read();
           iData[4] = Wire.read();
           Wire.endTransmission();           // End transmission and release I2C bus

           // combine humidity bytes and calculate humidity
           int rawHumidity = iData[1] << 8 | iData[2];
           rawHumidity =  (rawHumidity &= 0x3FFF);
           humidity = 100.0 / pow(2,14) * rawHumidity;
             
        Serial.print("Humidity: ");
        Serial.print(humidity);
         
          // combine temperature bytes and calculate temperature
          iData[4] = (iData[4] >> 2); // Mask away 2 least significant bits see HYT 221 doc
          int rawTemperature = iData[3] << 6 | iData[4];
          temperature = (165.0 / pow(2,14) * rawTemperature - 40)*10; 
        
        Serial.print("% - Temperature: ");
        Serial.print(165.0 / pow(2,14) * rawTemperature - 40);
        Serial.println("C");

  }
  else {
        Serial.println("Not enough bytes available on wire.");
  }
}

void readHYT2 () {
  int iData[4];
Wire.beginTransmission(HYT_ADDR2);
  Wire.write(0);    // initiate measurement
  Wire.endTransmission(); 
blinkWait();  
  Wire.beginTransmission(HYT_ADDR2);   // Begin transmission with given device on I2C bus
  Wire.requestFrom(HYT_ADDR2, 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) {                   
           iData[1] = Wire.read();
           iData[2] = Wire.read();
           iData[3] = Wire.read();
           iData[4] = Wire.read();
           Wire.endTransmission();           // End transmission and release I2C bus
         
          // combine humidity bytes and calculate humidity
           int rawHumidity = iData[1] << 8 | iData[2];
           rawHumidity =  (rawHumidity &= 0x3FFF);
           humidity2 = 100.0 / pow(2,14) * rawHumidity;
             
        Serial.print("Humidity2: ");
        Serial.print(humidity2);
                      
          // combine temperature bytes and calculate temperature
          iData[4] = (iData[4] >> 2); // Mask away 2 least significant bits see HYT 221 doc
          int rawTemperature = iData[3] << 6 | iData[4];
          temperature2 = (165.0 / pow(2,14) * rawTemperature - 40)*10; 
        
        Serial.print("% - Temperature2: ");
        Serial.print((165.0 / pow(2,14) * rawTemperature - 40));
        Serial.println("C");

  }
  else {
        Serial.println("Not enough bytes available on wire.");
  }
}


word getterTemperature() {
  return temperature;
}

byte getterHumidity() {
  return humidity;
}

word getterTemperature2() {
  return temperature2;
}

byte getterHumidity2() {
  return humidity2;
}


HYT939.jpg
HYT939.jpg (72.82 KiB) Viewed 5746 times


To change I2C address only connect one sensor and connect Z-UNO-PIN10 to Sensor-PIN-VDD(3.3V) instead of the power cable.
Most likely you don't get anything out of the serial monitor as it takes longer to open the monitor as the code takes to execute.

Code: Select all

// Sketch to change the address of a HYT humidity sensor

#include "Wire.h"
#define OLDADDRESS 0x28
#define NEWADDRESS 0x50
int powerPin = 11; //connect sensor VDD to pin 11

void setup()
{
  pinMode(powerPin, OUTPUT);
  Wire.begin();
  Serial.begin(9600); 
}

void loop()
{
  delay(5000);
  Serial.println("Changing the address of HYT sensor");
  Serial.print("Old address (HEX): ");
  Serial.println(OLDADDRESS, HEX);
  Serial.print("New address (HEX): ");
  Serial.println(NEWADDRESS, HEX);
  
  Serial.println("Power-on the sensor");
  digitalWrite(powerPin, HIGH); 

  Serial.println("Trying to put the sensor to Command mode");
  Wire.beginTransmission(OLDADDRESS);
  Wire.write(0xA0);        //start-command-mode
  Wire.write(0x00);        //highbyte
  Wire.write(0x00);        //lowbyte
  Wire.endTransmission();  //transmitting bytes
  Serial.println("Sensor should be now in Command mode");

  Wire.beginTransmission(OLDADDRESS);
  Wire.write(0x5C);        //change i2c address
  Wire.write(0x00);        //highbyte
  Wire.write(NEWADDRESS);  //lowbyte, new address
  Wire.endTransmission();
  Serial.println("Address should be now changed");

  Wire.beginTransmission(OLDADDRESS);
  Wire.write(0x80);        //normal mode
  Wire.write(0x00);        //highbyte
  Wire.write(0x00);        //lowbyte
  Wire.endTransmission();
  Serial.println("Sensor should be now in normal mode");

  for (uint8_t add = 0X0; add < 0X80; add++) {
    Wire.requestFrom(add, (uint8_t)1);
    if (Wire.available()) {
      Serial.print("Found I2C device from address: ");
      Serial.println(add, HEX);
    }
  }

  Serial.println("Power-off the sensor");
  digitalWrite(powerPin, LOW); 

  Serial.println("Done!");
  while (1){} //infinite loop
}

mdietinger@gmail.com
Posts: 39
Joined: 12 Aug 2016 12:08

Re: HYT 939(HYTxxx) Accurate temperature and humidity I2C se

Post by mdietinger@gmail.com » 07 Nov 2016 11:30

Deleted
Last edited by mdietinger@gmail.com on 07 Nov 2016 20:30, edited 1 time in total.

michap
Posts: 343
Joined: 26 Mar 2013 10:35
Contact:

Re: HYT 939(HYTxxx) Accurate temperature and humidity I2C se

Post by michap » 07 Nov 2016 14:02

Hi,

I have tested with arduino a long time ago this sensor - and it was working fine.
A little bit expensive,... but ok ...

[edit - removed some comment]

What do you mean with
mdietinger@gmail.com wrote: but was able to simulate them successfully.
If you are sending negative values to gateway it is working?
Have you tried to debug it with any Serial.print lines and checking the temp values?

Have you tried with signed int?
http://z-uno.z-wave.me/Reference/ZUNO_S ... ULTILEVEL/
Values returned by getter are signed. Values are interpreted according to the following transformation:
Sorry if I misunderstood anything ;)

Michael

mdietinger@gmail.com
Posts: 39
Joined: 12 Aug 2016 12:08

Re: HYT 939(HYTxxx) Accurate temperature and humidity I2C se

Post by mdietinger@gmail.com » 07 Nov 2016 14:30

Michael,

bellow is code example how I simulated negative temperature.
This will report as -1.20 in Z-Wave Controller (HC2)
Testing before was on int and when temperature went below 0° HC2 only showed "0°"
If you check the 10 sensor temperatur example that reports in byte, which should be perfectly fine fine for a one byte transmission +/-127.
Seems like z_wave protocol doesn't handle signed values and therefore parameters need to be send using unsigned.
Serial monitor will work just fine with signed values, but that doesn't reflect whats send to the controller.


Code: Select all

unsigned int temperature;

//temperature = (165.0 / pow(2,14) * rawTemperature - 40)*10; 
temperature = -12;


word getterTemperature() {
  return temperature;
}
regards,

Markus
Last edited by mdietinger@gmail.com on 14 Nov 2016 09:48, edited 2 times in total.

michap
Posts: 343
Joined: 26 Mar 2013 10:35
Contact:

Re: HYT 939(HYTxxx) Accurate temperature and humidity I2C se

Post by michap » 07 Nov 2016 14:33

sorry... have edited my comment above while you wrote your message :)

mdietinger@gmail.com
Posts: 39
Joined: 12 Aug 2016 12:08

Re: HYT 939(HYTxxx) Accurate temperature and humidity I2C se

Post by mdietinger@gmail.com » 07 Nov 2016 14:57

Have you tried with signed int?
http://z-uno.z-wave.me/Reference/ZUNO_S ... ULTILEVEL/
Values returned by getter are signed. Values are interpreted according to the following transformation:
that sentence contradicts below examples in the reference.

with signed int 1 would be 1, -1 would be 32768.
with unsigned int 1 would be 1, -1 would be 65535.

Based on my testing i would say documentation is incorrect.


BTW serial print doesn't show the values send to zwave controller.
For serial print signed values are required.
Last edited by mdietinger@gmail.com on 14 Nov 2016 09:48, edited 2 times in total.

michap
Posts: 343
Joined: 26 Mar 2013 10:35
Contact:

Re: HYT 939(HYTxxx) Accurate temperature and humidity I2C se

Post by michap » 07 Nov 2016 16:25

just had a bit closer look at the code.

You are using:

Code: Select all

,,, SENSOR_MULTILEVEL_SIZE_TWO_BYTES,                   SENSOR_MULTILEVEL_PRECISION_ONE_DECIMAL,
This means you must send "centi grad" - so temperature * 10

if temperature will be negative - a negative value will be reported mostly independent of the value type....

as sample (for demonstration only):

Code: Select all

int lastTemperatureValue1;
signed int lastTemperatureValue2;
unsigned int lastTemperatureValue3;
word lastTemperatureValue4;
....
void loop() {
  // sensor value:
float lastValue1=-12.1;
float lastValue2=-12.2;
float lastValue3=-12.3;
float lastValue4=-12.4;

lastTemperatureValue1=lastValue1*10;
lastTemperatureValue2=lastValue2*10;
lastTemperatureValue3=lastValue3*10;
lastTemperatureValue4=lastValue4*10;

zunoSendReport(1);
zunoSendReport(2);
zunoSendReport(3);
zunoSendReport(4);
delay(30000);
}

word getterTemp1(void) {
  return lastTemperatureValue1;
}
word getterTemp2(void) {
  return lastTemperatureValue2;
}
...
will report to Z-Way the right temperature values ( I see it in interface).

Michael

michap
Posts: 343
Joined: 26 Mar 2013 10:35
Contact:

Re: HYT 939(HYTxxx) Accurate temperature and humidity I2C se

Post by michap » 07 Nov 2016 16:39

I just have seen that you do this (*10) ...

But you could test the negative temperature easy in this line

temperature = (165.0 / pow(2,14) * rawTemperature - 70)*10 ;

then temp should be negative.

Sorry for confusion, seems I'm a little bit unconcentrated today while reading posts ... ;)

Michael

mdietinger@gmail.com
Posts: 39
Joined: 12 Aug 2016 12:08

Re: HYT 939(HYTxxx) Accurate temperature and humidity I2C se

Post by mdietinger@gmail.com » 07 Nov 2016 16:45

Strange,

will test your code this evening.
Would expect differences between 1&2 versus 3&4 due to different handling of negative values.
Just know int didn't work for me.

mdietinger@gmail.com
Posts: 39
Joined: 12 Aug 2016 12:08

Re: HYT 939(HYTxxx) Accurate temperature and humidity I2C se

Post by mdietinger@gmail.com » 07 Nov 2016 20:29

Michael,

did test your code.
Same result for int and unsigned integer.
Seems z_UNO does the correct conversion to word type automatically.
Maybe I mixed up "getter variable type" at some time and used int there.

Will update original posting.

thanks, Markus

Post Reply