Can someone explain this piece of code?

This is taken from the playground LED direct drive sample code:

void setPattern(int pattern) {
  for (int i = 0; i < 8; i++) {
    for (int j = 0; j < 8; j++) {
      leds[i][j] = patterns[pattern][i][j];
    }
  }
}

void slidePattern(int pattern, int del) {
  for (int l = 0; l < 8; l++) {
    for (int i = 0; i < 7; i++) {
      for (int j = 0; j < 8; j++) {
        leds[j][i] = leds[j][i+1];
      }
    }
    for (int j = 0; j < 8; j++) {
      leds[j][7] = patterns[pattern][j][0 + l];
    }
    delay(del);
  }
}

I am driving a 6x20 matrix however it is not sliding anything (nor displaying text)

Thanks for the help!

Apparently:

  • setPatern(...) copies an array to another array;
  • "patterns" is an array of 2-dimensional arrays, holding the character/sprite definitions;
  • "leds" is the display memory; it holds either 0 or 1, representing the state of each LED in the matrix;
  • so, setPatern(int patern) copies the specified predefined "patern" to the display memory;
  • slidePatern() shifts the display memory by one column to the left and copies in the right-most column of the display memory the left-most column from the specified "patern";

"The secret to write good code is to write it as if the next one that will read your code is a serial killer that knows where you live. "

You would need to modify both the hardware and the software (example code) to make it working with a 6x20 matrix. Big time code changes.

thanks for the responses. Here is how i have modified the code so far but to no avail.

#include <FrequencyTimer2.h>


/*
 * Show messages on an 8x8 led matrix,
 * scrolling from right to left.
 *
 * Uses FrequencyTimer2 library to
 * constantly run an interrupt routine
 * at a specified frequency. This
 * refreshes the display without the
 * main loop having to do anything.
 *
 */


#define T { \
    {0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, \
    {0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, \
    {0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, \
    {0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, \
    {0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, \
    {0, 0, 0, 0, 1, 1, 0, 0, 0, 0} \
}
#define E { \
    {0, 0, 0, 1, 1, 1, 1, 0, 0, 0}, \
    {0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, \
    {0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, \
    {0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, \
    {0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, \
    {0, 0, 0, 1, 1, 1, 1, 0, 0, 0} \
}
#define S { \
    {0, 0, 0, 0, 1, 1, 1, 0, 0, 0}, \
    {0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, \
    {0, 0, 0, 0, 1, 1, 0, 0, 0, 0}, \
    {0, 0, 0, 0, 0, 1, 1, 0, 0, 0}, \
    {0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, \
    {0, 0, 0, 0, 1, 1, 0, 0, 0, 0} \
}

byte col = 0;
byte leds[6][10];

// pin[xx] on led matrix connected to nn on Arduino (-1 is dummy to make array start at pos 1)
int pins[17]= {-1, 14, 15, 16, 17, 18, 19, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};

// col[xx] of leds = pin yy on led matrix
int cols[10] = {pins[7], pins[8], pins[9], pins[10], pins[11], pins[12], pins[13], pins[14], pins[15], pins[16]};

// row[xx] of leds = pin yy on led matrix
int rows[6] = {pins[1], pins[2], pins[3], pins[4], pins[5], pins[6]};

const int numPatterns = 4;
byte patterns[numPatterns][6][10] = {
  T,E,S,T
};

int pattern = 0;

void setup() {
  // sets the pins as output
  for (int i = 1; i <= 16; i++) {
    pinMode(pins[i], OUTPUT);
  }

  // set up cols and rows
  for (int i = 1; i <= 10; i++) {
    digitalWrite(cols[i - 1], LOW);
  }

  for (int i = 1; i <= 6; i++) {
    digitalWrite(rows[i - 1], LOW);
  }

  clearLeds();

  // Turn off toggling of pin 11
  FrequencyTimer2::disable();
  // Set refresh rate (interrupt timeout period)
  FrequencyTimer2::setPeriod(1000);
  // Set interrupt routine to be called
  FrequencyTimer2::setOnOverflow(display);

  setPattern(pattern);
}

void loop() {
    pattern = ++pattern % numPatterns;
    slidePattern(pattern, 60);
}

void clearLeds() {
  // Clear display array
  for (int i = 0; i < 6; i++) {
    for (int j = 0; j < 10; j++) {
      leds[i][j] = 0;
    }
  }
}

void setPattern(int pattern) {
  for (int i = 0; i < 6; i++) {
    for (int j = 0; j < 10; j++) {
      leds[i][j] = patterns[pattern][i][j];
    }
  }
}

void slidePattern(int pattern, int del) {
  for (int l = 0; l < 8; l++) {
    for (int i = 0; i < 7; i++) {
      for (int j = 0; j < 8; j++) {
        leds[j][i] = leds[j][i+1];
      }
    }
    for (int j = 0; j < 8; j++) {
      leds[j][7] = patterns[pattern][j][0 + l];
    }
    delay(del);
  }
}

// Interrupt routine
void display() {
  digitalWrite(cols[col], LOW);  // Turn whole previous column off
  col++;
  if (col == 10) {
    col = 0;
  }
  for (int row = 0; row < 6; row++) {
    if (leds[col][5 - row] == 1) {
      digitalWrite(rows[row], LOW);  // Turn on this led
    }
    else {
      digitalWrite(rows[row], HIGH); // Turn off this led
    }
  }
  digitalWrite(cols[col], HIGH); // Turn whole column on at once (for equal lighting times)
  delayMicroseconds(900);  // Delay so that on times are longer than off time = brighter leds
}

Also, my 6x20 matrix is set up like this:

I believe my problem is that the original code is only addressing the one led per column where mine needs to address each column in both directions.

I assume you are not just wiring up this matrix to the Arduino without any current limiting resistors or external drivers.

If you just have this then it will not work.

There is nothing limiting the current and the arduino can't supply the power to drive a row of 12 LEDs.

From the schematic you pointed to, as far as I understand, at every node in the matrix, there is a pair of LEDs connected opposite to each other. This would mean that at any time, when one of the LEDs in a node is on, the other is off and viceversa. So, what I am trying to say is that the LEDs in anode are not really independent, they cannot be controlled independently.

From the schematic you pointed to, as far as I understand, at every node in the matrix, there is a pair of LEDs connected opposite to each other. This would mean that at any time, when one of the LEDs in a node is on, the other is off and viceversa. So, what I am trying to say is that the LEDs in anode are not really independent, they cannot be controlled independently

Surely if you put 0v at both ends of the wire (or 5v at both ends) then neither LED will light. Put 0v at one end and 5v at the other and one LED will light; put them the other way around and the other LED will light.

So instead of the original code taking one sweep through each column in turn it needs to deal with each column twice, once with the current in each direction. This might make the refresh rate too slow.

Andrew

I assume you are not just wiring up this matrix to the Arduino without any current limiting resistors or external drivers.

If you just have this then it will not work.

There is nothing limiting the current and the arduino can't supply the power to drive a row of 12 LEDs.

would it still matter even if i am using frequencytimer2? ibasically all that is happening is that every other row lights up but there is no shifting

You must always fit a current limiting resistor in series with a LED, no matter how you drive it in software. And an Arduino pin can only ever supply 40mA absolute max. You should not attempt to draw that maximum current from more than one pin at a time.

I feel like i am going down the wrong path now. Should i be using shift registers or MAX chip to control this 6x20 array properly?

Andrew, you are perfectly right. I promise I will refrain from posting when I am drunk.

Should i be using shift registers or MAX chip to control this 6x20 array properly

A Max chip will provide the drive and the current limit but it will not work with those LEDs facing forward and back, it will only work with a conventional matrix. If you want to drive the matrix the way you have it you need a driver for the row and the column. As you need to drive both high and low you should probably use the sort of chip you would use to drive a motor. In that case you need a resistor in line with EACH LED to limit the current to a safe value.
Then you can get fancy with the software.

A Max chip will provide the drive and the current limit but it will not work with those LEDs facing forward and back, it will only work with a conventional matrix. If you want to drive the matrix the way you have it you need a driver for the row and the column. As you need to drive both high and low you should probably use the sort of chip you would use to drive a motor. In that case you need a resistor in line with EACH LED to limit the current to a safe value.
Then you can get fancy with the software

Well I do not necessarily need to have this arrangement (leds opposite each other). It was just saving me pins. I will check out other methods.

By EACH LED, you mean I will be using 120 resistors correct? Not just one on each row/column?

Thanks again for the advice.

By EACH LED, you mean I will be using 120 resistors correct?

Yep. :slight_smile:

If you restrict it to just columns and rows then the brightness will change depending on how many LEDs you have on in that row/column. This will range from not enough current to see to too much for the LED depending on which resistor value you choose.
That is the advantage of the Max chip or indeed the TLC5945, they control the current so you don't have to have a limiting resistor in each LED.

Yep.

If you restrict it to just columns and rows then the brightness will change depending on how many LEDs you have on in that row/column. This will range from not enough current to see to too much for the LED depending on which resistor value you choose.
That is the advantage of the Max chip or indeed the TLC5945, they control the current so you don't have to have a limiting resistor in each LED.

Thanks Mike, I guess I better head back to the drawing board!

So which would you personally choose? MAX or TLC5945? I am aiming for a low price point here as well.

Thanks

I would go for the TLC as you get brightness control. However the advantage of the MAX is that you can set it running and forget it.

Ok I am going to start throwing out things here and gonna see what sticks.

Let say I have a 6x20 matrix (not in previous arrangement of opposite LED's) and needs to be bi-color.

First, can I do this with MAX chips or does it have to be an 8x8 pattern.

Second, if the MAX chips will work, I am assuming I will need 4 of them because it takes 2 of them to drive an 8X8 bi-color matrix correct?

RGB 6x20 matrix would be nominal but that would be cost prohibitive (trying to stay under $75 in parts).

The Max chip can drive up to an 8 X 8 matrix.
Therefore for a 6 X 20 matrix you will need 3 MAX chips.
If they need to be Bi coloured then you will need 6 MAX chips. Have you got common anode or cathode LEDs?

You might be able to get away with less by filling in, that is by saying 8 X 8 is 64 LEDs and 6 X 20 is 120 LEDs.
However the driving software would be a nightmare as the mapping would be quite odd.

Anyway get the MAX data sheet and start reading it.

Is your 6x20 matrix something pre-built that you cannot get around? I would start experimentation with a 6x8 matrix first, get a feeling of how that works, then expand to 6x20, or more.

It is sort of something that I am stuck with right now. These will be individual LED's soldered together so i guess it could be common anode or common cathode. It seems like there should be some other (cheaper) way.

Is it really that big of a coding nightmare to do 6x20?

By the way, if you look back at my earlier posts, you'll see the LED matrix I tried building. Mike said I would need hundreds of resistors for that type of build but the creator of the circuit (NerdKits) told me that they were not needed because the uC is the limiting factor by only drawing a couple mA.

I guess I am confused now because doesnt persistance of vision keep current draw down? I dont want to light this whole thing up at one time, just 20 leds at the most.

NerdKits - DIY Marquee LED Array Display <--they use 5x24 matrix with no resistors or driver chips

Note: I could care less about led brightness or consistency.