diff options
| author | Tomasz Kramkowski <tomasz@kramkow.ski> | 2025-10-16 19:33:17 +0100 | 
|---|---|---|
| committer | Tomasz Kramkowski <tomasz@kramkow.ski> | 2025-10-16 19:33:17 +0100 | 
| commit | cdf2a5026e45ac2b65001ed41cc67d86590a681a (patch) | |
| tree | 56fda9ee1cc0159e725952802547e5e6d327428e /src/dual_hx711.rs | |
| download | scale-drv-example-master.tar.gz scale-drv-example-master.tar.xz scale-drv-example-master.zip | |
Diffstat (limited to 'src/dual_hx711.rs')
| -rw-r--r-- | src/dual_hx711.rs | 75 | 
1 files changed, 75 insertions, 0 deletions
| diff --git a/src/dual_hx711.rs b/src/dual_hx711.rs new file mode 100644 index 0000000..13ec247 --- /dev/null +++ b/src/dual_hx711.rs @@ -0,0 +1,75 @@ +// SPDX-FileCopyrightText: 2025 Tomasz Kramkowski <tomasz@kramkow.ski> +// SPDX-License-Identifier: GPL-3.0-or-later + +//! Driver for reading from two HX711 ADCs with a shared clock. +//! +//! (Datasheet)[https://cdn.sparkfun.com/assets/b/f/5/a/e/hx711F_EN.pdf] +//! +//! Existing implementations could not handle a combined setup. + +use embassy_stm32::timer::GeneralInstance4Channel; +use embedded_hal::digital::InputPin; +use embedded_hal_async::digital::Wait; + +use crate::pulse::Pulse; + +/// Dual HX711 driver +pub struct DualHx711<'a, T: GeneralInstance4Channel, A: InputPin + Wait, B: InputPin + Wait> { +    clock: Pulse<'a, T>, +    a: A, +    b: B, +} + +/// Sign extend a two's complement number stored in the low 24 bits of a u32 to +/// an i32 +fn convert_c24_to_i32(n: u32) -> i32 { +    ((n << 8) as i32) >> 8 +} + +impl< +        'a, +        T: GeneralInstance4Channel, +        E, +        A: InputPin<Error = E> + Wait, +        B: InputPin<Error = E> + Wait, +    > DualHx711<'a, T, A, B> +{ +    /// Create a new driver from clock and data pins +    /// +    /// Clock pin must be a `Pulse` configured to produce an appropriately timed +    /// clock signal. Refer to the HX711 datasheet for more details. +    /// +    /// Currently only implements CH.A, Gain:128 mode +    pub fn new(clock: Pulse<'a, T>, a: A, b: B) -> Self { +        Self { clock, a, b } +    } + +    /// Read the next available conversion from both HX711s +    pub async fn read(&mut self) -> Result<(i32, i32), E> { +        self.a.wait_for_low().await?; +        self.b.wait_for_low().await?; +        let mut val = (0, 0); +        for _ in 0..24 { +            self.clock.trigger_and_wait().await; +            val.0 <<= 1; +            val.0 |= self.a.is_high()? as u32; +            val.1 <<= 1; +            val.1 |= self.b.is_high()? as u32; +        } +        // Only implement CH.A, Gain:128 mode +        self.clock.trigger_and_wait().await; +        Ok((convert_c24_to_i32(val.0), convert_c24_to_i32(val.1))) +    } +} + +#[cfg(test)] +mod tests { +    use super::*; + +    fn convert_twos_complement() { +        assert_eq!(convert_c24_to_i32(0), 0); +        assert_eq!(convert_c24_to_i32(0x7fffff), 8388607); +        assert_eq!(convert_c24_to_i32(0x800000), -8388608); +        assert_eq!(convert_c24_to_i32(0xffffff), -1); +    } +} | 
