A LEGO EV3DEV iOS remote
Now LEGO has an iOS app that you can use as a remote. It is very good and lets you design your own controls. But to use it you need to be running the LEGO scratch interface. If you‘ve chosen to download ev3dev.org OS and your running that you need something else’.
But wait BEFORE you read on, be warned that the something else in this tutorial needs a Wifi connection. Something like LEGO recommended EDIMAX USB adaptor, without it this tutorial won’t work.
If you haven’t got a EDIMAX USB, go get one; trust me it will make you life easier, it isn’t expensive I find it on amazon for just $15.
Next you need the iOS app of course, here is a link to it. Although this is only half of the story, you also need to write some code your side. You are after all learning about robotics and coding, no. That is why you downloaded ev3dev.org image :) But wait, just before you start; watch the video here; this is what your building.
Lets make a start.
#!/usr/bin/env pybricks-micropython
from pybricks import ev3brick as brick
from pybricks.ev3devices import Motor, UltrasonicSensor, ColorSensor, GyroSensor, InfraredSensor
from pybricks.parameters import Port,Color
from pybricks.robotics import DriveBase
from pybricks.tools import print, wait, StopWatch
from time import sleep
import threading
import sysimport random
import socket
import os
In the above section we simply included all the libraries you’ll need to make this app work.
hostName = socket.gethostname()
hostIPA = socket.gethostbyname(hostName)
print("hostIP",hostIPA)
port = random.randint(50000,50999)
os.system('setfont Lat15-TerminusBold32x16')
print("host",hostIPA)
print("port",port)
Then you get the IP address of your robot and the port to connect to it. The app, remoteCode will ask you for this information when you run it.
online = True
currentPitch = 0
currentRoll = 0
lastPitch = 0
lastRoll = 0def nextMove(pitch, roll):
print("nextMove",pitch,roll)
global currentPitch
global currentRoll
global lastPitch
global lastRoll if currentPitch == 0:
currentPitch = round(pitch / 180 * 100,0)
currentRoll = round(roll / 720 * 100,0) # turns need to be slow and deliberate, this reduces roll by 4
return # convert values into percentages and make gradual change
newPitch = round((((pitch / 180 * 100) + currentPitch)/2),0)
newRoll = round((((roll / 720 * 100) + currentRoll)/2),0)
currentPitch = newPitch
currentRoll = newRoll
try:
if lastPitch != currentPitch or lastRoll != currentRoll:
joy_pair.on(currentRoll,currentPitch,radius=100)
lastPitch = currentPitch
lastRoll = currentRoll
except AssertionError as error:
print("oh foo bar",error)
pass
Next we define a sub route that will do the moving. A subroutine that will called within the main loop.
backlog = 1
size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((hostIPA,port))
s.listen(backlog)#print("here")
try:
client, address = s.accept()
while online:
data = client.recv(size)
command = data.decode('utf-8')
if data:
if command[:2] == "@:": # analog or motion co-ordinate stream
mCommands = command.split("\n")
for mCommand in mCommands:
if len(mCommand) != 0:
cords = mCommand[2:]
cord = cords.split(":")
try:
if cord[0].isnumeric and cord[1].isnumeric:
roll = float(cord[0])
pitch = float(cord[1])
joy_pair.on(roll,pitch,radius=100) except: # AssertionError as error:
pass # ignore corrupted data
except AssertionError as error:
print("Closing app socket",error)
client.close()
s.close()
exit()
And finally the main loop, which sets up a connect using sockets between your robot and the app and then interprets the data send back from it too make the robot move.
This code will work with either the motion or pad interfaces; it won’t work with the keyboard. I leave that for the reader to figure out.