©  Gene Harding 2018
Gene HardingProgramming LEGO® EV3 My Blockshttps://doi.org/10.1007/978-1-4842-3438-9_7

7. Advanced Topics

Gene Harding1 
(1)
South Bend, Indiana, USA
 

Learning Topics

My Blocks, geometry, unit conversion, calibration, feedback, looping constructs, proportional control, variables, conditional constructs , torque, and traction

Requirements

  1. 1.

    Move forward or backward a specified distance.

     
  2. 2.

    Ensure movement is straight (i.e., eliminate the “wiggle”).

     
  3. 3.

    Enable optional “handoffs” so the robot does not have to stop at the end of the My Block.

     
  4. 4.

    Move as quickly as possible without wheel slip.

     

Handoffs: Continuing at Speed When the My Block Ends

Learning topics covered: My Blocks, conditional constructs

There are arguably two primary challenges to navigating a challenge board: precision and speed. The handoff technique deals with the constraint of time, and thus addresses the issue of navigation speed. Time is an important factor because each FLL Robot Game round only lasts 2.5 minutes, or 150 seconds. Saving a few seconds here and there can allow for more completed missions to achieve higher point totals.

To illustrate the usefulness of a handoff, consider the start of a mission set programmed by one of my former teams. The robot had to go forward more than 20", detect a line, curve to the left, detect another line, follow that line to its intersection with another line, then continue following the second line for a specified distance before making a right turn. It was necessary to stop before making the right turn, but not any time before. Imagine how the run would look if the robot stopped after every single My Block leading up to the turn: forward, stop, find line, stop, curve left, stop, find line, stop, follow line, stop, find line, stop, follow line, stop, turn right. All of these unnecessary stops waste time. If each stop wastes around 0.5 seconds, then just the beginning portion of the mission set would waste 3.0 seconds. Using the handoff technique saved several seconds per mission set, which allowed the team to add a few missions to their Robot Game strategy. The savings are even greater when acceleration and deceleration are used in the Forward and Backup My Blocks (covered later).

This technique is a feature to enable faster navigation that can be added to several My Blocks, such as Forward, LineFind, LineTFind , LineFollow , and WallFollow . For now, we start with Forward2 and make several changes to create a Forward3 My Block that can execute Handoffs at speed. The first change is to add something at the end of the program to allow the robot to either stop or continue at speed. This programming block is called a Switch block, shown in Figure 7-1. It has multiple “branches” where program flow can continue. The chosen path depends on the value of the input. In this case there will be two possible paths: one to tell the robot to stop and the other to tell the robot to continue at speed.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig1_HTML.jpg
Figure 7-1

Switch block

The second addition will be an input to tell the robot which branch of the Switch block to follow. Because there are only two possibilities, a Logic input will work well (i.e., either True or False). Let’s name the input BrakeAtEnd. If BrakeAtEnd is True, the robot will stop when it reaches the end of the My Block; if it is False, the robot will continue moving at its present speed and control will pass to the next program block.

The wiggle correction code creates an issue with Handoffs that will require more changes. Imagine a handoff between two My Blocks, both of which perform wiggle correction to keep the robot going straight. Now, suppose the first My Block is in the middle of doing a correction when it reaches the specified distance, so it is not pointed quite straight ahead. What happens when the next My Block begins? It loads GyroStart with the current direction and starts tracking that direction, which is slightly off. We can fix this problem by passing the GyroStart value from one My Block to the next.

Thus, the third change to make to Forward3 is to add a numeric output, GyroOut, to pass the GyroStart value to the next My Block. Likewise, a numeric input, GyroIn, is needed to accept the output of the previous My Block; and a logic input, Handoff , must be added to indicate that a handoff has happened. If RcvHandoff is True, GyroStart will be loaded with GyroIn from the previous My Block; if RcvHandoff is False, GyroStart will be loaded with the current direction just like in Forward2. Finally, the value of GyroStart must go to the output in case it is needed for a Handoff. The changes to create Forward3 from Forward2 are summarized here:
  • Add logic input BrakeAtEnd to indicate whether robot should stop, or not, after executing this My Block.

  • Add Switch block at end to either stop robot or continue at speed, depending on value of BrakeAtEnd.

  • Add numeric output GyroOut to pass GyroStart value to next My Block.

  • Add numeric input GyroIn to receive GyroStart value from previous My Block.

  • Add logic input RcvHandoff to indicate whether the My Block is receiving a Handoff or not.

  • Add a Switch block at the beginning to load GyroStart with either GyroIn or the current direction, depending on the value of Handoff.

  • Add a GyroStart variable to the end of the program chain, in “Read – Numeric” mode, and wire its output to the GyroOut output of the My Block.

Because Forward3 will have new inputs and a new output, it cannot simply be copied from Forward2 in the Project Properties window. A new My Block must be created using the My Block Builder. The good news, however, is that the blocks can be copied from inside Forward2 so that the entire program does not have to be re-created from scratch. Begin by copying Forward2 in the Project Properties window, then go to the programming window for the new My Block, double-click the tab, and rename the new My Block “Temp.” It will be deleted later.

In Temp, unplug the Distance input from the first Math block, and the Power input from the loop. Now the program blocks can be copied to a new program without leaving “hanging” connections from the My Block inputs. (It is safer to make a temporary program for this purpose than to modify the original My Block and redo the connections later.)

Next, create a new program, paste the blocks into the new program, and connect them to the Start block. Select everything but the Start block and select ToolsMy Block Builder. Name it Forward3 and select an appropriate icon. Add the following parameters:
  • BrakeAtEnd: Parameter Type Input, Data Type Logic, Default Value True, and select an appropriate icon.

  • Distance: Parameter Type Input, Data Type Number, Default Value 5, and select an appropriate icon.

  • Power: Parameter Type Input, Data Type Number, Default Value 30, and select an appropriate icon.

  • GyroIn: Parameter Type Input, Data Type Number, Default Value 0, and select an appropriate icon.

  • GyroOut: Parameter Type Output, Data Type Number, and select an appropriate icon.

  • RcvHandoff : Parameter Type Input, Data Type Logic, Default Value False, and select an appropriate icon.

Double-check to make sure everything is correct, then click Finish to create the My Block.

Now you are ready to set up Forward3 to allow Handoffs, but first drag the output block for GyroOut out of the way so it does not get covered up as you add programming blocks. Begin by adding a Switch block to the very end of the program, and set the mode to Logic. If BrakeAtEnd is true, the robot should stop, so drag the last Move Steering block (the one with mode set to Off) into the True branch of the Switch block, then use a data wire to connect the BrakeAtEnd My Block input to the Logic input of the Switch block. As before in Forward2, connect the Distance input to the “a” input of the first Math block and the Power input to the first Move Steering block (the one inside the loop).

A second Switch block is needed near the beginning of the program to determine what value to load into GyroStart. Place this Switch block before the first Math block, set its mode to Logic, and connect RcvHandoff to its control input. If RcvHandoff is False, the My Block needs to load GyroStart with the value from the gyro sensor, so drag the Gyro Sensor and Variable (GyroStart) blocks to the False branch of the Switch block. In the True branch of the Switch block, GyroStart needs to be loaded with GyroIn, but note that the Switch block will not allow you to connect a data wire when it is in “Flat View ” (try it and see for yourself). It will allow this action when in “Tabbed View .” The view can be toggled back and forth by clicking the upper left corner of the Switch block. Tabbed View only shows one of the multiple branches at a time, however, which I believe makes reading the program code harder. What we will do is always load the value of GyroIn into GyroStart, just before the Switch block, then either leave it alone if RcvHandoff is true or overwrite it with the current gyro sensor value if RcvHandoff is False. To accomplish this, just insert a Variable block for GyroStart, with mode set to “Write – Numeric,” just before the Switch block, then connect GyroIn to it with a data wire. Finally, add a GyroStart Variable block to the end of the program chain, with mode set to “Read – Numeric,” and wire its output to the GyroOut output of the My Block. The program should look something like Figure 7-2. Modify the comments appropriately and try it. Remember that there must be a block after Forward3 in the program to test whether the motors really continue running. A Wait block set for a time of a few seconds works well for this type of test.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig2_HTML.jpg
Figure 7-2

Forward3 My Block with option to stop or continue running at end

Forward3 can be copied, named Backup3, and modified with the same four changes that were made to convert Forward2 to Backup2:
  • Negate the Distance conversion factor because the motor counters will be starting at zero and decrementing to negative values.

  • Change the Loop block exit condition from “≥” to “≤”.

  • Reverse the steering correction by changing the formula from “(a-b)*c” to “(b-a)*c”, or by negating the gain value, “c”.

  • Add a Math block before the loop to negate the Power input before it is passed to the Move Steering block inside the loop.

Of course, remember to adjust the comments appropriately.

Accelerating and Decelerating Using Forward3 My Blocks

Learning topics covered: My Blocks, torque , traction

This section and the next address the fourth requirement stated at the beginning of this chapter: Move as quickly as possible without wheel slip. The problem is traction. If the motor power is set to a starting value that is too high, the wheels or tires can slip (i.e., “peel out”) as the robot picks up speed from a standstill. Likewise, the wheels can skid if the robot stops suddenly. The solution presented here is to accelerate smoothly to some maximum speed, then decelerate smoothly.

A relatively simple solution uses the Forward3 My Block from the previous section. Acceleration and deceleration will be implemented in discrete steps by cascading multiple Forward3 blocks together. The following example describes how to begin from a standstill, accelerate to a top speed, and then decelerate and stop. It uses several Forward3 blocks, and requires some trial and error to verify proper operation.

Begin with a Forward3 block with a starting power that will not generate wheel slip. For the robots that my team has used over the years, a power of 20 was usually safe, although this is a determination you will have to make experimentally. The following assumptions apply to this example:
  • A starting power of 20 percent will not generate wheel slip.

  • Power increases in steps of 20 percent will not generate wheel slip while the robot is moving.

  • 1" is a sufficient distance for each acceleration step.

  • Maximum desired power is 80 percent.

  • Distance to move is 20".

The implementation involves seven Forward3 blocks. The first block uses a power of 20 for a distance of 1", with BrakeAtEnd set to False. The second and third blocks are the same, except that each uses a power 20 percent higher than its preceding block. The fifth, sixth, and seventh blocks each step power down 20 percent, and BrakeAtEnd is True for the final block. Because blocks 1 through 3 and 5 through 7 each specify a distance of 1" (6" total), the fourth block, running at 80 percent power, specifies the remaining 14" for a total distance of 20". This program is shown in Figure 7-3.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig3_HTML.jpg
Figure 7-3

Acceleration and deceleration implemented with cascaded Forward3 My Blocks

If wheel slip occurs, which might only be noticeable by observing inconsistent distances, the acceleration and deceleration could be made less aggressive by using smaller power increments and decrements at each step. Alternatively, if quicker transit time is desired, the program could be made more aggressive by using larger power steps if it does not cause wheel slippage.

This approach to acceleration, although it works, is tedious to use inside a program and can result in very large programs.

Accelerating and Decelerating with a Single My Block

Learning topics covered: My Blocks, geometry , unit conversion , feedback , looping constructs , proportional control , variables, conditional constructs , torque , traction

Implementing acceleration and deceleration inside a single My Block results in cleaner programs, but the My Block itself involves a substantial increase in complexity over any of the programs developed to this point in the book. If done well, however, it should be simpler to use, smoother, and less error prone.

Before digging into the program, it is useful to think through what it must do at a conceptual level. Let us first consider the case of a robot beginning from a standstill, accelerating to some maximum speed, maintaining that speed for some distance, then decelerating to a stop. This is illustrated in Figure 7-4(a). Inputs to the My Block would include the maximum speed and distance to travel. The rate of acceleration and deceleration would be a constant value that would depend on factors like the wheel or tire size and texture of the mat surface. This value can be determined experimentally, but based on my experience with FLL robots, a good starting point is probably one wheel rotation, 360°, to accelerate from a stop to top speed. The motor blocks allow us to control power, which is essentially the same as speed, so let’s substitute power for speed on the vertical axis of Figure 7-4(a). The acceleration rate is the slope of the line labeled Accelerate. The vertical distance is then 100 percent power. The horizontal distance is one wheel rotation, 360°. The slope of the line is thus the rate of change in speed or power, so we will call it ChgRate:
$$ ChgRate=frac{100\% Power}{360^{{}^{circ}}}=0.278frac{\%}{{}^{{}^{circ}}} $$
(10)
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig4_HTML.jpg
Figure 7-4

Basic accelerate /decelerate plots

We define ChgRate as a constant in the My Block, which we will name Forward4 . For deceleration we negate ChgRate so that it is a negative number with the same magnitude.

There are three values in Figure 7-4(a) that must be calculated inside the My Block. They are depicted in red italics in the figure: EndAccel, StartDecel, and DistDeg. DistDeg is the same as Distance in the previous Forward My Blocks, except converted from inches to degrees. The value was calculated in previous My Blocks, so it only needs to be saved to a variable in the Forward4 My Block. EndAccel is the distance (in degrees) at which the robot reaches top speed (motor power), which is the same as the distance needed to accelerate . StartDecel is the point (in degrees) at which the robot must begin decelerating. Before finding this value, the distance needed to decelerate must first be calculated. We call this value DecelDist. Also, because the variable name StartDecel is too long to show completely inside the name window of a Variable block , the name is shortened to StrtDecel.

At-speed handoffs complicate the calculations a bit because the starting or ending powers might be nonzero. This introduces two more inputs: StartPwr and EndPwr.

The rest of the inputs and output for the Forward4 MyBlock will be the same as for the Forward3 My Block: MaxPwr (replaces Power), Distance, GyroIn, GyroStart, RcvHandoff , BrakeAtEnd, and GyroOut. The inputs, outputs, and key internal values are summarized in Table 7-1.
Table 7-1

Forward4 My Block Parameters

Parameter

Unit

Type

StartPwr

%

Input

MaxPwr

%

Input

EndPwr

%

Input

Distance

Inches

Input

GyroIn

Degrees

Input

RcvHandoff

Logic

Input

BrakeAtEnd

Logic

Input

EndAccel

Degrees

Internal, calculated

DecelDist

Degrees

Internal, calculated

StrtDecel

Degrees

Internal, calculated

DistDeg

Degrees

Internal, calculated

ChgRate

%/degree

Internal, constant

GyroStart

Degrees

Internal storage for GyroIn

GyroOut

Degrees

Output

Before we begin programming, it will be useful to think about what the Forward4 My Block must do at a high level. We do this by first listing the tasks to accomplish, then representing it visually with a flowchart . The tasks to be performed are as follows.
  1. 1.

    Input several values: StartPwr, MaxPwr, EndPwr, Distance, GyroIn (stored in GyroStart), RcvHandoff , and BrakeAtEnd.

     
  2. 2.

    Perform initial calculations for EndAccel, DecelDist, StrtDecel, and DistDeg.

     
  3. 3.

    Execute a loop to increase power (by ChgRate each loop) to some maximum value while adjusting steering to keep direction straight ahead.

     
  4. 4.

    Execute a loop to maintain maximum power, while adjusting steering, until time to start decelerating.

     
  5. 5.

    Execute a loop to decrease power to some minimum value while adjusting steering.

     
  6. 6.

    Either stop both motors or leave them running, depending on the value of BrakeAtEnd.

     
  7. 7.

    Store the value of GyroStart into GyroOut so it will be passed to the next My Block, in case it is needed.

     
A flowchart is a graphical representation of the procedures to be executed by a program. Figure 7-5 shows these steps illustrated in a flowchart. Notice the similarity of the sections in the gray shaded boxes. It looks like an opportunity to make a My Block that will be embedded inside this My Block! Is this possible? Yes, and in this case it makes a lot of sense.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig5_HTML.jpg
Figure 7-5

Flowchart of Forward4 My Block

Begin by creating a My Block with the appropriate inputs and output. The start of this My Block will look much like the Forward3 My Block, so select the first three blocks of Forward3 and open the My Block Builder window. Set up the following inputs and output:
  • StartPwr, Input, Number, Default Value 0.

  • MaxPwr, Input, Number, Default Value 60.

  • EndPwr, Input, Number, Default Value 0.

  • Distance, Input, Number, Default Value 12.

  • GyroIn, Input, Number, Default Value 0.

  • RcvHandoff , Input, Logic, Default Value False.

  • BrakeAtEnd, Input, Logic, Default Value True.

  • GyroOut, Output, Number.

The first part of Forward4 should look similar to Figure 7-6.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig6_HTML.jpg
Figure 7-6

First part of Forward4 , similar to Forward3

The next section of the program will calculate EndAccel, DecelDist, DistDeg, and StrtDecel, then determine whether there is sufficient room for the robot to accelerate and decelerate in the allotted distance.

The variables StartPwr and MaxPwr are used later in the program, so start by defining them. From the Data Operations programming tab, drag a Variable block to the end of the program chain. Name it StartPwr and set its mode to “Write – Numeric.” Click the name box in its upper right corner and select Add Variable . Type StartPwr for the variable name and press Enter. Connect the My Block input StartPwr to its input with a data wire. Repeat the process to create a variable named MaxPwr, also wired to the corresponding My Block input.

Next, add the variable ChgRate. Set its mode to “Write – Numeric” and its value to 0.278. Drag another Variable block to the end of the program chain, set its mode to “Read – Numeric,” click the name box, and choose “ChgRate.” Now we are ready to begin the calculations. Figure 7-7 illustrates the initialization of StartPwr and MaxPwr, as well as the calculations described later of EndAccel, DecelDist, DistDeg, and StrtDecel.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig7_HTML.jpg
Figure 7-7

Calculating EndAccel, DecelDist, DistDeg, and StrtDecel

EndAccel and DecelDist can be calculated using the standard linear equation from basic algebra:
$$ y= mx+b $$
(11)
where y is the final motor power (which correlates to robot speed), m is the rate of acceleration (+ChgRate) or deceleration (–ChgRate), x is the horizontal distance in degrees of wheel rotation, and b is the starting motor power (~robot speed).
Solving for x and substituting values to find EndAccel yields:
$$ x=frac{y-b}{m}	o EndAccel=frac{MaxPwr- StartPwr}{ChgRate} $$
(12)
Equation 12 is straightforward to implement with an advanced Math block, so add a Math block to the end of the program chain, set its mode to “ADV,” and set the equation to (a-b)/c. Use data wires to make the following connections to the Math block:
  • “a” Math block parameter: MaxPwr input.

  • “b” Math block parameter: StartPwr input.

  • “c” Math block parameter: ChgRate variable.

Add a Variable block to the end of the program chain with mode set to “Write – Numeric.” Click the variable naming box, select “Add Variable,” and create a new variable named EndAccel. Wire the output of the Math block to the input of the EndAccel variable. This is illustrated in the first four blocks of Figure 7-7.

DecelDist can be found using the same approach as EndAccel:
$$ DecelDist=frac{EndPwr- MaxPwr}{- ChgRate}=frac{MaxPwr- EndPwr}{ChgRate} $$
(13)
Add another Math block to the program, “ADV” mode, formula (a-b)/c, and use data wires to make the following connections:
  • “a” Math block parameter: MaxPwr My Block input.

  • “b” Math block parameter: EndPwr My Block input.

  • “c” Math block parameter: ChgRate variable.

As with EndAccel earlier, add a Variable block to the end of the program chain, with mode set to “Write – Numeric.” Click in the variable name box, select “Add Variable ,” and create a new variable named DecelDist. Wire the output of the Math block to the input of the DecelDist variable, as shown in Figure 7-7.

The distance to be traveled, in degrees, was calculated in Forward, Forward2, and Forward3 . The difference in Forward4 is that the value will be stored into a variable named DistDeg. As in the previous My Blocks, add a Math block to the program chain with mode set to Multiply. Wire its inputs using data wires:
  • “a” Math block parameter: Distance input.

  • “b” Math block parameter: 51.4 (or whatever is appropriate to convert inches to degrees of wheel rotation for your robot).

Then, add a Variable block with mode set to “Write – Numeric,” create a new variable named DistDeg, and wire the output of the Math block to its input, as shown in Figure 7-7.

Next, calculate the point where the robot must begin decelerating, StrtDecel. It is the difference between DistDeg and DecelDist:
$$ StrtDecel= DistDeg- DecelDist $$
(14)

To do this calculation, add two Variable blocks to the program chain with mode set to “Read – Numeric”: one for DecelDist and the other for DistDeg. Then add a Math block configured to Subtract, and another Variable block with mode set to “Write – Numeric” for parameter StrtDecel. Wire the first two variables to the Math block’s input, and the Math block’s output to StrtDecel, as shown in Figure 7-7.

The next task the program needs to perform is to consider the My Block’s input parameters and determine whether they allow enough space to accelerate and decelerate . If there is, the program can continue normally, but what if there is not? How can we know, and how do we deal with that situation?

The test to determine if there is enough space is straightforward. Refer to Figure 7-4 again. In Figure 7-4 (a and b) there is sufficient room because DistDeg is at least as big as the sum of EndAccel and DecelDist, and that is the test:
$$ DistDegge AccelDist+ DecelDist $$
(15)

If this condition is true, then the program can continue operating. Otherwise, as shown in Figure 7-4(c), there is not enough room and the program must somehow handle an error condition. In this case there are so many different situations that could lead to this error that it is probably wise to just flag it, stop the program, and let the user make appropriate adjustments to the My Block parameters.

To determine if there is enough room to accelerate and decelerate , we sum EndAccel and DecelDist, calculate DistDeg, compare those two numbers, and output a logic value to a Switch block. In the True branch of the Switch block, the program will continue normal operation. In the False branch it will flag an error and stop execution. Next, we add blocks to implement these steps.

Add a Variable block to the program chain, configured as “Read – Numeric,” for the variable EndAccel. Do the same for the variable DecelDist. Then add a Math block in “Add” mode and connect the EndAccel and DecelDist variables to its inputs with data wires, as shown in the first three blocks of Figure 7-8.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig8_HTML.jpg
Figure 7-8

Determining if there is enough room to accelerate and decelerate

Add a Variable block for DistDeg next, with mode set to “Read – Numeric,” followed by a Compare block with mode set to “Greater Than or Equal To.” This block will perform the test to determine if there is enough room to accelerate and decelerate . Connect the DistDeg Variable block output to the Compare block “a” parameter input with a data wire. Connect the “Add” Math block, the output of which is EndAccel+DecelDist, to the Compare block “b” parameter input. Finally, add a Switch block to the program chain, with mode set to Logic, and connect the Compare block output to the Switch block input with a data wire, as shown in Figure 7-8.

The True branch of the Switch block will contain instructions to make the robot accelerate, maintain speed as needed, and decelerate . The False branch of the Switch block will contain code to handle situations when there is not enough room to accelerate and decelerate fully. Let’s deal with the False branch first. When there is not enough room to accelerate and decelerate, we need to provide clear feedback to the user and terminate the program early. The feedback will take two forms: The brick status light will turn red and an error message will be displayed. We will also turn off the drive motors before exiting the Switch block.

Turning the brick status light to red is easy. From the Action tab, drag a Brick Status Light block into the False branch of the Switch block, set its mode to “On,” Color to “2” (red), and Pulse parameter to “False.” Next, add a Move Steering block with mode set to “Off” and Brake at End parameter set to “False,” as shown in Figure 7-9. (Turning off Brake at End will allow the robot to coast down instead of suddenly halting, which is probably better if it happens to be at a high motor power.)
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig9_HTML.jpg
Figure 7-9

Code to turn brick status light red, stop motors, and output error message

A good error message should be clear, so we will use several lines to describe the problem. The message should be something like the one shown in Figure 7-10. Because this message is five lines it will take five Display blocks. Add a Display block right after the Move Steering block, set its mode to “Text – Grid,” and set the display text (upper right box) to “ERROR:”. Set its parameters as follows:
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig10_HTML.jpg
Figure 7-10

Error message

  • Clear Screen: True.

  • x: 0.

  • y: 0.

  • Color: False.

  • Font: 2.

Add four more Display blocks to the program chain with all of their modes set to “Text – Grid,” Clear Screen and Color set to “False,” x set to “2” (to indent the error description), and Font set to “2.” For the first one set the Text to “Not enough” and y to “3”; the second block’s Text to “room to” and y to “5”; the third block’s Text to “accel and” and y to “7”; and the last block’s Text to “decel.” and y to “9.” The code in the False branch of the Switch block should look something like Figure 7-9.

As depicted in Figure 7-5, when the program is operating normally the next phases will be to accelerate to top speed, maintain that speed if needed, and decelerate to final speed. The same code can be used for all three functions, making it perfect for a My Block. This My Block will need three inputs: starting power, acceleration or deceleration rate, and distance at which to stop accelerating or decelerating.

Because the new My Block will use the wiggle correction code, we can take that code from Forward3. Copy all of the blocks from Forward3 (except the Start, Input, and Output blocks) to a temporary program and delete the blocks before and after the loop . There might be a short black line protruding from the bottom of the Move Steering block’s power input, indicating that the software is confused about how to handle the missing connection. (The My Block input parameters did not come with the code when it was copied, so the connection to the power input was broken.) To remedy this, change the Move Steering block’s mode from On to Off and back to On, then reconnect the data wire from the Math block to the Move Steering block’s Steering input. At this point the new program should look like Figure 7-11. Now we need to add code to increase the power steadily.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig11_HTML.jpg
Figure 7-11

Start of ChgFwdSpd My Block

The new code will go inside the loop (ForwardLoop in Figure 7-11). Its function is to increase the motor power as the robot moves forward. Each time the loop executes, it will calculate a new power based on the distance the robot has traveled since entering the loop. Because the power needs to increase (or decrease, as the case may be) as the robot moves forward, it makes sense to mathematically link the power value to the robot’s distance traveled, as shown in Equation 16.
$$ NewPwr= StChgPwr+{ChgRate}^{ast}left( CurrentDist- StDist
ight) $$
(16)
whereNewPwr is the new power value for Move Steering block, in percent;StChgPwr is the starting change power before the loop started executing, in percent;ChgRate is the rate at which power will change, in percent per degree of wheel rotation;CurrentDist is the total distance traveled, in degrees of wheel rotation; andStDist is the distance traveled before the loop started executing, in degrees of wheel rotation.
Thus, the quantity (CurrentDist – StDist) is the distance the robot has traveled since beginning loop execution. Multiplying that quantity by ChgRate gives the amount of power to add to the starting power, StChgPwr, and it increases steadily as the robot moves forward. StChgPwr and ChgRate will be inputs to the My Block. StDist can be read from a motor rotation sensor before the loop begins, and CurrentDist can be read from a motor rotation sensor each time the loop executes. Because the NewPwr formula involves four parameters, it can be done with a single math block in Advanced mode. The first part of the loop should look something like Figure 7-12. Note that variables have been created for StDist, ChgRate, and StChgPwr. These variables must also be inserted in front of the loop, where they are in Write mode so they can be loaded with values. Inside the loop they are in Read mode so their values can be passed to the Math block. Using variables in this fashion keeps the data wires inside the loop rather than crossing the loop boundary, as shown in Figure 7-13.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig12_HTML.jpg
Figure 7-12

First part of loop in ChgFwdSpd My Block

You might want to manually type values into the data variables (and also the loop Threshold value) to experiment with the program before you convert it to a My Block. Once you are ready, create the My Block ChgFwdSpd with inputs ChgDist, StChgPwr, and ChgRate. It should look something like Figure 7-13. Take some time to experiment with using ChgFwdSpd in a program before moving on.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig13_HTML.jpg
Figure 7-13

ChgFwdSpd My Block

There is a new issue that might show up in the ChgFwdSpd My Block. Recall that we tuned the gain in Forward3 using a relatively low power (~30 percent) for the drive motors to prevent wheel slippage. If the robot tracks well and the steering is stable across a wide range of speeds, a fixed gain is fine. If the robot does not track well or it exhibits steering oscillations at some speeds, it might be appropriate to vary the gain with speed: higher gain for higher speeds, lower gain for lower speeds. A Math block, inserted after the Math block that computes drive motor power, can do this. Set the Math block to Divide mode, connect the computed motor power to the “a” input, and set the “b” input to a value that allows the robot to track without steering oscillations. For my robot a value of 15 worked well. A little experimentation should reveal a value that works for your robot.

Forward4 is almost done. The next thing to do is add the programming blocks to populate the True portion of the Switch block. Take another look at the flowchart of Figure 7-5. Three ChgFwdSpd My Blocks are needed: one to accelerate, one to maintain top speed, and one to decelerate . Start with the blocks to accelerate . These blocks will start the B and C motors at power of StartPwr, and increase the power at a rate of ChgRate until it reaches the distance EndAccel. In the True branch of the Switch block, add the three variables ChgRate, StartPwr, and EndAccel, all in mode “Read – Numeric.” Then add a ChgFwdSpd My Block and wire the variables to the corresponding inputs of ChgFwdSpd, as shown in Figure 7-14.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig14_HTML.jpg
Figure 7-14

Blocks in Forward4 to accelerate

The next three blocks will maintain top speed by holding the B and C motors at MaxPwr until it is time to begin decelerating at the distance of StrtDecel. Add MaxPwr and StrtDecel to the program chain in mode “Read – Numeric,” then insert a ChgFwdSpd My Block. The parameter ChgRate should be 0, so set that value manually, then wire the two variables to the appropriate ChgFwdSpd inputs, as shown in Figure 7-15.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig15_HTML.jpg
Figure 7-15

Blocks in Forward4 to maintain top speed

The last several blocks will decelerate the robot from MaxPwr at a rate of –ChgRate until DistDeg is reached. An extra Math block is needed to negate ChgRate, so add the variable ChgRate in mode “Read – Numeric” to the program chain, followed by a Math block in Multiply mode. Wire ChgRate to the Math block’s “a” input, and set the “b” input to a value of –1. Insert MaxPwr and DistDeg variables and a ChgFwdSpd My Block. Wire the Math block output to the ChgRate input of the ChgFwdSpd My Block, DistDeg to the ChgDist input, and MaxPwr to the StChgPwr input, as shown in Figure 7-16.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig16_HTML.jpg
Figure 7-16

Blocks in Forward4 to decelerate

The entire Switch block with True program chain to accelerate and decelerate , and False program chain to turn the brick status light red, stop both motors, and output an error message is shown in Figure 7-17.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig17_HTML.jpg
Figure 7-17

Switch block to accelerate and decelerate (True branch) or stop robot and indicate error (False branch)

Only two things remain: stopping both motors if BrakeAtEnd is True, and outputting the value of GyroStart (to the My Block output GyroOut) in case there is another My Block following Forward4 .

First insert a variable block at the very beginning of the program with mode set to “Write –Logic,” and set the variable name to BrakeAtEnd. Wire the My Block input BrakeAtEnd to this variable. Note that although they have the same name, the My Block input parameter BrakeAtEnd is not the same as the variable BrakeAtEnd, which is why the former must be wired to the latter.

Next, add another variable block to the very end of the program, with mode set to “Read – Logic” and name set to BrakeAtEnd. Insert a Switch block in Logic mode, and wire the BrakeAtEnd variable to its input. Inside the True branch of the Switch block, insert a Move Steering block set to mode Off. Finally, add a Variable block set to mode “Read – Numeric” and name set to GyroStart, and wire it to the GyroOut output of the My Block. The end of the Forward4 program should look like Figure 7-18.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig18_HTML.jpg
Figure 7-18

Last part of Forward4 My Block

Remember to add comments. They will be very important in a My Block as large and complicated as Forward4 . The full Forward4 My Block is shown in Figure 7-19.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig19_HTML.jpg
Figure 7-19

Forward4 My Block

Adding Handoffs to LineFind

Learning topics covered: My Blocks, feedback , looping constructs , conditional constructs

Handoffs at speed are probably most useful when transitioning from one type of My Block to another. For instance, the black lines on a competition mat can be very useful as is, but what if one wants to find a line and keep moving, instead of stopping? If the handoff feature implemented in the earlier My Blocks is implemented in the LineFind My Block, then the robot could move forward until it is close to the line (e.g., using a Forward4 My Block), then find the line to get a position fix (waypoint), and hand off to another Forward4 My Block without ever slowing down. This approach would not only eliminate wasted time stopping and starting, but also allow the robot to move at a relatively high speed, saving even more time. Let’s modify the LineFind My Block to incorporate handoffs at speed.

Begin by copying the FindWhite and FindBlack loops from LineFind and pasting them into a new program. Next, copy the first three blocks (Motor Rotation, GyroStart Variable , and Switch blocks) from Forward3 and insert them just before the FindWhite loop in the new program.

Because the robot will sometimes continue moving after it finds the black line, it will be helpful to have some user feedback to indicate whether the robot detects the line when it passes over it. We can do this by changing the brick status light to a different color. From the Action tab, drag a Brick Status Light block to the end of the program chain, right after the FindBlack loop . Set its mode to On, Color to 1 (orange), and Pulse to False. As this block is almost at the end of the program, you will need to leave the light on or it will flash so quickly that it will not be noticeable. This means that the calling program (the program that contains this My Block) will have to turn it back to flashing green. We will return to that after we finish the My Block.

Now, copy the Switch block and GyroStart Variable block at the end of Forward3 , and paste them to the end of the program chain. Select all of the blocks in the new program, except the Start block, then go to ToolsMy Block Builder. Name the My Block LineFind2, select an appropriate icon, and set up its parameters as follows:
  • BrakeAtEnd: Input, Logic, default True.

  • Port: Input, Number, default 1.

  • Power: Input, Number, default 30.

  • RcvHandoff : Input, Logic, default False.

  • GyroIn: Input, Number, default 0.

  • GyroOut: Output, Number.

Remember to pick an appropriate icon for each parameter, double-check everything, and click Finish to create LineFind2. Finally, wire the inputs and outputs as follows:
  • GyroIn to the first GyroStart variable block .

  • RcvHandoff to the input of the first Switch block.

  • Power to the Power input of each Move Steering block.

  • Port to the Port input of each Loop block.

  • BrakeAtEnd to the input of the last Switch block.

  • The output of the final GyroStart Variable block to the GyroOut output of the My Block.

Of course, don’t forget to properly comment your new My Block, which should look something like Figure 7-20.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig20_HTML.jpg
Figure 7-20

LineFind2 My Block with handoff capability

Now, let’s write a brief test program to make sure the handoff function works properly, and to see how to handle the orange light. Recall that the brick status light normally flashes green while a program is running. A good practice for dealing with the light is to add code to the calling program that leaves the light orange for a second or two, then changes it back to flashing green. That way you will know that the program is operating normally until the status light is changed to orange or red by another program block.

Create a new program and insert a Forward4 My Block, then a LineFind2 My Block, and last a Forward4 My Block. Set the My Blocks’ parameters as follows:
  • First Forward4: StartPwr 20, MaxPwr 100, EndPwr 100, Distance 12, GyroIn 0, RcvHandoff False, BrakeAtEnd False, and wire GyroOut to the GyroIn input of the LineFind2 My Block.

  • LineFind2: BrakeAtEnd False, Port 1 (or whatever port is used for the color sensor), Power 100, RcvHandoff True, and wire GyroOut to the GyroIn input of the last Forward4 My Block.

  • Last Forward4 : StartPwr 100, MaxPwr 100, EndPwr 20, Distance 8, RcvHandoff True, and BrakeAtEnd True.

Dealing with the status light is a perfect time to use parallel program execution. Instead of adding the following blocks to the end of the program chain, add them underneath the last Forward4 My Block, connected to each other but not the rest of the program:
  • Wait block : Mode Time, Seconds 1 (or 2).

  • Brick Status Light block: Mode On, Color 0 (green), Pulse True.

  • Wait block: Mode Time, Seconds 2.

Grab the Sequence Plug Exit of the LineFind2 My Block and drag it to the Sequence Plug Entry of the first Wait block . The test program should look something like Figure 7-21. Position the robot more than a foot away from a black line and run the program. The robot should accelerate smoothly to top speed, navigate straight to the black line, turn the status light orange while continuing at top speed, decelerate and stop 8” after the black line, and wait for a couple of seconds with the green light flashing.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig21_HTML.jpg
Figure 7-21

Handoff test program

The approach used in this section can be used to add Handoffs to other programs, such as LineFollow , LineTFind , WallFollow , and WallLean . Once you do this you will have a fairly complete and potent suite of My Blocks to enable navigation to pretty much any point on the game board, allowing you to focus more on the mission programming.

Combo Program

Learning topics covered: My Blocks, looping constructs , conditional constructs

For competition, it is normally most effective to combine multiple missions together into a “mission set” on the game board so that a single program can accomplish them before the robot returns to base. Once back in base, the two team members at the table reconfigure the robot by changing attachments and selecting a different program to execute the next mission set. Selecting the next program requires scrolling up or down to the correct program, which usually takes a few seconds and occasionally leads to an error (selecting the wrong program). Wouldn’t it be nice if there was a way to avoid that error-prone selection process and save a few seconds at the same time?

Toward the end of our last season, my son, Graham, came up with a really cool idea we called the Combo program, so this section is dedicated to him. The concept uses a Switch block inside of a Loop block. The Loop block is in Unlimited mode, so once the program starts it runs continuously until stopped by the user. The Switch block is in mode Brick Buttons – Measure, which means it executes a different branch dependent on which button is pressed on the brick. Each mission program is converted to a My Block and inserted into a different branch of the Switch block. The default branch contains no blocks, so it does nothing but loop, waiting for the user to press a button on the brick. Because the brick has five buttons, this approach should work for up to five different mission sets.

I should note that we tried to implement this program near the end of the season, were not immediately successful, and decided to abandon it because we were so close to competition. It was not clear whether it did not work because we were doing something wrong or because the mission programs were so complex that the brick could not handle them being converted to My Blocks and executed inside a Switch block inside a Loop block. Theoretically, it should work fine, and the program I describe here worked well, but the My Blocks in this program are very small and simple compared to what the kids were running in competition. Nevertheless, if you want to try it, here’s how.

First, convert your mission programs to My Blocks. Although they do not need inputs, it might be useful to create two or three “dummy” inputs for each one so the My Block is wide enough to display a useful name. Then, create a new program and name it Combo. Add a Loop block to start the program chain, and name it InfiniteLoop (or a similarly descriptive name). Place a Switch block inside the Loop block, and set its mode to “Brick Buttons – Measure.” Click the “Add Case” button (see Figure 7-22) until there is one more case than the number of your mission sets. For example, five mission sets requires six cases in the Switch block. For each branch, click the indicator at the top and select a different button to activate it. Select the default button for the “no button press” branch. Finally, place a different mission program My Block into each branch of the Switch block. Leave the “no button press” branch empty. Your program should look something like Figure 7-23.
../images/461934_1_En_7_Chapter/461934_1_En_7_Fig22_HTML.jpg
Figure 7-22

Switch block controls and indicators

../images/461934_1_En_7_Chapter/461934_1_En_7_Fig23_HTML.jpg
Figure 7-23

Combo program

Conclusion

If you have successfully implemented the My Blocks described in this chapter, you should have a powerful suite of My Blocks to help your robot navigate quickly and accurately on a game board. Next, the final chapter moves away from programming to discuss several topics related to building and managing a team, preparing for competition, and competing.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.31.209