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_scheduler_plan_relative(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to tick relative from current spin.
void twr_hts221_set_update_interval(twr_hts221_t *self, twr_tick_t interval)
Set measurement interval.
void twr_scheduler_plan_current_relative(twr_tick_t tick)
Schedule current 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.
void twr_hts221_deinit(twr_hts221_t *self)
Deinitialize HTS221.
void twr_scheduler_plan_current_absolute(twr_tick_t tick)
Schedule current task to absolute tick.
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_scheduler_plan_current_from_now(twr_tick_t tick)
Schedule current task to tick relative from now.
void twr_i2c_init(twr_i2c_channel_t channel, twr_i2c_speed_t speed)
Initialize I2C channel.
uint64_t twr_tick_t
Timestamp data type.
twr_hts221_event_t
Callback events.
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.
twr_tick_t twr_tick_get(void)
Get absolute timestamp since start of program.
twr_i2c_channel_t
I2C channels.
void twr_scheduler_unregister(twr_scheduler_task_id_t task_id)
Unregister specified task.
bool twr_hts221_measure(twr_hts221_t *self)
Start measurement manually.
struct twr_hts221_t twr_hts221_t
HTS221 instance.
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.
void twr_hts221_init(twr_hts221_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize HTS221.
#define TWR_TICK_INFINITY
Maximum timestamp value.
void twr_scheduler_plan_absolute(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to absolute tick.
I2C communication speed is 400 kHz.
bool twr_hts221_get_humidity_percentage(twr_hts221_t *self, float *percentage)
Get measured humidity as percentage.