Did you buy a new MINDSTORMS set, and is your EV3 brain catching dust? Time to pick it back up because you can use EV3 as a remote control device for your new hubs. Bluetooth and a few lines of Python do the trick.
In previous articles, I outlined how you could do remote control the other way around: SPIKE or Robot Inventor controlling the EV3 brick. At the time, I couldn’t figure out a simple way to control the new hubs over Bluetooth without too much lag. Today I figured I could use the raw REPL to do just that. It is a system I use in the Ultrasonic Sensor breakout board and for the OpenMV camera.
Bluetooth Classic RFCOMM for communication between EV3 and new hubs
There are a few obstacles for talking to the new SPIKE Prime and Robot Inventor hubs over Bluetooth:
- While the new hubs have booth Bluetooth Low Energy and Bluetooth Classic, the EV3 brick only supports Bluetooth classic.
- By default, the EV3 brick sets up an internet tethering connection over Bluetooth. To get a serial port – also known as virtual com port or RFCOMM – you need some lines of arcane Pybricks code.
# Original author: Pybricks from uctypes import addressof, sizeof from uctypes import struct as cstruct from usocket import socket, SOCK_STREAM from pybricks.bluetooth import ( str2ba, sockaddr_rc, AF_BLUETOOTH, BTPROTO_RFCOMM ) def get_bluetooth_rfcomm_socket(address, channel): # Create an empty byte array to fit a struct as defined in the sockaddr_rc dictionary addr_data = bytearray(sizeof(sockaddr_rc)) # Create c structure with the fields as in sockaddr, at the address of the empty array addr = cstruct(addressof(addr_data), sockaddr_rc) # Fill the rc_famiy field addr.rc_family = AF_BLUETOOTH # Fill the rc_bdaddr field with a string to bt address converson str2ba(address, addr.rc_bdaddr) # Fill the channel field. addr.rc_channel = channel # New socket sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM) # Connect the socket to the newly created address in memort sock.connect(addr_data) return sock
- Unlike a serial port with
write()methods, RFCOMM uses a socket with send() and recv().
- The new LEGO hubs are deep down some kind of Pyboards. But they use unconventional firmware. Normally you’d be free to use any serial protocol over Bluetooth or turn on the REPL using dupterm(). This is not the case with the LEGO firmware. The hubs spew telemetry over Bluetooth all the time, and you can’t turn off the REPL.
Working around these obstacles, I developed a script that stops the telemetry and sends Micropython commands all the time. Basically, it calculates everything on the EV3 side, 30 times per second. If the calculated motor power would be 73% duty cycle, the script will send a command like
Programming auto-centering control sticks on EV3
A minor challenge is to use the EV3 motors as control sticks. By default, they don’t auto-center. However, when driving a car, you expect the throttle to go to zero if you release it. You also expect the steering to return to the center if you let go.
To create this behavior, I have the motors return to zero using the `
track_target()` method. By default, track_target generates a lot of force. So I lowered the force using the motor settings.
m = Motor(Port.B) m.reset_angle(0) # Default: 400, 1200, 5, 23, 5, 0 for kp, ki, kd, integral_range, integral_rate, feed_forward m.control.pid(30, 0, 0, 23, 5, 0) while not ev3.buttons.pressed(): m.track_target(0)
Get the EV3 scripts as Visual Studio Code projects.
I developed two scripts that use the REPL system for remote control. One steers a simple tank, the other steers a car with a steering linkage system. I made no building instructions for the tank and the remote control because they are so simple. For the car, you can download building instructions on my website.
You can run the projects quickly via Visual Studio Code. Do this by opening a new window, clicking ‘Run a command…’ and ‘choosing Git:clone.’ VS Code will automatically suggest using the MINDSTORMS extension.
Let me know what you make!
Ask questions in the comments below or just post a link to the stuff you are making with this code. I’m looking forward to it!