periph / conn

Go·Hardware·Lean - Interfaces
https://periph.io
Apache License 2.0
67 stars 12 forks source link

WaitForEdge generated unexpected results #37

Open zombie-k opened 10 months ago

zombie-k commented 10 months ago

Describe the bug WaitForEdge generated unexpected results,Problems arise when using edge detection for ultrasonic ranging,When the sensor is stationary, the calculated values ​​deviate significantly

To Reproduce Steps to reproduce the behavior:

  1. Run program
    
    package main

import ( "fmt" "log" "periph.io/x/conn/v3/gpio" "periph.io/x/conn/v3/gpio/gpioreg" "periph.io/x/host/v3" "time" )

var ( trig gpio.PinIO echo gpio.PinIO )

func Test() { if _, err := host.Init(); err != nil { log.Fatal(err) }

trig = gpioreg.ByName("23")
echo = gpioreg.ByName("24")
trig.Out(gpio.Low)
echo.In(gpio.PullDown, gpio.BothEdges)

for {
    test(trig, echo)
    time.Sleep(time.Millisecond* 10)
}

}

func test(trig gpio.PinIO, echo gpio.PinIO) { trig.Out(gpio.Low) time.Sleep(time.Microsecond 2) trig.Out(gpio.High) time.Sleep(time.Microsecond 10) trig.Out(gpio.Low)

// Low -> High
echo.WaitForEdge(time.Second)

ts := time.Now()
// High -> Low
echo.WaitForEdge(time.Second)
cost := time.Since(ts)
dis := float32(cost.Nanoseconds()) * 0.000000343 / 2.0 * 100
fmt.Printf("distance: %vcm\n", dis)

}


2. Run it.
3. See error

**Expected behavior**
The expected result is 180+-cm, but the actual value will be 180+-cm at one time and 8+-cm at another time, and the two will alternate repeatedly. (180+- is the current true value)

**Platform (please complete the following information):**
 - OS: Raspbian bookworm
 - Board Raspberry Pi 4

**Additional context**
I have used polling to verify and can get the expected results
maruel commented 10 months ago

The problem with WaitForEdge() is that the implementation in https://github.com/periph/host/blob/main/sysfs/gpio.go is dependent on sysfs which is sensitive to timing issues from linux.

zombie-k commented 10 months ago

The problem with WaitForEdge() is that the implementation in https://github.com/periph/host/blob/main/sysfs/gpio.go is dependent on sysfs which is sensitive to timing issues from linux.

The problem with WaitForEdge() is that the implementation in https://github.com/periph/host/blob/main/sysfs/gpio.go is dependent on sysfs which is sensitive to timing issues from linux.

So for my problem, I can only use polling instead of WaitForEdge, right? Or is there any way to avoid this timing-sensitive problem?

gsexton commented 1 week ago

@zombie-k A new implementation of GPIO has been created that uses ioctl() interface, and not sysfs. You might try re-testing your code with the HEAD of periph.io/x/host.

You can clone the repo, and in your go.mod file put:

replace periph.io/x/host/v3 v3.8.2 => path to cloned repo

and rebuild it. Note that you'll need to remove any references to sysfs from your code.

maruel commented 1 week ago

Simpler, you can do the following:

go get periph.io/x/host/v3@7540d26b4dc114207d0e5f7603b0f176bf5805dd

No need for a replace statement or checking out locally.