1 #include <twr_hts221.h>
3 #define HTS221_WHO_AM_I 0x0F
4 #define HTS221_WHO_AM_I_RESULT 0xBC
5 #define HTS221_AV_CONF 0x10
6 #define HTS221_CTRL_REG1 0x20
7 #define HTS221_CTRL_REG2 0x21
8 #define HTS221_CTRL_REG3 0x22
9 #define HTS221_STATUS_REG 0x27
10 #define HTS221_HUMIDITY_OUT_L 0x28
11 #define HTS221_HUMIDITY_OUT_H 0x29
12 #define HTS221_TEMP_OUT_L 0x2A
13 #define HTS221_TEMP_OUT_H 0x2B
14 #define HTS221_CALIB_OFFSET 0x30
15 #define HTS221_CALIB_0 0x30
16 #define HTS221_CALIB_1 0x31
17 #define HTS221_CALIB_2 0x32
18 #define HTS221_CALIB_3 0x33
19 #define HTS221_CALIB_4 0x34
20 #define HTS221_CALIB_5 0x35
21 #define HTS221_CALIB_6 0x36
22 #define HTS221_CALIB_7 0x37
23 #define HTS221_CALIB_8 0x38
24 #define HTS221_CALIB_9 0x39
25 #define HTS221_CALIB_A 0x3A
26 #define HTS221_CALIB_B 0x3B
27 #define HTS221_CALIB_C 0x3C
28 #define HTS221_CALIB_D 0x3D
29 #define HTS221_CALIB_E 0x3E
30 #define HTS221_CALIB_F 0x3F
31 #define HTS221_BIT_PD 0x80
32 #define HTS221_BIT_BDU 0x04
33 #define HTS221_BIT_ONE_SHOT 0x01
34 #define HTS221_BIT_T_DA 0x01
35 #define HTS221_BIT_H_DA 0x02
36 #define HTS221_MASK_ODR 0x03
37 #define HTS221_ODR_ONE_SHOT 0x00
38 #define HTS221_ODR_1_HZ 0x01
39 #define HTS221_ODR_7_HZ 0x02
40 #define HTS221_ODR_12_HZ 0x03
43 #define _TWR_HTS221_DELAY_RUN 50
44 #define _TWR_HTS221_DELAY_INITIALIZATION 50
45 #define _TWR_HTS221_DELAY_MEASUREMENT 50
47 static void _twr_hts221_task_interval(
void *param);
49 static void _twr_hts221_task_measure(
void *param);
51 static bool _twr_hts221_load_calibration(
twr_hts221_t *
self);
55 memset(
self, 0,
sizeof(*
self));
57 self->_i2c_channel = i2c_channel;
58 self->_i2c_address = i2c_address;
63 self->_tick_ready = _TWR_HTS221_DELAY_RUN;
68 _twr_hts221_load_calibration(
self);
76 ctrl_reg1 &= ~HTS221_BIT_PD;
86 self->_event_handler = event_handler;
87 self->_event_param = event_param;
92 self->_update_interval = interval;
108 if (self->_measurement_active)
113 self->_measurement_active =
true;
122 if (!self->_humidity_valid)
127 *percentage =
self->_h0_rh + ((
self->_reg_humidity -
self->_h0_t0_out) * self->_h_grad);
129 if (*percentage >= 100.f)
137 static void _twr_hts221_task_interval(
void *param)
146 static void _twr_hts221_task_measure(
void *param)
152 switch (self->_state)
154 case TWR_HTS221_STATE_ERROR:
156 self->_humidity_valid =
false;
158 self->_measurement_active =
false;
160 if (self->_event_handler != NULL)
165 self->_state = TWR_HTS221_STATE_INITIALIZE;
169 case TWR_HTS221_STATE_INITIALIZE:
171 self->_state = TWR_HTS221_STATE_ERROR;
180 ctrl_reg1 &= ~HTS221_BIT_PD;
187 self->_state = TWR_HTS221_STATE_MEASURE;
189 self->_tick_ready =
twr_tick_get() + _TWR_HTS221_DELAY_INITIALIZATION;
191 if (self->_measurement_active)
198 case TWR_HTS221_STATE_MEASURE:
200 self->_state = TWR_HTS221_STATE_ERROR;
209 ctrl_reg1 |= HTS221_BIT_PD;
216 if (!
twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, HTS221_CTRL_REG1, HTS221_BIT_PD | HTS221_BIT_BDU))
226 self->_state = TWR_HTS221_STATE_READ;
232 case TWR_HTS221_STATE_READ:
234 self->_state = TWR_HTS221_STATE_ERROR;
245 if ((reg_status & HTS221_BIT_H_DA) == 0)
260 self->_reg_humidity = ((uint16_t) retval[1] << 8) | retval[0];
267 ctrl_reg1 &= ~HTS221_BIT_PD;
274 self->_humidity_valid =
true;
276 self->_state = TWR_HTS221_STATE_UPDATE;
280 case TWR_HTS221_STATE_UPDATE:
282 self->_measurement_active =
false;
284 if (self->_event_handler != NULL)
289 self->_state = TWR_HTS221_STATE_MEASURE;
295 self->_state = TWR_HTS221_STATE_ERROR;
302 static bool _twr_hts221_load_calibration(
twr_hts221_t *
self)
305 uint8_t calibration[16];
309 for (i = 0; i < 16; i++)
311 if (!
twr_i2c_memory_read_8b(self->_i2c_channel, self->_i2c_address, HTS221_CALIB_OFFSET + i, &calibration[i]))
317 self->_h0_rh = (int16_t) calibration[0];
319 h1_rh = (int16_t) calibration[1];
322 self->_h0_t0_out = (int16_t) calibration[6];
323 self->_h0_t0_out |= ((int16_t) calibration[7]) << 8;
325 h1_t0_out = (int16_t) calibration[10];
326 h1_t0_out |= ((int16_t) calibration[11]) << 8;
328 if ((h1_t0_out - self->_h0_t0_out) == 0)
333 self->_h_grad = (float) (h1_rh - self->_h0_rh) / (float) (h1_t0_out - self->_h0_t0_out);
335 uint16_t t0_degC = (int16_t) calibration[2];
336 t0_degC |= (int16_t) (0x03 & calibration[5]) << 8;
339 uint16_t t1_degC = (int16_t) calibration[3];
340 t1_degC |= (int16_t) (0x0C & calibration[5]) << 6;
void twr_hts221_deinit(twr_hts221_t *self)
Deinitialize HTS221.
void twr_hts221_set_update_interval(twr_hts221_t *self, twr_tick_t interval)
Set measurement interval.
bool twr_hts221_measure(twr_hts221_t *self)
Start measurement manually.
struct twr_hts221_t twr_hts221_t
HTS221 instance.
bool twr_hts221_get_humidity_percentage(twr_hts221_t *self, float *percentage)
Get measured humidity as percentage.
void twr_hts221_set_event_handler(twr_hts221_t *self, void(*event_handler)(twr_hts221_t *, twr_hts221_event_t, void *), void *event_param)
Set callback function.
void twr_hts221_init(twr_hts221_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize HTS221.
twr_hts221_event_t
Callback events.
@ TWR_HTS221_EVENT_ERROR
Error event.
@ TWR_HTS221_EVENT_UPDATE
Update event.
void twr_i2c_init(twr_i2c_channel_t channel, twr_i2c_speed_t speed)
Initialize I2C channel.
bool twr_i2c_memory_write_8b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t data)
Memory write 1 byte to I2C channel.
bool twr_i2c_memory_read_8b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t *data)
Memory read 1 byte from I2C channel.
twr_i2c_channel_t
I2C channels.
@ TWR_I2C_SPEED_400_KHZ
I2C communication speed is 400 kHz.
void twr_scheduler_plan_current_from_now(twr_tick_t tick)
Schedule current task to tick relative from now.
void twr_scheduler_plan_current_relative(twr_tick_t tick)
Schedule current task to tick relative from current spin.
void twr_scheduler_plan_current_absolute(twr_tick_t tick)
Schedule current task to absolute tick.
void twr_scheduler_plan_absolute(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to absolute tick.
void twr_scheduler_unregister(twr_scheduler_task_id_t task_id)
Unregister specified task.
void twr_scheduler_plan_relative(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to tick relative from current spin.
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
#define TWR_TICK_INFINITY
Maximum timestamp value.
twr_tick_t twr_tick_get(void)
Get absolute timestamp since start of program.
uint64_t twr_tick_t
Timestamp data type.