diff --git a/platforms/sphero/ollie/README.md b/platforms/sphero/ollie/README.md index 437db4d1..14ac903f 100644 --- a/platforms/sphero/ollie/README.md +++ b/platforms/sphero/ollie/README.md @@ -1,7 +1,6 @@ # Sphero Ollie -The Sphero Ollie is toy robot that is controlled using Bluetooth LE. - +The Sphero Ollie is a toy robot from Sphero that is controlled using Bluetooth LE. For more information, go to [http://www.sphero.com/ollie](http://www.sphero.com/ollie) ## How to Install ``` @@ -10,9 +9,65 @@ go get -d -u gobot.io/x/gobot/... && go install gobot.io/x/gobot/platforms/ble ## How to Use ```go -// code here +package main + +import ( + "os" + "time" + + "gobot.io/x/gobot" + "gobot.io/x/gobot/platforms/ble" + "gobot.io/x/gobot/platforms/sphero/ollie" +) + +func main() { + bleAdaptor := ble.NewClientAdaptor(os.Args[1]) + ollie := ollie.NewDriver(bleAdaptor) + + work := func() { + gobot.Every(1*time.Second, func() { + r := uint8(gobot.Rand(255)) + g := uint8(gobot.Rand(255)) + b := uint8(gobot.Rand(255)) + ollie.SetRGB(r, g, b) + }) + } + + robot := gobot.NewRobot("ollieBot", + []gobot.Connection{bleAdaptor}, + []gobot.Device{ollie}, + work, + ) + + robot.Start() +} ``` ## How to Connect -Instructions here... +The Sphero Ollie is a Bluetooth LE device. + +You need to know the BLE ID of the Ollie you want to connect to. The Gobot BLE client adaptor also lets you connect by friendly name, aka "2B-1247". + +### OSX + +To run any of the Gobot BLE code you must use the `GODEBUG=cgocheck=0` flag in order to get around some of the issues in the CGo-based implementation. + +For example: + + GODEBUG=cgocheck=0 go run examples/ollie.go 2B-1247 + +OSX uses its own Bluetooth ID system which is different from the IDs used on Linux. The code calls thru the XPC interfaces provided by OSX, so as a result does not need to run under sudo. + +### Ubuntu + +On Linux the BLE code will need to run as a root user account. The easiest way to accomplish this is probably to use `go build` to build your program, and then to run the requesting executable using `sudo`. + +For example: + + go build examples/ollie.go + sudo ./minidrone 2B-1247 + +### Windows + +Hopefully coming soon... diff --git a/platforms/sphero/ollie/ollie_driver.go b/platforms/sphero/ollie/ollie_driver.go index 2dd89a24..31f3f0f6 100644 --- a/platforms/sphero/ollie/ollie_driver.go +++ b/platforms/sphero/ollie/ollie_driver.go @@ -9,8 +9,7 @@ import ( "gobot.io/x/gobot/platforms/ble" ) -var _ gobot.Driver = (*Driver)(nil) - +// Driver is the Gobot driver for the Sphero Ollie robot type Driver struct { name string connection gobot.Connection @@ -20,22 +19,35 @@ type Driver struct { } const ( - // service IDs - SpheroBLEService = "22bb746f2bb075542d6f726568705327" + // SpheroBLEService is the primary service ID + SpheroBLEService = "22bb746f2bb075542d6f726568705327" + + // RobotControlService is the service ID for the Sphero command API RobotControlService = "22bb746f2ba075542d6f726568705327" - // characteristic IDs - WakeCharacteristic = "22bb746f2bbf75542d6f726568705327" + // WakeCharacteristic characteristic ID + WakeCharacteristic = "22bb746f2bbf75542d6f726568705327" + + // TXPowerCharacteristic characteristic ID TXPowerCharacteristic = "22bb746f2bb275542d6f726568705327" + + // AntiDosCharacteristic characteristic ID AntiDosCharacteristic = "22bb746f2bbd75542d6f726568705327" + // CommandsCharacteristic characteristic ID CommandsCharacteristic = "22bb746f2ba175542d6f726568705327" + + // ResponseCharacteristic characteristic ID ResponseCharacteristic = "22bb746f2ba675542d6f726568705327" - // gobot events + // SensorData event SensorData = "sensordata" - Collision = "collision" - Error = "error" + + // Collision event + Collision = "collision" + + // Error event + Error = "error" ) type packet struct { @@ -55,10 +67,14 @@ func NewDriver(a *ble.ClientAdaptor) *Driver { return n } + +// Connection returns the connection to this Ollie func (b *Driver) Connection() gobot.Connection { return b.connection } +// Name returns the name for the Driver func (b *Driver) Name() string { return b.name } +// SetName sets the Name for the Driver func (b *Driver) SetName(n string) { b.name = n } // adaptor returns BLE adaptor @@ -67,16 +83,16 @@ func (b *Driver) adaptor() *ble.ClientAdaptor { } // Start tells driver to get ready to do work -func (s *Driver) Start() (err error) { - s.Init() +func (b *Driver) Start() (err error) { + b.Init() // send commands go func() { for { - packet := <-s.packetChannel - err := s.write(packet) + packet := <-b.packetChannel + err := b.write(packet) if err != nil { - s.Publish(s.Event(Error), err) + b.Publish(b.Event(Error), err) } } }() @@ -91,6 +107,7 @@ func (b *Driver) Halt() (err error) { return } +// Init is used to initialize the Ollie func (b *Driver) Init() (err error) { b.AntiDOSOff() b.SetTXPower(7) @@ -102,7 +119,7 @@ func (b *Driver) Init() (err error) { return } -// Turns off Anti-DOS code so we can control Ollie +// AntiDOSOff turns off Anti-DOS code so we can control Ollie func (b *Driver) AntiDOSOff() (err error) { str := "011i3" buf := &bytes.Buffer{} @@ -117,7 +134,7 @@ func (b *Driver) AntiDOSOff() (err error) { return } -// Wakes Ollie up so we can play +// Wake wakes Ollie up so we can play func (b *Driver) Wake() (err error) { buf := []byte{0x01} @@ -130,7 +147,7 @@ func (b *Driver) Wake() (err error) { return } -// Sets transmit level +// SetTXPower sets transmit level func (b *Driver) SetTXPower(level int) (err error) { buf := []byte{byte(level)} @@ -143,7 +160,7 @@ func (b *Driver) SetTXPower(level int) (err error) { return } -// Handle responses returned from Ollie +// HandleResponses handles responses returned from Ollie func (b *Driver) HandleResponses(data []byte, e error) { fmt.Println("response data:", data) @@ -151,27 +168,28 @@ func (b *Driver) HandleResponses(data []byte, e error) { } // SetRGB sets the Ollie to the given r, g, and b values -func (s *Driver) SetRGB(r uint8, g uint8, b uint8) { - s.packetChannel <- s.craftPacket([]uint8{r, g, b, 0x01}, 0x02, 0x20) +func (b *Driver) SetRGB(r uint8, g uint8, bl uint8) { + b.packetChannel <- b.craftPacket([]uint8{r, g, bl, 0x01}, 0x02, 0x20) } -// Tells the Ollie to roll -func (s *Driver) Roll(speed uint8, heading uint16) { - s.packetChannel <- s.craftPacket([]uint8{speed, uint8(heading >> 8), uint8(heading & 0xFF), 0x01}, 0x02, 0x30) +// Roll tells the Ollie to roll +func (b *Driver) Roll(speed uint8, heading uint16) { + b.packetChannel <- b.craftPacket([]uint8{speed, uint8(heading >> 8), uint8(heading & 0xFF), 0x01}, 0x02, 0x30) } -// Tells the Ollie to stop -func (s *Driver) Stop() { - s.Roll(0, 0) +// Stop tells the Ollie to stop +func (b *Driver) Stop() { + b.Roll(0, 0) } -// Go to sleep -func (s *Driver) Sleep() { - s.packetChannel <- s.craftPacket([]uint8{0x00, 0x00, 0x00, 0x00, 0x00}, 0x00, 0x22) +// Sleep says Go to sleep +func (b *Driver) Sleep() { + b.packetChannel <- b.craftPacket([]uint8{0x00, 0x00, 0x00, 0x00, 0x00}, 0x00, 0x22) } -func (s *Driver) EnableStopOnDisconnect() { - s.packetChannel <- s.craftPacket([]uint8{0x00, 0x00, 0x00, 0x01}, 0x02, 0x37) +// EnableStopOnDisconnect auto-sends a Stop command after losing the connection +func (b *Driver) EnableStopOnDisconnect() { + b.packetChannel <- b.craftPacket([]uint8{0x00, 0x00, 0x00, 0x01}, 0x02, 0x37) } func (s *Driver) write(packet *packet) (err error) {