Controls

Controls (aka "Control Flow") change the flow of your program and enable conditional or branching logic. For example, "if speed > 20, then turn LED lights red." There are lots of different types of controls to make interesting programs that go beyond a procedural set of Movement commands.

Delay

controls_delay await delay(4) continues to run active code for a duration(s), or creates a gap in activity if there are no active blocks. For example, use the below to set Speed to 100 for a duration of 4s, then stop:

async function startProgram() {
    setSpeed(100);
    await delay(2);
    setSpeed(0);
}

Loop

controls_loop

A loop (aka a "for" loop) repeats the designated code for a given number of times.

In Javascript, you define for loops via this template:

for (initialize loop variable; check loop condition; update loop variable) {
    // code to repeat goes here (contained between the '{' and '}' braces)
}

Here's a simple example that spins 90 degrees and says "Spin" 8 times.

async function startProgram() {
	setBackLed(255);
	for (var count_1 = 0; count_1 < 8; count_1++) {
		await speak('Spin', true);
		setHeading((getHeading() + 90));
		await delay(0.25);
	}
}

Notice that var count_1 creates a "loop variable" called count_1 to track the iterations through the loop. When you define new loop variables, you can use any name you like as long as it is unique.

A fun use of loops to blink random colors. To set a random color on the main LED's every 0.2s for 20 loops, use:

async function startProgram() {
	for (var count_1 = 0; count_1 < 20; count_1++) {
		setMainLed({ r: getRandomInt(0, 255), g: getRandomInt(0, 255), b: getRandomInt(0, 255) });
		await delay(0.2);
	}
}


To add a second loop to the random color program you need a new, unique variable name. An easy way to do this is to increment the count_# value using count_2. For example, the code below runs the random color loop, then uses a second loop that replicates the colors of a traffic light 4 times:

async function startProgram() {
	// random colors
	for (var count_1 = 0; count_1 < 20.0; count_1++) {
		setMainLed({ r: getRandomInt(0, 255), g: getRandomInt(0, 255), b: getRandomInt(0, 255) });
		await delay(0.1);
	}
	//traffic light
	for (var count_2 = 0; count_2 < 3.0; count_2++) {
	    setMainLed({ r: 0, g: 255, b: 0 });
		await delay(0.8);
		setMainLed({ r: 255, g: 243, b: 14 });
		await delay(0.8);
		setMainLed({ r: 255, g: 0, b: 0 });
		await delay(0.8);
	}
}

Loop Until

controls_loopUntil Loop until (aka "while not false" loop) repeats the code within until a condition is met. You will need to understand how to write conditions with Operators and Comparators before using Loop Until and the rest of the controls below.

while ( !testCondition ) {
    // code to loop until testCondition() is true, then exit the loop
}

In this template, testCondition is an expression that evaluates to true or false. The ! operator, meaning "not", reverses the value of the test condition. So, if the test condition is true, !test condition will evaluate to false and the loop will end. In other words, the loop terminates when the test condition becomes true.

For example, you can repeats speed increases and use Loop Until to reach a "Speed Limit", such as is 80 in this example. Given 20 + (20*x) = 80, you should see the Loop repeat 3 times (hearing the Notification sound each time) before reaching Speed 80 and then stopping with the Skid sound. You will need about 12ft of clear floor space to run this program:

async function startProgram() {
	setMainLed({ r: 33, g: 255, b: 20 });
	setSpeed(20);
	while ( !(getSpeed() === 80.0) ) { // Could also use Javascript's !== (not equal to) comparator
		await Sound.Game.Notification.play(true);
		setSpeed((getSpeed() + 20));
		await delay(1.5);
	}
	setMainLed({ r: 255, g: 26, b: 62 });
	setSpeed(0.0);
	await Sound.Mechanical.Skid.play(true);
}

Loop Forever

controls_loopForever Loop Forever (aka "while true" or "while 1" loop) repeats the code within forever, or until you stop the program.

while (true)
{
    // code to loop forever
}


For example, to create a game themed metronome that runs forever, use:

async function startProgram() {
	setBackLed(255);
	while (true) {
		await Sound.Game.Coin.play(true);
		setHeading((getHeading() + 180));
		await delay(1.2);
		await Sound.Game.Hit.play(true);
		setHeading((getHeading() - 180));
		await delay(1.2);
	}
}


You can nest a while loop inside the while 1 loop to make the metronome more interesting. For example, this version of the metronome replaces the delay code with a light sequence using a loop of light commands:

async function startProgram() {
	setBackLed(255.0);
	while (true) {
		await Sound.Game.Coin.play(true);
		setHeading((getHeading() + 180.0));
		//green light blinks
		for (var green_count = 0; green_count < 6; green_count++) {
			setMainLed({ r: 9, g: 255, b: 5 });
			await delay(0.1);
			setMainLed({ r: 255, g: 247, b: 245 });
			await delay(0.1);
		}
		await Sound.Game.Hit.play(true);
		setHeading((getHeading() - 180.0));
		//red light blinks
		for (var red_count = 0; red_count < 6; red_count++) {
			setMainLed({ r: 255, g: 15, b: 0 });
			await delay(0.1);
			setMainLed({ r: 255, g: 233, b: 227 });
			await delay(0.1);
		}
	}
}

If Then

controls_ifThen If Then statements execute the code within only if the given condition is true.

if (condition) {
    // code executed if condition is true
}


For example, if you hold the robot and shake it, the lights will turn green and speak "Shake". You need to nest an if...then statement within a while (true) loop like the one below. The parent while (true) keeps your program running forever, which gives you time your robot one or more times.

async function startProgram() {
	setStabilization(false);
	setBackLed(255);
	while (true) {
		if ((Math.sqrt((getAcceleration().x ** 2) + (getAcceleration().y ** 2) + (getAcceleration().z ** 2)) > 1.4)) {
			await speak(buildString("Shake"), false);
			setMainLed({ r: 0, g: 255, b: 0 });
			await delay(1);
		}
		await delay(0.025);
	}
}


Or

The OR operator, ||, allows the code to execute if any of a set of conditions is true. Let's take the prior program to make it so that the forward pitch or the table tap will change the main LED's to green:

async function startProgram() {
	setStabilization(false);
	setBackLed(255);
	while (true) {
		if (((Math.sqrt((getAcceleration().x ** 2) + (getAcceleration().y ** 2) + (getAcceleration().z ** 2)) > 1.4) || (getOrientation().pitch < -45))) {
			await speak(buildString("Shake or Pitch"), false);
			setMainLed({ r: 0, g: 255, b: 0 });
			await delay(1);
			setMainLed({ r: 0, g: 0, b: 0 });
		}
		await delay(0.025);
	}
}


And

The AND operator, &&, requires additional conditions to be true. You can add as many required conditions as you want, but let's just add a second requirement to get the LED's to turn green. The second condition will be a forward pitch measured by getOrientation().pitch. You will need to aim the robot ensuring the tail light faces you, pitch it forward 45°, then tap it on the table and the LED's will turn green if you have the pitch angle correct:

async function startProgram() {
	setStabilization(false);
	setBackLed(255);
	while (true) {
		if (((Math.sqrt((getAcceleration().x ** 2) + (getAcceleration().y ** 2) + (getAcceleration().z ** 2)) > 1.4) && (getOrientation().pitch < -45))) {
			await speak(buildString("Shake and Pitch"), false);
			setMainLed({ r: 0, g: 255, b: 0 });
			await delay(1);
			setMainLed({ r: 0, g: 0, b: 0 });
		}
		await delay(0.025);
	}
}


If Then Else

controls_ifThenElse If Then Else statements execute the code contained within the "if" code when the given condition is true; otherwise performs the "else" code.

if (condition) {
        // code executed if condition is true
    } else {
        // code executed if condition is false
    {
}


For example, let's build on the "if then" sample above by offering an "else" condition that sets the LED's to red when the condition is not true, but still turns green when you shake it:


async function startProgram() {
	setStabilization(false);
	setBackLed(255);
	while (true) {
		if ((Math.sqrt((getAcceleration().x ** 2) + (getAcceleration().y ** 2) + (getAcceleration().z ** 2)) > 1.4)) {
			await speak(buildString("Shake"), false);
			setMainLed({ r: 0, g: 255, b: 0 });
			await delay(1);
		} else {
			setMainLed({ r: 255, g: 0, b: 0 });
		}
		await delay(0.025);
	}
}


To create > 2 outcomes you can nest N "if then else" statements. For example, let's create a program with 3 conditions where the LED's are red at rest, blink green when you shake the robot and blink blue when you pitch the robot forward:

async function startProgram() {
	setStabilization(false);
	setBackLed(255);
	while (true) {
		if ((Math.sqrt((getAcceleration().x ** 2) + (getAcceleration().y ** 2) + (getAcceleration().z ** 2)) > 1.4)) {
			await speak(buildString("Shake"), false);
			setMainLed({ r: 0, g: 255, b: 0 });
			await delay(1);
		} else {
			if ((getOrientation().pitch < -45)) {
				await speak(buildString("Pitch"), false);
			    setMainLed({ r: 0, g: 0, b: 255 });
				await delay(1);
			} else {
			    setMainLed({ r: 255, g: 0, b: 0 });
				});
			}
		}
		await delay(0.025);
	}
}

Exit

controls_ExitProgram

exitProgram ends a program, the same as tapping the Stop button. For example, if you wanted a program to exit after one tap, use:

async function startProgram() {
	setStabilization(false);
	setBackLed(255);
	while (true) {
		if ((Math.sqrt((getAcceleration().x ** 2) + (getAcceleration().y ** 2) + (getAcceleration().z ** 2)) > 1.4)) {
			await speak(buildString("Shake"), false);
			setMainLed({
			setMainLed({ r: 0, g: 255, b: 0 });
			});
			await delay(1);
			await speak(buildString("Exit Program"), true);
			exitProgram();
		}
		await delay(0.025);
	}
}


Await

await requires a time-based command to complete. This automatically added to commands that require it in the block canvas like await roll and await delay that include a duration of time:

async function startProgram() {
	await roll(90, 100, 2);
}

Return

Return terminates the execution of a function and returns control to the calling function. A return statement can also return a value to the calling function. This is not available in the block canvas.

In the text canvas, you can use return to make functions that perform tasks you might re-use several times in your code, but these cannot be async functions, or have async functions in their body:

roundToTenths = function(decimalNum) {   // <-- Notice we didn't declare this function 'async'
    // No 'async' functions in here!
    var roundedNum = Math.round(decimalNum * 10.0) / 10.0;
    return roundedNum;
};

async function startProgram() {
    speak("Pi is approximately " + roundToTenths(Math.PI));
    await delay(3.0);
    exitProgram();
};