mirror of
https://github.com/hybridgroup/gobot.git
synced 2025-05-13 19:29:10 +08:00
Merge pull request #342 from hybridgroup/feature/beaglebone-4
Support for newer Beaglebone 4.x kernels
This commit is contained in:
commit
8bb0fbfbad
@ -10,7 +10,7 @@ import (
|
||||
|
||||
func main() {
|
||||
beagleboneAdaptor := beaglebone.NewAdaptor()
|
||||
led := gpio.NewLedDriver(beagleboneAdaptor, "usr0")
|
||||
led := gpio.NewLedDriver(beagleboneAdaptor, "usr1")
|
||||
|
||||
work := func() {
|
||||
gobot.Every(1*time.Second, func() {
|
||||
|
@ -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).
|
||||
|
||||
## How to Install
|
||||
|
||||
```
|
||||
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
|
||||
|
||||
```go
|
||||
@ -62,3 +42,40 @@ func main() {
|
||||
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
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -14,113 +15,22 @@ import (
|
||||
"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) {
|
||||
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
|
||||
type Adaptor struct {
|
||||
name string
|
||||
digitalPins []sysfs.DigitalPin
|
||||
pwmPins map[string]*pwmPin
|
||||
i2cDevice sysfs.I2cDevice
|
||||
ocp string
|
||||
helper string
|
||||
slots string
|
||||
name string
|
||||
kernel string
|
||||
digitalPins []sysfs.DigitalPin
|
||||
pwmPins map[string]*pwmPin
|
||||
i2cDevice sysfs.I2cDevice
|
||||
usrLed string
|
||||
ocp string
|
||||
analogPath string
|
||||
analogPinMap map[string]string
|
||||
slots string
|
||||
}
|
||||
|
||||
// NewAdaptor returns a new Beaglebone Adaptor
|
||||
@ -131,12 +41,27 @@ func NewAdaptor() *Adaptor {
|
||||
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)
|
||||
b.ocp = g[0]
|
||||
|
||||
g, _ = glob(slots)
|
||||
b.slots = fmt.Sprintf("%v/slots", g[0])
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// Name returns the Adaptor name
|
||||
@ -145,22 +70,37 @@ func (b *Adaptor) Name() string { return b.name }
|
||||
// SetName sets the Adaptor name
|
||||
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.
|
||||
func (b *Adaptor) Connect() error {
|
||||
if err := ensureSlot(b.slots, "cape-bone-iio"); err != nil {
|
||||
return err
|
||||
// enable analog
|
||||
if b.kernel[:1] == "4" {
|
||||
if err := ensureSlot(b.slots, "BB-ADC"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
b.analogPath = "/sys/bus/iio/devices/iio:device0"
|
||||
b.analogPinMap = analogPins44
|
||||
} else {
|
||||
if err := ensureSlot(b.slots, "cape-bone-iio"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
g, err := glob(fmt.Sprintf("%v/helper.*", b.ocp))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.analogPath = g[0]
|
||||
b.analogPinMap = analogPins3
|
||||
}
|
||||
|
||||
// enable pwm
|
||||
if err := ensureSlot(b.slots, "am33xx_pwm"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
g, err := glob(fmt.Sprintf("%v/helper.*", b.ocp))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.helper = g[0]
|
||||
|
||||
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
|
||||
func (b *Adaptor) DigitalWrite(pin string, val byte) (err error) {
|
||||
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()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -238,7 +178,7 @@ func (b *Adaptor) AnalogRead(pin string) (val int, err error) {
|
||||
if err != nil {
|
||||
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()
|
||||
|
||||
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
|
||||
func (b *Adaptor) translateAnalogPin(pin string) (value string, err error) {
|
||||
for key, value := range analogPins {
|
||||
for key, value := range b.analogPinMap {
|
||||
if key == pin {
|
||||
return value, nil
|
||||
}
|
||||
@ -396,3 +336,9 @@ func ensureSlot(slots, item string) (err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getKernel() string {
|
||||
result, _ := exec.Command("uname", "-r").Output()
|
||||
|
||||
return strings.TrimSpace(string(result))
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ func (n *NullReadWriteCloser) Read(b []byte) (int, error) {
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
var closeErr error = nil
|
||||
var closeErr error
|
||||
|
||||
func (n *NullReadWriteCloser) Close() error {
|
||||
return closeErr
|
||||
@ -54,16 +54,15 @@ func TestBeagleboneAdaptor(t *testing.T) {
|
||||
}
|
||||
fs := sysfs.NewMockFilesystem([]string{
|
||||
"/dev/i2c-1",
|
||||
"/sys/devices/bone_capemgr.4",
|
||||
"/sys/devices/ocp.3",
|
||||
"/sys/devices/ocp.3/gpio-leds.8/leds/beaglebone:green:usr1/brightness",
|
||||
"/sys/devices/ocp.3/helper.5",
|
||||
"/sys/devices/ocp.3/helper.5/AIN1",
|
||||
"/sys/devices/ocp.3/pwm_test_P9_14.5",
|
||||
"/sys/devices/ocp.3/pwm_test_P9_14.5/run",
|
||||
"/sys/devices/ocp.3/pwm_test_P9_14.5/period",
|
||||
"/sys/devices/ocp.3/pwm_test_P9_14.5/polarity",
|
||||
"/sys/devices/ocp.3/pwm_test_P9_14.5/duty",
|
||||
"/sys/devices/platform/bone_capemgr",
|
||||
"/sys/devices/platform/ocp/ocp4",
|
||||
"/sys/class/leds/beaglebone:green:usr1/brightness",
|
||||
"/sys/bus/iio/devices/iio:device0/in_voltage1_raw",
|
||||
"/sys/devices/platform/ocp/ocp4/pwm_test_P9_14.5",
|
||||
"/sys/devices/platform/ocp/ocp4/pwm_test_P9_14.5/run",
|
||||
"/sys/devices/platform/ocp/ocp4/pwm_test_P9_14.5/period",
|
||||
"/sys/devices/platform/ocp/ocp4/pwm_test_P9_14.5/polarity",
|
||||
"/sys/devices/platform/ocp/ocp4/pwm_test_P9_14.5/duty",
|
||||
"/sys/class/gpio/export",
|
||||
"/sys/class/gpio/unexport",
|
||||
"/sys/class/gpio/gpio60/value",
|
||||
@ -74,12 +73,13 @@ func TestBeagleboneAdaptor(t *testing.T) {
|
||||
|
||||
sysfs.SetFilesystem(fs)
|
||||
a := NewAdaptor()
|
||||
a.slots = "/sys/devices/bone_capemgr.4"
|
||||
a.ocp = "/sys/devices/ocp.3"
|
||||
a.slots = "/sys/devices/platform/bone_capemgr"
|
||||
a.ocp = "/sys/devices/platform/ocp/ocp4"
|
||||
a.kernel = "4.4"
|
||||
|
||||
a.Connect()
|
||||
|
||||
a.helper = "/sys/devices/ocp.3/helper.5"
|
||||
a.analogPath = "/sys/bus/iio/devices/iio:device0"
|
||||
|
||||
// PWM
|
||||
glob = func(pattern string) (matches []string, err error) {
|
||||
@ -91,39 +91,39 @@ func TestBeagleboneAdaptor(t *testing.T) {
|
||||
a.PwmWrite("P9_14", 175)
|
||||
gobottest.Assert(
|
||||
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",
|
||||
)
|
||||
gobottest.Assert(
|
||||
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",
|
||||
)
|
||||
|
||||
a.ServoWrite("P9_14", 100)
|
||||
gobottest.Assert(
|
||||
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",
|
||||
)
|
||||
gobottest.Assert(
|
||||
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",
|
||||
)
|
||||
|
||||
// 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")
|
||||
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"))
|
||||
|
||||
// DigitalIO
|
||||
a.DigitalWrite("usr1", 1)
|
||||
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",
|
||||
)
|
||||
|
||||
|
101
platforms/beaglebone/beaglebone_pins.go
Normal file
101
platforms/beaglebone/beaglebone_pins.go
Normal 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",
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user