Skip to content

Commit 7efdecb

Browse files
authored
Merge pull request #27 from hss-mateus/release
2 parents f8f156d + 302ed50 commit 7efdecb

File tree

3 files changed

+115
-22
lines changed

3 files changed

+115
-22
lines changed

Cargo.lock

Lines changed: 11 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ frequency = "always"
1818
[dependencies]
1919
embedded-hal = "1.0"
2020
bitmatch = "0.1.1"
21+
embedded-hal-async = "1.0.0"
2122
# dimensioned = "0.8.0" # Compile-time dimensional analysis for various unit systems using Rust's type system
2223

2324
[features]

src/lib.rs

Lines changed: 103 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use bitmatch::bitmatch;
66
use core::unimplemented;
77
use embedded_hal as hal;
8+
use embedded_hal_async::spi::SpiBus as AsyncSpiBus;
89
use hal::spi::SpiBus;
910
//
1011
// saturation
@@ -93,6 +94,37 @@ impl<SPIERROR> From<SPIERROR> for Hx711Error<SPIERROR> {
9394
}
9495
}
9596

97+
impl<SPI> Hx711<SPI>
98+
{
99+
#[inline]
100+
/// Get the current mode.
101+
pub fn mode(&mut self) -> Mode {
102+
self.mode
103+
}
104+
105+
/// To power down the chip the PD_SCK line has to be held in a 'high' state. To do this we
106+
/// would need to write a constant stream of binary '1' to the `SPI` bus which would totally defy
107+
/// the purpose. Therefore it's not implemented.
108+
// If the SDO pin would be idle high (and at least some MCU's seem to do that in mode 1) then the chip would automatically
109+
// power down if not used. Cool!
110+
pub fn disable(&mut self) -> ! {
111+
// when PD_SCK pin changes from low to high and stays at high for longer than 60µs, HX711 enters power down mode
112+
// When PD_SCK returns to low, chip will reset and enter normal operation mode.
113+
// this can't be implemented with SPI because we would have to write a constant stream
114+
// of binary '1' which would block the process
115+
unimplemented!("power_down is not possible with this driver implementation");
116+
}
117+
118+
/// Power up / down is not implemented (see disable)
119+
pub fn enable(&mut self) -> ! {
120+
// when PD_SCK pin changes from low to high and stays at high for longer than 60µs, HX711 enters power down mode
121+
// When PD_SCK returns to low, chip will reset and enter normal operation mode.
122+
// this can't be implemented with SPI because we would have to write a constant stream
123+
// of binary '1' which would block the process
124+
unimplemented!("power_down is not possible with this driver implementation");
125+
}
126+
}
127+
96128
impl<SPI> Hx711<SPI>
97129
where
98130
SPI: SpiBus,
@@ -171,33 +203,83 @@ where
171203
self.read()?; // read writes Mode for the next read()
172204
Ok(m)
173205
}
206+
}
174207

175-
#[inline]
176-
/// Get the current mode.
177-
pub fn mode(&mut self) -> Mode {
178-
self.mode
208+
impl<SPI> Hx711<SPI>
209+
where
210+
SPI: AsyncSpiBus,
211+
{
212+
/// opens a connection to a HX711 on a specified `SPI`.
213+
///
214+
/// The data sheet specifies PD_SCK high time and PD_SCK low time to be in the 0.2 to 50 us range,
215+
/// therefore bus speed has to be between 5 MHz and 20 kHz.
216+
pub fn new_async(spi: SPI) -> Self {
217+
Hx711 {
218+
spi,
219+
mode: Mode::ChAGain128,
220+
}
179221
}
180222

181-
/// To power down the chip the PD_SCK line has to be held in a 'high' state. To do this we
182-
/// would need to write a constant stream of binary '1' to the `SPI` bus which would totally defy
183-
/// the purpose. Therefore it's not implemented.
184-
// If the SDO pin would be idle high (and at least some MCU's seem to do that in mode 1) then the chip would automatically
185-
// power down if not used. Cool!
186-
pub fn disable(&mut self) -> Result<(), Hx711Error<SPI::Error>> {
187-
// when PD_SCK pin changes from low to high and stays at high for longer than 60µs, HX711 enters power down mode
188-
// When PD_SCK returns to low, chip will reset and enter normal operation mode.
189-
// this can't be implemented with SPI because we would have to write a constant stream
190-
// of binary '1' which would block the process
191-
unimplemented!("power_down is not possible with this driver implementation");
223+
/// reads a value from the HX711 and returns it
224+
/// # Errors
225+
/// Returns `SPI` errors
226+
pub async fn read_async(&mut self) -> Result<i32, SPI::Error> {
227+
// check if data is ready
228+
// When output data is not ready for retrieval, digital output pin DOUT is high.
229+
// Serial clock input PD_SCK should be low. When DOUT goes
230+
// to low, it indicates data is ready for retrieval.
231+
let mut txrx: [u8; 1] = [SIGNAL_LOW];
232+
233+
while txrx[0] != 0x00 {
234+
self.spi.transfer_in_place(&mut txrx).await?;
235+
}
236+
237+
let mut buffer: [u8; 7] = [CLOCK, CLOCK, CLOCK, CLOCK, CLOCK, CLOCK, self.mode as u8];
238+
239+
self.spi.transfer_in_place(&mut buffer).await?;
240+
241+
Ok(decode_output(&buffer)) // value should be in range 0x800000 - 0x7fffff according to datasheet
192242
}
193243

194-
/// Power up / down is not implemented (see disable)
195-
pub fn enable(&mut self) -> Result<(), Hx711Error<SPI::Error>> {
196-
// when PD_SCK pin changes from low to high and stays at high for longer than 60µs, HX711 enters power down mode
244+
/// Reset the chip to it's default state. Mode is set to convert channel A with a gain factor of 128.
245+
/// # Errors
246+
/// Returns `SPI` errors
247+
#[inline]
248+
pub async fn reset_async(&mut self) -> Result<(), SPI::Error> {
249+
// when PD_SCK pin changes from low to high and stays at high for longer than 60µs,
250+
// HX711 enters power down mode.
197251
// When PD_SCK returns to low, chip will reset and enter normal operation mode.
198-
// this can't be implemented with SPI because we would have to write a constant stream
199-
// of binary '1' which would block the process
200-
unimplemented!("power_down is not possible with this driver implementation");
252+
// speed is the raw SPI speed -> half bits per second.
253+
254+
// max SPI clock frequency should be 5 MHz to satisfy the 0.2 us limit for the pulse length
255+
// we have to output more than 300 bytes to keep the line for at least 60 us high.
256+
257+
let mut buffer: [u8; 301] = RESET_SIGNAL;
258+
259+
self.spi.transfer_in_place(&mut buffer).await?;
260+
self.mode = Mode::ChAGain128; // this is the default mode after reset
261+
262+
Ok(())
263+
}
264+
265+
/// Set the mode to the value specified.
266+
/// see the Mode struct for possible values
267+
/// # Usage
268+
///
269+
/// ```rust
270+
/// my_hx711.set_mode_async(Mode::ChAGain128).await?;
271+
/// value1_chanel_a = my_hx711.read_async().await?
272+
/// value2_chanel_a = my_hx711.read_async().await?
273+
/// my_hx711.set_mode_async(Mode::ChBGain32).await?;
274+
/// value_chanel_b = my_hx711.read_async().await?
275+
///```
276+
/// # Errors
277+
/// Returns `SPI` errors
278+
#[inline]
279+
pub async fn set_mode_async(&mut self, m: Mode) -> Result<Mode, SPI::Error> {
280+
self.mode = m;
281+
self.read_async().await?; // read writes Mode for the next read()
282+
Ok(m)
201283
}
202284
}
203285

0 commit comments

Comments
 (0)