1
0
mirror of https://github.com/hybridgroup/gobot.git synced 2025-05-14 19:29:32 +08:00

Merge pull request #342 from hybridgroup/feature/beaglebone-4

Support for newer Beaglebone 4.x kernels
This commit is contained in:
Ron Evans 2016-12-03 14:33:40 +01:00 committed by GitHub
commit 8bb0fbfbad
5 changed files with 221 additions and 157 deletions

View File

@ -10,7 +10,7 @@ import (
func main() { func main() {
beagleboneAdaptor := beaglebone.NewAdaptor() beagleboneAdaptor := beaglebone.NewAdaptor()
led := gpio.NewLedDriver(beagleboneAdaptor, "usr0") led := gpio.NewLedDriver(beagleboneAdaptor, "usr1")
work := func() { work := func() {
gobot.Every(1*time.Second, func() { gobot.Every(1*time.Second, func() {

View File

@ -5,31 +5,11 @@ The BeagleBone is an ARM based single board computer, with many different GPIO i
For more info about the BeagleBone platform click [here](http://beagleboard.org/Products/BeagleBone+Black). For more info about the BeagleBone platform click [here](http://beagleboard.org/Products/BeagleBone+Black).
## How to Install ## How to Install
``` ```
go get -d -u github.com/hybridgroup/gobot/... && go install github.com/hybridgroup/gobot/platforms/beaglebone go get -d -u github.com/hybridgroup/gobot/... && go install github.com/hybridgroup/gobot/platforms/beaglebone
``` ```
## Cross compiling for the Beaglebone Black
You must first configure your Go environment for arm linux cross compiling
```bash
$ cd $GOROOT/src
$ GOOS=linux GOARCH=arm ./make.bash --no-clean
```
Then compile your Gobot program with
```bash
$ GOARM=7 GOARCH=arm GOOS=linux go build examples/beaglebone_blink.go
```
If you are running the official Angstrom or Debian linux through the usb->ethernet connection, you can simply upload your program and execute it with
```bash
$ scp beaglebone_blink root@192.168.7.2:/home/root/
$ ssh -t root@192.168.7.2 "./beaglebone_blink"
```
## How to Use ## How to Use
```go ```go
@ -62,3 +42,40 @@ func main() {
robot.Start() robot.Start()
} }
``` ```
## How to Connect
### Compiling
Simply compile your Gobot program like this:
```bash
$ GOARCH=arm GOOS=linux go build examples/beaglebone_blink.go
```
If you are running the official Debian Linux through the usb->ethernet connection, or are connected to the board using WiFi, you can simply upload your program and execute it with the `scp` command like this:
```bash
$ scp beaglebone_blink root@192.168.7.2:/home/root/
$ ssh -t root@192.168.7.2 "./beaglebone_blink"
```
### Updating your board to the latest OS
We recommend updating your BeagleBone to the latest Debian OS. It is very easy to do this using the Etcher (https://etcher.io/) utility program.
First, download the latest BeagleBone OS from http://beagleboard.org/latest-images
Now, use Etcher to create an SD card with the OS image you have downloaded.
Once you have created the SD card, boot your BeagleBone using the new image as follows:
- Insert SD card into your (powered-down) board, hold down the USER/BOOT button (if using Black) and apply power, either by the USB cable or 5V adapter.
- If all you want to do it boot once from the SD card, it should now be booting.
- If using BeagleBone Black and desire to write the image to your on-board eMMC, you'll need to follow the instructions at http://elinux.org/Beagleboard:BeagleBoneBlack_Debian#Flashing_eMMC. When the flashing is complete, all 4 USRx LEDs will be steady on or off. The latest Debian flasher images automatically power down the board upon completion. This can take up to 45 minutes. Power-down your board, remove the SD card and apply power again to be complete.
These instructions come from the Beagleboard web site's "Getting Started" page located here:
http://beagleboard.org/getting-started

View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
@ -14,112 +15,21 @@ import (
"github.com/hybridgroup/gobot/sysfs" "github.com/hybridgroup/gobot/sysfs"
) )
var slots = "/sys/devices/bone_capemgr.*"
var ocp = "/sys/devices/ocp.*"
var usrLed = "/sys/devices/ocp.3/gpio-leds.8/leds/beaglebone:green:"
var glob = func(pattern string) (matches []string, err error) { var glob = func(pattern string) (matches []string, err error) {
return filepath.Glob(pattern) return filepath.Glob(pattern)
} }
var pins = map[string]int{
"P8_3": 38,
"P8_4": 39,
"P8_5": 34,
"P8_6": 35,
"P8_7": 66,
"P8_8": 67,
"P8_9": 69,
"P8_10": 68,
"P8_11": 45,
"P8_12": 44,
"P8_13": 23,
"P8_14": 26,
"P8_15": 47,
"P8_16": 46,
"P8_17": 27,
"P8_18": 65,
"P8_19": 22,
"P8_20": 63,
"P8_21": 62,
"P8_22": 37,
"P8_23": 36,
"P8_24": 33,
"P8_25": 32,
"P8_26": 61,
"P8_27": 86,
"P8_28": 88,
"P8_29": 87,
"P8_30": 89,
"P8_31": 10,
"P8_32": 11,
"P8_33": 9,
"P8_34": 81,
"P8_35": 8,
"P8_36": 80,
"P8_37": 78,
"P8_38": 79,
"P8_39": 76,
"P8_40": 77,
"P8_41": 74,
"P8_42": 75,
"P8_43": 72,
"P8_44": 73,
"P8_45": 70,
"P8_46": 71,
"P9_11": 30,
"P9_12": 60,
"P9_13": 31,
"P9_14": 50,
"P9_15": 48,
"P9_16": 51,
"P9_17": 5,
"P9_18": 4,
"P9_19": 13,
"P9_20": 12,
"P9_21": 3,
"P9_22": 2,
"P9_23": 49,
"P9_24": 15,
"P9_25": 117,
"P9_26": 14,
"P9_27": 115,
"P9_28": 113,
"P9_29": 111,
"P9_30": 112,
"P9_31": 110,
}
var pwmPins = map[string]string{
"P9_14": "P9_14",
"P9_21": "P9_21",
"P9_22": "P9_22",
"P9_29": "P9_29",
"P9_42": "P9_42",
"P8_13": "P8_13",
"P8_34": "P8_34",
"P8_45": "P8_45",
"P8_46": "P8_46",
}
var analogPins = map[string]string{
"P9_39": "AIN0",
"P9_40": "AIN1",
"P9_37": "AIN2",
"P9_38": "AIN3",
"P9_33": "AIN4",
"P9_36": "AIN5",
"P9_35": "AIN6",
}
// Adaptor is the gobot.Adaptor representation for the Beaglebone // Adaptor is the gobot.Adaptor representation for the Beaglebone
type Adaptor struct { type Adaptor struct {
name string name string
kernel string
digitalPins []sysfs.DigitalPin digitalPins []sysfs.DigitalPin
pwmPins map[string]*pwmPin pwmPins map[string]*pwmPin
i2cDevice sysfs.I2cDevice i2cDevice sysfs.I2cDevice
usrLed string
ocp string ocp string
helper string analogPath string
analogPinMap map[string]string
slots string slots string
} }
@ -131,12 +41,27 @@ func NewAdaptor() *Adaptor {
pwmPins: make(map[string]*pwmPin), pwmPins: make(map[string]*pwmPin),
} }
b.setSlots()
return b
}
func (b *Adaptor) setSlots() {
ocp := "/sys/devices/ocp.*"
slots := "/sys/devices/bone_capemgr.*"
b.kernel = getKernel()
if b.kernel[:1] == "4" {
ocp = "/sys/devices/platform/ocp/ocp*"
slots = "/sys/devices/platform/bone_capemgr"
}
b.usrLed = "/sys/class/leds/beaglebone:green:"
g, _ := glob(ocp) g, _ := glob(ocp)
b.ocp = g[0] b.ocp = g[0]
g, _ = glob(slots) g, _ = glob(slots)
b.slots = fmt.Sprintf("%v/slots", g[0]) b.slots = fmt.Sprintf("%v/slots", g[0])
return b
} }
// Name returns the Adaptor name // Name returns the Adaptor name
@ -145,13 +70,21 @@ func (b *Adaptor) Name() string { return b.name }
// SetName sets the Adaptor name // SetName sets the Adaptor name
func (b *Adaptor) SetName(n string) { b.name = n } func (b *Adaptor) SetName(n string) { b.name = n }
// Kernel returns the Linux kernel version for the BeagleBone
func (b *Adaptor) Kernel() string { return b.kernel }
// Connect initializes the pwm and analog dts. // Connect initializes the pwm and analog dts.
func (b *Adaptor) Connect() error { func (b *Adaptor) Connect() error {
if err := ensureSlot(b.slots, "cape-bone-iio"); err != nil { // enable analog
if b.kernel[:1] == "4" {
if err := ensureSlot(b.slots, "BB-ADC"); err != nil {
return err return err
} }
if err := ensureSlot(b.slots, "am33xx_pwm"); err != nil { b.analogPath = "/sys/bus/iio/devices/iio:device0"
b.analogPinMap = analogPins44
} else {
if err := ensureSlot(b.slots, "cape-bone-iio"); err != nil {
return err return err
} }
@ -159,7 +92,14 @@ func (b *Adaptor) Connect() error {
if err != nil { if err != nil {
return err return err
} }
b.helper = g[0] b.analogPath = g[0]
b.analogPinMap = analogPins3
}
// enable pwm
if err := ensureSlot(b.slots, "am33xx_pwm"); err != nil {
return err
}
return nil return nil
} }
@ -217,7 +157,7 @@ func (b *Adaptor) DigitalRead(pin string) (val int, err error) {
// valid usr pin values are usr0, usr1, usr2 and usr3 // valid usr pin values are usr0, usr1, usr2 and usr3
func (b *Adaptor) DigitalWrite(pin string, val byte) (err error) { func (b *Adaptor) DigitalWrite(pin string, val byte) (err error) {
if strings.Contains(pin, "usr") { if strings.Contains(pin, "usr") {
fi, err := sysfs.OpenFile(usrLed+pin+"/brightness", os.O_WRONLY|os.O_APPEND, 0666) fi, err := sysfs.OpenFile(b.usrLed+pin+"/brightness", os.O_WRONLY|os.O_APPEND, 0666)
defer fi.Close() defer fi.Close()
if err != nil { if err != nil {
return err return err
@ -238,7 +178,7 @@ func (b *Adaptor) AnalogRead(pin string) (val int, err error) {
if err != nil { if err != nil {
return return
} }
fi, err := sysfs.OpenFile(fmt.Sprintf("%v/%v", b.helper, analogPin), os.O_RDONLY, 0644) fi, err := sysfs.OpenFile(fmt.Sprintf("%v/%v", b.analogPath, analogPin), os.O_RDONLY, 0644)
defer fi.Close() defer fi.Close()
if err != nil { if err != nil {
@ -306,7 +246,7 @@ func (b *Adaptor) translatePwmPin(pin string) (value string, err error) {
// translateAnalogPin converts analog pin name to pin position // translateAnalogPin converts analog pin name to pin position
func (b *Adaptor) translateAnalogPin(pin string) (value string, err error) { func (b *Adaptor) translateAnalogPin(pin string) (value string, err error) {
for key, value := range analogPins { for key, value := range b.analogPinMap {
if key == pin { if key == pin {
return value, nil return value, nil
} }
@ -396,3 +336,9 @@ func ensureSlot(slots, item string) (err error) {
} }
return return
} }
func getKernel() string {
result, _ := exec.Command("uname", "-r").Output()
return strings.TrimSpace(string(result))
}

View File

@ -42,7 +42,7 @@ func (n *NullReadWriteCloser) Read(b []byte) (int, error) {
return len(b), nil return len(b), nil
} }
var closeErr error = nil var closeErr error
func (n *NullReadWriteCloser) Close() error { func (n *NullReadWriteCloser) Close() error {
return closeErr return closeErr
@ -54,16 +54,15 @@ func TestBeagleboneAdaptor(t *testing.T) {
} }
fs := sysfs.NewMockFilesystem([]string{ fs := sysfs.NewMockFilesystem([]string{
"/dev/i2c-1", "/dev/i2c-1",
"/sys/devices/bone_capemgr.4", "/sys/devices/platform/bone_capemgr",
"/sys/devices/ocp.3", "/sys/devices/platform/ocp/ocp4",
"/sys/devices/ocp.3/gpio-leds.8/leds/beaglebone:green:usr1/brightness", "/sys/class/leds/beaglebone:green:usr1/brightness",
"/sys/devices/ocp.3/helper.5", "/sys/bus/iio/devices/iio:device0/in_voltage1_raw",
"/sys/devices/ocp.3/helper.5/AIN1", "/sys/devices/platform/ocp/ocp4/pwm_test_P9_14.5",
"/sys/devices/ocp.3/pwm_test_P9_14.5", "/sys/devices/platform/ocp/ocp4/pwm_test_P9_14.5/run",
"/sys/devices/ocp.3/pwm_test_P9_14.5/run", "/sys/devices/platform/ocp/ocp4/pwm_test_P9_14.5/period",
"/sys/devices/ocp.3/pwm_test_P9_14.5/period", "/sys/devices/platform/ocp/ocp4/pwm_test_P9_14.5/polarity",
"/sys/devices/ocp.3/pwm_test_P9_14.5/polarity", "/sys/devices/platform/ocp/ocp4/pwm_test_P9_14.5/duty",
"/sys/devices/ocp.3/pwm_test_P9_14.5/duty",
"/sys/class/gpio/export", "/sys/class/gpio/export",
"/sys/class/gpio/unexport", "/sys/class/gpio/unexport",
"/sys/class/gpio/gpio60/value", "/sys/class/gpio/gpio60/value",
@ -74,12 +73,13 @@ func TestBeagleboneAdaptor(t *testing.T) {
sysfs.SetFilesystem(fs) sysfs.SetFilesystem(fs)
a := NewAdaptor() a := NewAdaptor()
a.slots = "/sys/devices/bone_capemgr.4" a.slots = "/sys/devices/platform/bone_capemgr"
a.ocp = "/sys/devices/ocp.3" a.ocp = "/sys/devices/platform/ocp/ocp4"
a.kernel = "4.4"
a.Connect() a.Connect()
a.helper = "/sys/devices/ocp.3/helper.5" a.analogPath = "/sys/bus/iio/devices/iio:device0"
// PWM // PWM
glob = func(pattern string) (matches []string, err error) { glob = func(pattern string) (matches []string, err error) {
@ -91,39 +91,39 @@ func TestBeagleboneAdaptor(t *testing.T) {
a.PwmWrite("P9_14", 175) a.PwmWrite("P9_14", 175)
gobottest.Assert( gobottest.Assert(
t, t,
fs.Files["/sys/devices/ocp.3/pwm_test_P9_14.5/period"].Contents, fs.Files["/sys/devices/platform/ocp/ocp4/pwm_test_P9_14.5/period"].Contents,
"500000", "500000",
) )
gobottest.Assert( gobottest.Assert(
t, t,
fs.Files["/sys/devices/ocp.3/pwm_test_P9_14.5/duty"].Contents, fs.Files["/sys/devices/platform/ocp/ocp4/pwm_test_P9_14.5/duty"].Contents,
"343137", "343137",
) )
a.ServoWrite("P9_14", 100) a.ServoWrite("P9_14", 100)
gobottest.Assert( gobottest.Assert(
t, t,
fs.Files["/sys/devices/ocp.3/pwm_test_P9_14.5/period"].Contents, fs.Files["/sys/devices/platform/ocp/ocp4/pwm_test_P9_14.5/period"].Contents,
"16666666", "16666666",
) )
gobottest.Assert( gobottest.Assert(
t, t,
fs.Files["/sys/devices/ocp.3/pwm_test_P9_14.5/duty"].Contents, fs.Files["/sys/devices/platform/ocp/ocp4/pwm_test_P9_14.5/duty"].Contents,
"1898148", "1898148",
) )
// Analog // Analog
fs.Files["/sys/devices/ocp.3/helper.5/AIN1"].Contents = "567\n" fs.Files["/sys/bus/iio/devices/iio:device0/in_voltage1_raw"].Contents = "567\n"
i, _ := a.AnalogRead("P9_40") i, _ := a.AnalogRead("P9_40")
gobottest.Assert(t, i, 567) gobottest.Assert(t, i, 567)
i, err := a.AnalogRead("P9_99") _, err := a.AnalogRead("P9_99")
gobottest.Assert(t, err, errors.New("Not a valid pin")) gobottest.Assert(t, err, errors.New("Not a valid pin"))
// DigitalIO // DigitalIO
a.DigitalWrite("usr1", 1) a.DigitalWrite("usr1", 1)
gobottest.Assert(t, gobottest.Assert(t,
fs.Files["/sys/devices/ocp.3/gpio-leds.8/leds/beaglebone:green:usr1/brightness"].Contents, fs.Files["/sys/class/leds/beaglebone:green:usr1/brightness"].Contents,
"1", "1",
) )

View File

@ -0,0 +1,101 @@
package beaglebone
var pins = map[string]int{
"P8_3": 38,
"P8_4": 39,
"P8_5": 34,
"P8_6": 35,
"P8_7": 66,
"P8_8": 67,
"P8_9": 69,
"P8_10": 68,
"P8_11": 45,
"P8_12": 44,
"P8_13": 23,
"P8_14": 26,
"P8_15": 47,
"P8_16": 46,
"P8_17": 27,
"P8_18": 65,
"P8_19": 22,
"P8_20": 63,
"P8_21": 62,
"P8_22": 37,
"P8_23": 36,
"P8_24": 33,
"P8_25": 32,
"P8_26": 61,
"P8_27": 86,
"P8_28": 88,
"P8_29": 87,
"P8_30": 89,
"P8_31": 10,
"P8_32": 11,
"P8_33": 9,
"P8_34": 81,
"P8_35": 8,
"P8_36": 80,
"P8_37": 78,
"P8_38": 79,
"P8_39": 76,
"P8_40": 77,
"P8_41": 74,
"P8_42": 75,
"P8_43": 72,
"P8_44": 73,
"P8_45": 70,
"P8_46": 71,
"P9_11": 30,
"P9_12": 60,
"P9_13": 31,
"P9_14": 50,
"P9_15": 48,
"P9_16": 51,
"P9_17": 5,
"P9_18": 4,
"P9_19": 13,
"P9_20": 12,
"P9_21": 3,
"P9_22": 2,
"P9_23": 49,
"P9_24": 15,
"P9_25": 117,
"P9_26": 14,
"P9_27": 115,
"P9_28": 113,
"P9_29": 111,
"P9_30": 112,
"P9_31": 110,
}
var pwmPins = map[string]string{
"P9_14": "P9_14",
"P9_21": "P9_21",
"P9_22": "P9_22",
"P9_29": "P9_29",
"P9_42": "P9_42",
"P8_13": "P8_13",
"P8_34": "P8_34",
"P8_45": "P8_45",
"P8_46": "P8_46",
}
var analogPins3 = map[string]string{
"P9_39": "AIN0",
"P9_40": "AIN1",
"P9_37": "AIN2",
"P9_38": "AIN3",
"P9_33": "AIN4",
"P9_36": "AIN5",
"P9_35": "AIN6",
}
var analogPins44 = map[string]string{
"P9_39": "in_voltage0_raw",
"P9_40": "in_voltage1_raw",
"P9_37": "in_voltage2_raw",
"P9_38": "in_voltage3_raw",
"P9_33": "in_voltage4_raw",
"P9_36": "in_voltage5_raw",
"P9_35": "in_voltage6_raw",
}