google / periph

Older version of periph, see new version at https://github.com/periph
https://periph.io
Apache License 2.0
1.75k stars 167 forks source link

HX711: unstable readings and reading before data is ready #439

Closed chewr closed 3 years ago

chewr commented 4 years ago

Describe the bug The included HX711 driver does not respect the timing specifications described in the datasheet, and generates mostly false readings.

To Reproduce Steps to reproduce the behavior:

  1. Run program
    
    package main

import ( "fmt" "os" "periph.io/x/periph/experimental/devices/hx711" "periph.io/x/periph/host" "periph.io/x/periph/host/rpi" "time" )

func main() { host.Init() if err := mainE(); err != nil { fmt.Fprintln(os.Stderr, "error:", err) os.Exit(1) } }

func mainE() error { // HX711 board configured with CLK @ P1_31 and DOUT @ P1_29 hx, err := hx711.New(rpi.P1_31, rpi.P1_29) if err != nil { return err }

time.AfterFunc(10*time.Second, func() { hx.Halt() })

sampleCh := hx.ReadContinuous()
for s := range sampleCh {
    // observe that many samples are garbage
    fmt.Printf("%8d\n", s.Raw)
}
return nil

}


2. Run it.
3. See that many samples are garbage. For me, half of all samples is -1; and many samples are suspiciously 2^n - 1.

**Expected behavior**
The driver should ideally read data when data is ready. In this case we see that samples are occasionally read out as garbage because data isn't ready or DOUT isn't stable.

**Platform (please complete the following information):**
 - OS: Raspbian buster
 - Board: Raspberry Pi 2 Model B v1.1
 - Peripheral: Cheapo oem HX711 (https://www.amazon.com/gp/product/B00XRRNCOO/ref=ppx_yo_dt_b_asin_title_o04_s00?ie=UTF8&psc=1)

**Additional context**
The AviaSC datasheet (https://components101.com/sites/default/files/component_datasheet/HX711%20Datasheet.pdf) provides a timing specification for the HX711. Note that it specifies a minimum of .1us after a falling edge on DOUT before data is ready to be read, and that it additionally specifies that DOUT is not stable until .1us after the rising edge on CLK. Additionally, it expects pulse width on CLK to be at least 1us.

I checked out the driver and first tried to fix this by adding sleeps, but interrupts are too coarse-grained to make .1-100us sleeps meaningful. I replaced sleeps with fine-grained busy waits, and eliminated the readings of -1.

I continued to get odd 2^n - 1 readings, so I replaced the `WaitForEdge` call in `ReadTimeout` with a busy wait (`for !d.IsReady() {}`), and this seems to have eliminated all or almost all of the garbage readings I was getting. I think that this could be evidence of false GPIO edge detection as described in this thread: https://www.raspberrypi.org/forums/viewtopic.php?t=134394.

I have only tested this with one board. I intend to see if I can get better readings the other HX711 boards I have, and potentially with one of those fancy $15 HX711s they sell at Sparkfun if issues persist.
maruel commented 4 years ago

At worst maybe use https://periph.io/x/periph/host/cpu#Nanospin ?

maruel commented 3 years ago

If you still face issues, Please file a bug at https://github.com/periph/devices. Will close for now as there's no AI.