Example #1
0
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
}
Example #2
0
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)
	}

}
Example #3
0
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)
	}
}
Example #4
0
// 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")
	}
}
Example #5
0
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)
	}
}
Example #6
0
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)
		}
	}
}
Example #7
0
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)
	}
}
Example #8
0
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()
}
Example #9
0
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
}
Example #10
0
// 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
}