Array Define - Best Method

How can I define this array in programming space without wasting RAM memory?Array elements are constants.

byte  Pat2[5][18]={ {0,1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,2},
                    {0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,0,2,0},
                    {0,0,3,0,0,3,0,0,0,0,0,0,3,0,0,0,0,0},
                    {4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,4},
                    {0,0,0,5,0,0,0,0,0,5,0,0,0,0,0,0,5,0}
                    };

Thanks

You have 90 (5x18) bytes information to save which you must need 90 bytes RAM locations. Correct? To save RAM space, you can store it in flash/program memory

You have shown a 2-dimensional arrangement of your data in the decalarion. However, data bytes are always saved in consecutive memory locations.

Read about PROGMEM

There are lots of zero in your array (15 per line) and numbers are small. What is it representing ? May be there is a better representation tant will use up less space.

the user @nickgammon explains PROGMEM very well:
Gammon Forum : Electronics : Microprocessors : Putting constant data into program memory (PROGMEM)

as @J-M-L already pointed out, based on the values we can see, I assume there are more efficent ways to represent your data. For example instead of 5 x 18 = 90 Bytes, in a array of 16 x 3 bytes = 48

//                   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
byte  Pat2[5][18]={ {0,1,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,2},       //0  3 values
                    {0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,0,2,0},       //1  4 values
                    {0,0,3,0,0,3,0,0,0,0,0,0,3,0,0,0,0,0},       //2  3 values
                    {4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,4},       //3  3 values
                    {0,0,0,5,0,0,0,0,0,5,0,0,0,0,0,0,5,0}        //4  3 values
                    };
                    
                    
//5 x 18 =  90  Byte
 


struct MyStruct
{
   byte row;
   byte col;
   byte value;
};
MyStruct pat3[] = {{0, 1, 1},
                   {0, 4, 3},
                   {0, 17, 2},
                   {1, 3, 2},
                   {1, 7, 2},
                   {1, 11, 2},
                   {1, 16, 2},
                   // and so on ... 16 x 3 bytes = 48
                   };

and even this can be compressed even more, down to 32 should not be a big issue.

Without going too far away from your idea

struct MyStruct
{
   byte row:5;
   byte col:3;
   byte value;
};

Probably would do.

Except for line 1, it seems that for the other lines the value is the line number. Is line 1 correct? If it’s only 1s in there then it’s the index of the line+1 so could be even smaller

Of course that’s more computationally intensive to go find entry (x,y)

basically what I meant, just one remark:

row 0..4 --> 3 byte
col 0..17 --> 5 byte

This is the question, which should be answered before this thread completely derails into off topic speculation

Ooos indeed the other way around for the bitset

Yes we need to understand the use case, storing the whole thing in progmem could be good enough

Then you need to look at the resulting code and determine which takes more actual space in program memory, the original 80 byte array if stored in PROGMEM (with the associated code to read from PROGMEM), or the compressed array and the code to decompress it.

it depends for what the data is needed and how it should be used. When @Prasanjith will explain the usecase in more detail there might be another solution.

however, 3 sketches to compare:

//Sketch uses 1774 bytes (5%) of program storage space. Maximum is 32256 bytes.
//Global variables use 278 bytes (8%) of dynamic memory, leaving 1864 bytes for local variables. Maximum is 2048 bytes.

byte  Pat2[5][18] = { 
  {0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2},
  {0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0},
  {0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0},
  {4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 4},
  {0, 0, 0, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 5, 0}
};

void readData()
{
  for (int x = 0; x < 5; x++)
    for (int y = 0; y < 18; y++)
      Serial.println(Pat2[x][y]);
}

void setup() {
  Serial.begin(115200);
  readData();
}

void loop() {
}

PROGMEM

/*
PROGMEM
Sketch uses 1774 bytes (5%) of program storage space. Maximum is 32256 bytes.
Global variables use 188 bytes (9%) of dynamic memory, leaving 1860 bytes for local variables. Maximum is 2048 bytes.
*/

const byte Pat3[5][18] PROGMEM = { 
  {0, 1, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2},
  {0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0},
  {0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0},
  {4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 4},
  {0, 0, 0, 5, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 5, 0}
};

void readData()
{
  for (int x = 0; x < 5; x++)
    for (int y = 0; y < 18; y++)
      Serial.println(pgm_read_byte(&Pat3[x][y]));
}

void setup() {
  Serial.begin(115200);
  readData();
}

void loop() {
}

smaller Array:

/*
  small in RAM
  Sketch uses 1754 bytes (5%) of program storage space. Maximum is 32256 bytes.
  Global variables use 218 bytes (10%) of dynamic memory, leaving 1830 bytes for local variables. Maximum is 2048 bytes.
*/

struct MyStruct
{
  byte row: 3;
  byte col: 5;
  byte value;
};
MyStruct pat4[] = {
  {0, 1, 1},
  {0, 4, 3},
  {0, 17, 2},
  {1, 3, 2},
  {1, 7, 2},
  {1, 11, 2},
  {1, 16, 2},
  {2, 2, 3},
  {2, 5, 3},
  {2, 12, 3},
  {3, 0, 4},
  {3, 8, 4},
  {4, 3, 5},
  {4, 9, 5},
  {4, 16, 5}
};

void readData()
{
  size_t index = 0;
  for (int x = 0; x < 5; x++)
    for (int y = 0; y < 18; y++)
    {
      byte actual = 0;
      if (x == pat4[index].row && y == pat4[index].col)
      {
        actual = pat4[index].value;
        index++;
      }
      Serial.println(actual);
    }
}


void setup() {
  Serial.begin(115200);
  readData();
}

void loop() {
}

Many thanks.
Actually I am doing a LED matrix pattern design.
Matrix size is 5 rows and 18 columns.

The pattern data i need to store same like the matrix display in a 2D array.So I can index them nicely.

@Noiaca
Thanks for the effort.I planned to use the "progmem" method.Which is easier & readable & space saving..

To see your program output as follows, I have modified one line and have added two more lines with your readData() routine. Thanks for the program which serves as a good example to perform read/write operation with flash/program memory of the ATmega328P MCU of the UNO Board.

0 1 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 2 
0 0 0 2 0 0 0 2 0 0 0 2 0 0 0 0 2 0 
0 0 3 0 0 3 0 0 0 0 0 0 3 0 0 0 0 0 
4 0 0 0 0 0 0 0 4 0 0 0 0 0 0 0 0 4 
0 0 0 5 0 0 0 0 0 5 0 0 0 0 0 0 5 0 
void readData()
{
  for (int x = 0; x < 5; x++)
  {
    for (int y = 0; y < 18; y++)
    {
      Serial.print(pgm_read_byte(&Pat3[x][y]));
      Serial.print(' ');
    }
    Serial.println();
  }
}

Just a question,

Reading from program memory (pgm_read_byte) how will it perform? I mean reliability over 24/7 days run? Specially when this code is insert to a cheap ESP-01S boards? I heard reading from program memory does lots of coding stuff inside. Doing this all over & over will it be ok?

Your program’s code is in flash too… if that was not working, the code would not run reliably

My code works nicely at the time being. Just considering the reliability of this method...!!

I would not worry more about this than the program not loading. Even if you were storing the data in SRAM it would have to come from flash when you start the code.

If you are worried, add a CRC and compute the CRC


The ESP-01S does not have PROGMEM as such, PROGMEM is a specific method of handling data stored in flash memory on a processor in which the flash memory and dynamic memory (ram) are in separate address spaces, and therefore require different code to access. The ESP-01S has all its memory in a single address space, and can access both areas of memory with the same code, so the compiler essentially ignores PROGMEM and all its related special coding. The compiler will automatically store all const data in flash memory.

Please ignore, this is all incorrect, as stated in the subsequent post. Apologies for my unfamiliarity with the ESP8266 architecture.

I don't think so

cf Guide to PROGMEM on ESP8266 and Arduino IDE — ESP8266 Arduino Core 3.1.2-21-ga348833 documentation

Intro

PROGMEM is a Arduino AVR feature that has been ported to ESP8266 to ensure compatibility with existing Arduino libraries, as well as, saving RAM. On the esp8266 declaring a string such as const char * xyz = "this is a string" will place this string in RAM, not flash. It is possible to place a String into flash, and then load it into RAM when it is needed. On an 8bit AVR this process is very simple. On the 32bit ESP8266 there are conditions that must be met to read back from flash.