HTS221
HTS221は、STMicroelectronics製のI2C通信に対応した湿度/温度センサーである。ここでは、Arduino向けのI2C通信のサンプルを作成する方法を掲載する。
Document
Slave address
0x5f
Register address map
Who_am_I
Who_am_I用に割り振られたレジスタアドレスは、0x0F。0xBCが返ってくると、センサーが認識されている事になる。
#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では、湿度/温度計測時のそれぞれの間隔を設定できる。間隔を細かくすれば、それだけノイズを減らせるが、電流量が増える。
Configurationでは、0-2bit目(AVGH0-AVGH1)がHumidityの分解度、3-5bit目(AVGT0-AVGT1)がTemperatureの分解度の設定用に使われる。
Defialtの1Bの値は、bitに表すと下記表のようになる。
AVGTが011、AVGHが011となる。Temperatureのインターンバルの間隔が16, Humidityが32に設定されている。
一番いい精度に設定する場合は、下記のように111, 111をそろぞれ設定する。
#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にするとセンサーが停止する。また、湿度/温度の周期設定もおこなう。
Status Registerアドレスは0x27になっている。このアドレスの値をチェックする事で、それぞれのセンサーが利用可能になったかの確認が可能になる。
#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の設定
執筆中
温度の計算式
下記が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のコードを作成する。
// 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;
}
湿度の計算式
湿度の計算は、下記式により導き出される。
それぞれの値は、下記のCalibration用のレジスタから取得できる。
下記が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のコードを作成する。
// 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のアクセス用コード
#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();
}