Experiment Guide for the Johnny-Five Inventor's Kit

Pages
Contributors: rwaldron, reconbot, D___Run___, lyzadanger, Shawn Hymel
Favorited Favorite 8

Experiment 2: Multiple LEDs

Introduction

In Experiment 1 of the Johnny-Five Inventor's Kit (J5IK), you learned how to blink and pulse a single LED with a Tessel 2. In this experiment, you'll learn how to control multiple, colorful LEDs with Johnny-Five to create animated variations on a simple "Cylon effect." This article dives into structuring looping logic for your projects using Johnny-Five and JavaScript fundamentals.

Preflight Check

Whoa there, Turbo! If this is your first experiment with the Johnny-Five Inventor's Kit (J5IK) and the Tessel 2, there are a few things you gotta do first:
  1. Set up your computer
  2. Configure your Tessel 2
Note: These steps only have to be done once, but they are required. Internet connection may be necessary!

Suggested Reading

The following tutorials provide in-depth background on some of the hardware concepts in this experiment:

  • What is a Circuit? -- This tutorial will explain what a circuit is, as well as discuss voltage in further detail.
  • Voltage, Current, Resistance, and Ohm's Law -- Learn the basics of electronics with these fundamental concepts.
  • LEDs (Light-Emitting Diodes) -- LEDs are found everywhere. Learn more about LEDs and why they are used in so many products all over the world.
  • Resistors -- Why use resistors? Learn more about resistors and why they are important in circuits like this one.
  • Polarity -- Polarity is a very important characteristic to pay attention to when building circuits.

Parts Needed

You will need the following parts for this experiment:

  • 1x Tessel 2
  • 1x Breadboard
  • 6x LEDs (One of each color: red, orange, yellow, green, blue, purple)
  • 6x 100Ω Resistor
  • 7x Jumper Wires
Using a Tessel 2 without the kit? No worries! You can still have fun and follow along with this experiment. We suggest using the parts below:
Breadboard - Self-Adhesive (White)

Breadboard - Self-Adhesive (White)

PRT-12002
$5.50
48
Jumper Wires - Connected 6" (M/M, 20 pack)

Jumper Wires - Connected 6" (M/M, 20 pack)

PRT-12795
$2.10
2
LED - Assorted (20 pack)

LED - Assorted (20 pack)

COM-12062
$3.95
8
Resistor 100 Ohm 1/4 Watt PTH - 20 pack (Thick Leads)

Resistor 100 Ohm 1/4 Watt PTH - 20 pack (Thick Leads)

PRT-14493
$1.25

Tessel 2

DEV-13841
4 Retired

Hardware Hookup

Its now the fun part! It's time to start building your circuit. Let's take a look at what goes into building this circuit.

Polarized Components Pay special attention to the component’s markings indicating how to place it on the breadboard. Polarized components can only be connected to a circuit in one direction.

Build the Multiple-LED Circuit

alt text

Having a hard time seeing the circuit? Click on the wiring diagram for a closer look.

  1. Connect the LEDs to the breadboard. Make sure to connect their cathode legs to sockets in the ground column in the power rail.
  2. Plug in the 100Ω resistors in terminal rows shared with the anode legs of the LEDs, spanning the central notch.
  3. Connect jumper wires between the resistors and the Tessel 2. You may find it helpful to use colors that correspond to the LED's color.
  4. Use a jumper wire to connect the ground power rail of the breadboard to the Tessel 2's GND pin.

Lighting Up LEDs Side-to-Side

Open your favorite code editor, create a file called side-to-side.js and save it in the j5ik/ directory. Type — or copy and paste — the following JavaScript code into your side-to-side.js file:

language:javascript
var five = require("johnny-five");
var Tessel = require("tessel-io");
var board = new five.Board({
  io: new Tessel()
});
board.on("ready", () => {
  var leds = new five.Leds(["a2", "a3", "a4", "a5", "a6", "a7"]);
  var index = 0;
  var step = 1;

  board.loop(100, () => {
    leds.off();
    leds[index].on();
    index += step;
    if (index === 0 || index === leds.length - 1) {
      step *= -1;
    }
  });
});

Before you run this on your Tessel 2, pause for a moment. Can you tell what the program will do?

Type -- or copy and paste -- the following command into your terminal and press enter:

t2 run side-to-side.js

Once the program starts up, your multiple-LED circuit should light up in a pattern like this:

Exploring the Code

Before continuing, we recommend that you've read Experiment 1: Exploring the Code.

The side-to-side program lights up LEDs in the following pattern:

  1. From lowest pin number to highest pin number, turn on one LED at a time every 100 milliseconds, then:
  2. From highest pin number to lowest pin number, turn on one LED at a time every 100 milliseconds, then:
  3. Repeat from step 1.
Collections of LEDs With the Leds Class

Instead of instantiating each LED as its own object separately using the Led class (as we did in Experiment 1), we can create a single collection that contains all of the LEDs in one swoop:

language:javascript
board.on("ready", function() {
  var leds = new five.Leds(["a2", "a3", "a4", "a5", "a6", "a7"]);
});

Johnny-Five's Leds constructor takes an Array of pin numbers and creates an Led object for each of them. Each of these Led objects can be accessed and manipulated from the container-like leds object. Instances of the Leds class behave like Arrays but have some extra goodies (they're described as "Array-like objects").

Read up on JavaScript Arrays if the concept is new or you're feeling rusty.

Looping in Johnny-Five

To turn on LEDs one at a time, we need some way of creating a loop that executes every 100 milliseconds. We're in luck. Board object instances have a loop method that can do just that! Convenient!

language:javascript
board.on("ready", () => {
  board.loop(100, () => {
    // ... This function gets invoked every 100 milliseconds
  });
});

The function (in this case, an arrow function]) passed as the second argument to loop will get invoked every 100 milliseconds. Now, let's see what needs to happen in that loop.

Lighting Up, Lighting Down

Here's what we need to accomplish in each invocation of the loop callback function:

language:javascript
board.on("ready", () => {
  var index = 0;
  var step = 1;

  board.loop(100, () => {
    leds.off();            // 1. Turn all of the LEDs off
    leds[index].on();      // 2. Turn on the "next" active LED
    // ...                 // 3. Determine what the next active LED will be
  });
});

In step one, all LEDs are turned off. Leds instances have an off method that will turn off every Led in its collection. Easy peasy.

The variable index holds the index of the next LED that should get turned on. The initial value of index is 0. Why 0? Each Led in leds can be accessed by its numeric index, like an Array:

Reference LED
leds[0] Led object controlling red LED on Port A, Pin 2
leds[1] Led object controlling red LED on Port A, Pin 3
leds[2] Led object controlling red LED on Port A, Pin 4
leds[3] Led object controlling red LED on Port A, Pin 5
leds[4] Led object controlling red LED on Port A, Pin 6
leds[5] Led object controlling red LED on Port A, Pin 7

The first time the loop executes, index is 0, and it will turn on leds[0], which is the first (red) LED on Port A, Pin 2:

language:javascript
leds[index].on();

Step 3 sets us up for the next time the loop function executes. The value of index needs to be set to the index of the next LED that should turn on. This is what the step variable helps us with. Add step to index to get the index of the next LED to light up:

language:javascript
board.on("ready", () => {
  var index = 0;
  var step = 1;

  board.loop(100, () => {
    leds.off();            // 1. Turn all of the LEDs off
    leds[index].on();      // 2. Turn on the "next" active LED
    index += step;         // 3a. Add `step` to index
  });
});

At the completion of the first invocation of the loop callback function, index will hold the value 1.

During the second invocation, the second, orange LED (leds[1]) will light up. index will be incremented to 2.

And so on, lighting up red, orange, yellow, green, blue ... But then we get to the purple LED (Port A, Pin 7) at index 5. There is no Led element at leds[6], so what do we do now? Well, we can flip the sign of step, changing its value to -1:

language:javascript
board.on("ready", () => {
  var index = 0;
  var step = 1;

  board.loop(100, () => {
    leds.off();            // 1. Turn all of the LEDs off
    leds[index].on();      // 2. Turn on the "next" active LED
    index += step;         // 3a. Add `step` to index
    if (index === leds.length - 1) { // 3b. If we're at the highest index...
      step *= -1; // ...invert the sign of step
    }
  });
});

Now invocations of the loop callback function will decrease (decrement) the index value, and the LEDs will light up in reverse order. When the index gets down to 0 — the first LED — we need to swap the sign of step again:

language:javascript
board.on("ready", () => {
  var index = 0;
  var step = 1;

  board.loop(100, () => {
    leds.off();            // 1. Turn all of the LEDs off
    leds[index].on();      // 2. Turn on the "next" active LED
    index += step;         // 3a. Add `step` to index
    // If we are at the lowest OR the highest index...
    if (index === 0 || index === leds.length - 1) {
      step *= -1;
    }
  });
});

Using board.loop with the leds can be adapted in various ways to change the way the LEDs light up. Let's try a few variations.

Variation: One-by-One On, One-by-One Off

Now we'll light up each LED one at a time and keep them on as we go; the display will loop as:

  1. From lowest pin number to highest pin number, turn on each LED and keep it on.
  2. From highest pin number to lowest pin number, turn off each LED and keep it off.
  3. Repeat from step 1.

Open your favorite code editor, create a file called one-by-one-on-off.js and save it in the j5ik/ directory. Type — or copy and paste — the following JavaScript code into your one-by-one-on-off.js file:

language:javascript
var five = require("johnny-five");
var Tessel = require("tessel-io");
var board = new five.Board({
  io: new Tessel()
});
board.on("ready", () => {
  var leds = new five.Leds(["a2", "a3", "a4", "a5", "a6", "a7"]);
  var index = 0;
  var step = 1;

  board.loop(100, () => {
    leds.off().slice(0, index).on();
    index += step;
    if (index === 0 || index === leds.length) {
      step *= -1;
    }
  });
});

All of the changes are confined to the loop callback function. There's one line doing much of the heavy lifting here:

leds.off().slice(0, index).on();

This single line turns all of the LEDs off and then turns on all LEDs between 0 and the current index. slice is an Array method that returns a chunk of an array between the start and end indexes provided (leds isn't an Array, remember, but it acts like one, so it also has a slice method).

As in the previous example, this script will flip the sign on step when it reaches either end of the leds collection.

Run the script by typing -- or copying and pasting -- the following command in your terminal:

t2 run one-by-one-on-off.js

Once the program starts up, your LEDs circuit should display something like this:

Variation: One-by-One On, Clear and Repeat

Now let's simplify that same program: light up each pin, one at a time, and then turn them off; the display will loop as:

  1. From lowest pin number to highest pin number, turn on each LED and keep it on.
  2. Once all the LEDs are on, turn them all off
  3. Repeat from step 1.

Open your favorite code editor, create a file called one-by-one-clear-repeat.js and save it in the j5ik/ directory. Type -- or copy and paste -- the following JavaScript code into your one-by-one-clear-repeat.js file:

language:javascript
var five = require("johnny-five");
var Tessel = require("tessel-io");
var board = new five.Board({
  io: new Tessel()
});
board.on("ready", () => {
  var leds = new five.Leds(["a2", "a3", "a4", "a5", "a6", "a7"]);
  var index = 0;

  board.loop(100, () => {
    if (index === leds.length) {
      leds.off();
      index = 0;
    } else {
      leds[index].on();
      index++;
    }
  });
});    

Again, there is very little to change here, so we'll skip right to the operations within the call to board.loop(...).

language:javascript
board.loop(100, () => {
  if (index === leds.length) {
    leds.off();
    index = 0;
  } else {
    leds[index].on();  
    index++;
  }
});

The semantics for this program are slightly different from the previous examples. Because we're always lighting LEDs up in the same direction — lowest to highest index — we don't have to deal with the logic for swapping the sign on a step variable. Instead, a simple increment of the index value on each invocation of the loop callback function is all we need, resetting it to 0 when we run out of LED indexes.

  1. If the index equals the number of LEDs in the leds collection,
    1. Turn all leds off.
    2. Set the index back to 0.
  2. Else,
    1. Turn the led at present index on.
    2. Increment the index.

Type — or copy and paste — the following into your terminal:

t2 run one-by-one-clear-repeat.js

Once the program starts up, your LEDs circuit should display something like this:

Variation: Collision

Changing gears a bit, this next program will light LEDs from the middle, out, and back (there will be two LEDs lit at a time); the display will loop as:

  1. From the first to the last and the last to the first, by pin number, light the LEDs one at a time.
  2. Repeat from step 1.

Open your favorite code editor, create a file called collision.js and save it in the j5ik/ directory. Type — or copy and paste — the following JavaScript code into your collision.js file:

language:javascript
var five = require("johnny-five");
var Tessel = require("tessel-io");
var board = new five.Board({
  io: new Tessel()
});
board.on("ready", () => {
  var leds = new five.Leds(["a2", "a3", "a4", "a5", "a6", "a7"]);
  var index = 0;
  var step = 1;

  board.loop(100, () => {
    leds.off();
    leds[index].on();
    leds[leds.length - index - 1].on();

    index += step;

    if (index === 0 || index === leds.length - 1) {
      step *= -1;
    }
  });
});

This example contains logic more in line with the first few variations again — turning on the correct LED and then determining what the next LED's index will be:

  1. Turn all leds off.
  2. Turn the leds at index and its counterpart on.
  3. Update the index with step (either 1 or -1).
  4. If index equals 0, or index equals the number that corresponds to the last possible led in the leds collection, flip the sign of step.

Type — or copy and paste — the following into your terminal:

t2 run collision.js

Once the program starts up, your LEDs circuit should display something like this:

Building Further

  • Try writing your own algorithms for other patterns not shown here.

Reading Further