LEGO Air Drums

This is a quick holiday project.

I had some LEGO Move Hubs with me with a new Pybricks firmware image and a new version of ‘pybricksdev’ python library that works with them.

Move Hub has an internal IMU sensor. And batteries. And wireless communication. So I could make a kind of wireless game controller.

But Facebook keeps hitting me with ads of wireless MIDI drumsticks. I can do this with LEGO:

It wasn’t difficult – the Pybricks script is very short, inspired on an Arduino project from Andrea Richetta (‘Air Drum with Arduino Nano 33 IoT‘) – I just calculate the size of the acceleration vector (in fact it’s square since Move Hub doesn’t support float numbers so no complex math functions) and print something out whenever it changes ‘suddenly’:

from pybricks.hubs import MoveHub
from pybricks.tools import wait

ACC_THRESHOLD = 170
ACC_MARGIN = 50
TIME = 40
KEY = '1'

hub = MoveHub()
max_v = 0

while True:
    x,y,z = hub.imu.acceleration()
    v = x*x+y+y+z+z
    
    if v > ACC_THRESHOLD:
        max_v = v
    elif v < max_v-ACC_MARGIN:
        print(KEY)
        max_v = 0
        wait(TIME)

Then I just used ‘pybricksdev’ library in a pyhton script on my laptop to capture the output of the Move Hub and redirect it with ‘xdotool’ to a MIDI controller (VMPK) that generates MIDI events usable by Hydrogen (a MIDI drum engine).

I could have used something on python to directly generate the MIDI events instead of using VMPK… but I’m a lazy guy on holidays (or call it ‘Agile’ 😀 )

So I finally made a kind of tutorial:

All the source code available at github as usual.

Committed to Pybricks

So I committed 2 files to the Pybricks project:

not really to the project code but with a demo project that shows how to use the new ‘getchar’ function to pass commands from the Pybricks Chrome IDE to the hub in runtime.

getchar‘ works like the standard ‘input’ function but is doesn’t wait for ENTER so it is non-blocking. I already used ‘input’ to send commands to the Top Gear Rally Car and from the ‘client’ side (my EV3 python script) the only difference is not having to send a carriage return any more but from the hub side the responsiveness of the code should be now much better.

from pybricks.experimental import getchar

while True:
    c = getchar()
    if c == ord('a'):
        print('You pressed a! Now drive forwards...')
    elif c == ord('b'):
        print('You pressed b! Self destruct in 3, 2, 1...')

Another advantage of ‘getchar’ is allowing me to use Nordic nRF Toolbox UART tool to send commands to the hub:

The tool always send a termination code (we can choose LF / CR / CR+LF) but now ‘input’ considers it as just another character.

The usual companion video: