Upgrading to EV3 Python v2

This page is based on the 'official' upgrade page HERE. I have taken the contents of that page and tried to make them more digestible for beginner users. You should check the official page for information that may not have been copied to this page because it is too recent or because it is not appropriate for beginner users.

Cool new features

  • The new python library (version 2) includes some new motor classes such as MoveTank, and MoveSteering. These mirror the functionality of the Move Tank and Move Steering blocks in the standard Lego icon-based EV3 programming system, sometimes called EV3-G. The absence of MoveTank and MoveSteering in EV3 Python until now was a major weakness since these are amongst the most used blocks in traditional EV3 programing. Better still, the new functions will by default block program execution until the motor motion has completed so it is no longer necessary to include code to make the program wait.

  • In version 1 of the library you could only specify motor turn angles in degrees. In the new version you can specify rotations if you prefer. Similarly, the old version only accepted seconds as the time unit for motor rotation whereas now you can also use minutes if you wish, so you could request, for example, 100 revolutions per minute.

  • The new version has friendlier interfaces for operating motors and sensors: check out Motor.on_for_rotations() and the other on_for_* methods on motors.

  • For sensors, mode selection is now automatic, so you never need to set sensor modes as was necessary with version 1.

  • Easier interactivity via buttons: each button now has wait_for_pressed, wait_for_released and wait_for_bump.

  • There are similar and equally useful 'wait' features for sensors, such as touch_sensor.wait_for_pressed().

  • Improved Sound and Display interfaces.

  • New color conversion methods for the Color Sensor.
At the bottom of this page showing how a script made with version 1 looks much shorter and more legible in version 2.

Here's how to modify your old scripts to make them compatible with the new version:

Updating import statements

For the older Python library (v1), I recommended that beginner users should use the following import declaration for the EV3:
from ev3dev.ev3 import *

The new library (v2) has been designed to provide more control over what gets imported. For all platforms, you will now import from individual modules for things like sensors and motors, like this:

from ev3dev2.motor import Motor, OUTPUT_A
from ev3dev2.sensor.lego import TouchSensor, UltrasonicSensor

The platform (EV3, BrickPi, etc.) will now be automatically determined.

You can omit import statements for modules you don’t need, and add any additional ones that you do require.

I can see the benefit in only importing what is needed, but there is an obvious disadvantage to the new import format: it's much longer (more 'verbose') than the old one, which is unfortunate since a main feature of Python is meant to be that it is concise as opposed to verbose.

Remove references to 'connected' attribute

In version 1 of the library, to see whether a device such as the color sensor was correctly connected you would have to check its 'connected' attribute, usually in an 'assert' statement. With the new version, you will automatically get a useful error message if an expected device is not connected, so you do need to use the 'connected' attribute any more. In fact you MUST remove any references to the 'connected' attribute in your code.

'Screen' has been renamed to 'Display'

To match the name used by LEGO’s “EV3-G” graphical programming tools, we have renamed the 'Screen' to 'Display'.

Reorganization of RemoteControl, BeaconSeeker and InfraredSensor

If you have the home version of the EV3 kit then you have a remote control (also called a beacon) and an infrared sensor that are not included in the education version. Version 1 of the Python library referred to RemoteControl and BeaconSeeker classes. In the new library (v2) these have been integrated into the InfraredSensor class. Also, many of the properties on the InfraredSensor class have been renamed to make the meaning more obvious. Check out the InfraredSensor documentation for more info.

Re-designed Sound class

The names and interfaces of some of the Sound class methods have changed. Check out the Sound class docs for details.

Sample script comparison

This script is intended to make the robot drive forward until the touch sensor attached to a bumper detects a collision with an obstacle. The robot will then back up for two seconds and then stop.

Version 1

#!/usr/bin/env python3
from ev3dev.ev3 import *
from time import sleep

mB = LargeMotor('outB')
mC = LargeMotor('outC')
touch_sensor = TouchSensor()

# Start robot moving forward

# Wait until robot touches wall
while touch_sensor.value() == 0:

# Reverse away from wall for two seconds
mB.run_timed(time_sp=2000, speed_sp=-100)
mC.run_timed(time_sp=2000, speed_sp=-100)

# Wait for both motors to complete their motion

Version 2

#!/usr/bin/env python3
from ev3dev2.motor import MoveSteering, OUTPUT_B, OUTPUT_C
from ev3dev2.sensor.lego import TouchSensor

steer = MoveSteering(OUTPUT_B, OUTPUT_C)
touch_sensor = TouchSensor()

steer.on(steering=0, speed=10) # Start robot moving forward

touch_sensor.wait_for_pressed() # Wait until robot touches wall

# Reverse away from wall
steer.on_for_seconds(steering=0, speed=-10, seconds=2)

Comparing the two scripts, we see that the v1 script has 14 lines (not including bank lines or comments) and the v2 script has just 8 lines! That's already a huge improvement, but we notice many other improvements too, many of which make the script more legible or more similar to Lego's icon-based system, EV3-G:
  • in the v2 library we can use MoveSteering, for which there was no equivalent in the v1 library
  • we have neat code to make the script wait for the touch sensor to be pressed - we don't have to use a while loop for this
  • we don't have to include code to make the script pause (block) until the motors complete their motion since this is the default behaviour of on_for_seconds()
  • like in EV3-G, we give times in seconds rather than milliseconds for the motors to come on
  • on_for_seconds uses a speed parameter with allowed values -100 to +100, just like the power values in EV3-G. In version 1 the speed_sp values could be -1000 to +1000 or even larger numbers - it was never very clear what the maximum allowed values were. And the parameter name speed_sp was rather annoying, less concise than simply 'speed' and with an '_sp' ending then many users wouldn't even know the meaning of. It stands for 'setpoint' which means 'target', a reminder that just because you have requested a certain speed it does not mean the motor will instantly acquire that speed. Just like a car, it takes a finite time for the motor to reach the requested speed.
All in all, then, there a large number of improvements in version 2 of the library - I encourage you to adopt it immediately and I'm sure you will enjoy using it!

A Further Note on the Sample v2 Script Above

Note that the above arguments of on and on_for_seconds have been expressed as keyword arguments since the parameter names are given. Keyword arguments do not have to be given in order. The arguments can also be given without the parameter names, in which case they become positional arguments and must be given in the order above. For example, the last line could have been written:
steer.on_for_seconds(0, -10, 2)

You can even mix positional arguments and keyword arguments as long as you obey this rule: you can't put an argument where you specify the name (a keyword argument) before one where you don't (a positional argument).

So the last line could be written like this
steer.on_for_seconds(0, speed=-10, seconds=2)
but not like this
steer.on_for_seconds(steering=0, -10, seconds=2))

Probably the best approach, at least for beginners, is to include the argument names since this makes the script more clear.