func newButtons(redN, greenN int) (*buttons, error) { var red, green gpio.Pin var err error if red, err = gpio.OpenPin(redN, gpio.ModeInput); err != nil { return nil, err } if green, err = gpio.OpenPin(greenN, gpio.ModeInput); err != nil { _ = red.Close() return nil, err } btns := &buttons{ Presses: make(chan Button, 10), red: util.Debounced(red, 20*time.Millisecond), green: util.Debounced(green, 20*time.Millisecond), } btns.red.BeginWatch(gpio.EdgeFalling, func() { btns.Presses <- RedButton }) btns.green.BeginWatch(gpio.EdgeFalling, func() { btns.Presses <- GreenButton }) return btns, nil }
func main() { flag.Parse() log.Printf("Using pins %d as input and %d as output\n", *inN, *outN) in, err := gpio.OpenPin(*inN, gpio.ModeInput) if err != nil { log.Panicf("Unable to open pin %d: %v", *inN, err) } out, err := gpio.OpenPin(*outN, gpio.ModeOutput) if err != nil { log.Panicf("Unable to open pin %d: %v", *outN, err) } log.Print("Pins opened...\n") signals := make(chan os.Signal, 10) signal.Notify(signals, os.Interrupt, os.Kill) triggers := make(chan gpio.Edge, 120) in.BeginWatch(gpio.EdgeRising, func() { go func() { triggers <- gpio.EdgeFalling }() }) var sum, max time.Duration var count uint64 for { count++ log.Print("Start!\n") start := time.Now() out.Set() timeout := time.After(500 * time.Millisecond) select { case <-signals: average := time.Duration(uint64(sum) / count) log.Printf("Average delay: %v\n", average) log.Printf("Max delay: %v\n", max) return case <-triggers: took := time.Now().Sub(start) out.Clear() cleared := time.Now().Sub(start) log.Printf("Signal took %v, cleared in %v\n", took, cleared) sum += cleared if cleared > max { max = cleared } case t := <-timeout: took := t.Sub(start) log.Printf("Timed out after %v", took) } out.Clear() time.Sleep(500 * time.Millisecond) } }
func main() { flag.Parse() fmt.Printf("Opening pin %d and ticking with %.3f Hz", *pin, *T) pin, err := gpio.OpenPin(*pin, gpio.ModeOutput) if err != nil { fmt.Printf("Error opening pin %d: %s\n", pin, err) return } // turn the led off on exit c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt, os.Kill) go func() { for _ = range c { fmt.Printf("\nClearing and unexporting the pin.\n") pin.Clear() pin.Close() os.Exit(0) } }() // Calculate half period periodMs := (1 / *T) * 1000 tt := time.Duration(periodMs/2) * time.Millisecond fmt.Println("") for { fmt.Print("\rsetting...") pin.Set() time.Sleep(tt) pin.Clear() fmt.Print("\rclearing...") time.Sleep(tt) } }
// test opening pins from a non priviledged user fails func TestOpenPinUnpriv(t *testing.T) { checkNotRoot(t) pin, err := gpio.OpenPin(rpi.GPIO_P1_22, gpio.ModeInput) if err == nil { pin.Close() t.Fatalf("OpenPin is expected to fail for non priv user") } }
func TestOpenPin(t *testing.T) { checkRoot(t) pin, err := gpio.OpenPin(rpi.GPIO_P1_22, gpio.ModeInput) if err != nil { t.Fatal(err) } err = pin.Close() if err != nil { t.Fatal(err) } }
func main() { flag.Parse() var i, n int var err error var v string pins := make([]int, 100) // should be good for anyone for _, v = range strings.Split(*pinNumbers, ",") { i, err = strconv.Atoi(v) if err == nil { pins[n] = i n++ } } if n == 0 { log.Fatalf("No pins specified, got %s", *pinNumbers) } else { log.Printf("Watching %d pins: %#v", n, pins[:n]) } toggle := make(chan PinEvent, 10) for _, i = range pins[:n] { var pin gpio.Pin var gpioNum = i pin, err = gpio.OpenPin(gpioNum, gpio.ModeInput) if err != nil { log.Fatal(err) } defer pin.Close() pin.BeginWatch(gpio.EdgeBoth, func() { toggle <- PinEvent{gpioNum, pin.Get()} }) } // clean up on exit die := make(chan os.Signal) signal.Notify(die, os.Interrupt) for { select { case <-die: log.Println("Signal received, returning") return case e := <-toggle: log.Printf("Pin %d is now %t", e.Number, e.Value) } } }
func TestSetDirection(t *testing.T) { checkRoot(t) pin, err := gpio.OpenPin(rpi.GPIO_P1_22, gpio.ModeInput) if err != nil { t.Fatal(err) } defer pin.Close() if dir, err := pin.Mode(), pin.Err(); dir != gpio.ModeInput || err != nil { t.Fatalf("pin.Mode(): expected %v %v , got %v %v", gpio.ModeInput, nil, dir, err) } pin.SetMode(gpio.ModeOutput) if pin.Err() != nil { t.Fatal(err) } if dir, err := pin.Mode(), pin.Err(); dir != gpio.ModeOutput || err != nil { t.Fatalf("pin.Mode(): expected %v %v , got %v %v", gpio.ModeOutput, nil, dir, err) } }
func main() { flag.Parse() fmt.Printf("Opening pin %d and ticking with %.3f Hz", *pin, *T) pin, err := gpio.OpenPin(*pin, gpio.ModeOutput) if err != nil { fmt.Printf("Error opening pin %d: %s\n", pin, err) return } // turn the led off on exit signals := make(chan os.Signal, 1) dying := make(chan int) signal.Notify(signals, os.Interrupt, os.Kill) go func() { closed := false for s := range signals { fmt.Printf("\nGot %v, exiting...\n", s) if !closed { close(dying) } break } }() // Calculate half period periodMs := (1 / *T) * 1000 tt := time.Duration(periodMs/2) * time.Millisecond // run without blocking go loop(dying, tt, pin) <-dying // equivalently, just call loop in this goroutine //loop(dying, tt, pin) fmt.Print("Clearing and unexporting the pin.\n") pin.Clear() pin.Close() }
func NewFromConfig(cfg config.DoorConfig) (d *Door, err error) { // can you do it right in less lines? // begin pin-opening boilerplate openPins := make([]gpio.Pin, 6) var i int var savedError error mustPin := func(n int, mode gpio.Mode) gpio.Pin { if pin, err := gpio.OpenPin(n, mode); err != nil { savedError = err panic(err) } else { openPins[i] = pin i++ return pin } } defer func() { if e := recover(); e != nil { err = savedError log.Printf("recovered %v", e) for _, p := range openPins { if p == nil { return } p.Close() } } }() // end pin-opening boilerplate d = &Door{ sensors: &sensors{ locked: mustPin(cfg.Pins.SenseLocked, gpio.ModeInput), unlocked: mustPin(cfg.Pins.SenseUnlocked, gpio.ModeInput), door: mustPin(cfg.Pins.SenseDoor, gpio.ModeInput), }, controls: &controls{ enable: mustPin(cfg.Pins.LatchEnable, gpio.ModeLow), lock: mustPin(cfg.Pins.LatchLock, gpio.ModeLow), unlock: mustPin(cfg.Pins.LatchUnlock, gpio.ModeLow), }, subsMutex: &sync.Mutex{}, } d.dying = make(chan struct{}) d.state.State = &State{} d.state.Mutex = &sync.Mutex{} d.state.State.Door = NotChecked d.state.State.Latch = Unknown var found State d.sensors.fetchDoorState(&found) d.sensors.fetchLatchState(&found) _, old := d.state.lockedSet(found) d.notify(old, found) go d.monitorPins() return d, nil }
// OpenPin returns a gpio.Pin implementation specalised for the RPi. func OpenPin(number int, mode gpio.Mode) (gpio.Pin, error) { initOnce.Do(initRPi) p, err := gpio.OpenPin(number, mode) return &pin{Pin: p, pin: uint8(number)}, err }