Remote ultrasonic sensor for EV3 with micro:bit

This post is part 1 of 1 of  EV3 and micro:bit

Been testing the micro:bit BLE Uart service. It’s a service that uses Nordic chipset features to deliver a simple TX/RX mechanism so we talk with the micro:bit without having to create our own BLE services.

Someone offered me a ultrasonic sensor this week. It’s a HC-SR04, very common with Arduino projects but can also be used with the micro:bit, there’s even a “sonar” extension available in the Makecode editor.

So I added the BLE Uart service and started writing the distance values to the TX characteristic every second:

Nordic nRF Connect App reads them fine but gatttool doesn’t… except when in Interactive mode. Strange!

After a while, I found out a note that explains that the way the TX characteristic works forces us to keep the connection or reset the micro:bit regularly. That’s why Interactive mode works (it keeps the connection). So I have to forget gatttool for a while and use something better like python.

On Ubuntu, my scripts worked fine. Latest version of pygatt (4.0.3) allow me to subscribe to the TX Characterist (in “Indication” mode only – almost the same as notifications but with an extra acknowledge step) and I was getting distance values on my laptop through BLE.

But on the EV3 the scripts failed because “No characteristic found matching”. Why? I’m using same version of pygatt and don’t think that kernel version make much difference now that pybluez has settled.

I was almost giving up when something worked: decided to use the python exception mechanism to retry several times the subscribing step.

So instead of just

device.subscribe("6e400002-b5a3-f393-e0a9-e50e24dcca9e", callback=handle_data, indication=True)

I included the subscribe command in a loop that only ends when the command completes:

while True:
    try:
        device.subscribe("6e400002-b5a3-f393-e0a9-e50e24dcca9e", callback=handle_data, indication=True)
        break
    except pygatt.exceptions.BLEError:
        print("unknown characteristic")

And it works?! Usually just retrying once:

Connecting…
Connected
unknown characteristic
Dist = 1.19 m
Dist = 1.19 m
Dist = 1.18 m

My micro:bit github page now includes the python script used on the above video

If you wonder about the format of the data, the micro:bit sends the distance value as a string of bytes, each byte being the ASCII code of the character, so 40 cm is sent as a “4” followed by a “0”:

34h 30h

EV3 and micro:bit

Almost 2 and a half years ago I bought a BBC micro:bit, planning to give it as a xmas present to my geek nephew. Unfortunately (for him) I decided that he wasn’t geek enough for this small ARM-based controller as I found out it was too confusing to set it up properly for BLE usage.

At that time I managed to get EV3 working with it but it was very awkward. Most of my problems were related to making a proper connection because the firmware required BT to be paired before accepting BLE commands but I also had problemas with the python BLE library I was using (gattlib).

This weekend I had a long day at work upgrading some Microsoft servers and had the time, between downloads and reboots (argh!) to return to this little fellow. So I found out it is now much, much easier to configure it… thanks to Microsoft! Yes, same Microsoft.

I used Makecode Editor to configure my micro:bit from a browser: just added the Bluetooth extension, included th e Bluetooth blocks that activate the proper BLE services and enabled using BLE without the need to pair BT first.

On the ev3dev side it was also easy to use it with python but with a different library: pygatt.

Interestingly, a new version of pygatt was released this very same weekend.

Details and code samples at another Microsoft site (github).

Two demo videos:

  • using the two buttons to control a Medium motor:
  • using the LED Matrix:

I love opensource

Today I got a nice note from a guy named Kevin Walters. He used my mindstorms-vll code to control a MINDSTORMS MicroScout droid with a smarphone, using an Adafruit Feather M0 Bluefruit LE running CircuitPython 3.1.1 as a gateway controller:

https://learn.adafruit.com/bluetooth-remote-for-lego-droid

Thanks Kevin for quoting me and for the wonderful project.

LEGO Conveyex Imperial Transport

This post is part 1 of 1 of  Conveyex

So another never-to-be-completed project.

I like Star Wars but usually don’t care for LEGO Star Wars sets. But when the Conveyex set was released I liked it a lot. Probably because it looked like a monorail train and I was already gathering a few old LEGO monorail pieces. So I ordered one… or so I tought.

When I order from LEGO I take the chance to buy a few MINDSTORMS motors and some Power Function elements like cables or batteries. I had a few items already on my desired list so I didn’t notice exactly how many items I was ordering… and so I received 3 (three!) Conveyex sets.

Oh boy. What I am going to do with all these Conveyex?

Then I realized that the size of the set wagons is simillar to the monorail wagons. After assembling the first set I took off the wheels and with just a few extra bricks I got my first monorail version:

Since I was already trying to use Powered Up as a way to control the monorail motor it seemed natural to extend this first version to a bluetooth controled one:

This way the Conveyex could be controlled not just with the Powered Up train headset but also programmatically. That would allow me to use the Conveyex on a large animated diorama, with MINDSTORMS and other controllable elements:

So this was the beginning. Now I “just” needed to extend the train with a few more wagons. And the rail with a few more tracks. Seemed simple.

But the old LEGO monorail system wasn’t meant for long trains. The system was designed for just 1 engine in the middle and 1 wagon at each side:


The wagons connect to the engine through a custom coupling system. As far as I know, there is no way to connect other LEGO elements to the engine couplings. Extending the length is possible by adding wagons and using some LEGO parts as custom couplers, like in LEGO trains.

Fortunately there is a company named 4DBrix that sell a few custom elements compatible with the monorail system. I ordered them some car extensions that has a “male” tab that connects to the engine and a “female” socket that allow extra wagons to be added. It worked but then the overall weight started to be feel too demanding for the monorail motor. Perhaps a single motor could move a train with 2 or 3 wagons and an engine but I also wanted ramps (of course!) and that seemed too much. So I wondered if it is possible to use more than one monorail motor…

It is:

The monorail track is really just a long gear. So the two motors are directly coupled together and just add their force (oh well… after a while I found out that this is not always true).

But the way that the Powered Up Hub was designed it is not the best for such a setup – the 6x AAA batteries would drain too fast and I would have to remove the Hub to replace them. Once in a while it might be acceptable but certainly not every 30 minutes. The good old Power Functions LiPo battery is much better – it allows in place recharging and it also looks like it can supply a few more milliamps than the PUP Hub (not confirmed).

So I picked my LEGO relay idea and built a Powered Up version:

and then applied it to the Conveyex:

So now the Powered Up Hub batteries are only used to keep the Hub ON and sometimes to change the relay state. Need to measure it but I suspect that it would work a few hours. And no custom cable is used, just 100% LEGO electric parts.

So today the Conveyex is already looking good:

The model uses 2 monorail motors, 4 wagons and an engine car:

From left to right:

  • Powered Up Hub wagon
  • Monorail motor
  • Relay wagon
  • Power Functions LiPo battery wagon
  • still no purpose wagon
  • Monorail wagon
  • Engine car

So the Conveyex is really just 2 monorail trains linked together (in the above drawing, the extra space reflects the custom coupling I had to build, longer than the monorail coupling sustem). The wagons aren’t all of the same size because the wagons length from the LEGO Conveyex are in facto a bit too larger and make the monorail derail at regular curves and ramps – so I built the Relay wagon 4 studs shorter.

The weight is not equally distributed, the front train is lighter than the back train. So sometimes, when the Conveyex is moving on ramps, the two trains move at different speeds – like when the front train already reached the top and the back train is still moving up in the ramp:

On the video above the LiPo was adjusted for 4/7 of output power. The front train gained too much speed and the monorail coupling couldn’t handle and disconnected. Now I’m running the Conveyex with the LiPo at 5/7 of output power and this never happened again but probably will need to add more weight to the “still no purpose wagon”… crazy ideas welcome 🙂

LEGO Powered Up Relay

I needed a way to turn a LEGO motor ON and OFF using a Powered Up hub but keeping power supplies independent. This way I can control a large current demanding motor without draining out the Hub batteries (and also without the need to use a custom cable).

So I used a Power Functions switch as a relay:

LEGO Powered Up relay

Also took the chance to try LDCad on linux. Not so easy to use as LEGO Digital Designer (I am a zero with CAD) but after a while I got a pretty close model. To create a PDF with the instructions I then used LPub3D – I couldn’t install the ‘.deb’ file because of missing dependencies no longer available for my Ubuntu laptop but found out that the ‘.AppImage’ works fine.

The instructions on this PDF file also have a list of the parts that I needed to get from LDView (LPub3D generates a nice image with all the parts but without describing those parts). I also couldn’t install the ‘.deb’ version so I used the ‘.exe’ for Windows, it runs fine with Wine.

The model uses a Powered Up / WeDo 2 motor but it can also use a Power Function M motor or a MINDSTORMS medium motor so this relay may use with different technologies (IR, Bluetooth, Wi-Fi, USB) as long as you just need an ON/OFF control of the motor.

Using a Power Functions LiPo battery you can still regulate the output power

A video of the relay working:


And another showing how I use it in my LEGO Imperial Conveyex Transport based on the old LEGO monorail system:

Big thanks to Roland Melkert, Trevor Sandy, Travis Cobbs who designed these great open source tools (and probably many others who contributed).

LEGO Wireless Protocol officially available

LEGO released the specs for the Powered Up BLE-based protocol (LWP):

https://lego.github.io/lego-ble-wireless-protocol-docs

Interestingly the document is also available as an open souce (MIT license) project at Github:

https://github.com/LEGO/lego-ble-wireless-protocol-docs

Is’s always a good sign when a big company like LEGO embraces open source so let’s hope for the best

Merry Christmas to all!

XAC with EV3

This post is part 4 of 6 of  Xbox Adaptive Controller

Running ev3dev (‘4.14.71-ev3dev-2.3.0-ev3 (stretch)’.

BT works, just needed to edit ‘/sys/module/bluetooth/parameters/disable_ertm’.

dmesg:

Bluetooth: HIDP (Human Interface Emulation) ver 1.2
Bluetooth: HIDP socket layer initialized
hid-generic 0005:045E:0B0C.0002: unknown main item tag 0x0
Bluetooth: received HCILL_WAKE_UP_IND in state 2
input: Xbox Adaptive Controller as /devices/platform/soc@1c00000/serial8250.2/tty/ttyS2/hci0/hci0:1/0005:045E:0B0C.0002/input/input3
hid-generic 0005:045E:0B0C.0002: input,hidraw1: BLUETOOTH HID v9.03 Gamepad [Xbox Adaptive Controller] on a0:e6:f8:60:16:60

I don’t have a ‘/dev/input/js0’  because ev3dev ‘joydev’ has been deprecated.

But I can still read it with ‘cat /dev/input/event3’ but since it looks like garbage its better to use ‘evtest’:

No device specified, trying to scan all of /dev/input/event*
Not running as root, no devices may be available.
Available devices:
/dev/input/event0: LEGO MINDSTORMS EV3 Speaker
/dev/input/event1: EV3 Brick Buttons
/dev/input/event2: C-Media USB Headphone Set 
/dev/input/event3: Xbox Adaptive Controller
Select the device event number [0-3]: 3
Input driver version is 1.0.1
Input device ID: bus 0x5 vendor 0x45e product 0xb0c version 0x903
Input device name: "Xbox Adaptive Controller"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 1 (KEY_ESC)
    Event code 2 (KEY_1)
    Event code 3 (KEY_2)
    Event code 4 (KEY_3)
    Event code 5 (KEY_4)
    Event code 6 (KEY_5)
    Event code 7 (KEY_6)
    Event code 8 (KEY_7)
    Event code 9 (KEY_8)
    Event code 10 (KEY_9)
    Event code 11 (KEY_0)
    Event code 12 (KEY_MINUS)
    Event code 13 (KEY_EQUAL)
    Event code 14 (KEY_BACKSPACE)
    Event code 15 (KEY_TAB)
    Event code 16 (KEY_Q)
    Event code 17 (KEY_W)
    Event code 18 (KEY_E)
    Event code 19 (KEY_R)
    Event code 20 (KEY_T)
    Event code 21 (KEY_Y)
    Event code 22 (KEY_U)
    Event code 23 (KEY_I)
    Event code 24 (KEY_O)
    Event code 25 (KEY_P)
    Event code 26 (KEY_LEFTBRACE)
    Event code 27 (KEY_RIGHTBRACE)
    Event code 28 (KEY_ENTER)
    Event code 29 (KEY_LEFTCTRL)
    Event code 30 (KEY_A)
    Event code 31 (KEY_S)
    Event code 32 (KEY_D)
    Event code 33 (KEY_F)
    Event code 34 (KEY_G)
    Event code 35 (KEY_H)
    Event code 36 (KEY_J)
    Event code 37 (KEY_K)
    Event code 38 (KEY_L)
    Event code 39 (KEY_SEMICOLON)
    Event code 40 (KEY_APOSTROPHE)
    Event code 41 (KEY_GRAVE)
    Event code 42 (KEY_LEFTSHIFT)
    Event code 43 (KEY_BACKSLASH)
    Event code 44 (KEY_Z)
    Event code 45 (KEY_X)
    Event code 46 (KEY_C)
    Event code 47 (KEY_V)
    Event code 48 (KEY_B)
    Event code 49 (KEY_N)
    Event code 50 (KEY_M)
    Event code 51 (KEY_COMMA)
    Event code 52 (KEY_DOT)
    Event code 53 (KEY_SLASH)
    Event code 54 (KEY_RIGHTSHIFT)
    Event code 55 (KEY_KPASTERISK)
    Event code 56 (KEY_LEFTALT)
    Event code 57 (KEY_SPACE)
    Event code 58 (KEY_CAPSLOCK)
    Event code 59 (KEY_F1)
    Event code 60 (KEY_F2)
    Event code 61 (KEY_F3)
    Event code 62 (KEY_F4)
    Event code 63 (KEY_F5)
    Event code 64 (KEY_F6)
    Event code 65 (KEY_F7)
    Event code 66 (KEY_F8)
    Event code 67 (KEY_F9)
    Event code 68 (KEY_F10)
    Event code 69 (KEY_NUMLOCK)
    Event code 70 (KEY_SCROLLLOCK)
    Event code 71 (KEY_KP7)
    Event code 72 (KEY_KP8)
    Event code 73 (KEY_KP9)
    Event code 74 (KEY_KPMINUS)
    Event code 75 (KEY_KP4)
    Event code 76 (KEY_KP5)
    Event code 77 (KEY_KP6)
    Event code 78 (KEY_KPPLUS)
    Event code 79 (KEY_KP1)
    Event code 80 (KEY_KP2)
    Event code 81 (KEY_KP3)
    Event code 82 (KEY_KP0)
    Event code 83 (KEY_KPDOT)
    Event code 86 (KEY_102ND)
    Event code 87 (KEY_F11)
    Event code 88 (KEY_F12)
    Event code 96 (KEY_KPENTER)
    Event code 97 (KEY_RIGHTCTRL)
    Event code 98 (KEY_KPSLASH)
    Event code 99 (KEY_SYSRQ)
    Event code 100 (KEY_RIGHTALT)
    Event code 102 (KEY_HOME)
    Event code 103 (KEY_UP)
    Event code 104 (KEY_PAGEUP)
    Event code 105 (KEY_LEFT)
    Event code 106 (KEY_RIGHT)
    Event code 107 (KEY_END)
    Event code 108 (KEY_DOWN)
    Event code 109 (KEY_PAGEDOWN)
    Event code 110 (KEY_INSERT)
    Event code 111 (KEY_DELETE)
    Event code 119 (KEY_PAUSE)
    Event code 125 (KEY_LEFTMETA)
    Event code 126 (KEY_RIGHTMETA)
    Event code 127 (KEY_COMPOSE)
    Event code 158 (KEY_BACK)
    Event code 172 (KEY_HOMEPAGE)
    Event code 240 (KEY_UNKNOWN)
    Event code 241 (KEY_VIDEO_NEXT)
    Event code 304 (BTN_SOUTH)
    Event code 305 (BTN_EAST)
    Event code 306 (BTN_C)
    Event code 307 (BTN_NORTH)
    Event code 308 (BTN_WEST)
    Event code 309 (BTN_Z)
    Event code 310 (BTN_TL)
    Event code 311 (BTN_TR)
    Event code 312 (BTN_TL2)
    Event code 313 (BTN_TR2)
    Event code 314 (BTN_SELECT)
    Event code 315 (BTN_START)
    Event code 316 (BTN_MODE)
    Event code 317 (BTN_THUMBL)
    Event code 318 (BTN_THUMBR)
    Event code 319 (?)
    Event code 410 (KEY_SHUFFLE)
    Event code 704 (BTN_TRIGGER_HAPPY1)
    Event code 705 (BTN_TRIGGER_HAPPY2)
    Event code 706 (BTN_TRIGGER_HAPPY3)
    Event code 707 (BTN_TRIGGER_HAPPY4)
    Event code 708 (BTN_TRIGGER_HAPPY5)
    Event code 709 (BTN_TRIGGER_HAPPY6)
    Event code 710 (BTN_TRIGGER_HAPPY7)
    Event code 711 (BTN_TRIGGER_HAPPY8)
    Event code 712 (BTN_TRIGGER_HAPPY9)
    Event code 713 (BTN_TRIGGER_HAPPY10)
    Event code 714 (BTN_TRIGGER_HAPPY11)
    Event code 715 (BTN_TRIGGER_HAPPY12)
    Event code 716 (BTN_TRIGGER_HAPPY13)
    Event code 717 (BTN_TRIGGER_HAPPY14)
  Event type 3 (EV_ABS)
    Event code 0 (ABS_X)
      Value  32768
      Min        0
      Max    65535
      Fuzz     255
      Flat    4095
    Event code 1 (ABS_Y)
      Value  32767
      Min        0
      Max    65535
      Fuzz     255
      Flat    4095
    Event code 2 (ABS_Z)
      Value  32768
      Min        0
      Max    65535
      Fuzz     255
      Flat    4095
    Event code 5 (ABS_RZ)
      Value  32767
      Min        0
      Max    65535
      Fuzz     255
      Flat    4095
    Event code 7 (ABS_RUDDER)
      Value      0
      Min        1
      Max        8
    Event code 9 (ABS_GAS)
      Value      0
      Min        0
      Max     1023
      Fuzz       3
      Flat      63
    Event code 10 (ABS_BRAKE)
      Value      0
      Min        0
      Max     1023
      Fuzz       3
      Flat      63
    Event code 16 (ABS_HAT0X)
      Value      0
      Min       -1
      Max        1
    Event code 17 (ABS_HAT0Y)
      Value      0
      Min       -1
      Max        1
    Event code 40 (ABS_MISC)
      Value  32768
      Min        0
      Max    65535
      Fuzz     255
      Flat    4095
    Event code 41 (?)
      Value  32767
      Min        0
      Max    65535
      Fuzz     255
      Flat    4095
    Event code 42 (?)
      Value  32768
      Min        0
      Max    65535
      Fuzz     255
      Flat    4095
    Event code 43 (?)
      Value  32767
      Min        0
      Max    65535
      Fuzz     255
      Flat    4095
    Event code 44 (?)
      Value      0
      Min        0
      Max     1023
      Fuzz       3
      Flat      63
    Event code 45 (?)
      Value      0
      Min        0
      Max     1023
      Fuzz       3
      Flat      63
  Event type 4 (EV_MSC)
    Event code 4 (MSC_SCAN)
Key repeat handling:
  Repeat type 20 (EV_REP)
    Repeat code 0 (REP_DELAY)
      Value    250
    Repeat code 1 (REP_PERIOD)
      Value     33
Properties:
Testing ... (interrupt to exit)

Pressing the big button ‘A’:

Event: time 1538574732.484613, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90001
Event: time 1538574732.484613, type 1 (EV_KEY), code 304 (BTN_SOUTH), value 1
Event: time 1538574732.484613, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90010
Event: time 1538574732.484613, type 1 (EV_KEY), code 319 (?), value 1
Event: time 1538574732.484613, -------------- SYN_REPORT ------------
Event: time 1538574732.574441, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90001
Event: time 1538574732.574441, type 1 (EV_KEY), code 304 (BTN_SOUTH), value 0
Event: time 1538574732.574441, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90010
Event: time 1538574732.574441, type 1 (EV_KEY), code 319 (?), value 0
Event: time 1538574732.574441, -------------- SYN_REPORT ------------

So it is a bit less easy than with Ubuntu but we’ll get somewhere.

Bluetooth working

This post is part 3 of 6 of  Xbox Adaptive Controller

XAC working with bluetooth on my Ubuntu 18.04 laptop.

Only needed to edit ‘sys/module/bluetooth/parameters/disable_ertm’ replacing ‘N’ with ‘1’ or ‘Y’

After a few attempts of pairing my connection kept stable.

dmesg:

Bluetooth: HIDP (Human Interface Emulation) ver 1.2
Bluetooth: HIDP socket layer initialized
hid-generic 0005:045E:0B0C.0006: unknown main item tag 0x0
input: Xbox Adaptive Controller as /devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8:1.0/bluetooth/hci0/hci0:256/0005:045E:0B0C.0006/input/input23
hid-generic 0005:045E:0B0C.0006: input,hidraw3: BLUETOOTH HID v9.03 Gamepad [Xbox Adaptive Controller] on 34:f3:9a:88:60:7a
Bluetooth: hci0: last event is not cmd complete (0x0f)

a lot more of those hci 0x0f errors will keep appearing but connection holds.

Also got a ‘/dev/input/js0’ device but with much more Axles (15) and Buttons (31). But buttons seem duplicated – for instance the big round button ‘A’ is both Button 0 and Button 15 (previously it was only Button 0).

Nice!

Note 1: this workaround is not permanent.
Note 2: according to wikipedia, ERPM stands for ‘enhanced retransmission mode‘ and is ‘an improved version of retransmission and flow control modes’. Several posts related to using Xbox bluetooth controllers in linux suggest disabling it.

RTFM!

This post is part 2 of 6 of  Xbox Adaptive Controller

Great work Microsoft!

I now have 19 inputs that I can use with whatever I want.

Digital inputs are easy: just connect a switch. Any kind of switch, including LEGO RCX touch sensors.

But 4 of them can be also be analog… and no documentation at all to tell me what voltage levels I can use and if there is any kind of internal protection.