Random pixels in LED array animation

I am making a project based on a LED matrix display (specifically the Red LED Dot Matrix Display for Arduino) wherein the array is controlled LED by LED, in an animated way. There are two parts to the animation.

  • Vertical bars, scrolling inwards from the left & right
  • A pair of boxes of LEDs which expand to fill the display, then contract back to nothing
    The 2nd part with the boxes is working as expected, but the vertical bars animation shows random pixels as the bars scroll inwards.

There is also a video of the random pixel effect, but I doubt it shows the effect better than the image above (though it does show the expanding/contracting box working as expected). The video is around 5 seconds long.

I've tried using different settings for the Serial.begin(115200); rate. I saw 2 working sketches that used 7500 & 9600 - tried both (and 115200) as well as 9000. The random pixels appeared in all. Given the other sketches work exactly as expected (one for scrolling text, the other for the Game of Life) I think the wiring is correct. I've run out of ideas what else could be wrong, but cannot see a problem in the code used in the sketch.

Is there a problem with this sketch?

/* Combination of closing bars and expanding/contracting boxes */
#include <SPI.h>
#include <DMD2.h>

SoftDMD dmd(1,1);
 
const int W = 32;
const int H = 16;

const int MAX = 255;
const int PULSE_DELAY = 10;

const int BARS[16][16] = {
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // 1
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // 2
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // 3
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // 4
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // 5
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // 6
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // 7
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // 8
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // 9
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // 10
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // 11
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // 12
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, // 13
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // 14
  {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // 15
  {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}  // 16
};

void setup() {
  Serial.begin(9600);
  dmd.setBrightness(MAX);
  dmd.begin();
}

void loop() {
  closeGate();
  growShrinkBox();
}

void gateAtPosition(int i) {
  dmd.fillScreen(false);
  for (int xx=0; xx<i; xx++) {
    for (int yy=0; yy<H; yy++) {
      if (BARS[xx+16-i][yy] == 0) {
        dmd.setPixel(xx,yy,GRAPHICS_OFF);
        dmd.setPixel(W-xx-1,yy,GRAPHICS_OFF);
      } else {
        dmd.setPixel(xx,yy,GRAPHICS_ON);
        dmd.setPixel(W-xx-1,yy,GRAPHICS_ON);
      }
    }
  }
}

void closeGate() {
  int delayReduction = 12;
  int delayStep = 300;
  for (int ii=0; ii<=16; ii++) {
    gateAtPosition(ii);
    delay(delayStep);
    delayStep -= delayReduction;
  }
  delay(1000);
}

void fillBox(int x, int y, int w, int h) {
  for (int xx=x; xx<=x+w; xx++) {
    for(int yy=y; yy<=y+h; yy++) {
      dmd.setPixel(xx,yy,GRAPHICS_ON);
    }
  }
}

void growShrinkBox() {
  dmd.fillScreen(false);
  int boxDelay = 60;
  for (int ii=1; ii<=8; ii++) {
    fillBox(8-ii, 8-ii, ii*2, ii*2);
    fillBox(24-ii, 8-ii, ii*2, ii*2);
    delay(boxDelay);
  }
  for (int ii=8; ii>=0; ii--) {
    dmd.fillScreen(false);
    fillBox(8-ii, 8-ii, ii*2, ii*2);
    fillBox(24-ii, 8-ii, ii*2, ii*2);
    delay(boxDelay);
  }
}

Some apparent out by one errors....

BARS[xx+16-i][yy]
for (int ii=0; ii<=16; ii++) {

Besides the off by 1, if you give your variables better names

void gateAtPosition(int currentColumn) {
  dmd.fillScreen(false);
  for (int column=0; column < currentColumn; column++) {
    for (int row=0; row < H; row++) {
      if (BARS[column+W/2-currentColumn][row] == 0) {
        dmd.setPixel(column,row,GRAPHICS_OFF);
        dmd.setPixel(W-column-1,row,GRAPHICS_OFF);
      } else {
        dmd.setPixel(column,row,GRAPHICS_ON);
        dmd.setPixel(W-column-1,row,GRAPHICS_ON);
      }
    }
  }
}

void closeGate() {
  int delayReduction = 12;
  int delayStep = 300;
  for (int column=0; column < W/2; column++) {
    gateAtPosition(column);
    delay(delayStep);
    delayStep -= delayReduction;
  }
  delay(1000);
}

it appears you are accessing your BARS array in reverse. Arrays are row, column but since yours is square, it doesn't get noticed. Your comments along BARS should also be changed to 0..15 since that is how you index them.

Also an int array is very wasteful for just a monochrome bitmap. You’d do better with a bool array, or even better bit flags in a byte.
Or you don’t really need a bitmap at all. You could just as easily draw the bars with the fillBox function.

drewthommo:
The 2nd part with the boxes is working as expected, but the vertical bars animation shows random pixels as the bars scroll inwards.

Finally figured out (stumbled across) the problem. It was power. When I started this question, the project was powering the board from a 12V transformer (via the jack, rather than USB).

Now that Arduino is powered via USB (at 5V), it's working perfectly.

Some advice was recommending to power both LED arrays directly form the Arduino, but each can consume 3 Amps at maximum. Both arrays together, as powered from the Arduino, was just too dim.