Guidance w/ memory usage + large multidimensional arrays

Hello,

I have a project requiring large arrays to make animations out of >500 LED bulbs. I'm using an UNO and believe I'm running out of PROGMEM. Example array size is array[300][64], and looks like:

#include <avr/pgmspace.h>
const int animation1[300][64] PROGMEM = {
    { 0b00000100, 0b00000100, 0b00000000, 0b00000000, 0b00000111, 0b00000000, 0b10000000, 0b00000000, 0b11000000, 0b00001100, 0b11000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b01000000, 0b00000000, 0b00000110, 0b00000000, 0b00000010, 0b00000000, 0b00000001, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00010000, 0b00000010, 0b00000000, 0b00000000, 0b00100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b11000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00010000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b01000000, 0b00000000, 0b00000000, 0b00000010, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b10000000, 0b0000000 },
    { 0b00000100, 0b00000100, 0b00000000, 0b00000000, 0b00001110, 0b00000000, 0b10000000, 0b00000000, 0b10000000, 0b00011000, 0b10000000, 0b00000000, 0b00000000, 0b01110000, 0b00000000, 0b10000000, 0b00000000, 0b00000100, 0b00000000, 0b00000100, 0b00000000, 0b00000011, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00100000, 0b00000001, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b10000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00010000, 0b00000000, 0b00000100, 0b00000000, 0b00000000, 0b00000000, 0b01000000, 0b00000000, 0b00000000, 0b00000000, 0b00110000, 0b00001001, 0b00000000, 0b00001000, 0b00000000, 0b0000000 },
    { 0b00100000, 0b00010000, 0b00010000, 0b00000000, 0b11000000, 0b00000000, 0b00000000, 0b00000011, 0b00000000, 0b10000100, 0b00000000, 0b00000011, 0b01001100, 0b00000000, 0b10001100, 0b00000000, 0b00000000, 0b01110000, 0b00000000, 0b00000000, 0b00000000, 0b00001000, 0b00010000, 0b00000000, 0b00000000, 0b00000000, 0b00000100, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b10000000, 0b00000000, 0b00000000, 0b00000000, 0b00110000, 0b00011000, 0b00000000, 0b01000000, 0b01000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00100000, 0b00000000, 0b00100111, 0b00000000, 0b10000000, 0b00000010, 0b00000000, 0b00000000, 0b00000000, 0b00100010, 0b00001000, 0b00000000, 0b00000010, 0b00000000, 0b0000000 }
    // etc for 300 rows...
};

It will work with 9, sometimes 10 rows of data before the lights indicate memory issues. Can anyone provide guidance on:

  • What can I do to compress this data?
  • Is PROGMEM the best option for this? Will I need more flash memory in order to support such large arrays?

Thanks!

Why are you wasting half your array?

believe I'm running out of PROGMEM.

Why believe, when the compiler tells you whether you are or not?

300 * 64 * 2 (for int) is 38400 bytes. The uno only has 31k available, and that also has to fit your code.

I'm not sure how you're getting it to compile like that, let alone have lights indicating a memory issue!

If you're only declaring it as having 10 rows, not 300, though, you should have plenty of space - in that case, I would venture a guess that your sketch is copying the whole array into RAM somewhere - 10 rows is 1280 bytes, and it wouldn't be unreasonable if the rest of your sketch took 744 or more bytes of RAM...

Anyway, switching to byte instead of int will halve the amount of program memory required for the array, since it looks like all the elements in the array are between 0 and 255, so will fit in a byte.

I quickly noticed the INT issue too. Why, oh why, do people automatically use INT when declaring variables ? Think about what the data is, and declare appropriately.

For instance, I often see things such as:

int ledPin = 2;

when assigning an Arduino pin. A byte can hold a number from 0 to 255, so why not use it. Also, in the majority
of cases, that pin assignment isn't going to change, so a better declaration and assignment would be:

const byte ledPin = 2;

I've even seen:

unsigned int ledPin = 2; // WHY? just why ?

In the OP's case, as is noted earlier, he's declaring the array as INT when it quite obviously only holds bytes. So his values are being stored in a variable placeholder that is something like 4 times bigger than the maximum value being used. That's wasting a huge amount of storage memory.

When declaring and assigning, everyone please, think about what type of data is being used and declare accordingly.

300x64 = 19200 bytes

If your program isn't too big it might fit.

Can't you compress your data, or use an algorithm to provide it?

Allan

unsigned int ledPin = 2; // WHY? just why ?

So you don't assign it a negative value. Can't use pin -4, after all.

I've seen code where the pin numbers were stored in floats. So, you could use pin 3.14159, I guess.