Programming Lego Mindstorms EV3 with Python

Lego EV3

In our educational makerspace, our team has promoted the python programming language with young makers.   The python programming language has engaged students young and old for many reasons.   The language tends to be approachable and concise.   The language connects to a broad range of situations including Minecraft programming, Raspberry Pi, video game programming, and web development.   Software professionals love this language too!  Python is one of the most popular programming environments at Google!   

Lego Mindstorms have become a common tool for introducing students to robotics, sensors, and computational thinking.   I had heard that the Lego Mindstorm EV3 platform was based on Linux.   I started looking into ways that you could program Mindstorm robots using python and linux.  

There’s an amazing community of Linux/Lego hackers who have created a platform to fill this need.   Check out http://www.ev3dev.org/ .   All that you need to add to your Lego Mindstorm ev3 is a small wifi dongle, a microsd card and a way to write to it.    Here’s some tutorials to help you get started with installing the “ev3dev” environment and setting up Wifi.   Please keep in mind that using the “ev3dev” environment is completely reversible.    Just take out the microsd card from your “ev3.”

Here’s a sample program to give you a taste of programming “ev3” using python.   Using this small program, the user can control an ev3 robot using the keyboard.

 

 


import time
import termios
import tty
import ev3dev.ev3 as ev3
import sys

motor_left = ev3.LargeMotor('outB')
motor_right = ev3.LargeMotor('outC')
motor_a = ev3.MediumMotor('outA')

#==============================================

def getch():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)

return ch

#==============================================

def fire():
motor_a.run_timed(time_sp=3000, duty_cycle_sp=100)

#==============================================

def forward():
motor_left.run_direct(duty_cycle_sp=75)
motor_right.run_direct(duty_cycle_sp=75)

#==============================================

def back():
motor_left.run_direct(duty_cycle_sp=-75)
motor_right.run_direct(duty_cycle_sp=-75)

#==============================================

def left():
motor_left.run_direct( duty_cycle_sp=-75)
motor_right.run_direct( duty_cycle_sp=75)

#==============================================

def right():
motor_left.run_direct( duty_cycle_sp=75)
motor_right.run_direct( duty_cycle_sp=-75)

#==============================================

def stop():
motor_left.run_direct( duty_cycle_sp=0)
motor_right.run_direct( duty_cycle_sp=-0)

#==============================================

while True:
k = getch()
print(k)
if k == 'w':
forward()
if k == 's':
back()
if k == 'a':
left()
if k == 'd':
right()
if k == 'f':
fire()
if k == ' ':
stop()
if k == 'q':
exit()

In my case, I added a “wifi” module to my “ev3” while using ev3dev. This enabled me to use a secure shell terminal to access the “ev3” Linux environment. This program was saved in a python script called “robot_control.py” To execute the program, I simply type the following command into the Linux prompt.

python robot_control.py

Let’s break down this program into parts. In the following section, we import some code and setup variables to access the various motors of the “ev3” brick.

import time
import termios
import tty
import ev3dev.ev3 as ev3
import sys

motor_left = ev3.LargeMotor(‘outB’)
motor_right = ev3.LargeMotor(‘outC’)
motor_a = ev3.MediumMotor(‘outA’)

In the following function, we grab one character from the keyboard.


def getch():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)

return ch

To move the robot forward and backward, I use the following functions. There are similar functions for turning the robot, firing a marble gun and stopping.


def forward():
motor_left.run_direct(duty_cycle_sp=75)
motor_right.run_direct(duty_cycle_sp=75)

def back():
motor_left.run_direct(duty_cycle_sp=-75)
motor_right.run_direct(duty_cycle_sp=-75)

In the main loop of the program, we ask for one character from the user. Based on this input, the system executes different functions in the program. The robot follows the following protocol for movement:

w : move robot forward
s : move robot back
a : turn robot left
d : turn robot right
space bar : stop the robot
f : fire the marble gun.
q: quit the program.


while True:
k = getch()
print(k)
if k == 'w':
forward()
if k == 's':
back()
if k == 'a':
left()
if k == 'd':
right()
if k == 'f':
fire()
if k == ' ':
stop()
if k == 'q':
exit()