Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_sht30.c
1 #include <bc_sht30.h>
2 
3 #define _BC_SHT30_DELAY_RUN 20
4 #define _BC_SHT30_DELAY_INITIALIZATION 20
5 #define _BC_SHT30_DELAY_MEASUREMENT 20
6 
7 static void _bc_sht30_task_interval(void *param);
8 
9 static void _bc_sht30_task_measure(void *param);
10 
11 void bc_sht30_init(bc_sht30_t *self, bc_i2c_channel_t i2c_channel, uint8_t i2c_address)
12 {
13  memset(self, 0, sizeof(*self));
14 
15  self->_i2c_channel = i2c_channel;
16  self->_i2c_address = i2c_address;
17 
18  self->_task_id_interval = bc_scheduler_register(_bc_sht30_task_interval, self, BC_TICK_INFINITY);
19  self->_task_id_measure = bc_scheduler_register(_bc_sht30_task_measure, self, _BC_SHT30_DELAY_RUN);
20 
21  self->_tick_ready = _BC_SHT30_DELAY_RUN;
22 
23  bc_i2c_init(self->_i2c_channel, BC_I2C_SPEED_400_KHZ);
24 }
25 
26 void bc_sht30_set_event_handler(bc_sht30_t *self, void (*event_handler)(bc_sht30_t *, bc_sht30_event_t, void *), void *event_param)
27 {
28  self->_event_handler = event_handler;
29  self->_event_param = event_param;
30 }
31 
33 {
34  self->_update_interval = interval;
35 
36  if (self->_update_interval == BC_TICK_INFINITY)
37  {
38  bc_scheduler_plan_absolute(self->_task_id_interval, BC_TICK_INFINITY);
39  }
40  else
41  {
42  bc_scheduler_plan_relative(self->_task_id_interval, self->_update_interval);
43 
44  bc_sht30_measure(self);
45  }
46 }
47 
49 {
50  if (self->_measurement_active)
51  {
52  return false;
53  }
54 
55  self->_measurement_active = true;
56 
57  bc_scheduler_plan_absolute(self->_task_id_measure, self->_tick_ready);
58 
59  return true;
60 }
61 
62 bool bc_sht30_get_humidity_raw(bc_sht30_t *self, uint16_t *raw)
63 {
64  if (!self->_humidity_valid)
65  {
66  return false;
67  }
68 
69  *raw = self->_reg_humidity;
70 
71  return true;
72 }
73 
74 bool bc_sht30_get_humidity_percentage(bc_sht30_t *self, float *percentage)
75 {
76  uint16_t raw;
77 
78  if (!bc_sht30_get_humidity_raw(self, &raw))
79  {
80  return false;
81  }
82 
83  *percentage = 100.f * (float) raw / (65536.f - 1.f);
84 
85  if (*percentage >= 100.f)
86  {
87  *percentage = 100.f;
88  }
89  else if (*percentage <= 0.f)
90  {
91  *percentage = 0.f;
92  }
93 
94  return true;
95 }
96 
97 bool bc_sht30_get_temperature_raw(bc_sht30_t *self, uint16_t *raw)
98 {
99  if (!self->_temperature_valid)
100  {
101  return false;
102  }
103 
104  *raw = self->_reg_temperature;
105 
106  return true;
107 }
108 
109 bool bc_sht30_get_temperature_celsius(bc_sht30_t *self, float *celsius)
110 {
111  uint16_t raw;
112 
113  if (!bc_sht30_get_temperature_raw(self, &raw))
114  {
115  return false;
116  }
117 
118  *celsius = -45.f + (175.f * (float) raw / (65535.f));
119 
120  return true;
121 }
122 
123 static void _bc_sht30_task_interval(void *param)
124 {
125  bc_sht30_t *self = param;
126 
127  bc_sht30_measure(self);
128 
129  bc_scheduler_plan_current_relative(self->_update_interval);
130 }
131 
132 static void _bc_sht30_task_measure(void *param)
133 {
134  bc_sht30_t *self = param;
135 
136 start:
137 
138  switch (self->_state)
139  {
140  case BC_SHT30_STATE_ERROR:
141  {
142  self->_humidity_valid = false;
143  self->_temperature_valid = false;
144 
145  self->_measurement_active = false;
146 
147  if (self->_event_handler != NULL)
148  {
149  self->_event_handler(self, BC_SHT30_EVENT_ERROR, self->_event_param);
150  }
151 
152  self->_state = BC_SHT30_STATE_INITIALIZE;
153 
154  return;
155  }
156  case BC_SHT30_STATE_INITIALIZE:
157  {
158  self->_state = BC_SHT30_STATE_ERROR;
159 
160  uint8_t buffer[2];
161 
162  buffer[0] = 0x30;
163  buffer[1] = 0xa2;
164 
165  bc_i2c_transfer_t transfer;
166 
167  transfer.device_address = self->_i2c_address;
168  transfer.buffer = buffer;
169  transfer.length = sizeof(buffer);
170 
171  if (!bc_i2c_write(self->_i2c_channel, &transfer))
172  {
173  goto start;
174  }
175 
176  self->_state = BC_SHT30_STATE_MEASURE;
177 
178  self->_tick_ready = bc_tick_get() + _BC_SHT30_DELAY_INITIALIZATION;
179 
180  if (self->_measurement_active)
181  {
182  bc_scheduler_plan_current_absolute(self->_tick_ready);
183  }
184 
185  return;
186  }
187  case BC_SHT30_STATE_MEASURE:
188  {
189  self->_state = BC_SHT30_STATE_ERROR;
190 
191  uint8_t buffer[2];
192 
193  buffer[0] = 0x2c;
194  buffer[1] = 0x0d;
195 
196  bc_i2c_transfer_t transfer;
197 
198  transfer.device_address = self->_i2c_address;
199  transfer.buffer = buffer;
200  transfer.length = sizeof(buffer);
201 
202  if (!bc_i2c_write(self->_i2c_channel, &transfer))
203  {
204  goto start;
205  }
206 
207  self->_state = BC_SHT30_STATE_READ;
208 
209  bc_scheduler_plan_current_from_now(_BC_SHT30_DELAY_MEASUREMENT);
210 
211  return;
212  }
213  case BC_SHT30_STATE_READ:
214  {
215  self->_state = BC_SHT30_STATE_ERROR;
216 
217  uint8_t buffer[6];
218 
219  bc_i2c_transfer_t transfer;
220 
221  transfer.device_address = self->_i2c_address;
222  transfer.buffer = buffer;
223  transfer.length = sizeof(buffer);
224 
225  if (!bc_i2c_read(self->_i2c_channel, &transfer))
226  {
227  goto start;
228  }
229 
230  self->_reg_humidity = buffer[3] << 8 | buffer[4];
231  self->_reg_temperature = buffer[0] << 8 | buffer[1];
232 
233  self->_humidity_valid = true;
234  self->_temperature_valid = true;
235 
236  self->_state = BC_SHT30_STATE_UPDATE;
237 
238  goto start;
239  }
240  case BC_SHT30_STATE_UPDATE:
241  {
242  self->_measurement_active = false;
243 
244  if (self->_event_handler != NULL)
245  {
246  self->_event_handler(self, BC_SHT30_EVENT_UPDATE, self->_event_param);
247  }
248 
249  self->_state = BC_SHT30_STATE_MEASURE;
250 
251  return;
252  }
253  default:
254  {
255  self->_state = BC_SHT30_STATE_ERROR;
256 
257  goto start;
258  }
259  }
260 }
I2C transfer parameters.
Definition: bc_i2c.h:42
bool bc_sht30_get_humidity_percentage(bc_sht30_t *self, float *percentage)
Get measured humidity as percentage.
Definition: bc_sht30.c:74
Error event.
Definition: bc_sht30.h:19
uint64_t bc_tick_t
Timestamp data type.
Definition: bc_tick.h:16
I2C communication speed is 400 kHz.
Definition: bc_i2c.h:36
struct bc_sht30_t bc_sht30_t
SHT30 instance.
Definition: bc_sht30.h:28
void bc_scheduler_plan_absolute(bc_scheduler_task_id_t task_id, bc_tick_t tick)
Schedule specified task to absolute tick.
Definition: bc_scheduler.c:124
bool bc_sht30_get_temperature_raw(bc_sht30_t *self, uint16_t *raw)
Get measured temperature as raw value.
Definition: bc_sht30.c:97
uint8_t device_address
7-bit I2C device address
Definition: bc_i2c.h:45
Update event.
Definition: bc_sht30.h:22
bool bc_i2c_read(bc_i2c_channel_t channel, const bc_i2c_transfer_t *transfer)
Read from I2C channel.
Definition: bc_i2c.c:283
bc_scheduler_task_id_t bc_scheduler_register(void(*task)(void *), void *param, bc_tick_t tick)
Register task in scheduler.
Definition: bc_scheduler.c:56
void bc_scheduler_plan_current_absolute(bc_tick_t tick)
Schedule current task to absolute tick.
Definition: bc_scheduler.c:144
void bc_i2c_init(bc_i2c_channel_t channel, bc_i2c_speed_t speed)
Initialize I2C channel.
Definition: bc_i2c.c:54
bc_sht30_event_t
Callback events.
Definition: bc_sht30.h:16
void bc_sht30_init(bc_sht30_t *self, bc_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize SHT30.
Definition: bc_sht30.c:11
bc_tick_t bc_tick_get(void)
Get absolute timestamp since start of program.
Definition: bc_tick.c:7
void * buffer
Pointer to buffer which is being written or read.
Definition: bc_i2c.h:48
void bc_scheduler_plan_current_relative(bc_tick_t tick)
Schedule current task to tick relative from current spin.
Definition: bc_scheduler.c:149
bool bc_i2c_write(bc_i2c_channel_t channel, const bc_i2c_transfer_t *transfer)
Write to I2C channel.
Definition: bc_i2c.c:237
void bc_sht30_set_update_interval(bc_sht30_t *self, bc_tick_t interval)
Set measurement interval.
Definition: bc_sht30.c:32
void bc_sht30_set_event_handler(bc_sht30_t *self, void(*event_handler)(bc_sht30_t *, bc_sht30_event_t, void *), void *event_param)
Set callback function.
Definition: bc_sht30.c:26
void bc_scheduler_plan_relative(bc_scheduler_task_id_t task_id, bc_tick_t tick)
Schedule specified task to tick relative from current spin.
Definition: bc_scheduler.c:129
bc_i2c_channel_t
I2C channels.
Definition: bc_i2c.h:15
size_t length
Length of buffer which is being written or read.
Definition: bc_i2c.h:51
bool bc_sht30_get_humidity_raw(bc_sht30_t *self, uint16_t *raw)
Get measured humidity as raw value.
Definition: bc_sht30.c:62
void bc_scheduler_plan_current_from_now(bc_tick_t tick)
Schedule current task to tick relative from now.
Definition: bc_scheduler.c:154
#define BC_TICK_INFINITY
Maximum timestamp value.
Definition: bc_tick.h:12
bool bc_sht30_measure(bc_sht30_t *self)
Start measurement manually.
Definition: bc_sht30.c:48
bool bc_sht30_get_temperature_celsius(bc_sht30_t *self, float *celsius)
Get measured temperature in degrees of Celsius.
Definition: bc_sht30.c:109