Robot
JavaScript
Compiler
Language
Videos
Simulator
Games
Examples
Download
Cheat sheet

Holiday Lights Examples



Holiday Lights
The EV3 has a three color LED that can display the following colors:
  1. Green
  2. Red
  3. Orange
The examples shown below demonstrate different patterns in computer programming. Recognizing, understanding, and learning how to implement these patterns can help you to improve your programming skills.

The examples below are grouped into three main categories of behavior of the robot:

  1. Regular Flashing (based on timers)
  2. Irregular Flashing (using the random function)
  3. Flashing based on Sensor Input (sensor values as well as event handlers)



Regular Flashing

Example: While Loop
while true {
  setLED(2)
  sleep(500)
  setLED(1)
  sleep(500)
}

Increment and Decrement

Example: Post Increment and Decrement
color=1
while true {
  setLED(color++)    // Adds 1 to the color after the variable has been used
  sleep(500)
  setLED(color--)    // Subtracts 1 from the color after the variable has been used
  sleep(500)
}
Example: Pre Increment and Decrement
color=1
while true {
  setLED(++color)    // Adds 1 to the color before the variable is used
  sleep(500)
  setLED(--color)    // Subtracts 1 from the color before the variable is used
  sleep(500)
}

Use of the Not Operator "!" to Toggle Values

The Not Operator is a single character ("!") that can be used to reverse the Boolean value of a variable. Often this can be used to toggle a variable by assigning the Not variable such as:

a = !a

or:

Ok = !Ok

In the example below, a variable labeled showTheRedLED will contain a value of either true or false. The toggle function defined below will change the value each time the function is executed.

Example: Not Operator used to toggle values
var showTheRedLED = true
function toggleTheLED() {
    showTheRedLED = !showTheRedLED
    setLED(showTheRedLED + 1)
}
setInterval(toggleTheLED, 500)
waitHereWhile(true)
In the above example program you may have noticed that one (1) is being added to the showTheRedLED in the form of the expression:

showTheRedLED + 1

The value of the showTheRedLED variable is currently a Boolean value of either "true" or "false". In JavaScript (and many other languages), true and false are also represented by 1's and 0's. When adding a one (1) to the Boolean value we will end up with values that are 1's and 2's. This allows us to convert our true's and false's into red's and green's.

User-Defined Functions

JavaScript, like other languages, has built-in functions and also allows you to create your own user-defined functions. RobotJavaScript has about 50 built-in functions. The built-in functions perform some of the most basic actions/behaviors of the robot. You can create your own functions (i.e., user-defined functions) that are comprised of the simpler built-in functions as well as other user-defined functions.

You can create your own functions to perform tasks that you want the robot to perform. For example, you could create a function called "greenLED()" that would set the LED to the green color.

You need to use the keyword "function" when creating a function. This will be followed by the "identifier" (i.e., how your function shall be identified in the program). Two sets of symbols are then needed to complete the function definition. You will need to add a pair of parentheses and a pair of curly braces. The basic format of a function definition is shown below:

function myUserFunction() { }

Enter the statements that you want the robot to perform in between the curly braces. In the example below, we are going to simply set the LED using the built-in function: setLED(). To set the LED to a specific color, we enter the number of the color between the parentheses when 'calling' that function (i.e., when using that function in our program).

Example: If-Then-Else along with User-defined functions
function greenLED() { setLED(1) }
function redLED() { setLED(2) }
var showTheRedLED = true
while true {
  showTheRedLED = !showTheRedLED
  if showTheRedLED redLED() else greenLED()
  sleep(500)
}

Use of Two Intervals

The setInterval() function will add the identifier (i.e., the name) of a function (greenLED or redLED in this example) to a stack of timers along with the number of milliseconds between each execution of that function. In the example below, the redLED() function will be executed once per second whereas the greenLED() function will be executed twice per second. Though the greenLED() function is executed twice as often as the redLED() function, the LED appears to give equal time to each since the LED is changed to red once per second--after the greenLED() function was executed.

The setInterval() function illustrates the use of a "call-back" function. The setInterval() function sets the interval of time between each subsequent execution of the "call-back" function. In other words, the "call-back" function is executed every "x" milliseconds. It is important to remember that, when entering a "call-back" function, only the identifier of the function (i.e., its name) is entered. You do not need to enter the parentheses that typically follow all function names.

Example: Use of Two Intervals
function greenLED() { setLED(1) }
function redLED() { setLED(2) }
setInterval(greenLED, 500)
setInterval(redLED, 1000)
waitHereWhile(true)

Ternary Expressions

A Ternary expression is an abbreviated form of the if-then-else expression. The expression is created using the question mark and colon characters.

A condition (entered before the question mark) is evaluated. If the condition is true, then the expression that follows the question mark will be used, otherwise the expression that follows the colon will be used.

In the example below, the setLED() function will receive the value of either 2 or 1 depending on the value of the showTheRedLED variable.

Example: Ternary Expressions
var showTheRedLED = true
while true {
    showTheRedLED = !showTheRedLED
    setLED( showTheRedLED ? 2 : 1 )
    sleep(500)
}
Ternary expressions can include more than just literal numbers such as 1 and 2. You can execute functions (and even entire blocks of code) in the ternary expressions.

Example: Ternary Expressions
function greenLED() { setLED(1) }
function redLED() { setLED(2) }
var showTheRedLED = true
while(true) {
  showTheRedLED = !showTheRedLED
  showTheRedLED ? redLED() : greenLED()
  sleep(500)
}
Example: Ternary Expressions
showTheRedLED = true
while(true) {
  showTheRedLED = !showTheRedLED
  showTheRedLED ? setLED(2) : setLED(1)
  sleep(500)
}

Modulus

The Modulus operator (shown as a single percent sign) returns the remainder of a division problem. For example, 5 divided by 2 would have a remainder of 1. Therefore, the expression "5 % 2" would have the value of 1 and "6 % 2" would have the value of 0. Any integer divided by 2 will have a remainder of either 0 or 1. Since the LED colors for green and red are 1 and 2, we can add 1 to the result of the modulus expression to obtain numbers that we need for the red and green colors.

In the example below, a counter is incremented each time the function is executed. The expression (counter % 2) will result in either 0 or 1. When we add 1 to the result of the modulus expression we can then obtain the colors of red and green.

Example: Modulus
var counter = 0
function toggleTheLED() {
    counter++
    setLED((counter % 2) + 1)
}
setInterval(toggleTheLED, 500)
waitHereWhile(true)
The above code can be condensed a little further by allowing the increment to occur in the same statement as the setLED() so that we can set the LED and increment immediately.

Example: Modulus (version 2)
var counter = 0
while true {
  setLED((counter++ % 2) + 1)
  sleep(500)
}
Many math operators (+, -, *, /, %) can be combined with the assignment operator (=) to form a combination of operators such as: +=, -=, *=, /=, and %=. These combinations will perform both the math and the assignment operations. Instead of writing:

counter = counter + 2

you could write:

counter += 2

In our example of using modulus with 2 colors, we are going to want the equivalent expression of "counter = counter % 2" which can be written as:

counter %= 2

Because the result of the above expression will always be either 0 or 1, we will need to pre-increment the counter variable before using it as a parameter in the setLED() function.

Example: Modulus in an Operator Assignment
var counter = 0
function toggleTheLED() {
    counter %= 2
    setLED(++counter)
}
setInterval(toggleTheLED, 500)
waitHereWhile(true)

Enumeration

JavaScript, unlike some other languages, does not include a keyword for enumeration. But an easy work-around is to create an object with enumerated properties. In the example below, a "colors" object is created with two properties ("green" and "red"). In this example, each property is assigned a unique value.

The use of enumeration enables the code to become easier to read.

Instead of:

setLED(showTheRedLED ? 2 : 1)

we can write:

setLED(showTheRedLED ? colors.red : colors.green)

Example: Enumeration
colors = { green: 1, red: 2 }
var showTheRedLED = true
while true {
  showTheRedLED = !showTheRedLED
  setLED(showTheRedLED ? colors.red : colors.green)
  sleep(500)
}

Using a Switch Expression

In this example, a switch expression is used to select different cases (depending on the value of the variable being used in the switch).

Example: Switch
function greenLED() { setLED(1) }
function redLED() { setLED(2) }
var theLED = 1
while(true) {
  switch(theLED) {
  case 1:
    greenLED()
    theLED = 2
    break
  case 2:
    redLED()
    theLED = 1
    break
  }
  sleep(500)
}

Array

This is just an example of how to create an empty array and then push numbers onto the array. The elements of the array will contain values from 0 through 999. The array is then scanned and the setLED() function is passed the value of the array element again using "% 2 + 1".

Example: Array
a=[]                             // Create an empty array
for(j=0;j<1000;j++) a.push(j)    // Push 1000 numbers onto the array (0 to 999)
for(j=0;j<1000;j++) {            // Loop through the array
  setLED(a[j] % 2 + 1)           // Set the LED based on the modulus of the value of the array element plus one
  sleep(500)
}

Logical Or Expressions

Computers and robots are very efficient. They are so efficient, that they will refuse to spend time (and energy) evaluating expressions completely if the first part of an expression can determine the result of the entire expression. The Logical Or Expression considers if the value of either of two given expressions is true. As an example

a or b (written in computer language as: a || b )

If either a or b is true then the expression is evaluated to be true. If "a" is true, then the expression of "b" is never evaluated. The expression of "b" is only evaluated if "a" is false. The reason why the evaluation of "b" is dependent on "a" is because if "a" is true, then the entire expression evaluates to true regardless of the value of "b".

This conditional evaluation of an expression is similar to what occurs in an if-then-else expression. A previous example used the following if-then-else:

if(showTheRedLED)
setLED(colors.red)
else
setLED(colors.green)

If we eliminated the true part of the expression, we would get:

if(showTheRedLED)
else
setLED(colors.green)

written on one line as:

if(showTheRedLED) else setLED(colors.green)

Given the way that the Logical Or Expression is evaluated, we can drop the if and replace the else as in:

showTheRedLED || setLED(colors.green)

Example: Logical Or Expression
colors = { green: 1, red: 2 }
var showTheRedLED = true
function toggleTheLED() {
  showTheRedLED  = !showTheRedLED         // Toggle the value of the variable
  showTheRedLED  || setLED(colors.green)  // If the value of the variable is false, then the second part of the Logical Or Expression will be evaluated.
  !showTheRedLED || setLED(colors.red)    // If the value of the variable is true, then in order for the second part of the expression to be evaluated, we need to use the Not symbol "!".
}
setInterval(toggleTheLED, 500)
waitHereWhile(true)
Using a Logical Or Expression in this way may seem like an exercise in obfuscation. But it could have very practical uses in robotics. For example, if a robot must perform a series of steps in order to accomplish a mission you could create a function for each step and return a true or false depending on the success of that step. Program control will proceed starting at step 1 and continue until all steps are successfully completed. Any failure will result in the immediate stop at that step and the robot would then report the error. For example:

(step1() && step2() && step3() && step4()) || reportErrorNow()

In the above statement the Logical Or Expression will require that all of the steps be completed successfully OR the error will be reported.

If an error occurs on step2() then steps 3 and 4 will not be evaluated.

Randomized Flashing

The random() function returns a random number between 0 and 1. In this example, if the random number is greater than 0.5, then the LED will be toggled.

Example: Random Function to Toggle
var showTheRedLED = true
function toggleTheLED() {
    if random()> 0.5 showTheRedLED = !showTheRedLED
    setLED(showTheRedLED + 1)
}
setInterval(toggleTheLED, 250)
waitHereWhile(true)
Example: Random Function to determine length of the sleep
var counter = 0
while(true) {
  setLED((counter++ % 2) + 1)
  sleep(random() * 500)
}
Example: Random Function to determine length of the sleep (version 2)
while(true) {
  setLED(2)
  sleep(random() * 600)
  setLED(1)
  sleep(random() * 600)
}
Example: Random Function to select the color
function toggleTheLED() {
    setLED((random() * 2) + 1)
}
setInterval(toggleTheLED, 250)
waitHereWhile(true)
Example: Different Intervals using setInterval()
function greenLED() { setLED(1) }
function redLED() { setLED(2) }
setInterval(greenLED, 300)
setInterval(redLED, 305)
waitHereWhile true
Example: Fireworks Display
counter=0
while true {
  setLED(++counter % 3 + 1)
  sleep(50)
}

User Input Flashing

Example: Button Press
clearScreen()
rect(10,10,160,60)
drawText(15,30,'Press a key to')
drawText(15,45,'  select a color')
while true {
  keyPressed=waitForPress()
  switch keyPressed
  {
  case 1:
    setLED(1)
    break
  case 2:
    setLED(3)
    break
  case 3:
    setLED(2)
    break
  case 4:
    setLED(1)
    break
  case 5:
    setLED(3)
    break
  case 6:
    setLED(0)
    break
  }
}
Example: Touch Sensor Press
while true {
  if touchSensorPressed()
    setLED( 2 )
  else
    setLED( 1 )
}
Example: Touch Sensor Press (version 2)
while true {
  setLED( touchSensorPressed() ? 2 : 1 )
}
Example: Light Sensor Percent
while true {
  clearScreen()
  drawText(0, 10, 'Percent '+lightSensorPct(), 2)
  // Graph it ///////////////
  rect( 20, 40, 100, 40 )                   // x, y, width, height
  fillRect( 21, 41, lightSensorPct(), 38 )  // x, y, width, height
  if( lightSensorPct() < 40 ) {
    setLED( 2 )
  } else {
    setLED( 1 )
  }
  sleep( 100 )
}
Example: Ultrasonic Sensor
while(true) {
  clearScreen()
  drawText(10, 10, ultrasonicSensorValue())
  setLED( ultrasonicSensorValue() < 10 ? 2 : 1 )
  sleep( 100 )
}
Example: Gyro Sensor
center = { x: 89, y: 64, radius: 60 }            // Create a 'center' object to represent the center of the LCD screen.  Add a radius to be used in expressions for drawing the two circles and line.
resetGyroSensor()                                // Reset the sensor
while(true) {
  gyro = gyroSensorValue()                       // Assign the gyro sensor's value to a variable called 'gyro'.  The gyro variable will used in multiple places in the program.
  clearScreen()                                  // Clear the screen
  drawText( center.x-30, center.y-10, gyro, 2)   // Show the value of the gyro sensor
  setLED( abs(gyro) > 30 ? 2 : 1 )               // If the gyro sensor's value is more than 30 degrees from the starting point, set the LED to red; otherwise, set it to green.
  // Graph it =============
  gyro += 90
  // 90 degrees are being added to the sensor value so that the indicators below will point to the top of the LCD display if the sensor value is zero (0).
  circle( center.x, center.y, center.radius )    // Draw a center circle
  x2=center.x+cosin(gyro)*center.radius          // Calculate an x2 coordinate based on the center of the circle offset by the cosine of the gyro times the circle's radius
  y2=center.y-sin(gyro)*center.radius            // Calculate an y2 coordinate based on the center of the circle offset by the sine of the gyro times the circle's radius
  // Note that in calculating y2 the offset is subtracted from the coordinate because the y-scale on the LCD display increases in values from top to bottom (i.e., 0 on the y axis is at the top of the display)
  line( center.x, center.y, x2, y2 )  // line from the center to the edge of the circle
  fillCircle( x2, y2, 5 )  // Draw an indicator of the direction
  sleep( 100 )
}

Event Handling

Example: Touch Sensor Events
                                         // Create an event handler to handle the touchSensor events
function toHandleTheTouchSensor(event) { // A touchSensor event will occur when the touchSensor is pressed as well as when it is released.
  setLED(event.value+1)                  // If the touchSensor was pressed the event value will equal 1. The event value is zero when the touchSensor was released. 
}
                                         // Add an event listener to listen for touchSensor events and then handle them by passing the event to the callback function.
                                         // An event listener requires two parameters: 1) name of the event as a string and 2) identifier of the callback function (i.e., the event handler).
addEventListener('touchSensor',toHandleTheTouchSensor)
waitHereWhile(true)                      // Enter an infinite loop
Example: Gyro Sensor Events
center = { x: 89, y: 64, radius: 60 }            // Create a 'center' object to represent the center of the LCD screen.  Add a radius to be used in expressions for drawing the two circles and line.
function drawCircles(pointer) {                  // A primitive user defined drawing function to draw two circles and a line on the LCD screen.
  clearScreen()                                  // Clear the screen
  circle( center.x, center.y, center.radius )    // Draw a center circle
  x2=center.x+cosin(pointer)*center.radius       // Calculate an x2 coordinate based on the center of the circle offset by the cosine of the gyro times the circle's radius
  y2=center.y-sin(pointer)*center.radius         // Calculate an y2 coordinate based on the center of the circle offset by the sine of the gyro times the circle's radius
  // Note that in calculating y2 the offset is subtracted from the coordinate because the y-scale on the LCD screen increases in values from top to bottom (i.e., 0 on the y axis is at the top of the display)
  line( center.x, center.y, x2, y2 )             // line from the center to the edge of the circle
  fillCircle( x2, y2, 5 )                        // Draw an indicator of the direction
}
function toShowRotation(event) {
  drawCircles(event.value+90)                    // Graph the gyroSensor value passed to this event handler through the parameter 'event'.
  // 90 degrees was added to the sensor value so that the indicators below will point to the top of the LCD screen if the sensor value is zero (0).
  // When the point to be graphed is 90-degrees, the sine has a value of 1 and the cosine has a value of zero.
  drawText(center.x-30, center.y-10, event.value+'  ', 2)  // Try to center the gyroSensor value on the LCD screen.
  setLED( abs(gyro) > 30 ? 2 : 1 )               // If the gyro sensor's value is more than 30 degrees from the starting point, set the LED to red; otherwise, set it to green.
  beep(40, event.value*0.5+440, 20)              // Make a sound
}
resetGyroSensor()                                // Gyro will start out at zero
                                                 // Add an 'event listener'
addEventListener('gyroSensor',toShowRotation)    // The event listener requires two parameters: name of the event as a string, callback function to be executed when the event occurs
                                                 // Please note that the callback function is entered as a function name without the usual parentheses.
                                                 // The parentheses are omitted from the callback function because the addEventListener() function is not executing the callback.
                                                 // The addEventListener() function adds the callback to the specified event.  It is the specified event that will execute the callback.
waitHereWhile(true)
// In this example, the event handler (i.e., the callback function) 
Example: Gyro Sensor Events (version 2)
center = { x: 89, y: 64, radius: 60 }            // Create a 'center' object to represent the center of the LCD screen.  Add a radius to be used in expressions for drawing the two circles and line.
function drawCircles(pointer) {                  // A primitive user defined drawing function to draw two circles and a line on the LCD screen.
  clearScreen()                                  // Clear the screen
  circle( center.x, center.y, center.radius )    // Draw a center circle
  x2=center.x+cosin(pointer)*center.radius       // Calculate an x2 coordinate based on the center of the circle offset by the cosine of the gyro times the circle's radius
  y2=center.y-sin(pointer)*center.radius         // Calculate an y2 coordinate based on the center of the circle offset by the sine of the gyro times the circle's radius
  // Note that in calculating y2 the offset is subtracted from the coordinate because the y-scale on the LCD screen increases in values from top to bottom (i.e., 0 on the y axis is at the top of the display)
  line( center.x, center.y, x2, y2 )             // line from the center to the edge of the circle
  fillCircle( x2, y2, 5 )                        // Draw an indicator of the direction
}
function toShowRotation(event) {
  setLED( 2 )                                    // Indicate movement using a red flash
  drawCircles(event.value+90)                    // Graph the gyroSensor value passed to this event handler through the parameter 'event'.
  // 90 degrees was added to the sensor value so that the indicators below will point to the top of the LCD screen if the sensor value is zero (0).
  // When the point to be graphed is 90-degrees, the sine has a value of 1 and the cosine has a value of zero.
  drawText(center.x-30, center.y-10, event.value+'  ', 2)  // Try to center the gyroSensor value on the LCD screen.
  beep(40, event.value*0.5+440, 20)              // Make a sound
  sleep( 50 )                                    // Pause for a few milliseconds 
  setLED( 1 )                                    // Reset the LED to green
}
resetGyroSensor()                                // Gyro will start out at zero
                                                 // Add an 'event listener'
addEventListener('gyroSensor',toShowRotation)    // The event listener requires two parameters: name of the event as a string, callback function to be executed when the event occurs
                                                 // Please note that the callback function is entered as a function name without the usual parentheses.
                                                 // The parentheses are omitted from the callback function because the addEventListener() function is not executing the callback.
                                                 // The addEventListener() function adds the callback to the specified event.  It is the specified event that will execute the callback.
waitHereWhile(true)
// In this example, the event handler (i.e., the callback function)