2D array works. 3D doesn't.

Hi, Arduino forum.

I have been stuck on this problem all day and I can’t figure out why my array doesn’t work. If this array works, it could replace an awful long switch case function.

I get no errors. The program simply does not output anything.

This program is controlling an RGB led array.

Here is a piece of my code. the function “writeLetter” does not work, even though the only difference is one more array within the array. The function “letterA” works as it should.

The difference is:

from: A[5][5]
to: letterArray[256][5][5]

and

from: A[4-y][x]
to: letterArray[(int)letter-65][4-y][x]

I call the function with writeLetter('A', 2, 2, 0, 50, 50);.

void writeLetter(char letter, int width, int height, int red, int green, int blue)
{
  //boolean [antall-char(tegn)][char-width][char-height]
  boolean letterArray[256][5][5] = {//A
                                   {{0, 0, 1, 0, 0},
                                    {0, 1, 0, 1, 0},
                                    {1, 1, 0, 0, 1},
                                    {1, 1, 1, 1, 1},
                                    {1, 1, 0, 0, 1}},
                                    //B
                                   {{1, 1, 1, 1, 0},
                                    {1, 1, 0, 0, 1},
                                    {1, 1, 1, 1, 0},
                                    {1, 1, 0, 0, 1},
                                    {1, 1, 1, 1, 0}}};
  
  
  Serial.println(((int)letter)-65);
  uint32_t color = strip.Color(red, green, blue);
                     
  for(int x = 0; x < 5; x++)
  {
    for(int y = 0; y < 5; y++)
    {
      if(width > WIDTH-5 && letterArray[(int)letter-65][4-y][x] == true) strip.setPixelColor(width + x + y*WIDTH + (height-1)*WIDTH, color);
      else if(letterArray[(int)letter-65][4-y][x] == true) strip.setPixelColor(width + x + y*WIDTH + height*WIDTH, color);
    }
  }
}





//  y
//  ^
//  |     #
//  |   #   #
//  | # #     #
//  | # # # # #
//  | # #     #
//  ------------> x
void letterA(int width, int height, int red, int green, int blue)
{
  uint32_t color = strip.Color(red, green, blue);
  boolean A[5][5] = {{0, 0, 1, 0, 0},
                     {0, 1, 0, 1, 0},
                     {1, 1, 0, 0, 1},
                     {1, 1, 1, 1, 1},
                     {1, 1, 0, 0, 1}};                   
  for(int x = 0; x < 5; x++)
  {
    for(int y = 0; y < 5; y++)
    {
      if(width > WIDTH-5 && A[4-y][x] == true) strip.setPixelColor(width + x + y*WIDTH + (height-1)*WIDTH, color);
      else if(A[4-y][x] == true) strip.setPixelColor(width + x + y*WIDTH + height*WIDTH, color);
    }
  }
}

Thank you for your thought.

Strange. If I use “boolean letterArray[ x ][5][5]”
where x=2, 3, 4…19, 20
It works. More than 20, it makes some crazy light shows. More than 50, and it doesn’t work at all.

Input?

An array of 25655 = 6400 bytes, it’s big, it’s 78% of the Arduino Mega’s memory. What Arduino do you use, and don’t you have a red warning about memory usage, when you compile?

And because your values are only 0 or 1’s, you can greatly reduce the space used by that array, for example each of your 5x5 “character” can be held inside 5 bytes, and you can still reduce that if you add some complexity.

Edit: also, since this array is full of constants, you could put it inside progmem.

guix:
An array of 25655 = 6400 bytes, it's big, it's 78% of the Arduino Mega's memory. What Arduino do you use, and don't you have a red warning about memory usage, when you compile?

And because your values are only 0 or 1's, you can greatly reduce the space used by that array, for example each of your 5x5 "character" can be held inside 5 bytes, and you can still reduce that if you add some complexity.

Edit: also, since this array is full of constants, you could put it inside progmem.

Thank you for great input. When it compiled it said it only used 4334 bytes! Was it too much to calculate?

I am using an arduino UNO.

How can I hold each of my (about 70) "characters" inside 5 bytes? I thought I reduced the memory as much as possible by declaring it an boolean.

Progmem, which is flash memory. Why use that? Is it made for big numbers?

Thank you.

A boolean will take one byte because a byte is the smallest addressable unit of memory.

A byte = 8 bits, each bit can be either 0 or 1.

So you could have 5 bytes for a character, for example for letter A:

// "0b" is the prefix for the binary notation of a number
uint8_t A[5] =
{
   0b00100,
   0b01010,
   0b11001,
   0b11111,
   0b11001
};

This example is still wasting 3 unused bits per byte, so a waste of 15 bits per character, that is a total of 480 bytes if you really use 256 characters. Which is why I said it could be improved even more, to not waste anything, at the cost of readability and complexity...

To read a bit from a byte, there is an useful macro, bitRead. Don't forget that the first bit (id 0), is the right most bit, so if you want to read bits from left to right, you have to start from bit 4 and count down to 0. :wink:

You can use progmem to store constants, as the name say, it will store those in program's memory, as opposed to sram where all the variables (constants or not) are normally stored. See this for more info.

Good karma to you!
Thank you.

It works as it should now (uint8_t characters[128][5]).

But if I understand correctly, there is more flash memory than any other kind on the UNO, but it is not used as much?
Why use it/not use it? Why not only have one kind of memory?

Thanks for karma :wink:

Flash is not used as much as other memories, because your program (just the instructions of your program, not variables) is small, but your program could grow and use more Flash :wink:

There are different types of memory because they have different caracteristics.

For example, SRAM is volatile (it will be erased when not powered), but it's fast to read from/write to it and has unlimited write/erase cycles, so it's perfect to use this memory for program's variables that change very often and are accessed very often.

As opposed to EEPROM, which is non volatile, but is slow to read from/write to it, and has limited write/erase cycles (rated 100.000 cycles), it's good for storing data that rarely change and are rarely accessed.

Flash (progmem) is similar to EEPROM but still has some differences. It is faster, but write/erase cycles is even more limited (rated 10.000 cycles), and you can not write to it at runtime. It can be used for storing data that never change and need to be accessed often.

This makes sense. Thank you.