Firmware SDK
twr_sht30.c
1 #include <twr_sht30.h>
2 #include <twr_crc.h>
3 #include <twr_log.h>
4 
5 #define _TWR_SHT30_DELAY_RUN 20
6 #define _TWR_SHT30_DELAY_INITIALIZATION 50
7 #define _TWR_SHT30_DELAY_MEASUREMENT 20
8 
9 static void _twr_sht30_task_interval(void *param);
10 
11 static void _twr_sht30_task_measure(void *param);
12 
13 static bool _twr_sht30_write(twr_sht30_t *self, const uint16_t data);
14 
15 void twr_sht30_init(twr_sht30_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
16 {
17  memset(self, 0, sizeof(*self));
18 
19  self->_i2c_channel = i2c_channel;
20  self->_i2c_address = i2c_address;
21 
22  self->_task_id_interval = twr_scheduler_register(_twr_sht30_task_interval, self, TWR_TICK_INFINITY);
23  self->_task_id_measure = twr_scheduler_register(_twr_sht30_task_measure, self, _TWR_SHT30_DELAY_RUN);
24 
25  self->_tick_ready = _TWR_SHT30_DELAY_RUN;
26 
27  twr_i2c_init(self->_i2c_channel, TWR_I2C_SPEED_400_KHZ);
28 }
29 
31 {
32  _twr_sht30_write(self, 0xa230);
33  twr_scheduler_unregister(self->_task_id_interval);
34  twr_scheduler_unregister(self->_task_id_measure);
35 }
36 
37 void twr_sht30_set_event_handler(twr_sht30_t *self, void (*event_handler)(twr_sht30_t *, twr_sht30_event_t, void *), void *event_param)
38 {
39  self->_event_handler = event_handler;
40  self->_event_param = event_param;
41 }
42 
44 {
45  self->_update_interval = interval;
46 
47  if (self->_update_interval == TWR_TICK_INFINITY)
48  {
49  twr_scheduler_plan_absolute(self->_task_id_interval, TWR_TICK_INFINITY);
50  }
51  else
52  {
53  twr_scheduler_plan_relative(self->_task_id_interval, self->_update_interval);
54 
55  twr_sht30_measure(self);
56  }
57 }
58 
60 {
61  if (self->_measurement_active)
62  {
63  return false;
64  }
65 
66  self->_measurement_active = true;
67 
68  twr_scheduler_plan_absolute(self->_task_id_measure, self->_tick_ready);
69 
70  return true;
71 }
72 
73 bool twr_sht30_get_humidity_raw(twr_sht30_t *self, uint16_t *raw)
74 {
75  if (!self->_humidity_valid)
76  {
77  return false;
78  }
79 
80  *raw = self->_reg_humidity;
81 
82  return true;
83 }
84 
85 bool twr_sht30_get_humidity_percentage(twr_sht30_t *self, float *percentage)
86 {
87  uint16_t raw;
88 
89  if (!twr_sht30_get_humidity_raw(self, &raw))
90  {
91  return false;
92  }
93 
94  *percentage = 100.f * (float) raw / (65536.f - 1.f);
95 
96  if (*percentage >= 100.f)
97  {
98  *percentage = 100.f;
99  }
100  else if (*percentage <= 0.f)
101  {
102  *percentage = 0.f;
103  }
104 
105  return true;
106 }
107 
108 bool twr_sht30_get_temperature_raw(twr_sht30_t *self, uint16_t *raw)
109 {
110  if (!self->_temperature_valid)
111  {
112  return false;
113  }
114 
115  *raw = self->_reg_temperature;
116 
117  return true;
118 }
119 
121 {
122  uint16_t raw;
123 
124  if (!twr_sht30_get_temperature_raw(self, &raw))
125  {
126  return false;
127  }
128 
129  *celsius = -45.f + (175.f * (float) raw / (65535.f));
130 
131  return true;
132 }
133 
134 bool twr_sht30_get_temperature_fahrenheit(twr_sht30_t *self, float *fahrenheit)
135 {
136  float celsius;
137 
138  if (!twr_sht30_get_temperature_celsius(self, &celsius))
139  {
140  return false;
141  }
142 
143  *fahrenheit = celsius * 1.8f + 32.f;
144 
145  return true;
146 }
147 
149 {
150  float celsius;
151 
152  if (!twr_sht30_get_temperature_celsius(self, &celsius))
153  {
154  return false;
155  }
156 
157  *kelvin = celsius + 273.15f;
158 
159  if (*kelvin < 0.f)
160  {
161  *kelvin = 0.f;
162  }
163 
164  return true;
165 }
166 
167 static void _twr_sht30_task_interval(void *param)
168 {
169  twr_sht30_t *self = param;
170 
171  twr_sht30_measure(self);
172 
173  twr_scheduler_plan_current_relative(self->_update_interval);
174 }
175 
176 static void _twr_sht30_task_measure(void *param)
177 {
178  twr_sht30_t *self = param;
179 
180 start:
181 
182  switch (self->_state)
183  {
184  case TWR_SHT30_STATE_ERROR:
185  {
186  self->_humidity_valid = false;
187  self->_temperature_valid = false;
188 
189  self->_measurement_active = false;
190 
191  if (self->_event_handler != NULL)
192  {
193  self->_event_handler(self, TWR_SHT30_EVENT_ERROR, self->_event_param);
194  }
195 
196  self->_state = TWR_SHT30_STATE_INITIALIZE;
197 
198  return;
199  }
200  case TWR_SHT30_STATE_INITIALIZE:
201  {
202  self->_state = TWR_SHT30_STATE_ERROR;
203 
204  if (!_twr_sht30_write(self, 0xa230))
205  {
206  goto start;
207  }
208 
209  self->_state = TWR_SHT30_STATE_MEASURE;
210 
211  self->_tick_ready = twr_tick_get() + _TWR_SHT30_DELAY_INITIALIZATION;
212 
213  if (self->_measurement_active)
214  {
215  twr_scheduler_plan_current_absolute(self->_tick_ready);
216  }
217 
218  return;
219  }
220  case TWR_SHT30_STATE_MEASURE:
221  {
222  self->_state = TWR_SHT30_STATE_ERROR;
223 
224  if (!_twr_sht30_write(self, 0x0d2c))
225  {
226  goto start;
227  }
228 
229  self->_state = TWR_SHT30_STATE_READ;
230 
231  twr_scheduler_plan_current_from_now(_TWR_SHT30_DELAY_MEASUREMENT);
232 
233  return;
234  }
235  case TWR_SHT30_STATE_READ:
236  {
237  self->_state = TWR_SHT30_STATE_ERROR;
238 
239  uint8_t buffer[6];
240 
241  twr_i2c_transfer_t transfer;
242 
243  transfer.device_address = self->_i2c_address;
244  transfer.buffer = buffer;
245  transfer.length = sizeof(buffer);
246 
247  if (!twr_i2c_read(self->_i2c_channel, &transfer))
248  {
249  goto start;
250  }
251 
252  if ((twr_crc8(0x31, buffer, 2, 0xff) != buffer[2]) || (twr_crc8(0x31, buffer + 3, 2, 0xff) != buffer[5]))
253  {
254  goto start;
255  }
256 
257  self->_reg_humidity = buffer[3] << 8 | buffer[4];
258  self->_reg_temperature = buffer[0] << 8 | buffer[1];
259 
260  self->_humidity_valid = true;
261  self->_temperature_valid = true;
262 
263  self->_state = TWR_SHT30_STATE_UPDATE;
264 
265  goto start;
266  }
267  case TWR_SHT30_STATE_UPDATE:
268  {
269  self->_measurement_active = false;
270 
271  if (self->_event_handler != NULL)
272  {
273  self->_event_handler(self, TWR_SHT30_EVENT_UPDATE, self->_event_param);
274  }
275 
276  self->_state = TWR_SHT30_STATE_MEASURE;
277 
278  return;
279  }
280  default:
281  {
282  self->_state = TWR_SHT30_STATE_ERROR;
283 
284  goto start;
285  }
286  }
287 }
288 
289 static bool _twr_sht30_write(twr_sht30_t *self, const uint16_t data)
290 {
291  twr_i2c_transfer_t transfer;
292 
293  transfer.device_address = self->_i2c_address;
294  transfer.buffer = (void *) &data;
295  transfer.length = sizeof(data);
296 
297  return twr_i2c_write(self->_i2c_channel, &transfer);
298 }
bool twr_sht30_get_temperature_celsius(twr_sht30_t *self, float *celsius)
Get measured temperature in degrees of Celsius.
Definition: twr_sht30.c:120
bool twr_i2c_write(twr_i2c_channel_t channel, const twr_i2c_transfer_t *transfer)
Write to I2C channel.
Definition: twr_i2c.c:243
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_scheduler_plan_current_relative(twr_tick_t tick)
Schedule current task to tick relative from current spin.
bool twr_sht30_get_temperature_raw(twr_sht30_t *self, uint16_t *raw)
Get measured temperature as raw value.
Definition: twr_sht30.c:108
uint8_t device_address
7-bit I2C device address
Definition: twr_i2c.h:45
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
Definition: twr_scheduler.c:53
void twr_scheduler_plan_current_absolute(twr_tick_t tick)
Schedule current task to absolute tick.
bool twr_sht30_measure(twr_sht30_t *self)
Start measurement manually.
Definition: twr_sht30.c:59
void twr_sht30_deinit(twr_sht30_t *self)
Deinitialize SHT30.
Definition: twr_sht30.c:30
I2C transfer parameters.
Definition: twr_i2c.h:42
bool twr_sht30_get_temperature_fahrenheit(twr_sht30_t *self, float *fahrenheit)
Get measured temperature in degrees of Fahrenheit.
Definition: twr_sht30.c:134
twr_sht30_event_t
Callback events.
Definition: twr_sht30.h:16
void twr_scheduler_plan_current_from_now(twr_tick_t tick)
Schedule current task to tick relative from now.
void twr_sht30_init(twr_sht30_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize SHT30.
Definition: twr_sht30.c:15
uint8_t twr_crc8(const uint8_t polynomial, const void *buffer, size_t length, const uint8_t initialization)
Calculate CRC8.
Definition: twr_crc.c:3
void twr_i2c_init(twr_i2c_channel_t channel, twr_i2c_speed_t speed)
Initialize I2C channel.
Definition: twr_i2c.c:57
uint64_t twr_tick_t
Timestamp data type.
Definition: twr_tick.h:16
twr_tick_t twr_tick_get(void)
Get absolute timestamp since start of program.
Definition: twr_tick.c:7
size_t length
Length of buffer which is being written or read.
Definition: twr_i2c.h:51
twr_i2c_channel_t
I2C channels.
Definition: twr_i2c.h:15
void twr_scheduler_unregister(twr_scheduler_task_id_t task_id)
Unregister specified task.
Definition: twr_scheduler.c:77
void twr_sht30_set_update_interval(twr_sht30_t *self, twr_tick_t interval)
Set measurement interval.
Definition: twr_sht30.c:43
bool twr_sht30_get_humidity_percentage(twr_sht30_t *self, float *percentage)
Get measured humidity as percentage.
Definition: twr_sht30.c:85
bool twr_i2c_read(twr_i2c_channel_t channel, const twr_i2c_transfer_t *transfer)
Read from I2C channel.
Definition: twr_i2c.c:289
void * buffer
Pointer to buffer which is being written or read.
Definition: twr_i2c.h:48
Error event.
Definition: twr_sht30.h:19
void twr_sht30_set_event_handler(twr_sht30_t *self, void(*event_handler)(twr_sht30_t *, twr_sht30_event_t, void *), void *event_param)
Set callback function.
Definition: twr_sht30.c:37
bool twr_sht30_get_humidity_raw(twr_sht30_t *self, uint16_t *raw)
Get measured humidity as raw value.
Definition: twr_sht30.c:73
bool twr_sht30_get_temperature_kelvin(twr_sht30_t *self, float *kelvin)
Get measured temperature in kelvin.
Definition: twr_sht30.c:148
Update event.
Definition: twr_sht30.h:22
#define TWR_TICK_INFINITY
Maximum timestamp value.
Definition: twr_tick.h:12
void twr_scheduler_plan_absolute(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to absolute tick.
struct twr_sht30_t twr_sht30_t
SHT30 instance.
Definition: twr_sht30.h:28
I2C communication speed is 400 kHz.
Definition: twr_i2c.h:36