stianeikeland / go-rpio

:electric_plug: Raspberry Pi GPIO library for go-lang
MIT License
2.2k stars 221 forks source link

add GPIO frequency detection #33

Closed maurorappa closed 6 years ago

maurorappa commented 6 years ago

Hi,

I think it would be very useful if you can add a function which measure the frequency a GPIO pin change status. This will allow to interface with a multitude of sensors. Some examples of implementation in C are here: http://abyz.me.uk/rpi/pigpio/examples.html#C_code Arduino core library has a conceptually similar functio called pulseIn: https://www.arduino.cc/reference/en/language/functions/advanced-io/pulsein/

I tried to use a loop with pin.EdgeDetected() and a microsecond sleep but my RPI freezes all the time.

Thanks

drahoslove commented 6 years ago

Hi, think this seems to be quiet specific task to me and I think it does not make much sense, to be part of go-gpio, which is IMHO supposed to have only general functionality (similar to wiringPi and others), but I might be wrong.

Regarding the freezing issue, could you be more specific? Provide source code or something and I might be able to help.

maurorappa commented 6 years ago

I get your point, I'm trying to use this simple code to get frequency of a 440Hz square wave (50% duty cycle) I'm a generating with Arduino. This code freeze my RPi every time I run it (go version go1.11.1 linux/arm on Debian 9.4):

package main

import (
        "fmt"
        "github.com/stianeikeland/go-rpio"
        "os"
        "time"
)

var (
        S0 = rpio.Pin(7)
)

func main() {
    err := rpio.Open()
    if err != nil {
        fmt.Print(err)
        os.Exit(1)
    }
    S0.Input()
    S0.PullUp()
    S0.Detect(rpio.FallEdge)
    F :=0
    c := 0
        for c < 100000 {
        if S0.EdgeDetected() {
            F++
        }
                time.Sleep(time.Microsecond*10)
            c++
    }
    fmt.Printf("F: %dHz",F)
}

The arduino code is:

void setup() {
  }

void loop() {
  tone(10, 440);
  }

If I use a simple C utility it works perfectly:

/home/pi/freq_count_1 7
Monitoring gpios 7
Sample rate 5 micros, refresh rate 10 deciseconds
g=7 1 (403/411319032)
g=7 410 (410/999442)
g=7 406 (407/1001713)
...
drahoslove commented 6 years ago

I tested your code (without connecting to arduino, since I don't have any), and it does not freeze.

But there are several flaws in your code.

Every loop iteration will take 10us + some noticable overhead.

Consequently, your program runs for 5-20 or even more seconds. This might give an impression that it is frozen.

Is this your case, or does your Pi really completely freeze?

Anyway, try to replace your loop with this code:

timeout := time.After(time.Second)
loop: for {
    select {
        case <-timeout:
            break loop
        default:
            if S0.EdgeDetected() {
                F++
            }
        }
}

This should give you much better results.

maurorappa commented 6 years ago

Ok, I'll try tonight. I am aware the code was a bit rudimental, I'm just trying to understand how to make it work!

maurorappa commented 6 years ago

The test program was still crashing, so I decided to use GDB:

go build -gcflags "-N -l" -o freq freq2.go

gdb freq

(gdb) break 20 Breakpoint 1 at 0x9cf70: file /root/go/freq2.go, line 20. (gdb) break 21 Breakpoint 2 at 0x9cf80: file /root/go/freq2.go, line 21. (gdb) break 22 Breakpoint 3 at 0x9cf90: file /root/go/freq2.go, line 22. (gdb) break 23 Breakpoint 4 at 0x9cfa8: file /root/go/freq2.go, line 23. (gdb) run Starting program: /root/Go/freq [New LWP 544] [New LWP 545]

Thread 1 "freq" hit Breakpoint 1, main.main () at /root/go/freq2.go:20 20 /root/go/freq2.go: No such file or directory. (gdb) continue Continuing.

Thread 1 "freq" hit Breakpoint 2, main.main () at /root/go/freq2.go:21 21 in /root/go/freq2.go (gdb) continue Continuing.

Thread 1 "freq" hit Breakpoint 3, main.main () at /root/go/freq2.go:22 22 in /root/go/freq2.go (gdb) continue Continuing. CRASH!

Line 22 is:

cat -n freq2.go |grep 22

22      S0.Detect(rpio.FallEdge)

if I run the program without this line, it executes but it doesn't detect any frequency:

go run freq2.go

Starting frequency detection F: 0

so the question is: Am I using a 'wrong' pin? I changed pin, used the C program and worked, tried the Go program and crashed again.

I'm running out of ideas....any hint?

drahoslove commented 6 years ago

Some ideas:

Are you using raspbian or some other distro? My raspbian works fine. Raspbian GNU/Linux 8.0 (jessie) Linux zero 4.14.74+ #1149 Mon Oct 8 17:26:51 BST 2018 armv6l GNU/Linux

Try to disable SPI interface in sudo raspi-config.

Is there any reason your go source files are in /root/go instead of eg. /home/pi/go ?

Are you running your program as root? (You should not have to, but who knows)

drahoslove commented 6 years ago

The solution mentioned here https://github.com/stianeikeland/go-rpio/issues/35#issuecomment-443115624 should work for you as well.