From cdf2a5026e45ac2b65001ed41cc67d86590a681a Mon Sep 17 00:00:00 2001 From: Tomasz Kramkowski Date: Thu, 16 Oct 2025 19:33:17 +0100 Subject: Driver example --- src/dual_hx711.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/dual_hx711.rs (limited to 'src/dual_hx711.rs') 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 +// 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 + Wait, + B: InputPin + 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); + } +} -- cgit v1.2.3-70-g09d2