Learn EV3 Python‎ > ‎

Using Motors

This page does not describe all the available motor functions, only those of most interest to beginner EV3 Python programmers. For full descriptions see the official documentation.

There are big improvements to the motor functions in the new (version 2) EV3 Python library. Improvements include:
  • the introduction of MoveSteering and MoveTank functions that mimic the functionality of the Move Steering and Move Tank blocks in the standard Lego EV3 icon-based system, sometimes called EV3-G.

  • a whole series of new 'on' functions that are like the 'run' functions of the v1 library, but better. Because the 'on' functions are superior, you should use them rather than the 'run' functions, even though the 'run' functions are still available (at least for now...). Since the 'run' functions are inferior they will not be used on this site, though the old site focused on EV3 Python library v1 does describe the 'run' functions.

  • With the new functions it is possible to supply angle values in rotations as well as degrees, and time values in minutes as well as seconds. For example, you can request that a motor should turn at 10 rotations per minute.

  • The new library has a wait_until_not_moving() function for single motors which could be useful, for example, to detect whether gripper arms that are closing around an object have stopped moving (you would not know exactly what value of angle or time to use to make the arms close).

  • The new 'on' functions make the program 'block' (pause) until the motion has completed before continuing, which is the same behavior as the motor blocks in EV-G, and almost always what you want. If you don't want the function to block the program, that's an option too.

Common parameters used by the 'on' functions

speed

Most methods which run motors will accept a speed argument. speed is an integer which represents the percentage of the rated maximum speed of the motor. For example, if you set speed to 50 then the motor will run at 50% of its rated maximum speed (for functions that control two motors speed refers to the faster motor).
  • The rated maximum speed of the Lego EV3 large motor is 1050 degrees per second
  • The rated maximum speed of the Lego EV3 medium motor is 1560 degrees per second.
  • Motors are normally incapable of reliably and accurately achieving their rated maximum speed so you should not use speed values greater than 90.
  • In the official documentation you will often see references to 'tacho counts per second' but for the Lego EV3 motors this is simply the same as degrees per second.

As stated earlier, speed represents the percentage of the rated maximum speed of the motor. Therefore if a large motor and a medium motor are both set to speed=50 then they will run at different speeds. The large motor will run at 50% x 1050 = 525 degrees per second and the medium motor will run at 50% x 1560 = 780 degrees per second. It is also possible to specify speeds in degrees per second or rotations per second or degrees per minute or rotations per minute - for all these cases the large and medium motors will rotate at the same speed if you give them the same value e.g. 100 degrees per second. The way this works is that you supply the desired value e.g. in degrees per second and a function converts that into the corresponding speed value. For example SpeedDPS() converts a value in degrees per second into the corresponding speed value. The following script demonstrates the use of these conversion functions. Notice that these conversion functions have to be imported before they can be used in the script, as shown below. 

#!/usr/bin/env python3
from ev3dev2.motor import LargeMotor
from ev3dev2.motor import SpeedDPS, SpeedRPM, SpeedRPS, SpeedDPM
from time import sleep

lm = LargeMotor()

'''
This will run the large motor at 50% of its
rated maximum speed of 1050 deg/s.
50% x 1050 = 525 deg/s
'''
lm.on_for_seconds(speed = 50, seconds=3)
sleep(1)

'''
speed and seconds are both POSITIONAL
arguments which means
you don't have to include the parameter names as
long as you put the arguments in this order 
(speed then seconds) so this is the same as
the previous command:
'''
lm.on_for_seconds(50, 3)
sleep(1)

'''
This will run at 500 degrees per second (DPS).
You should be able to hear that the motor runs a
little slower than before.
'''
lm.on_for_seconds(speed=SpeedDPS(500), seconds=3)
sleep(1)

# 36000 degrees per minute (DPM) (rarely useful!)
lm.on_for_seconds(speed=SpeedDPM(36000), seconds=3)
sleep(1)

# 2 rotations per second (RPS)
lm.on_for_seconds(speed=SpeedRPS(2), seconds=3)
sleep(1)

# 100 rotations per minute(RPM)
lm.on_for_seconds(speed=SpeedRPM(100), seconds=3)

brake

Brake is a Boolean parameter, which means it can be either True or False. If it is True then once the motor completes its motion the motor will actively try to keep the motor in a fixed position. If brake is False then once the motor completes its motion the motor will coast gradually to a stop, slowed only by friction. brake is always True by default. brake is a keyword argument (a 'kwarg') so you do not need to include it in your motor command but if you do include you must include the name as well as the value, for example brake=False.

block

'Blocking' a program means making program execution pause until the current command has completed. Many v2 motor commands have a 'block' argument, and in almost every case block=True by default. The exception is the on() function, for which block=False by default. block is a keyword argument and therefore you do not necessarily have to include it in your code to run the command. If you don't include block= False then the default value block=True will be used (except for the on() function, for which block = False by default).

'on' functions to control a single motor

You may want to make one or more motors turn at a given speed
  • through a given angle
  • for a given time
  • 'forever' (until the motor is stopped by an off() command later during program execution)
  • until it stops moving (such as when a gripper closes on an object)
  • to a given position
  • until some other state is reached

Turn a single motor through a given angle
Use one of these:
on_for_rotations(speed, rotations, brake=True, block=True)
Rotate the motor at speed for rotations.
Example: turn on the single motor for 5 rotations at 50% of its rated maximum speed:
on_for_rotations(speed=50, rotations=5)
The names of positional arguments do not have to be given provided the arguments are given in the correct order and that you never put an un-named argument after a named argument, so this is the same as the above:
on_for_rotations(50, 5)
To make your scripts as clear as possible it is probably a good idea to include the names, as I normally do on this site.

As previously explained, speed is an integer percentage of the rated maximum speed of the motor. Conversion functions are available to convert units such as degrees per second into the corresponding speed value, as explained above. Example: to rotate the single motor for 5 rotations at 500 degrees per second:
on_for_rotations(speed=SpeedDPS(500)rotations=5)
Don't forget to import the conversion function before you use it, as shown in the first script on this page.

As previously mentioned, you don't need to include the keyword arguments brake and block if you want to use their default values True and True, as will normally be the case.

on_for_degrees(speed, degrees, brake=True, block=True)
Rotate the motor at speed for degrees.
Example: rotate the single motor for 90 degrees at 80% of rated maximum speed:
on_for_degrees(speed=80, degrees=90)

Run a single motor for a given time
on_for_seconds(speed, seconds, brake=True, block=True)
Rotate the motor at speed for seconds
Example: run the motor at 40% of the rated maximum speed for 3 seconds:
on_for_seconds(speed=40, seconds=3)

Run a single motor 'forever'
on(speed, brake=True, block=False)
Rotate the motor at speed 'forever'
Example: to turn on the motor at 45% of the rated maximum speed:
on(speed=45)

Stop a single motor

You'll often need this to turn off the motor that you have turned on 'forever' with on().

off()

Run a single motor until it stops moving

A good example would be when the arms of a gripper close around some object. You can't know exactly what angle or what time that motion corresponds to.
wait_until_not_moving()
This command would normally be issued after an on() command, as in this example. Just grab the moving wheel to stop it and the script will terminate.
#!/usr/bin/env python3
from ev3dev2.motor import LargeMotor, OUTPUT_B

large_motor = LargeMotor(OUTPUT_B)

large_motor.on(speed=50)
large_motor.wait_until_not_moving()

Turn a single motor to a given position

on_to_position(speed, position, brake=True, block=True)
It's important to realize that the position (angle) is on an infinite scale and that the motor will therefore turn in a predictable sense. For example, if the motor is at the 1° position and is instructed to go to the 359° degree position then it will turn in the positive direction through 358°. Don't argue that the initial and final positions are just 2° apart - they are 358° apart. If the motor is in position 180° and you instruct it to go to -540° then it will rotate 720° (two rotations) in the negative direction - it will end up in the same physical position as before it moved but it is now 'officially' at the new position of -540°.

As of October 2018 there may be a bug in the above command in that if you instruct the motor to turn to the position that it is already in then the program will freeze instead of just moving to the next instruction.

Run a single motor until some other state is reached

For other functions for single motors please see the official documentation.

'on' functions to control a motor pair

This group of functions includes the very important MoveSteering and MoveTank functions.

Just like for the Lego EV3 icon-based system, the MoveTank functions control two motors based on a left_speed value and a right_speed value.

Just like for the Lego EV3 icon-based system, the MoveSteering functions control two motors based on a steering value and a speed value (EV3-G calls speed 'power'). It's a bit more difficult to explain the meaning of these parameters, compared to the parameters of MoveTank. The steering value controls the path of the robot and can be any value between -100 and +100.
  • -100 means turn left on the spot
  • -50 means turn left with the left wheel not turning
  • 0 means go straight
  • +50 means turn right with the right wheel not turning
  • +100 means turn right on the spot
The speed value refers to the speed of the faster wheel (sometimes the wheels may be equally fast, such as when steering = 0). The speed of the slower wheel is automatically calculated based on the steering and speed values.

This chart may help you understand the relationship between MoveTank and MoveSteering. It is intended to show what values of left_speed and right_speed (the MoveTank parameters) correspond to all possible values of steering and a speed value of 40 (the MoveSteering parameters).


  • For all values of steering (-100 to +100) there is always at least one motor with a speed equal to the speed value, 40.
  • When steering=0 we note that left_speed and right_speed are both equal to speed, which is 40.
  • When steering=25 we note that left_speed=40 and right_speed=20.
  • When steering=50 we note that left_speed=40 and right_speed=0.
  • When steering=100 we note that left_speed=40 and right_speed=-40.
Before you can use these MoveTank and MoveSteering functions you must import them and you must define the motor pair. By default these functions will work with the Lego EV3 large motors and you don't need to import LargeMotor to use these functions with a pair of large motors. The following uses sensible names for the pairing of large motors:
steer_pair = MoveSteering(OUTPUT_B, OUTPUT_C)
tank_pair = MoveTank(OUTPUT_B, OUTPUT_C)
I recommend that you do not use names like drive_pair otherwise when you come across code like drive_pair.on_for_seconds(50,50,3) you won't know from that whether this is a steering command or a tank command - the movements would be very different.

You can also use the functions with a pair of medium motors but in that case you need to import MediumMotor. You also need to specify in the pairing that you are using medium motors like this:
tank_pair= MoveTank(OUTPUT_B, OUTPUT_C, motor_class=MediumMotor)

Here is a full script using a pair of medium motors:
#!/usr/bin/env python3
from ev3dev2.motor import MediumMotor, MoveSteering, OUTPUT_A, OUTPUT_D
from time import sleep

steer_pair = MoveSteering(OUTPUT_A, OUTPUT_D, motor_class=MediumMotor)

steer_pair.on_for_seconds(steering=0, speed=50, seconds=2)

You must use a matching pair of motors, so you can't pair a large motor with a medium motor.

Move Tank for a given angle

Use either on_for_rotations() or on_for_degrees().

on_for_rotations(left_speed, right_speed, rotations, brake=True, block=True)
Rotate the motors at left_speed and right_speed for rotations. Like for the speed parameter that is used with single motors, left_speed and right_speed are integer percentages of the rated maximum speed of the motor. Like for speed, you can use conversion functions like SpeedDPS() which converts degrees per second into the corresponding left_speed or right_speed.

If left_speed is not equal to right_speed (i.e. the robot will turn), the motor on the outside of the turn (the one with the faster speed) will rotate for the full rotations while the motor on the inside will have its number of rotations calculated according to the expected turn.

Example:
tank_pair = MoveTank(OUTPUT_B, OUTPUT_C)
# drive in a turn for 10 rotations of the outer (faster) motor
tank_pair.on_for_rotations(left_speed=50, right_speed=75, rotations=10)

Since these are positional arguments the names are optional so the same command can be written
tank_pair.on_for_rotations(50, 75, 10)
but it's probably better to include the names for clarity.

on_for_degrees(left_speed, right_speed, degrees, brake=True, block=True)
Rotate the motors at left_speed and right_speed for degrees. The only difference between on_for_rotations() and on_for_degrees() is that one uses rotations and the other uses degrees.

Move Tank for a given time

on_for_seconds(left_speed, right_speed, seconds, brake=True, block=True)
Rotate the motors at left_speed and right_speed for seconds.

Move Tank 'forever'

on(left_speed, right_speed)
Start rotating the motors according to left_speed and right_speed forever.

Stop the motors

off(brake=True)
Stop both motors immediately.

Example script

Make the robot move forward in a straight line until a touch sensor attached to a bumper is pressed, then stop both motors. Note that 'is_pressed' is not a function, so it does not need parentheses.  Note that it is not appropriate to use ts.wait_for_bump() here because when the bumper collides with an object that is a 'press' on the touch sensor rather than a 'bump' (a press and release). Finally, notice also that after the motors are turned off the brake will act on them for 5 seconds, during which time they will be very hard to turn by hand, whereas after the program terminates they will be much easier to turn.

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

ts = TouchSensor()
tank_pair = MoveTank(OUTPUT_B, OUTPUT_C)

tank_pair.on(left_speed=30, right_speed=30)

while not ts.is_pressed:  # while touch sensor is not pressed
    sleep(0.01)

tank_pair.off()
sleep(5)

Move Steering for a given angle

Use either on_for_rotations() or on_for_degrees().

on_for_rotations(steering, speedrotations, brake=True, block=True)
Rotate the motors so that the robot moves along the path determined by steering and such that the faster motor has a speed equal to speed and will move through an angle given by rotations. The speed and rotation angle of the slower motor is calculated automatically based on the values of steering and speed.

speed is an integer percentage of the rated maximum speed of the motor. You can use conversion functions like SpeedDPS() which converts degrees per second into the corresponding speed value.

Example:
steer_pair = MoveSteering(OUTPUT_B, OUTPUT_C)
# drive in a turn for 10 rotations of the outer motor
steer_pair.on_for_rotations(steering=-20, speed=75, rotations=10)

Since these are positional arguments the names are optional so the same command can be written
steer_pair.on_for_rotations(-20, 75, 10)
but it's probably better to include the names for clarity.

on_for_degrees(steering, speed, degrees, brake=True, block=True)
Rotate the motors so that the robot moves along the path determined by steering and such that the faster motor has a speed equal to speed and will move through an angle given by degrees. The speed and rotation angle of the slower motor is calculated automatically based on the values of steering and speedThe only difference between on_for_rotations() and on_for_degrees() is that one uses rotations and the other uses degrees.

Move Steering for a given time

on_for_seconds(steering, speed, seconds, brake=True, block=True)
Rotate the motors such that the robot moves long the path determined by steering at the speed determined by speed. The faster motor will have a speed equal to speed and the speed of the slower motor will be calculated as a function of the speed value and the steering value. (Sometimes the motors are equally fast, such as when steering = 0.)

Move Steering 'forever'

on(steering, speed)
Start rotating the motors according to steering and speed forever.

Stop the motors

off(brake=True)
Stop both motors immediately.

Speed Regulation and Synchronization

EV3 Python usually uses a feature called 'speed regulation' when using motors. When speed regulation is on, the motor controller will vary the power supplied to the motor to try to maintain the requested speed. It's comparable to the way your car's cruise control will try to maintain a constant speed even if your car goes up or down hills.

Although EV3 Python uses speed regulation is does not currently offer motor synchronization for motor pairs such that if one motor is slowed below its requested speed the other motor slows to match. Motor synchronisation IS a feature of EV3-G, and may one day be available in EV3 Python.

Other Notes
Note that if you have only one large motor plugged in to the EV3 then you do not need to specify which motor port it is plugged into. The same is true for the medium motor, and also for each type of sensor.

If you have two motors of the same type plugged into the EV3 and you run a command to move a single motor of that type without specifying a port letter then the port that is alphabetically first will be the one that receives the command. The very first script on this page is an example of this. There is nothing in the above script to say which motor should move, so the script will use the first large motor that it finds as it scans alphabetically through the motor ports. If you have large motors on ports B and C then motor B will move. If you wanted motor C to move then you could modify the beginning of the script like this:
#!/usr/bin/env python3
from ev3dev2.motor import LargeMotor, OUTPUT_C
from ev3dev2.motor import SpeedDPS, SpeedRPM, SpeedRPS, SpeedDPM
from time import sleep

lm = LargeMotor(OUTPUT_C)
Comments