Merge pull request #143 from hybridgroup/raspi

Add raspi support
This commit is contained in:
Ron Evans 2014-11-04 17:25:27 -08:00
commit 330e5a8bba
7 changed files with 477 additions and 0 deletions

32
examples/raspi_blink.go Normal file
View File

@ -0,0 +1,32 @@
package main
import (
"time"
"github.com/hybridgroup/gobot"
"github.com/hybridgroup/gobot/platforms/gpio"
"github.com/hybridgroup/gobot/platforms/raspi"
)
func main() {
gbot := gobot.NewGobot()
r := raspi.NewRaspiAdaptor("raspi")
led := gpio.NewLedDriver(r, "led", "7")
work := func() {
gobot.Every(1*time.Second, func() {
led.Toggle()
})
}
robot := gobot.NewRobot("blinkBot",
[]gobot.Connection{r},
[]gobot.Device{led},
work,
)
gbot.AddRobot(robot)
gbot.Start()
}

36
examples/raspi_blinkm.go Normal file
View File

@ -0,0 +1,36 @@
package main
import (
"fmt"
"time"
"github.com/hybridgroup/gobot"
"github.com/hybridgroup/gobot/platforms/i2c"
"github.com/hybridgroup/gobot/platforms/raspi"
)
func main() {
gbot := gobot.NewGobot()
r := raspi.NewRaspiAdaptor("raspi")
blinkm := i2c.NewBlinkMDriver(r, "blinkm")
work := func() {
gobot.Every(3*time.Second, func() {
r := byte(gobot.Rand(255))
g := byte(gobot.Rand(255))
b := byte(gobot.Rand(255))
blinkm.Rgb(r, g, b)
fmt.Println("color", blinkm.Color())
})
}
robot := gobot.NewRobot("blinkmBot",
[]gobot.Connection{r},
[]gobot.Device{blinkm},
work,
)
gbot.AddRobot(robot)
gbot.Start()
}

37
examples/raspi_button.go Normal file
View File

@ -0,0 +1,37 @@
package main
import (
"fmt"
"github.com/hybridgroup/gobot"
"github.com/hybridgroup/gobot/platforms/gpio"
"github.com/hybridgroup/gobot/platforms/raspi"
)
func main() {
gbot := gobot.NewGobot()
r := raspi.NewRaspiAdaptor("raspi")
button := gpio.NewButtonDriver(r, "button", "11")
led := gpio.NewLedDriver(r, "led", "7")
work := func() {
gobot.On(button.Event("push"), func(data interface{}) {
fmt.Println("button pressed")
led.On()
})
gobot.On(button.Event("release"), func(data interface{}) {
fmt.Println("button released")
led.Off()
})
}
robot := gobot.NewRobot("buttonBot",
[]gobot.Connection{r},
[]gobot.Device{button, led},
work,
)
gbot.AddRobot(robot)
gbot.Start()
}

72
platforms/raspi/README.md Normal file
View File

@ -0,0 +1,72 @@
# Raspi
This package contains the Gobot adaptor for the [Raspberry Pi](http://www.raspberrypi.org/).
## Getting Started
First you must install the appropriate Go packages
```
go get -d -u github.com/hybridgroup/gobot/... && go install github.com/hybridgroup/gobot/platforms/raspi
```
#### Cross compiling for the Raspberry Pi
You must first configure your Go environment for linux cross compiling
```bash
$ cd $GOROOT/src
$ GOOS=linux GOARCH=arm ./make.bash --no-clean
```
Then compile your Gobot program with
```bash
$ GOARM=6 GOARCH=arm GOOS=linux examples/raspi_blink.go
```
Then you can simply upload your program over the network from your host computer to the Raspi
``` bash
$ scp raspi_blink pi@192.168.1.xxx:/home/pi/
```
and execute it on your Raspberry Pi with
```bash
$ ./raspi_blink
```
## Example
```go
package main
import (
"time"
"github.com/hybridgroup/gobot"
"github.com/hybridgroup/gobot/platforms/gpio"
"github.com/hybridgroup/gobot/platforms/raspi"
)
func main() {
gbot := gobot.NewGobot()
r := raspi.NewRaspiAdaptor("raspi")
led := gpio.NewLedDriver(r, "led", "7")
work := func() {
gobot.Every(1*time.Second, func() {
led.Toggle()
})
}
robot := gobot.NewRobot("blinkBot",
[]gobot.Connection{r},
[]gobot.Device{led},
work,
)
gbot.AddRobot(robot)
gbot.Start()
}
```

7
platforms/raspi/doc.go Normal file
View File

@ -0,0 +1,7 @@
/*
Package raspi contains the Gobot adaptor for the Raspberry Pi.
For further information refer to raspi README:
https://github.com/hybridgroup/gobot/blob/master/platforms/raspi/README.md
*/
package raspi

View File

@ -0,0 +1,226 @@
package raspi
import (
"fmt"
"io"
"io/ioutil"
"os/exec"
"strconv"
"strings"
"github.com/hybridgroup/gobot"
"github.com/hybridgroup/gobot/sysfs"
)
var i2cLocationFor = func(rev string) string {
if rev == "1" {
return "/dev/i2c-0"
}
return "/dev/i2c-1"
}
var boardRevision = func() string {
cat, _ := exec.Command("cat", "/proc/cpuinfo").Output()
grep := exec.Command("grep", "Revision")
in, _ := grep.StdinPipe()
out, _ := grep.StdoutPipe()
grep.Start()
in.Write([]byte(string(cat)))
in.Close()
buf, _ := ioutil.ReadAll(out)
grep.Wait()
s := strings.Split(string(buf), " ")
a := fmt.Sprintf("0x%v", strings.TrimSuffix(s[len(s)-1], "\n"))
d, _ := strconv.ParseInt(a, 0, 64)
rev := ""
if d <= 3 {
rev = "1"
} else if d <= 15 {
rev = "2"
} else {
rev = "3"
}
return rev
}
type RaspiAdaptor struct {
gobot.Adaptor
revision string
digitalPins map[int]sysfs.DigitalPin
i2cDevice io.ReadWriteCloser
}
var pins = map[string]map[string]int{
"3": map[string]int{
"1": 0,
"2": 2,
"3": 2,
},
"5": map[string]int{
"1": 1,
"2": 3,
"3": 3,
},
"7": map[string]int{
"*": 4,
},
"8": map[string]int{
"*": 14,
},
"10": map[string]int{
"*": 15,
},
"11": map[string]int{
"*": 17,
},
"12": map[string]int{
"*": 18,
},
"13": map[string]int{
"1": 21,
"2": 27,
"3": 27,
},
"15": map[string]int{
"*": 22,
},
"16": map[string]int{
"*": 23,
},
"18": map[string]int{
"*": 24,
},
"19": map[string]int{
"*": 10,
},
"21": map[string]int{
"*": 9,
},
"22": map[string]int{
"*": 25,
},
"23": map[string]int{
"*": 11,
},
"24": map[string]int{
"*": 8,
},
"26": map[string]int{
"*": 7,
},
"29": map[string]int{
"3": 5,
},
"31": map[string]int{
"3": 6,
},
"32": map[string]int{
"3": 12,
},
"33": map[string]int{
"3": 13,
},
"35": map[string]int{
"3": 19,
},
"36": map[string]int{
"3": 16,
},
"37": map[string]int{
"3": 26,
},
"38": map[string]int{
"3": 20,
},
"40": map[string]int{
"3": 21,
},
}
// NewRaspiAdaptor creates a RaspiAdaptor with specified name and
func NewRaspiAdaptor(name string) *RaspiAdaptor {
return &RaspiAdaptor{
Adaptor: *gobot.NewAdaptor(
name,
"RaspiAdaptor",
),
revision: boardRevision(),
digitalPins: make(map[int]sysfs.DigitalPin),
}
}
// Connect starts conection with board and creates
// digitalPins and pwmPins adaptor maps
func (r *RaspiAdaptor) Connect() bool {
return true
}
// Finalize closes connection to board and pins
func (r *RaspiAdaptor) Finalize() bool {
for _, pin := range r.digitalPins {
if pin != nil {
pin.Unexport()
}
}
if r.i2cDevice != nil {
r.i2cDevice.Close()
}
return true
}
// digitalPin returns matched digitalPin for specified values
func (r *RaspiAdaptor) digitalPin(pin string, dir string) sysfs.DigitalPin {
var i int
if val, ok := pins[pin][r.revision]; ok {
i = val
} else if val, ok := pins[pin]["*"]; ok {
i = val
} else {
panic("not valid pin")
}
if r.digitalPins[i] == nil {
r.digitalPins[i] = sysfs.NewDigitalPin(i)
r.digitalPins[i].Export()
}
r.digitalPins[i].Direction(dir)
return r.digitalPins[i]
}
// DigitalRead reads digital value from pin
func (r *RaspiAdaptor) DigitalRead(pin string) (i int) {
i, _ = r.digitalPin(pin, sysfs.IN).Read()
return
}
// DigitalWrite writes digital value to specified pin
func (r *RaspiAdaptor) DigitalWrite(pin string, val byte) {
r.digitalPin(pin, sysfs.OUT).Write(int(val))
}
// PwmWrite Not Implemented
func (r *RaspiAdaptor) PwmWrite(pin string, val byte) {
fmt.Println("PwmWrite Is Not Implemented")
}
// I2cStart starts a i2c device in specified address
func (r *RaspiAdaptor) I2cStart(address byte) {
r.i2cDevice, _ = sysfs.NewI2cDevice(i2cLocationFor(r.revision), address)
}
// I2CWrite writes data to i2c device
func (r *RaspiAdaptor) I2cWrite(data []byte) {
r.i2cDevice.Write(data)
}
// I2cRead returns value from i2c device using specified size
func (r *RaspiAdaptor) I2cRead(size uint) []byte {
buf := make([]byte, size)
r.i2cDevice.Read(buf)
return buf
}

View File

@ -0,0 +1,67 @@
package raspi
import (
"io"
"os"
"testing"
"github.com/hybridgroup/gobot"
"github.com/hybridgroup/gobot/sysfs"
)
func initTestRaspiAdaptor() *RaspiAdaptor {
i2cLocationFor = func(rev string) string {
return os.DevNull
}
boardRevision = func() string {
return "3"
}
sysfs.WriteFile = func(path string, data []byte) (i int, err error) {
return
}
a := NewRaspiAdaptor("myAdaptor")
a.Connect()
return a
}
func TestRaspiAdaptorFinalize(t *testing.T) {
a := initTestRaspiAdaptor()
a.DigitalWrite("3", 1)
a.i2cDevice = new(gobot.NullReadWriteCloser)
gobot.Assert(t, a.Finalize(), true)
}
func TestRaspiAdaptorDigitalIO(t *testing.T) {
a := initTestRaspiAdaptor()
lastWritePath := ""
lastReadPath := ""
lastWriteData := []byte{}
sysfs.WriteFile = func(path string, data []byte) (i int, err error) {
lastWritePath = path
lastWriteData = data
return
}
sysfs.ReadFile = func(path string) (b []byte, err error) {
lastReadPath = path
return []byte("1"), nil
}
a.DigitalWrite("7", 1)
gobot.Assert(t, lastWritePath, "/sys/class/gpio/gpio4/value")
gobot.Assert(t, lastWriteData, []byte{49})
i := a.DigitalRead("13")
gobot.Assert(t, lastReadPath, "/sys/class/gpio/gpio27/value")
gobot.Assert(t, i, 1)
}
func TestRaspiAdaptorI2c(t *testing.T) {
a := initTestRaspiAdaptor()
a.I2cStart(0xff)
var _ io.ReadWriteCloser = a.i2cDevice
a.i2cDevice = new(gobot.NullReadWriteCloser)
a.I2cWrite([]byte{0x00, 0x01})
gobot.Assert(t, a.I2cRead(2), make([]byte, 2))
}