湿度/温度センサー HTS221をArduinoから制御する(I2C)

  • 8
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

HTS221

HTS221_pre.png

HTS221は、STMicroelectronics製のI2C通信に対応した湿度/温度センサーである。ここでは、Arduino向けのI2C通信のサンプルを作成する方法を掲載する。

Document

Slave address

0x5f

Register address map

hts221_addressnap.png

hts221_register.png

Who_am_I

Who_am_I用に割り振られたレジスタアドレスは、0x0F。0xBCが返ってくると、センサーが認識されている事になる。

who_am_i_resgiter.png

arduino
#define HTS221_WHO_AM_I 0x0F
#define HTS221_DEVICE 0xBC

bool SearchDevice()
{
  byte device = 0x00;
  readI2c(HTS221_WHO_AM_I, 1, &device);

  if(device == HTS221_DEVICE){
      return true;
  } else{
      return false;
  }
}

Configuration

Configurationは、0x10のRegister Addressを使用している。Defaultは、1B。
Configurationでは、湿度/温度計測時のそれぞれの間隔を設定できる。間隔を細かくすれば、それだけノイズを減らせるが、電流量が増える。

config_reg.png

config_bit.png

Configurationでは、0-2bit目(AVGH0-AVGH1)がHumidityの分解度、3-5bit目(AVGT0-AVGT1)がTemperatureの分解度の設定用に使われる。

config_table.png

Defialtの1Bの値は、bitに表すと下記表のようになる。

config_default.png

AVGTが011、AVGHが011となる。Temperatureのインターンバルの間隔が16, Humidityが32に設定されている。

一番いい精度に設定する場合は、下記のように111, 111をそろぞれ設定する。

arduino
#define HTS221_AVGT_256 0b111
#define HTS221_AVGH_512 0b111

void Configuration()
{
   int AV_CONF = HTS221_AVGT_256>>3 | HTS221_AVGH_512;
   writeI2c(HTS221_AV_CONF, AV_CONF);
}

Power onと使用可能かどうかの確認

センサーの稼働は、0x20のRegisterアドレスで設定できる。7bit目を1を設定すると、センサーが動き出し、0にするとセンサーが停止する。また、湿度/温度の周期設定もおこなう。

ctrl_reg1_reg.png

ctrl_reg1_table.png

ctrl_reg1.png

Status Registerアドレスは0x27になっている。このアドレスの値をチェックする事で、それぞれのセンサーが利用可能になったかの確認が可能になる。

status_reg.png

status_bit.png

status_table.png

arduino

#define HTS221_CTRL_REG1 0x20
#define HTS221_STATUS_REG 0x27

#define HTS221_PD_ON 0b10000000
#define HTS221_BDU_ON 0b100
#define HTS221_ODR_ONESHOT 0b00
#define HTS221_ODR_1KHZ 0b01
#define HTS221_ODR_7KHZ 0b10
#define HTS221_ODR_12_5KHZ 0b11

void PowerOn()
{
  int CTRL_REG1 = HTS221_PD_ON;
  CTRL_REG1 |= HTS221_ODR_1KHZ;
  writeI2c(HTS221_CTRL_REG1, CTRL_REG1);

  bool available = false;
  while(!available){
    byte tmp;
    readI2c(HTS221_STATUS_REG, 1, &tmp);
     if((tmp & 0b1) != 0b1){
       // not available humidity
     } else if((tmp & 0b10) != 0b10){
       // not available temperature
     } else {
        available = true;
     }
  }
}

HeaterとOnShotの設定

執筆中

ctrl_reg2_bit.png

ctrl_reg2_table.png

温度の計算式

temp_calc.png

temp_resgister.png

下記がSTMicroelectronics社のテクニカルシートに記載のソースコードになる。

STMicroelectronics社のサンプルコード
/**
* @brief Read HTS221 temperature output registers, and calculate temperature.
* @param Pointer to the returned temperature value that must be divided by 10 to get the value in ['C].
* @retval Error code [HTS221_ OK, HTS221_ ERROR].
*/
HTS221_Error_et HTS221_Get_Temperature(int16_ t *value)
{
  int16_t T0_out, T1_out, T_out, T0_degC_x8_u16, T1_degC_x8_u16;
  int16_t T0_degC, T1_degC;
  uint8_t buffer[4], tmp;
  uint32_t tmp32;

   /*1. Read from 0x32 & 0x33 registers the value of coefficients T0_degC_x8 and T1_degC_x8*/
  if(HTS221_ReadReg(HTS221_T0_DEGC_X8, 2, buffer))
    return HTS221_ERROR;

  /*2. Read from 0x35 register the value of the MSB bits of T1_degC and    T0_degC */
  if(HTS221_ReadReg(HTS221_T0_T1_DEGC_H2, 1, &tmp))
   return HTS221_ERROR;

  /*Calculate the T0_deg C and T1_deg C values*/
  T0_degC_x8_u16 = (((uint16_t)(tmp & 0x03)) << 8) | ((uint16_t)buffer[0]);
  T1_degC_x8_u16 = (((uint16_t)(tmp & 0x0C)) << 6) | ((uint16_ t)buffer[1]);
  T0_degC = T0_degC_x8_u16>>3;
  T1_degC = T1_degC_x8_u16>>3;

  /*3. Read from 0x3C & 0x3D registers the value of T0_OUT*/
  /*4. Read from 0x3E & 0x3F registers the value of T1_OUT*/
  if(HTS221_ReadReg(HTS221_T0_OUT_L, 4, buffer))
    return HTS221_ERROR;
  T0_out = (((uint16_t)buffer[1])<<8) | (uint16_t)buffer[0];
  T1_out = (((uint16_t)buffer[3])<<8) | (uint16_t)buffer[2];

  /* 5.Read from 0x2A & 0x2B registers the value T_OUT (ADC _OUT).*/
  if(HTS221_ReadReg(HTS221_TEMP_OUT_L_REG, 2, buffer))
   return HTS221_ERROR;
  T_out = (((uint16_ t)buffer[1])<<8) | (uint16_t)buffer[0];

  /* 6. Compute the Temperature value by linea r interpolation*/
  tmp32 = ((uint32_t)(T_out - T0_out)) * ((uint32_t)(T1_degC - T0_degC)*10);
  *value = tmp32 /(T1_out - T0_out) + T0_degC*10;

  return HTS221_OK;
}

これを参考にArduinoのコードを作成する。

arduino
// Temperature calibration registers
#define HTS221_T0_DEGC_X8 0x32
#define HTS221_T1_DEGC_X8 0x33
#define HTS221_T0_T1_DEGC_H2 0x35
#define HTS221_T0_OUT_L 0x3C
#define HTS221_T0_OUT_H 0x3D
#define HTS221_T1_OUT_L 0x3E
#define HTS221_T1_OUT_H 0x3F
#define HTS221_TEMP_OUT_L 0x2A
#define HTS221_TEMP_OUT_H 0x2B

int GetTemperature()
{
  int16_t T0_out, T1_out, T_out, T0_degC_x8_u16, T1_degC_x8_u16;
  int16_t T0_degC, T1_degC;
  uint8_t buffer[4];
  uint32_t tmp32;

  // T0_degC_x8,T1_degC_x8の値の取得
  readI2c(HTS221_T0_DEGC_X8, 1, &buffer[0]);
  readI2c(HTS221_T1_DEGC_X8, 1, &buffer[1]);
  readI2c(HTS221_T0_T1_DEGC_H2, 1, &buffer[2]);

  // T0_degC_x8,T1_degC_x8のH,Lを結合
  T0_degC_x8_u16 = (((uint16_t)(buffer[2] & 0x03)) << 8) | ((uint16_t)buffer[0]);
  T1_degC_x8_u16 = (((uint16_t)(buffer[2] & 0x0C)) << 6) | ((uint16_t)buffer[1]);

  // T0_T1_DEGC_H2の値の取得
  T0_degC = T0_degC_x8_u16>>3;
  T1_degC = T1_degC_x8_u16>>3;

  // T0_OUT_L, T0_OUT_H, T1_OUT_L, T1_OUT_Hの取得
  readI2c(HTS221_T0_OUT_L, 1, &buffer[0]);
  readI2c(HTS221_T0_OUT_H, 1, &buffer[1]);
  readI2c(HTS221_T1_OUT_L, 1, &buffer[2]);
  readI2c(HTS221_T1_OUT_H, 1, &buffer[3]);

  // L,Hの結合
  T0_out = (((uint16_t)buffer[1])<<8) | (uint16_t)buffer[0];
  T1_out = (((uint16_t)buffer[3])<<8) | (uint16_t)buffer[2];

  // TEMP_OUT_L, TEMP_OUT_Hの取得
  readI2c(HTS221_TEMP_OUT_L, 1, &buffer[0]);
  readI2c(HTS221_TEMP_OUT_H, 1, &buffer[1]);

  // L,Hの結合
  T_out = (((uint16_t)buffer[1])<<8) | (uint16_t)buffer[0];

  tmp32 = ((uint32_t)(T_out - T0_out)) * ((uint32_t)(T1_degC - T0_degC)*10);
  return tmp32 /(T1_out - T0_out) + T0_degC*10;
}

湿度の計算式

湿度の計算は、下記式により導き出される。

humidity_calc.png

それぞれの値は、下記のCalibration用のレジスタから取得できる。

humidity_map.png

下記がSTMicroelectronics社のテクニカルシート記載のサンプルコードになる。

STMicroelectronics社のサンプルコード
/**
* @brief Read HTS221 Humidity output registers, and calculate humidity.
* @param Pointer to the returned humidity value that must be divided by 10 to get the value in [%].
* @retval Error code [HTS221_ OK, HTS221_ ERROR].
*/
HTS221_ Error_et HTS221_ Get_Humidity(uint16_t* value)
{
  int16_t H0_T0_ou t, H1_T0_ou t, H_T_ou t;
  int16_t H0_rh, H1_rh;
  uint8_t buffer[2];
  uint32_t tmp;

  /* 1. Read H0_rH and H1_rH coefficients*/
  if(HTS221_ReadReg(HTS221_H0_RH_X2, 2, buffer))
  H0_rh = buffer[0]>>1;
  H1_rh = buffer[1]>>1;

  /*2. Read H0_T0_OUT */
  if(HTS221_ ReadReg(HTS221_H0_T0_OUT_L, 2, buffer))
    return HTS221_ ERROR;
  H0_T0_out = (((uint16_t)buffer[1])<<8) | (uint16_t)buffer[0];

  /*3. Read H1_T0_OUT */
  if(HTS221_ReadReg(HTS221_H1_T0_OUT_L, 2, buffer))
    return HTS221_ERROR;
  H1_T0_out = (((uint16_t)buffer[1])<<8) | (uint16_ t)buffer[0];

  /*4. Read H_T_OUT */
  if(HTS221_ReadReg(HTS221_HR_OUT_L_REG, 2, buffer))
    return HTS221_ERROR;
  H_T_out = (((uint16_t)buffer[1])<<8) | (uint16_t)buffer[0];

  /*5. Compute the RH [%] value by linear interpolation */
    tmp = ((uint32_t)(H_T_out - H0_T0_out)) * ((uint32_t)(H1_rh - H0_rh)*10);
   *value = tmp/(H1_T0_out - H0_T0_out) + H0_rh*10;

  /* Saturation condition*/
  if(*value>1000 ) *value = 1000
    return HTS221_ OK;
}

これを参考にArduinoのコードを作成する。

Arduino
// Humidity calibration registers
#define HTS221_HR_OUT_L_REG 0x28
#define HTS221_HR_OUT_H_REG 0x29
#define HTS221_H0_RH_X2 0x30
#define HTS221_H1_RH_X2 0x31
#define HTS221_H0_T0_OUT_L 0x36
#define HTS221_H0_T0_OUT_H 0x37
#define HTS221_H1_T0_OUT_L 0x3A
#define HTS221_H1_T0_OUT_H 0x3B

int GetHumidity()
{
  uint16_t H0_T0_out, H1_T0_out, H_T_out;
  uint16_t H0_rh, H1_rh;
  uint8_t buffer[2];
  uint32_t humidity;

  // H0_rH, H1_rHの読み込み
  readI2c(HTS221_H0_RH_X2, 1, &buffer[0]);
  readI2c(HTS221_H1_RH_X2, 1, &buffer[1]);
  // 取れてくる値がX2なので、1/2にする
  H0_rh = (buffer[0]&0xff)>>1;
  H1_rh = (buffer[1]&0xff)>>1;

  // H0_T0_OUTの読み込み
  readI2c(HTS221_H0_T0_OUT_L, 1, &buffer[0]);
  readI2c(HTS221_H0_T0_OUT_H, 1, &buffer[1]);
  // H,Lを結合する
  H0_T0_out = (((uint16_t)buffer[1])<<8) | (uint16_t)buffer[0];

  // H1_T0_OUT 読み込み
  readI2c(HTS221_H1_T0_OUT_L, 1, &buffer[0]);
  readI2c(HTS221_H1_T0_OUT_H, 1, &buffer[1]);  
  // H, Lを結合する
  H1_T0_out = (((uint16_t)buffer[1])<<8) | (uint16_t)buffer[0];

  // Read H_T_OUTの読み込み
  readI2c(HTS221_HR_OUT_L_REG, 1, &buffer[0]);
  readI2c(HTS221_HR_OUT_H_REG, 1, &buffer[1]);  
  // H,Lを結合する
  H_T_out = buffer[1]<<8 | buffer[0];

  // RHの計算
  double rh_dx = ((int16_t)H1_rh - (int16_t)H0_rh)*10;
  humidity = ((int16_t)H_T_out - (int16_t)H0_T0_out)*rh_dx / ((int16_t)H1_T0_out - (int16_t)H0_T0_out);
  humidity = (int16_t)(humidity + H0_rh*10);

  if(humidity > 1000){
    humidity = 1000;
  }
  return humidity;
}

I2Cのアクセス用コード

Arduino
#define HTS221_SLAVE_ADDRESS 0x5F

// I2Cへの書き込み
void writeI2c(byte register_addr, byte value) {
  Wire.beginTransmission(HTS221_SLAVE_ADDRESS);  
  Wire.write(register_addr);         
  Wire.write(value);                 
  Wire.endTransmission();        
}

// I2Cへの読み込み
void readI2c(byte register_addr, int num, byte *buf) {
  Wire.beginTransmission(HTS221_SLAVE_ADDRESS); 
  Wire.write(register_addr);           
  Wire.endTransmission(false);         

  //Wire.beginTransmission(DEVICE_ADDR); 
  Wire.requestFrom(HTS221_SLAVE_ADDRESS, num);  

  int i = 0;
  while (Wire.available())
  {
    buf[i] = Wire.read(); 
    i++;   
  }
  //Wire.endTransmission();         
}