This tutorial will show how to connect an I2C joystick to the LMS-ESP32 board and read that I2C sensor from the LEGO MINDSTORMS or SPIKE Prime hub. Many third-party sensors use that protocol, from langer range finders to IR matrix sensors, gesture recognition hardware, and humidity sensors. The LMS-ESP32 board will run some Micropython code to drive the sensor and respond to readout requests from the LEGO hub.
We assume you have set up and connected your LMS-ESP32 board to the LEGO hub for this tutorial. It also helps if you know your way around Thonny and the basics of UART communication with the board.
I2C devices and the LEGO MINDSTORMS hub
I2C is a protocol invented by Philips in the early ’80s using only two wires (clock and data) to establish a fully bi-directional communication line. It uses a bus topology, where a single master can drive multiple slaves on the same bus. Each slave on the bus must have a unique address.
The ESP32 has multiple I2C bus drivers, and we can assign them to almost any two pins. In the code snippet below, we assign driver 1 to pins 4 and 5. And we name the driver object ‘i2c’.
from machine import I2C, Pin i2c=I2C(1,sda=Pin(5), scl=Pin(4)) i2c.scan()
On our LMS-ESP32 board, pins 4 and 5 are wired to the white Grove port. Grove is a common standard with easy-to-connect GND, 3.3V, SDA, and SCL pins. The SDA and SCL pins are connected to GPIO5 and GPIO4, respectively.
i2c.scan() function, we can scan for I2C devices present on the bus. If you connect an I2C device, you should see an array with one or more addresses (some I2C sensors can have multiple addressable I2C devices).
I2C Joysticks from M5Stack
In this tutorial, we want to connect an I2C joystick. We then use the readings from that joystick to move a pixel on the LED screen of the Lego hub. There are many i2c joysticks, but we choose the M5Stack joystick. The M5stack units all come with LEGO-compatible attachment holes, and it has a handy Grove port.
Video tutorial for connecting the i2c joystick to LEGO MINDSTORMS and SPIKE Prime hub
Now that you have all hardware collected and set up, you’re ready for the video tutorial about connecting the I2C joystick to MINDSTORMS.
The pixel on the LEGO hub is not very visible in the video above. Therefore, the movement of the pixel has been recorded with slightly better light conditions below.
Code used in this tutorial
LMS-ESP32 code (joy_LMS_ESP.py)
from machine import I2C,Pin from uartremote import * # import UartRemote library ur=UartRemote() i2c=I2C(1,sda=Pin(5),scl=Pin(4)) # initialize I2C port as first hardware port # clock = Pin(4) and data = Pin(5) def read_joy(): q=i2c.readfrom(82,3) # read 3 bytes from I2C sensor at address 82 x=q # x coordinate is first byte y=q # y coordinate is 2nd byte button=q # button pressed results in value 1 in the final byte return x,y,button ur.add_command(read_joy,'repr') # add the command 'read_joy' for use by the SPIKE Prime ur.loop() # loop and wait for receiving 'read_joy' command
i2c.readfrom(82,3) we read 3 bytes from the I2C device at address 82. The joystick encodes the x-position (between 0 and 255) in the first byte, the y-position (between 0 and 255) in the second byte, and the status of the pressed button in the third byte (0 or 1).
LEGO Hub code (joy_SPIKE.py)
from projects.uartremote import UartRemote import hub import time hub.display.pixel(0, 0, 9) ur=UartRemote('D') # LMS-ESP32 is connected to port "D", change if otherwise def plot_pixel(x,y): hub.display.clear() hub.display.pixel(x,y,9) # plot pixel @ coordinate (x,y) with intensity 9 while not hub.button.left.was_pressed(): ack,joy=ur.call('read_joy') x_pixel=joy]//52 # joystick value between 0..255, x_pixel = 0..4 y_pixel=joy//52 # joystick value between 0..255, y_pixel = 0..4 plot_pixel(4-x_pixel,y_pixel) # mirror in x directorion: 4 - x_pixel time.sleep_ms(50) # sleep 50ms (~20 loops per second)
In this demo program, we use the
hub.display.clear() method to clear the display. Once the screen is clear,
hub.display.pixel(x,y,brightness) shows a pixel on position
(x,y). Since the joystick returns values between 0 and 255 and the screen needs pixel coordinates
(x_pixel,y_pixel) between 0 and 4, there are some calculations to do. In Python, the
// division results in integer numbers, no remainder, and no fractions. So
255 // 52 is 4, and
51 // 52 is 0.
Need more help with MicroPython, LEGO Hubs, and I2C joysticks?
This tutorial is part of a multi-part tutorial. First, we set up the hardware, then we explain communication; next, you’ll learn about controlling RGB LEDs and then about I2C joysticks. You can also load MicroPython modules dynamically with our library. And there are more libraries to come.
We’d love to see what you build, and maybe we can help you with some questions. Drop us a line on Facebook!