JavaScript: LED Matrix Display with Johnny-Five on Node.js

The Johnny-Five Tutorial Series is geared towards Arduino programming on Node.js, using the Johnny-Five framework. Get caught up here.


LED Matrix signs are everywhere: roadways (even cars themselves!), store awnings, offices, the grocery store deli, airports, train stations, taxi stands, libraries, alarm clocks, and so on. The use cases are so broad because the technology is very old and well-proven. LED Matrix displays are controlled by one or more shift registers. The shift register, which first appeared in the Colossus Mark II in 1943-44, is a sequential logic circuit comprised of flip-flops connected in a chain. Output from one flip-flop is the input to the next flip-flop. Readers won’t specifically need to understand shift registers for this tutorial, but I recommend All About Circuits: Shift Registers for further reading. Today, we’ll be wiring up a simple LED matrix display and using it to display symbols and messages. Let’s get started!

Parts:

Connect the following:

  • LED Matrix: J1
    • VCC to 5V
    • GND to GND
    • DIN to Digital 2
    • CS to Digital 4
    • CLK to Digital 3

Before we continue, let’s clarify some labelling terminology:

  • DIN: “Data IN”, corresponds to the data pin
  • CS: “Chip Select”, corresponds to the cs pin
  • CLK: “CLocK”, corresponds to the clock pin

First, let’s get comfortable with the Led.Matrix API, save the following as led-matrix-basics.js:

var five = require("johnny-five");
var board = new five.Board();

board.on("ready", function() {

  var matrix = new five.Led.Matrix({
    pins: {
      data: 2,
      clock: 3,
      cs: 4
    }
  });

  matrix.on();

  /*

  A single Led.Matrix object can control one
  or more led matrix devices. All methods of
  Led.Matrix objects expect the target device's
  index as their first argument. Since this
  might seem cumbersome when there is only
  one matrix device, use the `device()` method
  to create a display device bound to an index.

  */

  this.repl.inject({
    display: matrix.device(0)
  });
});

Run node led-matrix-basics.js and wait for the program to connect to the board. Once connected, try the following commands one-at-a-time:

// Control one led at a time
// display.led(row 0-7, column 0-7, 0|1)

// Turn on the top-left led:
display.led(0, 0, 1);

// Turn on the top-right led:
display.led(0, 7, 1);

// Turn on the bottom-left led:
display.led(7, 0, 1);

// Turn on the bottom-right led:
display.led(7, 7, 1);

// Clear the device at index 0
display.clear(0);

Controlling an entire row or column also requires only a single value: an 8-bit (0-255) binary value can be used to tell the register which leds in a given row are “on” and which are “off”. To help understand the row and column APIs, use the following interactive 8-bit value generator:

8x8 Matrix: 8-Bit Value Generator

// Control one row or column at a time by 
// providing a single 8-bit value that 
// represents which leds to "fill". 
// 
// row(0-7, 0-255);
// column(0-7, 0-255);

// HINT: Paste or type one loop at a time!

// Turn on all leds in each row
for (var x = 0; x < 8; x++) {
  display.row(x, 255);
}

// Turn off all leds in each row
for (var x = 0; x < 8; x++) {
  display.row(x, 0);
}

// Turn on all leds in each column
for (var y = 0; y < 8; y++) {
  display.column(y, 255);
}

// Turn off all leds in each column
for (var y = 0; y < 8; y++) {
  display.column(y, 0);
}

Now that we’re familiar with controlling row and column display, the next logical step is to display entire 8x8 “drawings” with the draw() method. The draw() method will accept a string value containing the “name” of a single character or icon that corresponds to a predefined character or an array of eight 8-bit values (one value for each row) for custom characters.

// Predefined Characters

0 1 2 3 4 5 6 7 8 9   
! " # $ % & ' ( ) * + , - . / : ; < = > ? @ 
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` 
a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~

Back in the program, try the following calls to the draw method:

// Draw "0"
display.draw("0");

// Draw "A"
display.draw("A");

// This one is a surprise:
display.draw([0x00, 0x00, 0x24, 0x00, 0x81, 0x42, 0x3c, 0x00]);

Now that we’re familiar with the basics of controlling an Led.Matrix instance, save the following as led-matrix-controller.js:

/*
  NOTE: In the video, there is a "winking smiley face" shown. 
        This version of the program omits the "winking smiley 
        face" for the sake of simplicity. Readers are encouraged 
        to implement a solution to reproduce the "animation".
*/
var readline = require("readline");
var five = require("johnny-five");
var board = new five.Board({
  repl: false
});

board.on("ready", function() {

  var rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });

  var display = new five.Led.Matrix({
    pins: {
      data: 2,
      clock: 3,
      cs: 4
    }
  });

  var message = [];

  function update() {
    if (message.length) {
      // When a message is ready to be written,
      // write one character at a time to device 0.
      display.draw(0, message.shift());

      // When the end of the message has been reached,
      // show the readline prompt.
      if (!message.length) {
        rl.prompt();
        return;
      }

      setTimeout(update, 500);
    }
  }

  rl.prompt();
  rl.on("line", function(text) {
    message = (text + " ").split("");
    update();
  });

  display.on();
});

Run node led-matrix-controller.js to see the program in action! Type a message into the console and hit the <ENTER> key to display it!

Homework

Based on the program above, use the LED Matrix to display data readings from a sensor.

This entry was posted by Rick Waldron (@rwaldron) on July 09, 2014 in JavaScript, Node.js, Arduino, Johnny-Five, NodeBots and Feature.

Comments