Skip to content

Instantly share code, notes, and snippets.

@ali1234
Created October 17, 2015 15:47
Show Gist options
  • Save ali1234/5e5758d9c591090291d6 to your computer and use it in GitHub Desktop.
Save ali1234/5e5758d9c591090291d6 to your computer and use it in GitHub Desktop.
Control Sphero BB-8 from Linux.
#!/usr/bin/env python
# BB-8 Python driver by Alistair Buxton <a.j.buxton@gmail.com>
from bluepy import btle
import time
class BB8(btle.DefaultDelegate):
def __init__(self, deviceAddress):
btle.DefaultDelegate.__init__(self)
# Address type must be "random" or it won't connect.
self.peripheral = btle.Peripheral(deviceAddress, btle.ADDR_TYPE_RANDOM)
self.peripheral.setDelegate(self)
self.seq = 0
# Attribute UUIDs are identical to Ollie.
self.antidos = self.getSpheroCharacteristic('2bbd')
self.wakecpu = self.getSpheroCharacteristic('2bbf')
self.txpower = self.getSpheroCharacteristic('2bb2')
self.roll = self.getSpheroCharacteristic('2ba1')
self.notify = self.getSpheroCharacteristic('2ba6')
# This startup sequence is also identical to the one for Ollie.
# It even uses the same unlock code.
print 'Sending antidos'
self.antidos.write('011i3', withResponse=True)
print 'Sending txpower'
self.txpower.write('\x0007', withResponse=True)
print 'Sending wakecpu'
self.wakecpu.write('\x01', withResponse=True)
def getSpheroCharacteristic(self, fragment):
return self.peripheral.getCharacteristics(uuid='22bb746f'+fragment+'75542d6f726568705327')[0]
def dumpCharacteristics(self):
for s in self.peripheral.getServices():
print s
for c in s.getCharacteristics():
print c, hex(c.handle)
def cmd(self, did, cid, data=[], answer=True, resetTimeout=True):
# Commands are as specified in Sphero API 1.50 PDF.
# https://github.com/orbotix/DeveloperResources/
seq = (self.seq&255)
self.seq += 1
sop2 = 0xfc
sop2 |= 1 if answer else 0
sop2 |= 2 if resetTimeout else 0
dlen = len(data)+1
chk = (sum(data)+did+cid+seq+dlen)&255
chk ^= 255
msg = [0xff, sop2, did, cid, seq, dlen] + data + [chk]
print 'cmd:', ' '.join([chr(c).encode('hex') for c in msg])
# Note: withResponse is very important. Most commands won't work without it.
self.roll.write(''.join([chr(c) for c in msg]), withResponse=True)
def handleNotification(self, cHandle, data):
print 'Notification:', cHandle, data.encode('hex')
def waitForNotifications(self, time):
self.peripheral.waitForNotifications(time)
def disconnect(self):
self.peripheral.disconnect()
if __name__ == '__main__':
# Connect by address. Use "sudo hcitool lescan" to find address.
bb = BB8('EE:D7:9A:A7:79:77')
# Dump all GATT stuff.
#bb.dumpCharacteristics()
# Request some sensor stream.
bb.cmd(0x02, 0x11, [0, 80, 0, 1, 0x80, 0, 0, 0, 0])
for i in range(255):
# Set RGB LED colour.
bb.cmd(0x02, 0x20, [254, i, 2, 0])
# Wait for streamed data.
bb.waitForNotifications(1.0)
# Must manually disconnect or you won't be able to reconnect.
bb.disconnect()
@redhowe
Copy link

redhowe commented Jan 6, 2016

Hi all, unfortunately I am having the same issue as others where the BB8 will not allow a phone connection after connecting with the python driver. Advice please as allowing it to 'sleep' didn't do the trick here.

@NickLeBoeuf
Copy link

Hello, did you try to press the small reset button on the base when bb8 is charging ? I did not yet test the python driver, but with this reset button i was able to pair/unpair different phones/tablets on my bb8. Hope this helps.

@redhowe
Copy link

redhowe commented Jan 7, 2016

NickLeBoeuf - thanks! I had completely forgotten about that button which did the trick. Any idea what is causing the issue with switching back to other apps?

@WasylF
Copy link

WasylF commented Sep 16, 2016

Hello Ali! Thanks for your code!!!
Does it work for ollie too?

Copy link

ghost commented Oct 18, 2017

good evening,

Congratulations on the code, I need to get information from the BB8 as the data of your sensors, IMU, accelerometer, gyroscope, can you do something like this?

@harmitbadyal
Copy link

Hello,
Thank you so much for the code!
I have an issue whenever I run the BB8test.py. Here is the output that comes up on my terminal. Any help would be greatly appreciated!

"File "BB8test.py", line 8, in <module>
    bb8.connect()
  File "/home/pi/Projects/SpheroBB8-python/BB8_driver.py", line 259, in connect
    self.bt = BTInterface(self.deviceAddress)
  File "/home/pi/Projects/SpheroBB8-python/BB8_driver.py", line 138, in __init__
    self.peripheral = btle.Peripheral(deviceAddress, btle.ADDR_TYPE_RANDOM)
  File "/usr/local/lib/python2.7/dist-packages/bluepy/btle.py", line 391, in __init__
    self._connect(deviceAddr, addrType, iface)
  File "/usr/local/lib/python2.7/dist-packages/bluepy/btle.py", line 439, in _connect
    raise BTLEDisconnectError("Failed to connect to peripheral %s, addr type: %s" % (addr, addrType), rsp)
bluepy.btle.BTLEDisconnectError: Failed to connect to peripheral D7:74:05:73:09:55, addr type: random

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment