Learn EV3 Python‎ > ‎Robot Educator‎ > ‎

Beyond Basics Ex 1-6

To see how each of these exercises can be solved in the standard Lego EV3 programming environment (EV3-G) click HERETo see how each of these exercises can be solved with EV3 Basic click HERE

Exercise 1: Multitasking

The interest of the exercise is of course that it demonstrates multitasking i.e. the ability of an EV3 program to run multiple branches or 'threads' simultaneously. A thread is a part of program code that can run independently and at the same time as other parts of the program. You can learn more about threads HERE.

Objective: 
The robot will continuously play the Lego 'Motor idle' sound until the robot has moved straight forward for two wheel rotations at speed 50.

Solution:
Coming!

Notes:

Exercise 2: Loop

Objective:
The program first makes the brick's status light pulse red for two seconds, then clicks twice and moves forwards one wheel rotation, repeatedly clicking and moving until the touch sensor is pressed.

Solution:

Coming!

Notes:

Exercise 3: IF structure (called 'Switch' in the Lego software)

Objective:
This will be a simple 'line follower' program using a single color sensor. The intention is that the robot will follow a black line that has been drawn on a white mat. This is a little difficult to do using only a single color sensor. Imagine that the robot is moving along the line with the sensor over the black line, then the sensor will detect very little light being reflected. If the robot wanders off the line then the sensor will detect a strong reflected light intensity, but how useful is that information? The robot won't know whether it has wandered off the left side of the line or the right, so it won't know how to turn back towards the line. So the trick is not to try to follow 'the line', it is to follow one edge of the black line, let's say the right edge. Now if the sensor detects that it is over white then we know the robot should turn left to find the edge again and if the sensor detects that it is over black then the robot should turn right to find the edge again. In other words...
  • If the color sensor detects weak reflected light (i.e. over black surface) then the robot should make a medium right turn (motor B speed = 50%, motor C speed = 0%).
  • If the color sensor detects strong reflected light (i.e. over white surface) then the robot should make a medium left turn (motor B speed = 0%, motor C speed = 50%).
Solution:

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

btn = Button() # will use any button to stop script

# Connect EV3 color sensor and check connected.
cl = ColorSensor() 
assert cl.connected, "Connect a color sensor to any sensor port"

# Put the color sensor into COL-REFLECT mode
# to measure reflected light intensity.
# In this mode the sensor will return a value between 0 and 100
cl.mode='COL-REFLECT'

# Attach large motors to ports B and C
mB = LargeMotor('outB')
mC = LargeMotor('outC')

while not btn.any():    # exit loop when any button pressed
    if cl.value()<30:   # weak reflection so over black line
        # medium turn right
        mB.run_forever(speed_sp=450)
        mC.stop(stop_action='brake')
    else:   # strong reflection (>=30) so over white surface
        # medium turn left
        mB.stop(stop_action='brake')
        mC.run_forever(speed_sp=450)
      
mB.stop(stop_action='brake')
mC.stop(stop_action='brake')

Notes:
  1. This solution works very well because there are only two options and therefore a simple if structure is neatly appropriate.
  2. I originally had while True: instead of while not btn.any(): but that meant that in order to terminate the script I had to use Ctrl+C which left one of the motors still turning even after the script had terminated, with no obvious way to stop the motor. The above script includes neat code (highlighted in green) which allows for the loop to be exited by pressing any button on the EV3, allowing the last two lines to run.

Exercise 4: Multiple Switch

Note: this exercise assumes that the color sensor on port 3 is aligned horizontally or pointing upwards so you can present differently colored sides of the 'multi-color cuboid' to it.

Objective:
  • If the color sensor detects no color or a color other than yellow or blue then the robot should continuously move straight forward with a power of 40% (speed_sp=360).
  • If a yellow object is presented to the color sensor then the robot should continuously turn gently right (with the left motor at 40% power and the right motor at 10% power).
  • If a blue object is presented to the color sensor then the robot should continuously turn gently left (with the left motor at 10% power and the right motor at 40% power).
Solution:

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

btn = Button() # will use any button to stop script

# Connect EV3 color sensor and check connected.
cl = ColorSensor() 
assert cl.connected, "Connect a color sensor to any sensor port"

# Put the color sensor into COL-COLOR mode
# to try to identify standard colors and return a
# corresponding integer between 0 and 7
cl.mode='COL-COLOR'

# Attach large motors to ports B and C
mB = LargeMotor('outB')
mC = LargeMotor('outC')

while not btn.any():    # exit loop when any button pressed
    code=cl.value()
    if code==4:  # yellow
        mB.run_forever(speed_sp=360)
        mC.run_forever(speed_sp=90)
    elif code==2:  # blue
        mB.run_forever(speed_sp=90)
        mC.run_forever(speed_sp=360)
    else:
        # no color detected or a color other than yellow or blue
        mB.run_forever(speed_sp=360)
        mC.run_forever(speed_sp=360)
    sleep(0.01)
    
mB.stop(stop_action='brake')
mC.stop(stop_action='brake')

Notes:
  1. Since there are three options in this exercise a simple if...else... statement is insufficient. Instead we must use if...elif...else..., as above. elif is short for 'else if'.
  2. It would have been complicated to test for 'no color or any color other than yellow or blue' so I simply put it last and used 'else'. This correctly runs if the blue or yellow color has not been responded to in previous lines.
  3. Recall that to test for equality you must use the == operator. The = sign is used to assign values to variables.
  4. The sleep line may not be useful or necessary?

Exercise 5: 'Data wires'

In the icon-based Lego EV3 programming environment it is often necessary to use 'data wires' to transfer data between programming blocks. Fortunately, this is not meaningful or necessary in a textual programming environment like EV3 Python.

Objective:
In this program the robot does not move and it is assumed that an object such as your hand will be brought towards the ultrasound sensor on the robot. A loop continually measures the distance to an object (assumed to be initially more than 8 cm away), and displays the measured distance on the brick's screen. The loop exits when the program detects that the distance to the reflecting object has become less than 8 cm, and an image of two eyes called 'Up' is then displayed for two seconds.

Solution:

This program assumes that have you have downloaded all the standard Lego image files in BMP format to the brick in accordance with the instructions in the 'Display an image file' section on this page. This script uses a font (helvB24) which is included only in EV3 Python v0.8.0 and beyond so be sure to have the latest version.

#!/usr/bin/env python3
from ev3dev.ev3 import *
from time import sleep
import ev3dev.fonts as fonts
from PIL import Image, ImageDraw, ImageFont

lcd = Screen()

# Connect ultrasonic sensor to any sensor port
# and check it is connected.
us = UltrasonicSensor() 
assert us.connected, "Connect a US sensor to any sensor port"
# Put the US sensor into distance mode.
us.mode='US-DIST-CM'

while us.value()> 80:   # 8 cm converted to mm
    lcd.clear()
    lcd.draw.text((40,50),str(us.value()/10)+' cm'font=fonts.load('helvB24'))
    lcd.update()
    sleep(0.1) # so the display doesn't change too frequently

pic = Image.open('pics/Up.bmp')
lcd.image.paste(pic, (0,0))
lcd.update()

sleep(5)  # when running from Brickman, need time to admire image

Notes:
  1. The above script writes to the LCD display. Such scripts can easily be run from Brickman but if you want to run them from SSH then you should first run the command sudo chvt 6 in the console. Once you have run the script and terminated it with Ctrl+C, run sudo chvt 1 to get Brickman back.

Exercise 6: Random

Objective:
The program will first generate a random integer between -70 and 70 inclusive. The robot should drive forward at this speed for one second, then pause for one second, then generate a new random number and repeat forever.

Solution:
The values -70 to +70 are for EV3-G. The speed values of EV3-G correspond to speed_sp values that are 9 times bigger in EV3 Python, e.g. a speed of 100 in EV3-G corresponds to speed_sp=900 in EV3 Python and a speed of 70 in EV3-G corresponds to a speed_sp value of 630.  Therefore we need to generate random integers between -630 and +630 in our script. In Python, random integers between a and b inclusive can be generated with randint(a, b). The randint() function is part of the random library so the random library must be imported before the function can be used. We will include code such that the script can be terminated with a long press on any EV3 button.

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

btn = Button() # will use any button to stop script

# Attach large motors to ports B and C
mB = LargeMotor('outB')
mC = LargeMotor('outC')

# exit loop with a long press on any EV3 button
while not btn.any():
    # generate a random integer between -630 and +630 inclusive
    rand=random.randint(-630,630)
    mB.run_forever(speed_sp=rand)
    mC.run_forever(speed_sp=rand)
    sleep(1)
    mB.stop(stop_action='brake')
    mC.stop(stop_action='brake')
    sleep(1)
    
mB.stop(stop_action='brake')
mC.stop(stop_action='brake')

Notes:
Let's compare this solution with an EV3 Basic solution and the official EV3-G solution to the same problem. Bear in mind that the official EV3-G solution has no comments.

Here's the EV3 Basic solution. It uses a function Math.GetRandomNumber(maxNumber) which generates a random integer between 1 and the specified maxNumber (inclusive).

While "True"
    'generate a random integer between 1 and 141 inclusive
    rand=Math.GetRandomNumber(141)  
    rand=rand-71   'the random number is now in the range -70 to 70
    Motor.Start("BC", rand)
    Program.Delay(1000)
    Motor.Stop("BC","True")
    Program.Delay(1000)  
EndWhile

Here's the official EV3-G solution from the EV3 Education software:



You are now ready to tackle Beyond Basics exercises 7-11.
Comments