LoginSignup
9
10

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-01-19

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();         
}
9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10