1
- use embedded_hal :: {
2
- delay :: DelayNs ,
3
- digital :: { InputPin , OutputPin } ,
4
- } ;
1
+ use embassy_time :: { with_timeout , Duration , Instant } ;
2
+ use embedded_hal :: digital :: { InputPin , OutputPin } ;
3
+ use embedded_hal_async :: delay :: DelayNs ;
4
+ use embedded_hal_async :: digital :: Wait ;
5
5
6
6
/// How long to wait for a pulse on the data line (in microseconds).
7
- const TIMEOUT_US : u16 = 1_000 ;
7
+ const TIMEOUT_US : u64 = 1_000 ;
8
8
9
9
/// Error type for this crate.
10
10
#[ derive( Debug ) ]
@@ -39,7 +39,7 @@ pub struct Measurement {
39
39
40
40
impl < GPIO , D , E > Dht11 < GPIO , D >
41
41
where
42
- GPIO : InputPin < Error = E > + OutputPin < Error = E > ,
42
+ GPIO : InputPin < Error = E > + OutputPin < Error = E > + Wait ,
43
43
D : DelayNs ,
44
44
{
45
45
/// Creates a new DHT11 device connected to the specified pin.
@@ -48,22 +48,22 @@ where
48
48
}
49
49
50
50
/// Performs a reading of the sensor.
51
- pub fn read ( & mut self ) -> Result < Measurement , Error < E > > {
51
+ pub async fn read ( & mut self ) -> Result < Measurement , Error < E > > {
52
52
let mut data = [ 0u8 ; 5 ] ;
53
53
54
54
// Perform initial handshake
55
- self . perform_handshake ( ) ?;
55
+ self . perform_handshake ( ) . await ?;
56
56
57
57
// Read bits
58
58
for i in 0 ..40 {
59
59
data[ i / 8 ] <<= 1 ;
60
- if self . read_bit ( ) ? {
60
+ if self . read_bit ( ) . await ? {
61
61
data[ i / 8 ] |= 1 ;
62
62
}
63
63
}
64
64
65
65
// Finally wait for line to go idle again.
66
- self . wait_for_pulse ( true ) ?;
66
+ self . wait_for_pulse ( true ) . await ?;
67
67
68
68
// Check CRC
69
69
let crc = data[ 0 ]
@@ -80,55 +80,50 @@ where
80
80
} )
81
81
}
82
82
83
- fn perform_handshake ( & mut self ) -> Result < ( ) , Error < E > > {
83
+ async fn perform_handshake ( & mut self ) -> Result < ( ) , Error < E > > {
84
84
// Set pin as floating to let pull-up raise the line and start the reading process.
85
85
self . gpio . set_high ( ) . map_err ( Error :: Gpio ) ?;
86
- self . delay . delay_ms ( 1 ) ;
86
+ self . delay . delay_ms ( 1 ) . await ;
87
87
88
88
// Pull line low for at least 18ms to send a start command.
89
89
self . gpio . set_low ( ) . map_err ( Error :: Gpio ) ?;
90
- self . delay . delay_ms ( 20 ) ;
90
+ self . delay . delay_ms ( 20 ) . await ;
91
91
92
92
// Restore floating
93
93
self . gpio . set_high ( ) . map_err ( Error :: Gpio ) ?;
94
- self . delay . delay_us ( 40 ) ;
94
+ self . delay . delay_us ( 40 ) . await ;
95
95
96
96
// As a response, the device pulls the line low for 80us and then high for 80us.
97
- self . read_bit ( ) ?;
97
+ self . read_bit ( ) . await ?;
98
98
99
99
Ok ( ( ) )
100
100
}
101
101
102
- fn read_bit ( & mut self ) -> Result < bool , Error < E > > {
103
- let low = self . wait_for_pulse ( true ) ?;
104
- let high = self . wait_for_pulse ( false ) ?;
102
+ async fn read_bit ( & mut self ) -> Result < bool , Error < E > > {
103
+ let low = self . wait_for_pulse ( true ) . await ?;
104
+ let high = self . wait_for_pulse ( false ) . await ?;
105
105
Ok ( high > low)
106
106
}
107
107
108
- fn wait_for_pulse ( & mut self , level : bool ) -> Result < u32 , Error < E > > {
109
- let mut count = 0 ;
108
+ async fn wait_for_pulse ( & mut self , level : bool ) -> Result < u64 , Error < E > > {
109
+ let timeout_duration = Duration :: from_micros ( TIMEOUT_US ) ;
110
+ let start = Instant :: now ( ) ;
110
111
111
- while self . gpio . is_high ( ) . map_err ( Error :: Gpio ) ? != level {
112
- count += 1 ;
113
- if count > TIMEOUT_US {
114
- return Err ( Error :: Timeout ) ;
112
+ let wait_future = async {
113
+ if level {
114
+ self . gpio . wait_for_rising_edge ( ) . await . map_err ( Error :: Gpio )
115
+ } else {
116
+ self . gpio . wait_for_falling_edge ( ) . await . map_err ( Error :: Gpio )
115
117
}
116
- self . delay . delay_us ( 1 ) ;
117
- }
118
+ } ;
118
119
119
- Ok ( u32:: from ( count) )
120
- }
121
- }
120
+ // Wait for the pulse with timeout.
121
+ with_timeout ( timeout_duration, wait_future)
122
+ . await
123
+ . map_err ( |_| Error :: Timeout ) ??;
124
+ let elapsed = Instant :: now ( ) - start;
122
125
123
- impl < GPIO , D , E > Drop for Dht11 < GPIO , D >
124
- where
125
- GPIO : InputPin < Error = E > + OutputPin < Error = E > ,
126
- D : DelayNs ,
127
- {
128
- fn drop ( & mut self ) {
129
- // Set pin high (floating with pull-up) as safe state
130
- // Ignore errors during drop
131
- let _ = self . gpio . set_high ( ) ;
132
- self . delay . delay_us ( 40 ) ;
126
+ // Using microseconds for finer measurement.
127
+ Ok ( elapsed. as_micros ( ) )
133
128
}
134
129
}
0 commit comments