Controlling LEGO hubs: a mqtt2pybricks gateway

This post is part 1 of 1 of  mqtt2pybricks gateway

We finally moved to a new home. Not an apartment on a 6th floor with dozens of crazy and noisy neighbors but a real house with a garden and a garage.

I also quit my job and I am taking a rest. So I finally have both time and opportunity to look into domotics.

I installed OpenHAB on a Raspberry Pi and started adding ‘things’ to get familiar with it. The first was a Nedis dehumidifier I bought a few months after moving – we moved to a place with its own micro-weather, lots of humidity, and my wife and the younger kid have allergies problems so I’m trying to keep humidity levels low.

Although the dehumidifier has builtin wi-fi we were using it just on manual mode but since it was easy to integrate with OpenHAB I started with it.

OpenHAB offers ‘bridges’ for several types of devices. This dehumidifier is a Tuya device so I added a Tuya bridge and found that I could read humidity and temperature values even when the dehumidifier was in standby mode (previously, to know the humidity level of the room I needed to turn it on to be shown on the display and just humidity, no temperature readings).

So I ordered two Tuya humidity+temperature sensors to monitor our bedroom and the #2 bedroom.

And then I added a older humidifier to OpenHAB through an also older wi-fi power plug. The humidifier has a ‘mechanic’ power switch so I left it always ON and control it from the power plug.

And then the third humidifier. But this one has a ‘digital’ power switch so you need to press it to turn it ON/OFF. And no builtin wi-fi. So a fingerbot-like gadget was needed. I chose a Switchbot Bot:

It is a Bluetooth BLE device, is supposed to be used with the SwitchBot Hub that works as a wi-fi to BLE gateway but I found a description of its API so used python to control it and created my own mqtt2switchbot gateway with a Raspberry Pi Zero 2W (using ‘bleak’ and ‘pahoo-mqtt’) and adding a MQTT broker to my OpenHAB server.

So I can control Bluetooth BLE devices from my domotics central.

And LEGO Hubs are BLE devices.

So the next obvious step was controlling LEGO from my domotics central 😀

Zynthian – an Open Synth Platform

So this MIDI thing keeps evolving.

The second revision of the LEGO Laser Harp is almost done and I was looking for a way to make it sound more like Jean-Michael Jarre. I found a site with lots of files related to his instruments including the Elka Synthex used on Rendez-Vous album.

Since ‘Yoshimi’ (and is ‘father’ ZynAddSubFX) is a software audio synth there is probably a way to configure it to generate the sounds of the Elka Synthex… but that’s not something I can do, would need to use other’s work (and found nothing, except that the file format is ‘.xiz’).

But that page had soundfonts. And since Fluidsynth and Timidity++ can use soundfonts I can use one of those soft synths instead of Yoshimi. But it would be like going back to the initial setup so I decided to try another option I already had found a few months ago: Zynthian.

Zynthian is based on the Raspberry Pi and is sold as a kit – a case, a few buttons or knobs, a sound card and a touchscreen. But it’s also ‘open’ so we can use it with our own devices and I already have the basic ingredients.

So I downloaded an image for my Raspberry Pi 4 and tried an headless setup with just a USB audio card. It worked… sort of… I could configure most of it from the browser except the “music instrument” itself, I needed to create a “layer” and choose a synth and couldn’t find how to do it from the browser.

I connected a screen to the HDMI port and a mouse to the USB port and used the GUI. And saved a ‘snapshot’ so I don’t need to do it again after a restart. And now it really works in headless mode.

I now have a MIDI synth that accepts ipMIDI over wi-fi and can use soundfonts. If this works good I might order a Hifiberry sound card and make a LEGO case for my Zynthian box.

Installing ‘bluepy’ on EV3

Another python BLE library – not the most maintained, certainly not the most trendy but at the moment the only one I managed to install and use on EV3 (running ev3dev of course): bluepy.

Short instructions:

  • start from a totally fresh ev3dev installation
  • enable Wi-Fi and Bluetooth (assuming you have a USB hub with a compatible Wi-Fi dongle and a compatible BLE dongle)
  • update:

sudo apt update
sudo apt upgrade
sudo apt dist-upgrade

  • install ‘pip’ and ‘bluepy’ requirements (~15 min):

sudo apt install python3-pip libglib2.0-dev libcap2-bin

  • update ‘pip’:

python3 -m pip install --upgrade pip

  • install ‘bluepy ‘at last (~25 min):

python3 -m pip install bluepy

  • give proper permissions:

sudo setcap 'cap_net_raw,cap_net_admin+eip' ~/.local/lib/python3.5/site-packages/bluepy/bluepy-helper

  • test it:

robot@ev3dev:~$ /home/robot/.local/bin/blescan
Scanning for devices…
Device (new): 90:84:2b:4b:bf:59 (public), -70 dBm
Flags: <06>
Tx Power: <00>
Incomplete 128b Services:
Complete Local Name: 'Pybricks Hub'

A few notes:

  • I used ‘ev3dev-stretch-ev3-generic-2020-04-10’ that’s the same version that LEGO EDECUATION calls ‘EV3 Micropython 2.0’ and already includes Pybricks
  • bluepy uses a “bluepy-helper” based on BlueZ’s gatttool, it has been deprecated and sooner or later will be removed from BlueZ stack
  • there are some known bugs in ‘bluepy’ that have been fixed in a fork, see ‘ble-serial‘ instructions on how to install it if you think it might help

this had been used with this script to control the Top Gear technic car after flashing the Control+ hub with Pybricks 3.0.0a firmware:

sometimes the script fails after establishing the connection with the Nordic UART Service, not sure why yet.

EV3 Code Pilot

This post is part 2 of 3 of  barcode

The first MINDSTORMS programmable bricks, the RCX, had several “incarnation”. Most people remember the yellow brick but there were several others, including the Code Pilot that used light sequences as commands. Those VLL codes could be printed as barcodes:

From ‘http://www.elecbrick.com/lego/’

and the Code Pilot set had a companion sheet with some codes and also key notes that could be used as a barcode piano.

So let’s try a simple set of instructions:

The barcodes are just EAN-13 code generated online from EAN-13 barcode generator. They all start with ‘560’ (the code for Portugal-based companies) and the remaining 12 digits are just 1/2/…/5 left padded with zeros. The last digit is the checksum code and is generated by the tool.

So my first program uses a nested dictionary with the EAN-13 codes paired with an action to be spoken. So the program waits for a barcode to be read, checks for the action to be spoken and execute the action we chose:

Source code:

https://github.com/JorgePe/ev3-barcode/blob/master/codepilot01.py

The code sheet used and further developments I might make are also at github:

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:

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).

The new LEGO Powered Up Remote Control

This post is part 1 of 2 of  LEGO Powered Up Remote Control

This week I got a question from Nathan Kunicki about using the BOOST Tacho Motor with the new Powered Up hub.

He already succeeded with the other WeDo 2 and BOOST devices so the motor was the last challenge. So I tried a few ideas but nothing.

I told him that probably the motor was not supported by the current firmware… and then he told me that when we use the new Remote it works (as if a WeDo 2 motor, just ON or OFF).

Well… my lovely wife just gave me this weekend my future birthday gift: the new LEGO Cargo Train. And it has a Powered Up remote so… let me try it.

No, we couldn’t find a way to control the motor. But I learned a bit about the Remote (thanks Nathan!) Enough to use it as a standalone BLE controller without the LEGO Powered Up “HUB NO.4″… it’s so easy that any BLE master can use it.

And, of course, the MINDSTORMS EV3 when running ev3dev:

to be continued…

 

Making an Android app for LEGO Powered Up – explanation

So how does this “App Inventor”-thing work?

To create an app for Android we just need a browser to access the online app creator tool. We have a Design view where we add our components like buttons and sliders and a Blocks view where we use the method blocks provided  by each component we added to our Design.

We can build our app and download an ‘apk’ file to install on our Android phone or tablet but that’s not practical while we are still testing some ideas and debugging the way our blocks work. So the best way is installing the MIT AI2 Companion App on our Android device so every action we make in the online tool is synchronized to it through USB or wi-fi.

App Inventor 2 provides a Palette with lots of usefull components but to use LEGO Powered Up we need to add an Extension that allows AI2 to talk with Bluetooth Low Energy devices. At the moment BluetoothLE is the only supported extension and I must say they have been doing a great work this last year (they even gave me access to a beta version a few months ago while fixing a bug I was dealing with) including writing a good explanation of all the blocks provided with some examples for Arduino and BBC micro:bit.

After importing the extension  we just drag it to the Viewer to get a ‘BluetoothLE1′ component at the bottom of the Viewer, on the “Non-visible components” area. Doesn’t seem much but if we change to Blocks view and look to this component we’ll see lots of blocks.

So let’s start creating our App!

We will use some BluetoothLE blocks to communicate with our LEGO “HUB NO.4” device. This blocks require a ServiceUUID and a CharUUID that we will store in global variables:

Currently the ServiceUUID and CharUUID are the same as LEGO BOOST hub but please note that there is no guarantee that future firmware releases will keep them allways equal.

We will also create a list of our devices:

Yes, a list of one device is silly but I have more devices like my BOOST Vernie and of course I’m planning to have a few more Powered Up devices in a near future so a list is usefull. You can call whatever you want to your devices but you need the Bluetooth address of it (so “PUP#1” is just an easy to remember tag that I choose for my “90:84:2B:06:AB:5D” hub).

You can get your BT address installing Nordic nRF Connect for Mobile app on your Android device and scanning nearby BLE devices while turning your LEGO hub on. If you changed its name with the LEGO App you will see a BLE device with that name, if not you will see “HUB NO.4” or “Smart Hub”, depending on the firmware version of your hub:

Now we go to Design View and add all components needed:

From the ‘User Interface’ section:

  • two buttons: ‘BtnConnection’ and ‘BtnRst’
  • one ListPicker

From the ‘Drawing and Animation’ section:

  • one Canvas
  • one ImgSprite

And from the ‘Sensors’ section:

  • one Clock

I added a few others that are really not needed, just used them for aligning and cosmetic purposes.  I also renamed the buttons names to better remember their purpose and changed some of their properties.

Now back to our Blocks view, we need to take care of what happens when our App starts:

We start a Bluetooth LE scan to find all BLE devices nearby. This is necessary later on when we want to connect to our LEGO device.

Then we create our list of Hubs (seen above), set the text of the Button used for the BLE connection, draw our Joystick at the center of the canvas and initialize our Clock.

This Clock will be used to keep the BLE connection active after we connect: we need to keep talking with the LEGO hub because after a pre-defined period without communication it will shutdown to prevent battery draining.

For now we just keep the clock disabled and set the period  to match the global variable “TRACKSPERIOD”.

We also define what happens when we click our ListPicker:

(we change the text to the friendly name of the chosen LEGO hub)

Now we define what happens when we click on our connection Button – we want it to connect to the device we chose whenever there is no connection yet and to disconnect when already is:

(we also activate or deactivate our Clock at the sametime)

I will not explain the blocks related to the Joystick – they are used to calculate the duty cycle (speed) of the two motors from the position of the joystick. These values are store in two global variables: ‘SpeedA’ and ‘SpeedB’.

The next important part is sending the calculated values to the motors.

The hexadecimal command used to control a WeDo 2 Motor (we should probably call it a “Powered Up Medium Motor) is:

0800810 p 115100 dt

where:

  • ‘p’ is ‘0’ if we are using ‘Port A’ and ‘1’ if using ‘Port B’
  • dt is the hexadecimal representation of the duty cycle (a percentage value)

The AI2 BuetoothLE extension uses a list of decimal values so

8 0 129 0/1 17 81 0 dt

Lucky for us the extension also accepts signed or unsigned values so we don’t need to take care of the conversion when duty cycle is negative:

so every time the Clock reaches our “TRACKSPERIOD” value it sends the commands for the two motors. Setting a smaller period allows a better control but also increases the activity of the App so for too small periods it might not work properly. And, of course, setting a larger period will increase the latency of our control and might also cause our connection to drop.

Hope this explanation is clear enough for anyone that wants to try their own app. Feel free to make questions on my YouTube channel, I’ll try to answer the best I can.

Making an Android app for LEGO Powered Up

The new LEGO trains are now Powered Up based.

Like WeDo 2 and BOOST, this is a Bluetooth 4 Low Energy (BLE) device that uses the new type of 6-pin plug that LEGO announced a couple of years ago with the WeDo 2. At that time this new design was referenced as Power Functions 2 or PF2 but the final name is now Powered Up.

Unlike BOOST, the new smart hub included with the trains doesn’t include motors. LEGO found a way to arrange 6 AAA batteries inside it in such a compact way that the final size is exactly the same of the Power Functions LiPo or AAA batteries… with all the new electronics included:

Others like Sariel and Hispabrick already reviewed this device so I’ll just show how to to use it.

This new hub announces itself as “HUB NO.4”.  It will probably have a much better name but for now I will call it this way.

A good thing with “HUB NO.4” is that it  provides the same UUID services as BOOST. So most of the examples I wrote for BOOST work with Powered Up with just a few modifications.

For instance, the LEGO WeDo 2 motors can be used the same way as with BOOST:

gatttool -b 90:84:2B:06:AB:5D --char-write-req --handle 0x0e --value 0800810011510060

The handle (“0Eh”) is the same. The payload is also simillar, with the same 3 initial bytes (“080081”, hexadecimal) followed by a fourth byte that selects the output port (“00” = port A, “01” = port B), followed by the same 3 bytes (“115100”) and finally the last byte is the duty cycle (or speed) applied to the motor (“60h” = 100d = 100%).

Since I already had an Android app made with MIT App Inventor 2 for the  Vernie model of the BOOST set I made just a few modifications to make it work with “HUB NO.4”:

  • removed the blocks that controlled the head and cannon trigger
  • removed the blocks that sensed the colors
  • added the BT address of my “HUB NO.4” to the list of devices to pick
  • changed the motor commands used by BOOST (simultaneous control of pair A+B) by the motor commands of two WeDo 2 motors

That’s it!

This the Designer view:

and this is the Blocks view:

If you’re interested, I exported the project as an “.aia” file. It’s not polished (for instance the blocks still make references to Vernie) but you get a good base to start.

In my next article I try to explain how this App was created.