How to connect Bluetooth gamepad to the LEGO hub directly using a word blocks program.


Updated on:

In this article, you’ll learn how to connect a Bluetooth gamepad to the SPIKE Prime or Robot Inventor hub without lag but with Word Blocks/Scratch. We use an extra piece of hardware, the LMS-ESP32, to convert the Bluetooth signals to a LEGO LPF2 sensor format.

Bluetooth Gamepad as a LEGO sensor in Word Blocks

In a previous post, we showed how to connect a PS4 or Nintendo gamepad to the new LEGO Robot Inventor or SPIKE Prime hubs using Python on the LEGO hub. That post gives some background on the different types of Bluetooth supported by LEGO hubs.

In this how-to guide, we use the  LMS-ESP32 board flashed with a new firmware that presents the LMS-ESP32 board as a standard sensor. We ‘fool’ the Large Hub into thinking it is a LEGO Distance sensor. The name of this specific firmware is Bluepad32. It is open-source and Arduino-based.

Next, we created several MyBlocks to read the two analog joysticks, the D-Pad, and all the buttons on a gamepad. And there is more! We have experimental support for driving NeoPixel LEDs and Servo motors connected to the LMS-ESP32 from the Word Block environment. Read about this near the end of this blog.

Hot Rod controlled by lag-less Bluetooth Gamepad in Word Blocks

The video below shows the Hot Rod model controlled by a Nintendo Gamepad. A PS4 gamepad works too. The program runs on the LEGO hub and is written in Word Blocks.

After powering on the LMS-ESP32, the Nintendo gamepad needs to be paired using the small pairing button. Once the pairing is done, the car receives gamepad data, and you can drive around the room! Read on for step-by-step instructions to set this up.

Step-by-step guide for programming Gamepad direct link in LEGO Word Blocks

This guide explains how to set up a lag-less direct gamepad connection to the LEGO Robot Inventor or SPIKE Prime hub, programmed with Scratch / Word Blocks.

  1. Build the Hot Rod or any other contraption that you want to remotely control

    We build the Hot Rod model in this example.

  2. Flash your LMS-ESP32 board with the BluePad32-LMS firmware

    Head over to the Web-based LMS-ESP32 installer. Connect the USB port of your LMS-ESP32 to your PC, select “BluePad32 for LMS word blocks projects” and select ‘CONNECT’. You can flash the Micropython firmware back at any time using the same web-based esp32 flash tool.

  3. Connect the LMS-ESP32 board to the LEGO hub

    In this example, we assume that you connect the LMS-ESP32 to Port D of the LEGO hub

  4. Obtain the LMS words block program

    Download the Hot Rod Word Block Program and open the program in the MINDSTORMS Robot Inventor app.
    The main program looks like this:

    The forever loop calls the gamepad MyBlock with the LMS-ESP32 port as a parameter. This MyBlock refreshes the two variables gp_x and gp_y with the values of the analog joystick of the gamepad. These values range from -512 to 512.
    In this program, below the main loop, you will find the definitions of the various MyBlocks that we defined for getting the GamePad to work.

  5. Connect the GamePad to the LMS-ESP32

    Depending on the type of GamePad you use, you will have to connect the gamepad by pressing a pairing button. Once you have connected the gamepad, a distance sensor will show up that is connected to port D. The preview of the MINDSTORMS app shows only positive values of the x-direction. By moving the analog joystick to the right, you should see the ‘distance’ increase.

  6. Run the program

    You can run the program now and control the vehicle with the analog joystick of the gamepad.

How the Bluetooth gamepad Word Blocks template works

The MINDSTORMS word block environment does not allow for low-level reading of a LEGO Sensor. We provide a BluePad32 Word Blocks template that implements all the MyBlocks needed for working with the BluePad32 firmware. The template contains a simple test main loop. You can replace the loop with your own main loop. In MINDSTORMS Word blocks you can not copy MyBlocks from one program to the other, consequently, we use a template program from which you can start your own implementation.

Gamepad MyBlock

The gamepad MyBlock reads the gamepad status in the global variables gp_x, gp_y, gp_rx, gp_ry, gp_buttons and gp_dpad.  When the port-parameter is left empty, the default port will be Port A.  Otherwise, use a single character A-F to configure the port to which the LMS-ESP32 is connected.
The table below shows the definition of the global gamepad-related variable.

VariableMode, wordDescription
gp_xM0, word 0Gamepad left axis X
gp_yM0, word 1Gamepad left axis Y
gp_rxM0, word 2Gamepad right axis x
gp_ryM0, word 3Gamepad right axis y
buttonsM0, word 4Button status
A=2, B=1, X=8, Y=4,
left shoulder=16, right shoulder=32,
left trigger=64, right trigger=128
analogue left stick= 256,
analog right stick=512
dpadM0, word 5Dpad status
up=1, down=2, right=4, left=8

When multiple keys are pressed simultaneously, the value read from the button or dpad variables is the sum of the corresponding values of the buttons pressed. Since there is no Bitwise or operator in Word Blocks, we added a MyBlock to check for a specific key pressed.

NeoPixels and Servo motor MyBlocks (experimental)

Up to 4 servo motors can be connected to the LMS-ESP32 on GPIO ports 21,22,23 and 25. A NeoPixel array can be connected to the default GPIO pin 12.
The servo motors and NeoPixels can be controlled by the above MyBlocks. Below we describe each of the MyBlocks.


This MyBlock needs to be called once at the start of your program, only if you are using servo’s and/or neopixels. The MyBlock initializes the byte arrays and global variables needed for communicating with the LMS-ESP32.


Every time a change needs to be communicated to the LMS-ESP32 with regards to servo’s or neopixels, this function needs to be called. When the port parameter is left empty, the default port will be Port A.  Multiple changes to the neopixels can be accumulated before calling this function.


This MyBlock sets the values (0-180) for the servo’s S1, S2, S3, and S4 which are connected to GPIO21, 22, 23, and 25, respectively. After calling this MyBlock, the send_servo_neo(port) MyBlock needs to be called.


Initializes num NeoPixels connected to GPIO Pin pin. By default, an array of 64 neopixels is defined at GPIO12.


This MyBlock sets all NeoPixels to the value (0,0,0), effectively switching them off. To effectuate this command, it should be followed by a call to send_servo_neo(port).


This MyBlock sets the values for NeoPixel number nr to  r,g,b. Only after calling the send_servo_neo(port) MyBlock, the new values are passed to the LMS-ESP32.  Multiple neopixels can be set before calling send_servo_neo(port) function. To show the newly set NeoPixels, the function neopixel_show should be called, again followed by a call to send_servo_neo(port).


This MyBlock lets the LMS-ESP32 show the new values of the NeoPixels. A call to this MyBlock should be followed by a call to send_servo_neo(port).

Debug MyBlocks

In the MINDSTORMS robot inventor app, a special debug mode can be enabled. This also gives access to 4 so-called Debug Blocks. You can read how to enable debug mode on the GitHub page of Maarten Pennings.
We use the following 3 debug Blocks:

Debug blocks that can be accessed from debug mode

The first Blocks reads the n-th raw value of the sensor from the specified mode. Each sensor can have multiple modes. In the BluePad32-LMS firmware, we emulate a single sensor in a single mode.
The second Block allows sensing data – this can be an array of values – to the specified mode M0 of the sensor.
The third Block switches between modes of a sensor. This needs to be called prior to reading or sending values from another mode than the last one used.

Implementation of gamepad MyBlock using debug Blocks

Using the Debug Blocks for reading raw values of a sensor we fill global variables according to the status of the GamePad. Below the MyBlock definition is shown.

Each of the global variables is filled with the value read from mode M0 of the sensor with a mapping of the specific word to the variable as shown in the table above.

Like this article? Help us make more!

Your support matters

We appreciate your support on Patreon and YouTube! Small things count.

Become a Patron

Don't miss a thing

Subscribe below to get an email when we publish a new article.

Share this with someone who needs to know

8 thoughts on “How to connect Bluetooth gamepad to the LEGO hub directly using a word blocks program.”

  1. Hi Anton,
    Is the source code for the “BluePad32 for word blocks” firmware available somewhere?
    I want to recompile it with a newer version of BluePad32 because the current version doesn’t support PS3 controllers.
    Thanks in advance

    • Hi Sandor,
      sure, the source code can be found in this Github repository. I recently moved from the idf-based build to a native Arduino environment, as described in the
      Use the latest BluePad32 Arduino library with the .ino file in the BluePad32_LPF2 directory and you should be fine. Let me know whether you succeed building your own firmware.

  2. Thanks! It works like a charm with the current (v3.7.3) version of Bluepad32.
    Now I’m trying to implement the communication the other way around: trigger a callback from word blocks to use the controller’s rumble function.

    • Once you get it fully working, could you send pull requests to our original project on github, or send a link to your own github project, so that we all can learn from your changes?


Leave a Reply

Item added to cart.
0 items - 0.00