periph/conn

WaitForEdge generated unexpected results

Opened this issue · 4 comments

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)
}
  1. Run it.
  2. 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

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.

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?

@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.

Simpler, you can do the following:

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

No need for a replace statement or checking out locally.