@@ -4,10 +4,17 @@ use crate::{
4
4
types:: { Address , HeatingDuration , HeatingPower , Measurement , Precision , SensorData } ,
5
5
} ;
6
6
use core:: marker:: PhantomData ;
7
+ #[ cfg( feature = "blocking" ) ]
7
8
use embedded_hal:: blocking:: {
8
9
delay:: DelayMs ,
9
10
i2c:: { Read , Write , WriteRead } ,
10
11
} ;
12
+ #[ cfg( feature = "async" ) ]
13
+ use embedded_hal_async:: {
14
+ delay:: DelayUs ,
15
+ i2c:: { I2c , SevenBitAddress } ,
16
+ } ;
17
+ #[ cfg( feature = "blocking" ) ]
11
18
use sensirion_i2c:: i2c;
12
19
13
20
const RESPONSE_LEN : usize = 6 ;
@@ -46,6 +53,7 @@ impl From<Precision> for Command {
46
53
}
47
54
}
48
55
56
+ #[ cfg( feature = "blocking" ) ]
49
57
impl < I , D , E > Sht4x < I , D >
50
58
where
51
59
I : Read < Error = E > + Write < Error = E > + WriteRead < Error = E > ,
@@ -187,3 +195,157 @@ where
187
195
Ok ( ( ) )
188
196
}
189
197
}
198
+
199
+ #[ cfg( feature = "async" ) ]
200
+ impl < I , D , E > Sht4x < I , D >
201
+ where
202
+ I : I2c < SevenBitAddress , Error = E > ,
203
+ D : DelayUs ,
204
+ {
205
+ /// Creates a new driver instance using the given I2C bus. It configures the default I2C
206
+ /// address 0x44 used by most family members.
207
+ ///
208
+ /// For operating multiple devices on the same bus,
209
+ /// [`shared-bus`](https://github.com/Rahix/shared-bus) might come in handy.
210
+ pub fn new ( i2c : I ) -> Self {
211
+ Self :: new_with_address ( i2c, Address :: Address0x44 )
212
+ }
213
+
214
+ /// Crates a new driver instance using the given I2C bus and address. This constructor allows
215
+ /// to instantiate the driver for the SHT40-BD1B which uses the non-default I2C address 0x45.
216
+ ///
217
+ /// For operating multiple devices on the same bus,
218
+ /// [`shared-bus`](https://github.com/Rahix/shared-bus) might come in handy.
219
+ pub fn new_with_address ( i2c : I , address : Address ) -> Self {
220
+ Sht4x {
221
+ i2c,
222
+ address,
223
+ _delay : PhantomData ,
224
+ }
225
+ }
226
+
227
+ /// Destroys the driver and returns the used I2C bus.
228
+ pub fn destroy ( self ) -> I {
229
+ self . i2c
230
+ }
231
+
232
+ /// Activates the heater and performs a measurement returning measurands in SI units.
233
+ ///
234
+ /// **Note:** The heater is designed to be used up to 10 % of the sensor's lifetime. Please
235
+ /// check the
236
+ /// [datasheet](https://sensirion.com/media/documents/33FD6951/624C4357/Datasheet_SHT4x.pdf),
237
+ /// section 4.9 _Heater Operation_ for details.
238
+ pub async fn heat_and_measure (
239
+ & mut self ,
240
+ power : HeatingPower ,
241
+ duration : HeatingDuration ,
242
+ delay : & mut D ,
243
+ ) -> Result < Measurement , Error < E > > {
244
+ let raw = self . heat_and_measure_raw ( power, duration, delay) . await ?;
245
+
246
+ Ok ( Measurement :: from ( raw) )
247
+ }
248
+
249
+ /// Activates the heater and performs a measurement returning raw sensor data.
250
+ ///
251
+ /// **Note:** The heater is designed to be used up to 10 % of the sensor's lifetime. Please
252
+ /// check the
253
+ /// [datasheet](https://sensirion.com/media/documents/33FD6951/624C4357/Datasheet_SHT4x.pdf),
254
+ /// section 4.9 _Heater Operation_ for details.
255
+ pub async fn heat_and_measure_raw (
256
+ & mut self ,
257
+ power : HeatingPower ,
258
+ duration : HeatingDuration ,
259
+ delay : & mut D ,
260
+ ) -> Result < SensorData , Error < E > > {
261
+ let command = Command :: from ( ( power, duration) ) ;
262
+
263
+ self . write_command_and_delay_for_execution ( command, delay)
264
+ . await ?;
265
+ let response = self . read_response ( ) . await ?;
266
+ let raw = self . sensor_data_from_response ( & response) ;
267
+
268
+ Ok ( raw)
269
+ }
270
+
271
+ /// Performs a measurement returning measurands in SI units.
272
+ pub async fn measure (
273
+ & mut self ,
274
+ precision : Precision ,
275
+ delay : & mut D ,
276
+ ) -> Result < Measurement , Error < E > > {
277
+ let raw = self . measure_raw ( precision, delay) . await ?;
278
+ Ok ( Measurement :: from ( raw) )
279
+ }
280
+
281
+ /// Performs a measurement returning raw sensor data.
282
+ pub async fn measure_raw (
283
+ & mut self ,
284
+ precision : Precision ,
285
+ delay : & mut D ,
286
+ ) -> Result < SensorData , Error < E > > {
287
+ let command = Command :: from ( precision) ;
288
+
289
+ self . write_command_and_delay_for_execution ( command, delay)
290
+ . await ?;
291
+ let response = self . read_response ( ) . await ?;
292
+ let raw = self . sensor_data_from_response ( & response) ;
293
+
294
+ Ok ( raw)
295
+ }
296
+
297
+ /// Reads the sensor's serial number.
298
+ pub async fn serial_number ( & mut self , delay : & mut D ) -> Result < u32 , Error < E > > {
299
+ self . write_command_and_delay_for_execution ( Command :: SerialNumber , delay)
300
+ . await ?;
301
+ let response = self . read_response ( ) . await ?;
302
+
303
+ Ok ( u32:: from_be_bytes ( [
304
+ response[ 0 ] ,
305
+ response[ 1 ] ,
306
+ response[ 3 ] ,
307
+ response[ 4 ] ,
308
+ ] ) )
309
+ }
310
+
311
+ /// Performs a soft reset of the sensor.
312
+ pub async fn soft_reset ( & mut self , delay : & mut D ) -> Result < ( ) , Error < E > > {
313
+ self . write_command_and_delay_for_execution ( Command :: SoftReset , delay)
314
+ . await
315
+ }
316
+
317
+ async fn read_response ( & mut self ) -> Result < [ u8 ; RESPONSE_LEN ] , Error < E > > {
318
+ let mut response = [ 0 ; RESPONSE_LEN ] ;
319
+
320
+ self . i2c
321
+ . read ( self . address . into ( ) , & mut response)
322
+ . await
323
+ . map_err ( Error :: I2c ) ?;
324
+ sensirion_i2c:: crc8:: validate ( & response) ?;
325
+
326
+ Ok ( response)
327
+ }
328
+
329
+ fn sensor_data_from_response ( & self , response : & [ u8 ; RESPONSE_LEN ] ) -> SensorData {
330
+ SensorData {
331
+ temperature : u16:: from_be_bytes ( [ response[ 0 ] , response[ 1 ] ] ) ,
332
+ humidity : u16:: from_be_bytes ( [ response[ 3 ] , response[ 4 ] ] ) ,
333
+ }
334
+ }
335
+
336
+ async fn write_command_and_delay_for_execution (
337
+ & mut self ,
338
+ command : Command ,
339
+ delay : & mut D ,
340
+ ) -> Result < ( ) , Error < E > > {
341
+ let code = command. code ( ) ;
342
+
343
+ self . i2c
344
+ . write ( self . address . into ( ) , & code. to_be_bytes ( ) )
345
+ . await
346
+ . map_err ( Error :: I2c ) ?;
347
+ delay. delay_ms ( command. duration_ms ( ) as u32 ) . await ;
348
+
349
+ Ok ( ( ) )
350
+ }
351
+ }
0 commit comments