Beyond Basics Ex 12-18

Exercise 12: Compare

Objective:

The color sensor will be set to recognise standard colors (mode 2). If the sensor detects green then the robot will advance for one wheel rotation and otherwise the 'Click' sound will be played once to completion and the robot will then pause. The robot will continue checking until the program is interrupted.

Solution:

This program assumes that have you have downloaded all the standard Lego sound and image files to the brick in accordance with the instructions on this page.

'Connect color sensor to port 3

Sensor.SetMode(3,2)   'Set color sensor to mode 2: detect standard colors

While "True" 

    ColorCode=Sensor.ReadRawValue(3,0)

    If ColorCode=3 Then   'color 3 = green

        Motor.Move("BC",50,360,"True")

    Else

        Speaker.Play(100,"Sounds/Click")

        'File and folder names in the brick are case-sensitive!

        Speaker.Wait()  'Wait until the sound finishes playing

        Program.Delay(1000)   'pause 1 second

    EndIf

EndWhile

Notes:

Exercise 13: Variables

Variables are, of course, a very basic concept in any programming language, and you have already been using them often in previous exercises. However, it is only in official Lego exercise 13 'Variables' of the 'Beyond Basics' sequence that the 'Variables' programming block is presented. In Lego's EV3-G programming environment, changing the contents of a variable is remarkably complicated: you have to first make a copy of the variable you want to change, then you can modify the copy, such as add one to it, then you have to write the modified copy back into the variable!! I think the poor handling of variables is one of the biggest weaknesses of EV3-G, along with the fact that it is icon-based and therefore a poor preparation for a career in programming.

For us clever EV3 Basic programmers, this exercise won't introduce anything new. You already know that a variable is like a named container that can contain a text string, a number, a logical value (true or false), or an array. Actually this lesson will teach you something new: how to detect the moment that a touch sensor button is pressed (or released) as opposed to simply detecting whether the button is in the pressed state.

Objective:

The user will press the touch sensor several times and then, 5 seconds after the program was launched, the robot will move straight forward with speed 50 for a number of wheel rotations equal to the number of times the sensor was pressed. 

Solution:

The official EV3-G solution to this problem (shown below) is to use a thread (a branch of code that can run simultaneously with other threads) to interrupt the main loop after 5 seconds. I think the best EV3 Basic solution would not use threads, partly because I am not sure that EV3 Basic has a neat way for code in a thread to interrupt a loop in a different thread.

Counting the number of presses needs a little thought. Each complete 'press' is really a 'press and release' - this double action is what the Lego software calls a 'bump'. We could look for the presses or releases or both - my program looks for releases. When the touch sensor button is released then its value (as read with Sensor.ReadPercent) will change from 100 to 0, so my program compares the current value of the sensor ('CurrentState') with the value that it had the last time the While loop was run through ('PreviousState'). If the current value is 0 and the previous value was 100 then the button has just been released and we can add one to the press count ('Presses').

Sensor.SetMode(1,0)  'Set the touch sensor on port 1 to mode 0

Presses=0  'Number of presses (actually releases)

PreviousState=0

While EV3.Time<5000    'loop until 5 seconds have passed

    CurrentState=Sensor.ReadPercent(1)

    If PreviousState=100 And  CurrentState=0 Then 'button has been released

        Presses=Presses+1

    EndIf

    PreviousState=CurrentState   'Ready for next loop

    Program.Delay(10)

EndWhile

Motor.Move("BC",50,Presses*360,"True")

Notes:

Exercise 14: Color sensor - calibrate

The EV3 color sensor was probably calibrated in the factory so that it returns (in mode 0, reflected light intensity) a value of 100% when a perfectly pure white surface is brought near the sensor and 0% when a perfectly black surface is brought near. But in the real world such surfaces are rare and we are more likely to be working with ordinary white paper that is not a perfect white and ordinary black paper or black marker that is not perfectly back. Therefore when we use the color sensor we might be getting a reflectance reading of, say, 13 with our (not so) black surface and 87 with our (not so) white surface. Wouldn't it be convenient if we could recalibrate the sensor so that it gives a reading of almost exactly zero with our real-world black surface and almost exactly 100 with our real-world white surface? EV3-G has a special calibration block for this purpose but it does not work in the way most people expect, hence the existence of a special lesson in the 'Beyond Basics' section of the Lego software (Education edition) to show its correct use (see the corresponding program below). EV3-Basic users can also use code to 'recalibrate' the sensor (or at least to adjust the displayed value in the desired way).

Objective:

Write a program in which the color sensor (in mode 0, reflected light intensity) is recalibrated so that our real-world black surface gives a reflectance value of 0% and our real-world white surface gives a reflectance value of 100%. At the same time, the measured reflected light intensity should be continuously displayed on the LCD screen, so we should be able to see that after each recalibration the sensor does indeed give the expected values when presented a black or white surface.

The exact procedure will be this:

Solution:

This program assumes that have you have downloaded all the standard Lego sound and image files to the brick in accordance with the instructions on this page.

As in the EV3-G solution, we will use a separate thread to continuously display the sensor value (the ADJUSTED sensor value, that is, after the first and second clicks).

It's important that we don't simply look for a 'button pressed' state in order to trigger each of the three adjustments. If we only looked for a 'pressed' state of the button to launch each of the adjustments then it is likely that the first adjustment would happen so quickly that the button would still be in the 'pressed' state when the first adjustment completes, therefore the second adjustment would start immediately, before we are ready. We need to check not for a button state but for for change of button state. We could look for a 'press' or a 'release' or both. The EV3-G solution looks for both, i.e. a press followed by a release (which Lego calls a 'bump'). Our program will look for the release of the button each time, and will use code similar to that in the previous exercise. 

For this exercise, it is of course important to always hold the objects at the same distance from the sensor. My experiments suggest that objects should be held about 0.5 cm from the sensor since this gives the strongest possible reflected light intensity.

It is normal that after the adjustment has been made for 'black' the displayed value will then be negative when no object is near the color sensor.

Sensor.SetMode(1,0)  'Set touch sensor on port 1 to mode 0

Sensor.SetMode(3,0)  'Set color sensor on port 3 to mode 0

Thread.Run = DISPLAYVALUE   'launch the thread called DISPLAYVALUE

BlackAdjust=0   'BlackAdjust value will be subtracted from sensor reading

WhiteAdjust=1   'Adjusted-for-black reading will be divided by WhiteAdjust

' to give a reading which is now adjusted for both black AND white

Sub DISPLAYVALUE    'Continuously display the (adjusted) sensor reading

    While "True"

        LCD.StopUpdate()

        LCD.Clear()

        LCD.Text(1,45,55,2,Math.Round((Sensor.ReadPercent(3)-BlackAdjust)/WhiteAdjust))

        LCD.Update()

    EndWhile

EndSub

Sub WaitForBump

    Loop="True"

    While Loop

        CurrentState=Sensor.ReadPercent(1)

        If PreviousState=100 And  CurrentState=0 Then 'button has been released

            Loop="False"     'button has just been released so stop looping

        EndIf

        PreviousState=CurrentState   'Ready for next loop

        Program.Delay(10)

    EndWhile

EndSub

PreviousState=0

WaitForBump()

BlackAdjust=Sensor.ReadPercent(3)  'BlackAdjust value will be subtracted from

'sensor reading to give 'adjusted-for-black' reading which is now displayed

Speaker.Play(100,"Sounds/Click") 'File names on the brick are case-sensitive!

Speaker.Wait()

WaitForBump()

WhiteAdjust=(Sensor.ReadPercent(3)-BlackAdjust)/100

'Adjusted-for-black reading is divided by WhiteAdjust/100 to give a reading

'which is now adjusted for both black and white and which is now displayed.

'Bring your black and white objects near the sensor and they should now

'give adjusted readings of 0 and 100 (or very close)

Speaker.Play(100,"Sounds/Click")

Speaker.Wait()

WaitForBump()

BlackAdjust=0  'reset adjustment values

WhiteAdjust=1

Speaker.Play(100,"Sounds/Click")

Speaker.Wait()

Program.Delay(20000)  'You have 20 seconds to check that the

'initial values for your black and 'white surfaces have returned...

Notes:

Exercise 15: Messaging

Objective:

This program (or rather, this pair of programs) will allow two bricks to communicate with one another using Bluetooth (short range wireless radio communication). The programs will allow you to control the rotational speed of one wheel of the receiving robot, which will be moving in circles, by turning the right wheel (motor C) of the sender robot. That's right - we will be controlling the receiving robot by 'remote control' using BlueTooth (not using the EV3 infra-red 'beacon').

I don't own two bricks at the moment so this solution will have to wait...

Exercise 16: Logic

In computer programming the logical (or 'Boolean') values are 'true' and 'false'. Logical operators include AND, and OR

Objective:

The robot will move forward in a straight line towards an object until its color sensor detects a black surface AND the robot is within 6-25cm of the object that it is approaching. When BOTH these conditions are met the robot will stop moving.

Solution:

Really there are THREE conditions to be met:

Sensor.SetMode(4,0) 'Set ultrasound sensor on port 4 to mode 0: distance in mm

Sensor.SetMode(3,2) 'Set color sensor on port 3 to mode 2: detect standard colors

Motor.Start("BC",50)

While "True"   'forever

    Distance=Sensor.ReadRawValue(4,0)/10

    Color=Sensor.ReadRawValue(3,0)

    If Distance>6 And Distance<25 And Color = 1 Then   '1 = black

        Motor.Stop("BC", "True")

        Program.End()

    EndIf

EndWhile

Notes:

    Logical="True"

    Not = "True=False;False=True"   'an array

    LCD.Clear()

    LCD.Text(1,50,55,2,Not[Logical])   'notice the square brackets

    Program.Delay(3000)

In the video that accompanies the official EV3-G exercise the robot is initially far from the reflecting object and over a white mat. The conditions are met for the robot to move forward. It passes over a black line but does not stop because the robot is not yet within the defined range. It continues moving forward until it reaches a second black line and there it stops because it detects black AND the robot is within the defined range.

It seems to me the above EV3-G program has an error. It should not be necessary to repeatedly turn on the motors. Shouldn't the first motor block be placed before the loop, not within it?

Exercise 17: Maths - Advanced

This exercise uses the gyro sensor which is not included in the 'Home' version of the EV3 kit, though it is available for purchase as an optional extra, and the corresponding programming block can be downloaded to the Home version of the EV3-G software at no cost.

Recall that it is vitally important that the gyro sensor should be absolutely still when the brick is powered up or the sensor plugged in, otherwise the sensor reading will wander away from the correct value.

Objective:

The robot is assumed to have already moved along two perpendicular arms of a triangle, each with length 25 cm, and to have turned around 180° so it is now in the right location to begin tracing the hypotenuse but it is not pointing in the right direction. The robot should now turn slowly on the spot until the gyro sensor detects that the robot has turned at least 45°, then the motors should be turned off.

Then the robot should calculate the length of the hypotenuse using the actual angle turned by the robot (as measured by the gyro sensor) rather than the 45° angle that the robot should have turned. The calculation will be

                       hypotenuse length = adjacent arm length / cos(turn angle)

Note that Small Basic (and therefore also EV3 Basic) trigonometric functions (Sin(), Cos() etc) work in radians, not degrees.   1 radian = 57.3° (approx)

Then the robot should calculate the corresponding number of wheel rotations needed, given that the circumference of the standard Lego wheel is 17.6 cm. Then the robot should move at speed 30 in the correct direction and for the correct distance in order to trace out the hypotenuse of the triangle.

Solution:

Sensor.SetMode(2,0)   'Set gyro sensor on port 2 to mode 0

Motor.StartSync("BC",10,-10)'Robot slowly turns to the right on the spot

While Sensor.ReadRawValue(2,0) < 45

EndWhile

Motor.Stop("BC", "True")

'Small Basic trig functions like cos() work in RADIANS

Radians=Sensor.ReadRawValue(2,0)/57.3 'convert to radians.1 rad = 57.3°

Length = 25/Math.Cos(Radians)   'calculate length of hypotenuse

Rots=Length/17.6 'calculate wheel rotations (wheel circumference=17.6cm)

Motor.Move("BC",30, Rots*360, "True")'convert wheel rotations to degrees

Notes:

Exercise 18: Arrays

Objective:

First, the user will give coded instructions to the robot by showing it a sequence of four colors. Each color is an instruction to carry out a certain movement. Then the robot will carry out the corresponding movements. 

More specifically, the procedure will be:

Solution:

We will use an array to store the four color code numbers. An 'array' is a variable that can hold multiple values. In EV3 Basic you can have an array of numbers or an array of text strings but not an array of logical values. (This contrasts with EV3-G in which, I believe, you can have an array of numbers or an array of logical values but not an array of text strings.)

The order of the elements in an array is important, so the elements in an array are like a list. Each element in the list has an index number, and the first element has index number zero. Here is an example of a numeric array: [5; 2.7; 3.1] . This array has three elements - we say the array has a 'length' of three. The elements have index numbers 0, 1 and 2, so the third element has index number 2 not 3.

This exercise uses standard Lego sounds. It is assumed that have you have downloaded all the standard Lego sound and image files to the brick in accordance with the instructions on this page.

'Set color sensor on port 3 to mode 2: detect standard colors

Sensor.SetMode(3,2) 

Sub WaitForBump

    PreviousState=0

    Loop="True"

    While Loop

        CurrentState=Sensor.ReadPercent(1)

        If PreviousState=100 And  CurrentState=0 Then 'button has been released

            Loop="False"     'button has just been released so stop looping

        EndIf

        PreviousState=CurrentState   'Ready for next loop

        Program.Delay(10)

    EndWhile

EndSub

ColorSounds[2]="Blue"          'NOT IN EV3-G VERSION

ColorSounds[3]="Green"

ColorSounds[4]="Yellow"

For i=0 to 3

    Speaker.Play(100,"Sounds/Click")

    Speaker.Wait()

  

    WaitForBump()

    'Wait for a valid color to be detected

    Loop="True"

    While Loop

        ColorCode=Sensor.ReadRawValue(3,0)

        If ColorCode=2 OR ColorCode=3 OR ColorCode=4 Then'blue,green,yellow

            ColorArray[i]=ColorCode

            Speaker.Play(100,"Sounds/"+ColorSounds[ColorCode]) 'NOT IN EV3-G

            Speaker.Wait()                           'NOT IN EV3-G VERSION

            Loop="False"  'prevent loop running again

        EndIf

    EndWhile

EndFor

Speaker.Play(100,"Sounds/Horn 2")

Speaker.Wait()

For k=0 to 3

    If ColorArray[k]=2 Then  'blue

        Motor.MoveSync("BC",0,50,345,"True")    

    ElseIf ColorArray[k]=3 Then    'green

        Motor.Move("BC",50,360,"True")    

    ElseIf ColorArray[k]=4 Then    'yellow

        Motor.MoveSync("BC",50,0,345,"True")

    EndIf  

EndFor

Notes:

Conclusion

You have now completed the EV3 Basic versions of the 'Basics' and 'Beyond Basics' exercises that are included in the Education version of the EV3 software. You have seen how EV3 Basic is almost always capable of performing the same tasks as the standard Lego EV3-G software, while at the same time giving you valuable experience of textual programming. But EV3 Basic is capable of handling programs that go beyond the capabilities of the standard Lego software (such as programs that allow for an interaction between the robot and the Small Basic graphical window). Going beyond what EV3-G can do will be the theme of the next set of exercises... so stay tuned!