Robot Educator
The education version of the Lego EV3 software proposes various example programs in a sequence called ‘Robot Educator’. You can see those programs and my commentaries HERE. Let’s see how to solve the same problems using EV3 Python. No, much better: YOU try to write a script to solve each challenge, only looking at my solution when you have have completed your own solution (or got stuck trying...).
As for all exercises on this site, it is assumed that you are using the official ‘Lego ‘Driving Base’ model, or something very similar, with motors attached to ports B and C. The official Lego 'Driving Base' model is also called the 'Educator Vehicle'.
The program solutions below can be copied into VS code so that you can test them, if you wish.
Further down this page you can find the 'Basics' exercises. Once you have completed them, follow these links for the 'Hardware' and 'Beyond Basics' exercises:
BASICS
Lesson 1 of the official Lego lesson sequence is about configuring blocks and is not relevant to EV3 Python and therefore not discussed here.
Lesson 2: Straight Move
Objective:
Make the robot advance such that the wheels rotate 2 rotations at 50% speed.
Wait one second
Make the robot move backwards such that the wheels rotate 2 rotations at 50% speed
Wait one second
Make the robot advance for one second at 50% speed
EV3 Python solution:
#!/usr/bin/env python3
from ev3dev2.motor import OUTPUT_B, OUTPUT_C, MoveSteering
from time import sleep
steer_pair = MoveSteering(OUTPUT_B, OUTPUT_C)
# Make the robot advance such that the wheels rotate 2 rotations
steer_pair.on_for_rotations(steering=0, speed=50, rotations=2)
sleep(1) # Wait one second
# Make the robot move BACKWARDS such that
# the wheels rotate 2 rotations at 50% speed
# NEVER SET THE ANGLE NEGATIVE
steer_pair.on_for_rotations(steering=0, speed=-50, rotations=2)
sleep(1) # Wait one second
# Make the robot advance for 1 second at 50% speed
steer_pair.on_for_seconds(steering=0, speed=50, seconds=1)
For comparison, here is the solution as it appears within the standard Lego icon-based programming environment:
You can find the Lego solutions to the other challenges HERE.
Notes:
The script above includes lines (highlighted) which detect when both motors have completed their movements. This code was explained on the motors page.
Lesson 3: Curved Move
Objective:
Make the robot do a hard turn right (on the spot) with 685° wheel rotation (speed 40%). The left wheel will turn forwards through that angle and the right wheel will turn backwards through the same angle so that the robot itself turns on the spot. Note that a hard right turn on the spot like this corresponds to a 'steering' setting of +100 in the Move Steering block of the standard Lego software and also to a 'steering' setting of +100 with the MoveSteering object in EV3 Python v2.
Wait one second
Medium turn right (equivalent to a 'steering' setting of 50 in the standard Lego software or EV3 Python, with only one wheel rotating) with a wheel rotation of 1380° (speed 40%).
Wait one second
Gentle turn right. A 'steering' setting of 25 in the Move Steering block of the standard Lego software or EV3 Python means that the right wheel with turn half as fast as the left wheel. Speed 50% applies to the faster (left) wheel, so the right wheel will have a speed of 25%. The faster-turning wheel should rotate through two rotations so the wheel rotating half as fast will rotate 1 rotation in the same time.
Solution:
#!/usr/bin/env python3
from ev3dev2.motor import OUTPUT_B, OUTPUT_C, MoveSteering
from time import sleep
steer_pair = MoveSteering(OUTPUT_B, OUTPUT_C)
# Make the robot do a hard turn right (on the spot) with
# 685 deg wheel rotation (speed 40%).
steer_pair.on_for_degrees(steering=100, speed=40, degrees=685)
sleep(1) # Wait one second
# Medium turn right, meaning only the left motor (B) will turn
steer_pair.on_for_degrees(steering=50, speed=40, degrees=1380)
sleep(1) # Wait one second
# Gentle turn right (steering=25) with speed 50%
# and two rotations of the faster wheel
steer_pair.on_for_rotations(steering=25, speed=50, rotations=2)
Lesson 4: Tank Move
Objective:
The intended movement in the official Lego lesson 4 is exactly the same as in lesson 3 above, but the idea is to show that the same movements can be obtained with Move Tank if desired:
#!/usr/bin/env python3
from ev3dev2.motor import OUTPUT_B, OUTPUT_C, MoveTank
from time import sleep
tank_pair = MoveTank(OUTPUT_B, OUTPUT_C)
# Make the robot do a hard turn right (on the spot) with
# 685 deg wheel rotation (speed 40%).
tank_pair.on_for_degrees(left_speed=40, right_speed=-40, degrees=685)
sleep(1) # Wait one second
# Medium turn right, meaning only the left motor (B) will turn
tank_pair.on_for_degrees(left_speed=50, right_speed=0, degrees=1380)
sleep(1) # Wait one second
# Gentle turn right (steering=25) with speed 50% for the faster wheel
# and two rotations of the faster wheel
tank_pair.on_for_rotations(left_speed=50, right_speed=25, rotations=2)
Lesson 5: Move Object
Objective:
This program uses the medium motor to lower the robot's gripper bar, trapping an object, then it does a medium left turn backwards, pulling the object with it, then it raises the gripper bar. It is assumed that the gripper bar is attached to the medium motor which is itself attached to port A. The photo shows the gripper bar attached to the standard Lego 'Driving Base' model, also called the 'Educator Vehicle' model.
Make the medium motor (on port A) turn +100° at 30% speed. In the standard 'driving base' model the medium motor is attached to a gripper which is assumed to start in a vertical position - this movement will cause the gripper to be lowered to the ground, hopefully enclosing an object within its grip as it does so.
Robot makes a medium left turn backwards. The left wheel should rotate backwards 1 rotation with speed -50% and the right wheel should not rotate.
Make the medium motor turn -100° at 30% speed. This will cause the gripper to be raised back into the vertical position.
Solution:
#!/usr/bin/env python3
from ev3dev2.motor import OUTPUT_A, OUTPUT_B, OUTPUT_C, MoveTank, MediumMotor
# Make a MediumMotor object, an instance of the MediumMmotor class
# Note that if only one medium motor is attached to the EV3
# then it is not necessary to specify the port as here
medium_motor = MediumMotor(OUTPUT_A)
tank_pair = MoveTank(OUTPUT_B, OUTPUT_C)
# Make the medium motor (on port A) turn 100 deg at -30% speed
medium_motor.on_for_degrees(speed=-30, degrees=100)
# Medium left turn backwards. The left wheel (B) should rotate backwards
# 1 rotation with speed 50% and the right wheel should not rotate.
tank_pair.on_for_rotations(left_speed=50, right_speed=0, rotations=1)
# Medium motor A turns 100 deg at +30% speed
medium_motor.on_for_degrees(speed=30, degrees=100)
Lesson 6: Stop at line
Objective:
This exercise assumes that a colour sensor is attached and is suspended just above (ideally 3 mm above) the ground, pointing at the ground. This program turns on the right motor to make the robot turn left, then waits until the detected brightness falls below a certain value (because the sensor has passed over a black line, for example), then turns off the motor.
Start the right motor moving with speed 50%.
Wait until the colour sensor detects that the brightness has fallen beneath a certain threshold value (see note below)
Turn off the motor.
Solution:
#!/usr/bin/env python3
from ev3dev2.motor import OUTPUT_C, LargeMotor
from ev3dev2.sensor.lego import ColorSensor
from time import sleep
# Connect an EV3 color sensor.
cl = ColorSensor()
mC = LargeMotor(OUTPUT_C)
# Make the right motor (motor C) turn at 50% speed
mC.on(speed=50)
# Wait until the colour sensor detects that the brightness
# has fallen beneath a threshold value of 40 (see note).
# Loop while over white surface
while cl.reflected_light_intensity > 40:
sleep(0.01)
mC.off()
Notes:
With the sensor 3 mm from the reflecting surface I get a value of 80 for white paper and 5 for a typical back surface. Therefore I have chosen for this script a threshold value of 40 to distinguish between black and white reflecting surfaces.
If the last line were omitted, would it make any difference? After all, the motor should stop when the program terminates, right? Well, the last line DOES make a difference because it makes the motor stop suddenly, whereas without the last line the motor would coast to a stop after the program ends, and that's less sudden.
Lesson 7: Stop at Angle
This exercise uses the gyro sensor. The gyro sensor is included in the education version of the EV3 but not in the home version, so if you have the home version you will not be able to test this program (it's always possible to buy additional sensors). Whenever you use the gyro sensor, be sure that the sensor is absolutely still when the program is launched otherwise its readings will wander away from the correct values. If you are not sure that this condition was met then simply unplug the sensor from its port and then reconnect it before running the program, while ensuring that the EV3 and the gyro sensor are perfectly still.
The gyro's angle property is the angle in which it is pointing relative to the angle that is was at when the program was launched (????). A clockwise angle is a positive angle. For example, if the sensor were to be rotated through 2 rotations counterclockwise after the program is launched then it would return an angle of -720 degrees.
Objective:
Start the left motor with speed 40% to initiate a medium turn right.
Wait until the gyro sensor detects that the robot has turned (at least) 45° in the positive direction (to the right). Note that the gyro measures the rotation of the robot itself and not the rotation of the motors or the wheels.
Then the robot moves straight ahead with speed 50% until the wheels have turned through one rotation.
Solution:
#!/usr/bin/env python3
from ev3dev2.motor import OUTPUT_B, OUTPUT_C, MoveTank
from ev3dev2.sensor.lego import GyroSensor
from time import sleep
# Connect gyro sensor.
gyro = GyroSensor()
tank_pair = MoveTank(OUTPUT_B, OUTPUT_C)
# Start the left motor with speed 40% to initiate a medium turn right.
tank_pair.on(left_speed=40, right_speed=0)
# Wait until the gyro sensor detects that the robot has turned
# (at least) 45 deg in the positive direction (to the right)
gyro.wait_until_angle_changed_by(45)
# Robot moves straight ahead with speed 50% until the wheels
# have turned through one rotation
tank_pair.on_for_rotations(left_speed=50, right_speed=50, rotations=1)
Lesson 8: Stop at Object
This project will use the ultrasound sensor. If you don't have the ultrasound sensor (because you bought the home edition of the EV3) you could perhaps substitute the IR sensor but it won't be possible to get exact distances because the IR sensor does not return exact distances. Also, the code will be different if you use the IR sensor. This difference means other small changes need to be made to the code. See note 2 for a solution using the infrared sensor.
Objective:
The robot will move forward in a straight line (speed=50%) until it has moved (at least) 11 cm closer to the reflecting object in front of it, then it will stop and pause for one second, then it will back up continuously (speed=-50%) until it detects that it has moved (at least) 6 cm away from the object, then it will stop.
Solution (using the ultrasound sensor):
We will make use of the fact that if the robot moves 11 cm closer and then 6 cm further away it will then be 5 cm from its starting position.
#!/usr/bin/env python3
from ev3dev2.motor import MoveSteering, OUTPUT_B, OUTPUT_C
from ev3dev2.sensor.lego import UltrasonicSensor
from time import sleep
steer_pair = MoveSteering(OUTPUT_B, OUTPUT_C)
us = UltrasonicSensor()
# Record the initial separation of the sensor and the object
startdistance = us.distance_centimeters
# Start robot moving forwards
steer_pair.on(steering=0, speed=50)
# Wait until robot has moved (at least) 11 cm closer
# to the reflecting object in front of it
while us.distance_centimeters > startdistance-11:
sleep(0.01)
steer_pair.off() # Stop moving forwards
sleep(1)
# Reverse at 50% speed
steer_pair.on(steering=0, speed=-50)
# Wait until robot is less than 5 cm from its starting position
while us.distance_centimeters < startdistance-5:
sleep(0.01)
steer_pair.off() # Stop moving backwards
Notes:
I find that the sensor can give unreliable readings (due to unwanted reflections) if the robot is on a hard, highly reflective surface or if the sensor is mounted too close to the floor.
If you use the infrared sensor in place of the ultrasound sensor then you must modify the code since these sensors use different commands to obtain the sensor reading and since the infrared sensor returns a 'proximity' value that is neither in cm nor in mm. To convert a proximity value into a VERY approximate distance in cm, multiply the proximity value by 0.7. Here is the same program, modified for the IR sensor. Changed lines are highlighted.
Although the code below is correct, the program works very badly because the proximity readings by the IR sensor are too erratic.
#!/usr/bin/env python3
from ev3dev2.motor import MoveSteering, OUTPUT_B, OUTPUT_C
from ev3dev2.sensor.lego import InfraredSensor
from time import sleep
steer_pair = MoveSteering(OUTPUT_B, OUTPUT_C)
ir = InfraredSensor()
# Since the IR values are very approximate,
# make sure the initial separation is at least 30cm
# Record the approximate initial distance of the object from the sensor in cm
# A 'proximity' value of 100 corresponds to approximately 70cm
# so proximity can be very roughly converted to cm
# by multiplying by 0.7
start_distance = int(ir.proximity*0.7)
# Start robot moving forwards
steer_pair.on(steering=0, speed=50)
# Wait until robot has moved (at least) 11 cm closer
# to the reflecting object in front of it
while ir.proximity*0.7 > start_distance-11:
sleep(0.01)
steer_pair.off() # Stop moving forwards
sleep(1)
# Reverse at 50% speed
steer_pair.on(steering=0, speed=-50)
# Wait until robot is less than 5 cm from its starting position
while ir.proximity*0.7 > start_distance-5:
sleep(0.01)
steer_pair.off() # Stop moving backwards
Now that you have complete the 'Basics' exercises you are ready to tackle the 18 'Beyond Basics' exercises which begin with Beyond Basics exercises 1-6.