8.8 KiB
Python library to interact with Move Hub
Move Hub is central robotic controller block of LEGO Boost Set.
Best way to start with this library is to look into demo.py
file, and run it.
If you have Vernie assembled, you might look into and run scripts from vernie
directory.
Features
- auto-detect and connect for Bluetooth device
- auto-detects devices connected to Hub
- angled and timed movement for motors
- LED color change
- motors: angled and timed movement, rotation sensor subscription
- push button status subscription
- tilt sensor subscription: 2 axis, 3 axis, bump detect modes
- color & distance sensor: several modes to measure distance, color and luminosity
- battery voltage subscription available
- permanent Bluetooth connection server for faster debugging
Usage
Install library like this:
pip install https://github.com/undera/pylgbst/archive/0.2.tar.gz
Then instantiate MoveHub object and start invoking its methods. Following is example to just print peripherals detected on Hub:
from pylgbst import MoveHub
hub = MoveHub()
for device in hub.devices:
print(device)
TODO: more usage instructions
General Information
connection params
hub's devices detect process & fields to access them
general subscription modes & granularity info
good practice is to unsubscribe, especially when used with DebugServer
Only one, very last subscribe mode is in effect, with many subscriber callbacks allowed.
Controlling Motors
MoveHub provides motors via following fields:
motor_A
motor_B
motor_AB
motor_external
- if external motor is attached to port C or D
Methods to activate motors are:
constant(speed_primary, speed_secondary)
timed(time, speed_primary, speed_secondary)
angled(angle, speed_primary, speed_secondary)
stop()
All these methods are synchronous by default, except stop()
. You can pass async
parameter to any of them to switch into asynchronous, which means command will return immediately, without waiting for rotation to complete.
An example:
from pylgbst import MoveHub
import time
hub = MoveHub()
hub.motor_A.timed(0.5, 0.8)
hub.motor_A.timed(0.5, -0.8)
hub.motor_B.angled(90, 0.8)
hub.motor_B.angled(-90, 0.8)
hub.motor_AB.timed(1.5, 0.8, -0.8)
hub.motor_AB.angled(90, 0.8, -0.8)
hub.motor_external.constant(0.2)
time.sleep(2)
hub.motor_external.stop()
Motor Rotation Sensors
Any motor allows to subscribe to its rotation sensor. Two sensor modes are available: rotation angle (EncodedMotor.SENSOR_ANGLE
) and rotation speed (EncodedMotor.SENSOR_SPEED
). Example:
from pylgbst import MoveHub, EncodedMotor
import time
def callback(angle):
print("Angle: %s" % angle)
hub = MoveHub()
hub.motor_A.subscribe(callback, mode=EncodedMotor.SENSOR_ANGLE)
time.sleep(60) # rotate motor A
hub.motor_A.unsubscribe(callback)
Tilt Sensor
MoveHub's internal tilt sensor is available through tilt_sensor
field. There are several modes to subscribe to sensor, providing 2-axis, 3-axis and bump detect data.
An example:
from pylgbst import MoveHub, TiltSensor
import time
def callback(pitch, roll, yaw):
print("Pitch: %s / Roll: %s / Yaw: %s" % (pitch, roll, yaw))
hub = MoveHub()
hub.tilt_sensor.subscribe(callback, mode=TiltSensor.MODE_3AXIS_FULL)
time.sleep(60) # turn MoveHub block in different ways
hub.tilt_sensor.unsubscribe(callback)
TiltSensor
sensor mode constants:
- MODE_2AXIS_SIMPLE - use
callback(state)
for 2-axis simple state detect - MODE_2AXIS_FULL - use
callback(roll, pitch)
for 2-axis roll&pitch degree values - MODE_3AXIS_SIMPLE - use
callback(state)
for 3-axis simple state detect - MODE_3AXIS_FULL - use
callback(roll, pitch)
for 2-axis roll&pitch degree values - MODE_BUMP_COUNT - use
callback(count)
to detect bumps
Color & Distance Sensor
Field named color_distance_sensor
holds instance of ColorDistanceSensor
, if one is attached to MoveHub. Sensor has number of different modes to subscribe.
Colors that are detected are part of COLORS
map (see LED section). Only several colors are possible to detect: BLACK
, BLUE
, CYAN
, YELLOW
, RED
, WHITE
. Sensor does its best to detect best color, but only works when sample is very close to sensor.
Distance works in range of 0-10 inches, with ability to measure last inch in higher detail.
Simple example of subscribing to sensor:
from pylgbst import MoveHub, ColorDistanceSensor
import time
def callback(clr, distance):
print("Color: %s / Distance: %s" % (clr, distance))
hub = MoveHub()
hub.color_distance_sensor.subscribe(callback, mode=ColorDistanceSensor.COLOR_DISTANCE_FLOAT)
time.sleep(60) # play with sensor while it waits
hub.color_distance_sensor.unsubscribe(callback)
Subscription mode constants in class ColorDistanceSensor
are:
COLOR_DISTANCE_FLOAT
- default mode, usecallback(color, distance)
wheredistance
is float value in inchesCOLOR_ONLY
- usecallback(color)
DISTANCE_INCHES
- usecallback(color)
measures distance in integer inches countCOUNT_2INCH
- usecallback(count)
- it counts crossing distance ~2 inches in front of sensorDISTANCE_HOW_CLOSE
- usecallback(value)
- value of 0 to 255 for 30 inches, larger with closer distanceDISTANCE_SUBINCH_HOW_CLOSE
- usecallback(value)
- value of 0 to 255 for 1 inch, larger with closer distanceLUMINOSITY
- usecallback(luminosity)
whereluminosity
is float value from 0 to 1OFF1
andOFF2
- seems to turn sensor LED and notifications offSTREAM_3_VALUES
- usecallback(val1, val2, val3)
, sends some values correlating to distance, not well understood at the moment
Tip: laser pointer pointing to sensor makes it to trigger distance sensor
LED
MoveHub
class has field led
to access color LED near push button. To change its color, use set_color(color)
method.
You can obtain colors are present as constants COLOR_*
and also a map of available color-to-name as COLORS
. There are 12 color values, including COLOR_BLACK
and COLOR_NONE
which turn LED off.
Additionally, you can subscribe to LED color change events, using callback function as shown in example below.
from pylgbst import MoveHub, COLORS, COLOR_NONE, COLOR_RED
import time
def callback(clr):
print("Color has changed: %s" % clr)
hub = MoveHub()
hub.led.subscribe(callback)
hub.led.set_color(COLOR_RED)
for color in COLORS:
hub.led.set_color(color)
time.sleep(0.5)
hub.led.set_color(COLOR_NONE)
hub.led.unsubscribe(callback)
Tip: blinking orange color of LED means battery is low.
Push Button
MoveHub
class has field button
to subscribe to button press and release events.
Note that Button
class is not real Peripheral
, as it has no port and not listed in devices
field of Hub. Still, subscribing to button is done usual way:
from pylgbst import MoveHub
def callback(is_pressed):
print("Btn pressed: %s" % is_pressed)
hub = MoveHub()
hub.button.subscribe(callback)
Power Voltage & Battery
MoveHub
class has field battery
to subscribe to battery voltage status. Callback accepts single parameter with current value. The range of values is unknown, it's 2-byte integer. Every time data is received, value is also written into last_value
field of Battery object.
from pylgbst import MoveHub
import time
def callback(value):
print("Voltage: %s" % value)
hub = MoveHub()
hub.battery.subscribe(callback)
time.sleep(1)
print ("Value: " % hub.battery.last_value)
Debug Server
Running debug server opens permanent BLE connection to Hub and listening on TCP port for communications. This avoids the need to re-start Hub all the time.
There is DebugServerConnection
class that you can use with it, instead of BLEConnection
.
Starting debug server is done like this:
sudo python -c "from pylgbst.comms import *; \
import logging; logging.basicConfig(level=logging.DEBUG); \
DebugServer(BLEConnection().connect()).start()"
Then push green button on MoveHub, so permanent BLE connection will be established.
TODO
- Give nice documentation examples, don't forget to mention logging
- document all API methods
- make sure unit tests cover all important code
- handle device detach and device attach events on ports C/D
- generalize getting device info + give constants (low priority)
- organize requesting and printing device info on startup - firmware version at least
- make debug server to re-establish BLE connection on loss
Links
- https://github.com/JorgePe/BOOSTreveng - source of protocol knowledge
- https://github.com/spezifisch/sphero-python/blob/master/BB8joyDrive.py - example with another approach to bluetooth libs
Some things around visual programming: