A Choice of Libraries

Two different open-source libraries are available for programming addressable LED matrices.

The Adafruit_Neo_Matrix Library
is focussed on WS2812-based matrices sold by Adafruit. This library and the Adafruit GFX
library on which it depends) provides a wide range of graphics primitives that make it easy
to start using addressable arrays.
The “FastLED” Library
is designed to achieve maximum performance across a wide variety of addressable LED matrices.
It is actively maintained, and up-to-date with respect to the types of matrices it supports.
Because of its flexibility and speed, it may be the library of choice for especially demanding
applications.

Two sketches are shown below, one using the Adafruit library and the other using the FastLED
library. They both achieve the same visual result, i.e.,
display an image, then
“wipe” the to the side, then
display another image, then
“wipe” that to the side.

Interestingly, several of the graphics tools to manipulate images were not available in
either the Adafruit library or the FastLED library; instead, these effects were
adapted from the Colorduino_FW library.

Both sketches adopt the use of an array of String‘s to describe an image. For example,

String heart[] = {"--------",
                  "--88-88-",
                  "-8111118",
                  "-8111118",
                  "-811118-",
                  "---818--",
                  "----8---",
                  "--------"
                 };

says:
“Use the background color for most of the array”, as designated by the hyphen (-).
“Use color 8 for the outline”.
* “Use color 1 for the interior”.

The correspondence between the color index (e.g., 1 or 8 in the “image” above)
and real R, G, B colors is given in a color palette at the top of the sketch.

Both sketches (and the underlying libraries) use data types (e.g., int8_t, uint8_t
and uint16_t) that not only specify an integer data type, but also guarantee a certain
storage size. This is in contrast to the commonly used generic types
(e.g., int, unsigned int, long, or unsigned long) whose length depends on the particular
microprocessor being used.

Example Using the Adafruit_NEO_Matrix Library

#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>

#define NUM_ROWS 8
#define NUM_COLS 8
#define NUM_LEDS ( NUM_ROWS * NUM_COLS )
#define DATA_PIN 6

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(NUM_ROWS, NUM_COLS, DATA_PIN,
                            NEO_MATRIX_TOP + NEO_MATRIX_RIGHT + NEO_MATRIX_COLUMNS + NEO_MATRIX_PROGRESSIVE,
                            NEO_GRB + NEO_KHZ800);

String smiley[] = {"--------",
                   "-33--33-",
                   "-3----3-",
                   "--------",
                   "--------",
                   "5------3",
                   "-3----3-",
                   "--3333--"};


String frownie[] = {"--------",
                   "-1----1-",
                   "-11--11-",
                   "--------",
                   "--------",
                   "--1111--",
                   "-1----1-",
                   "--------" };

// These arrays are used when creating special effects with the actual image arrays
String tempImage[] = {"--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------" };

String returnImage[] = {"--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------" };


// The color palette is called "colors[]".
// It consists of 10 values, numbered 0 through 9.
// Each color must be converted from its R, G, B value to a packed 16-bit value used by
// the Adafruit library.  The function matrix.Color() performs this conversion.
const uint16_t colors[] = { matrix.Color( 255, 255, 255), // white 0
                            matrix.Color( 255, 000, 000), // red   1
                            matrix.Color( 255, 140, 000), // orange 2
                            matrix.Color( 255, 255, 000), // yellow 3
                            matrix.Color( 000, 60, 000),  // green 4
                            matrix.Color( 000, 000, 255), // blue 5
                            matrix.Color( 255, 000, 255), // purple 6
                            matrix.Color( 139, 67, 19),   // brown 7 
                            matrix.Color( 000, 000, 000), // black 8
                            matrix.Color( 255, 255, 255)  // snow white 9
                          };

uint8_t bg = 8;          // Use index color #8 (black) for the background
uint8_t bgc = bg + 48;   // The ASCII character corresponding to the color at offset 8.

void setup() {
  matrix.begin();
  matrix.setBrightness(40);
}

void loop() {
  drawImage(smiley);
  delay(1000);
  wipeImageLeft(smiley);
  delay(500);

  drawImage(frownie);
  delay(1000);
  wipeImageLeft(frownie);
  delay(500);
}

void drawImage(String image[]) {
  uint8_t d;
  uint16_t offset;
  for (uint8_t j=0; j<NUM_ROWS; j++) {
    for (uint8_t i=0; i<NUM_COLS; i++) {
        offset = j*8 + i;

        if (image[j][i] == '-') { 
          matrix.drawPixel(i, j, colors[bg]);
        } else { 
          d = (uint8_t)image[j][i] - 48;
          matrix.drawPixel(i, j, colors[d]);
        }   
    }
  }
  matrix.show();
}

void wipeImageLeft(String img[]) {
  scrollLeft(img);
  drawImage(returnImage);
  matrix.show();
  delay(100);

  for (int i = 0; i < NUM_COLS; i++) {
    scrollLeft(returnImage);
    drawImage(returnImage);
    matrix.show();
    delay(100);
  }
}

void scrollLeft(String img[]) {
  for (int8_t yi = 0; yi < NUM_ROWS; yi++) {
    for (int8_t xi = 0; xi < NUM_COLS; xi++) {
      char c = img[yi][xi];
      tempImage[yi][xi] = c;
    }
  }

  for (int8_t yi = 0; yi < NUM_ROWS; yi++) {
    for (int8_t xi = 0; xi < NUM_COLS; xi++) {
      returnImage[yi][xi] = '-';
    }
  }

  for (int8_t yi = 0; yi < NUM_ROWS; yi++) {
    for (int8_t xi = 1; xi < NUM_COLS; xi++) {
      char c = tempImage[yi][xi-1];
      if ( c != bgc && c != '-')
        returnImage[yi][xi] = c;
    }
  }

  for (int8_t i = 0; i < NUM_COLS; i++)
    returnImage[i][0] = bgc;

}

Example Using the FastLED Library ##

#include <FastLED.h>
#define NUM_ROWS 8
#define NUM_COLS 8
#define NUM_LEDS ( NUM_ROWS * NUM_COLS )
#define DATA_PIN 6

CRGB leds[NUM_LEDS];

String smiley[] = {"--------",
                   "-33--33-",
                   "-3----3-",
                   "--------",
                   "--------",
                   "3------3",
                   "-3----3-",
                   "--3333--"};


String frownie[] = {"--------",
                   "-1----1-",
                   "-11--11-",
                   "--------",
                   "--------",
                   "--1111--",
                   "-1----1-",
                   "--------" };

// These arrays are used when creating special effects with the actual image arrays
String tempImage[] = {"--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------" };

String returnImage[] = {"--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------",
                      "--------" };

// The color palette is called "colors[]".
// It consists of 10 values, numbered 0 through 9.
// Each color must be converted from its R, G, B value to a packed 16-bit value used by
// the Adafruit library.  The function matrix.Color() performs this conversion.
CRGB colors[] = {
                    CRGB::White,     // 0
                    CRGB::Red,       // 1
                    CRGB::Orange,    // 2
                    CRGB::Yellow,    // 3
                    CRGB::Green,     // 4
                    CRGB::Blue,      // 5
                    CRGB::Purple,    // 6
                    CRGB::Brown,     // 7
                    CRGB::Black,     // 8
                    CRGB::GhostWhite //9
                };

uint8_t bg = 8;          // Use index color #8 (black) for the background
uint8_t bgc = bg + 48;   // The ASCII character corresponding to the color at offset 8.


void setup() {
  FastLED.addLeds<NEOPIXEL,DATA_PIN>(leds, NUM_LEDS); 
  FastLED.setBrightness(15);
}

void loop() {
  FastLED.clear();

  drawImage(smiley);
  delay(1000);
  FastLED.clear();
  delay(500);
  wipeImageLeft(smiley);
  delay(500);

  drawImage(frownie);
  delay(1000);
  FastLED.clear();
  delay(500);
  wipeImageLeft(frownie);
  delay(500);
}

void drawImage(String image[]) {
  uint8_t d;
  FastLED.clear();
  uint16_t offset;
  for (uint8_t j=0; j<NUM_ROWS; j++) {
    for (uint8_t i=0; i<NUM_COLS; i++) {
        offset = j*8 + i;

        if (image[j][i] == '-') { 
          leds[offset] = colors[bg];
        } else { 
          d = (uint8_t)image[j][i] - 48;
          leds[offset] = colors[d];
        }   
    }
  }
  FastLED.show();
}

void wipeImageLeft(String img[]) {
  FastLED.clear();
  scrollLeft(img);
  drawImage(returnImage);
  FastLED.show();
  delay(100);

  for (int i = 0; i < NUM_COLS; i++) {
    FastLED.clear();
    scrollLeft(returnImage);
    drawImage(returnImage);
    FastLED.show();
    delay(100);
  }
}

void scrollLeft(String img[]) {
  for (int8_t yi = 0; yi < NUM_ROWS; yi++) {
    for (int8_t xi = 0; xi < NUM_COLS; xi++) {
      char c = img[yi][xi];
      tempImage[yi][xi] = c;
    }
  }

  for (int8_t yi = 0; yi < NUM_ROWS; yi++) {
    for (int8_t xi = 0; xi < NUM_COLS; xi++) {
      returnImage[yi][xi] = '-';
    }
  }

  for (int8_t yi = 0; yi < NUM_ROWS; yi++) {
    for (int8_t xi = 1; xi < NUM_COLS; xi++) {
      char c = tempImage[yi][xi-1];
      if ( c != bgc && c != '-')
        returnImage[yi][xi] = c;
    }
  }

  for (int8_t i = 0; i < NUM_COLS; i++)
    returnImage[i][0] = bgc;

}