At SBrick (or SmartBrick) Kickstarter campaign I pledged for beta tester. My beta SBrick arrived at last from Hungary:
As it’s still an early version it has some issues (one of the four channels seems to be damaged and LEGO Power Function cables don’t fit tight to another channel’s plug) but it’s good enough for testing connectivity with Linux, particularly with ev3dev – my main goal as beta tester is to help in connecting LEGO Mindstorms EV3 to the Sbrick.
SBrick exposes 6 Bluetooth 4.0 Low Energy «services» (I am not familiar with the BLE jargon yet): Generic Access, Device Information and another 4 specific from the vendor. The first and second services expose this information:
Device Name = SBrick
Appearance = Generic Remote Control
Model Number = 4.0
Firmware Revision = 4.1
Hardware Revision = 4.0
Software Revision = 4.1
Manufacturer Name String = Vengit Ltd.
The other 4 services are specific from Vengit and expose a total of 8 «fields»:
– 5 Read Only
– 1 Write Only
– 1 Read/Write
– 1 Unknown
Meanwhile I got from Vengit the minimal information needed for controlling a motor connected to one of the 4 channels: the reomote control service UUID is ‘4dc591b0-857c-41de-b5f1-15abda665b0c’ and the remote control characteristic is ‘2b8cbcc-0e25-4bda-8790-a15f53e6010f’.
For practical uses, using the ‘gatttool’ command from BlueZ 5 (the Linux Bluetooth stack), the above information translates to writing to handle 0x0025 the commands supported by the SBrick firmware.
I only know two of those commands (00h = BRAKE e 01h = DRIVE)
- BRAKE Channel
- DRIVE Channel Direction DutyCycle
‘Channel’ is one of the 4 output ports available and can be 00h, 01h, 02h or 03h.
‘Direction’ can be clockwise (00h) or anticlockwise (01h).
‘DutyCycle’ is the power pretended for the motor, can go from 00h (none or “Coast”) to FFh (“full power”).
So to send a command from Linux (a Ubuntu PC, a Raspberry Pi with Raspbian or a Mindstorms EV3 with ev3dev) with a USB BT4.0/BLE dongle one just need to use the ‘gatttool’:
$ gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010000FF
The exemple above, sends to the Bluetooth device with address ’00:07:80:7F:28:E1′ (my SBrick) from the BT controller ‘hci0’ (my dongle) the command
DRIVE Channel#0 Clockwise 100%
As this command doesn’t keep the bluetooth connection open, the motor spins for around 3 secondss, then the connection drops and it stops (but if we use ‘gatttool’ in interactive mode with option “-I” or “–interactive” and send the equivalent commands, the motor will keep spinning).
Next video shows 2 motors spinning in opposite directions:
- DRIVE Channel#0 Clockwise 22%
- DRIVE Channel#2 Anticlockwise 17%
Next video shows an EV3 motor actiing as the reference for a Power Functionn Servo:
And a little better version of the same example, with a scale factor for matching the motor positions and a limitation of range to [-90º,+90º].
For that last video it was used this python script:
import traceback from sys import exit from time import sleep from subprocess import call from subprocess import check_output from math import trunc def reset_ev3motor(): call ("echo 0 > /sys/class/tacho-motor/motor0/position", shell=True); return; def rd_ev3motor(): v=check_output("cat /sys/class/tacho-motor/motor0/position",shell=True); return(trunc(float(v))); def sbrick_drive(channel,direction,dutycycle): " calls gatttool command from BlueZ, the official Linux Bluetooth protocol stack" if(dutycycle > 255): dt_hexa="0xFF"; else: dt_hexa=str(hex(int(dutycycle))); command="gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=01"+channel+direction+dt_hexa[2:]; # print(command); call (command, shell=True); return; def main(): try: pos=0.0; SCALE=255.0/90.0; reset_ev3motor(); while(True): pos=rd_ev3motor()*SCALE; if(pos>0): sbrick_drive("02","00",pos); else: sbrick_drive("02","01",-pos) sleep(0.1); except (KeyboardInterrupt, SystemExit): print "Exiting..."; except Exception: traceback.print_exc(file=sys.stdout); exit(0); if __name__ == "__main__": main()
I use the ‘call’ function from library ‘subprocess’ to get to ‘gatttool’. It’s an ugly trick but it works, I did’t find a python bluetooth BLE library yet.