Go Down

Topic: 16 x 16 LED Matrix Animation Limitations Using MAX7129 and ledControl Library (Read 424 times) previous topic - next topic

geckoman101

Hello all,

I have been experimenting using 4 x MAX7129's in series to drive 4 x (8x8) led matrices. Using the led control libraries I have successfully put together a few animations by splitting each 16 x 16 sprite "frame" into 4 x (8x8) matrices consecutively using states.

The issue I am running into however is that these 16 x 16 sprite bytes "frames" have to be global variables so that I can run them each separately through the function to split them into each 8x8 array.

To get more variability I have added additional functions to manipulate these frames by translating the array to the left / upwards to make the sprite move in those directions.

Is this the best method to do this? Would changing all these to local variables take up less space even though I would have to have many more arrays? Or is there somehow I can make my global variable matrices take up less space?

Here is my current code and photo of setup attached below:




noiasca

Is this the best method to do this? Would changing all these to local variables take up less space even though I would have to have many more arrays? Or is there somehow I can make my global variable matrices take up less space?
I see two possibilities:

a) you could store your data instead in RAM in the PROGMEM --> https://www.arduino.cc/reference/en/language/variables/utilities/progmem/

b) Currently you need 16x16 byte = 256 Byte for each picture. You use one byte for each dot. Break it down and use bits for the dots.
If you us an array of uint16_t[16] it will take only 32 bytes. Each element/index represents one row, each bit one dot.
Code: [Select]

0b0000000000000000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b1111111111111111


and so on. In this case you have a bitmask, wherein each bit represents one dot. You could even combine these two concepts and store the uint16_t[16] in PROGMEM.

how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

geckoman101

Will i need to convert the bit arrays back into bytes within each function in order to still use the display and translate functions?

noiasca

how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

Paul__B

I think you should look into the "Parola" library in the library manager.

noiasca

everything clear now?

I see you are using a function:

int rowValue(unsigned char address, byte i)

for your case 0 and 1 you need the 8 most significant bits. Therefore shift the bits by 8 to right:
Code: [Select]

result = A[i] >> 8;


for case 2 and 3 you need only the 8 less significant bits, therefore mask these 8 bits with and AND:
Code: [Select]

result = A[i] & 0b0000000011111111;


by the way: see also the description for the switch case: there is no reason to write duplicate code if you have cases which should do the same code.
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

geckoman101

Yes thank you for the help that makes the bit interpretation a lot clearer.

I see what you mean about the repeating cases for rowValue returns however I cannot see a way to assign the case case to two separate address values.

geckoman101

Actually I was able to simplify it by doing this:

switch (address) {

 case 0: case 1: {

results = . . .
break;
}

Is that what you were referring to?

noiasca

how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

geckoman101

Alright I am very close to getting this working. Upon testing I've noticed that the bit arrays are being clipped down to 8 instead of 16 somewhere along the way.

The only other issue is Case 3 displaying mirrored vertically, however im sure that can be fixed with some array transpose.

Here is my current code:

Code: [Select]
#include "LedControl.h"

#define Width 16
#define Height 16

/*
   pin 12 is connected to the DATA
   pin 11 is connected to the CLK
   pin 10 is connected to CS
*/

LedControl lc = LedControl(12, 11, 10, 4);


byte t9[16]  =  {0b0000000000000000,
        0b0000111111110001,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110001,
0b1111111111111111,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b1111111111111111
};

byte t10[16]  =  {0b0000000000000000,
0b0000111111110000,
0b0000111111110001,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110010,
0b1111111111111111,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b1111111111111111
};

byte t11[16]  =  {0b0000000000000000,
0b1000111111110000,
0b0000111111110000,
0b0000111111110001,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111110100,
0b1111111111111111,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b1111111111111111
};

byte t12[16]  =  {0b0000000000000000,
0b0000111111110000,
0b1000111111110000,
0b0000111111110000,
0b0000111111110001,
0b0000111111110000,
0b0000111111110000,
0b0000111111110000,
0b0000111111111000,
0b1111111111111111,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b1111111111111111
};

unsigned long delayTime = 1000;
//byte t1[16][16];
byte t2[16];
byte A[16];

void setup() {
  int devices = lc.getDeviceCount();
  //we have to init all devices in a loop
  for (int address = 0; address < devices; address++) {
    delay(10);
    /*The MAX72XX is in power-saving mode on startup*/
    lc.shutdown(address, false);
    /* Set the brightness to a medium values */
    lc.setIntensity(address, 1);
    /* and clear the display */
    lc.clearDisplay(address);
    Serial.begin(9600);
  }
  //randomize(t1);
}

void loop() {
 
  display(t9);

  delay(delayTime);
 
  display(t10);

  delay(delayTime);
 
  display(t11);

  delay(delayTime);
 
  display(t12);

  delay(delayTime);


}



void display(byte t1[16]) {
  for (unsigned char matrixCount = 0; matrixCount < 4; matrixCount++) {
    //lc.clearDisplay(matrixCount);
    for (unsigned int i = 0; i < 8; i++) {
        switch (matrixCount) {
          case 1: {
              A[i] = t1[i];
              break;
            }
          case 0: {
              A[i] = t1[i];
              break;
            }
          case 2: {
              A[i] = t1[i+8];
              break;
            }
          case 3: {
              A[i] = t1[i+8];
              break;
            }
        }
    }
    updateDisplay(matrixCount);
  }
}


void updateDisplay(unsigned char address) {
  if (address < 2 ) {
    for (int i = 0; i < 8; i++) {
      lc.setRow(address, i, rowValue(address, i));
      //delay(100);
    }
  } else {
    for (int i = 0; i < 8; i++) {
      lc.setRow(address, i, rowValue(address, 7-i));
      //delay(100);
    }
  }
}

int rowValue(unsigned char address,byte i) {
  int result;
  switch (address) {
    case 2: case 1: {
                Serial.println(A[i]);
        result = A[i] & 0b1111111100000000;
        break;
      }
    case 3: case 0: {
        result = A[i] & 0b0000000011111111;
        break;
      }
  }
  return result;
}

noiasca

Code: [Select]

byte t9[16]  =  {0b0000000000000000,

it's not a byte (holding one byte)... it should be uint16_t!
Code: [Select]

result = A[i] & 0b1111111100000000;

is wrong. You need to SHIFT like explained in #5

I guess you mixed up the combinations. In your Sketch form #1 case 0 and case 1 were the same. Now you combine case 1 and 2.  I guess this needs a fix also.





how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

Go Up