Is there a solution to the 'for function' memory? help me

Is there a solution to the 'for function' memory?

hello.

[Board Information]

  • Board: Arduino Mega 2560
  1. I want to save and read variables to the ‘SD card’.
  2. At this time, multiple data values ​​are stored and read through the ‘for function’.
  3. A memory (global variable) problem occurs.
  4. Please refer to the source code.
#include <SD.h>
File myFile;

uint16_t WM_MENU[65][32];
uint8_t  WM_MENU_D[65][32];

void setup() {
  Serial.begin(115200);   
  for (int i=0; i<65; i++){ for (int k=0; k<32; k++){
    WM_MENU[i][k]=i; WM_MENU_D[i][k]=i;
  }}
  delay(500); 
  SD.begin(53);
  SD_CARD_FUNC();  
}

void loop() {  }

void SD_CARD_FUNC(){

    myFile = SD.open("modes.txt", FILE_WRITE);
    if (myFile) {
      Serial.print(F("WRITE-FUNC : ")); // Serial.println(url);
     for (int i=0; i<65; i++){
          for (int k=0; k<32 ; k++){ 
            myFile.print(String(WM_MENU[i][k])); myFile.print(F("_")); 
          }
          myFile.println("");
          delay(1); 
     }       
     for (int i=0; i<65; i++){
          for (int k=0; k<32 ; k++){ 
            myFile.print(String(WM_MENU_D[i][k])); myFile.print(F("_")); 
          }
          myFile.println("");
          delay(1); 
     }       
        myFile.println("0");   myFile.close();
    }  
}
  1. In my opinion, this syntax is the problem.
    myFile.print(String(WM_MENU[i][k]));

[What I want to implement]

  1. Variable → SD save
  2. Read SD → Save variable

Is there any solution? help me.

Why are you casting to a String before saving to the SD card ?

1 Like

@UKHeliBob
Thank you for answer.

  1. Strings are used to differentiate. It was used to distinguish ‘array’.
  2. After saving to the 'SD card', you need to load it again and put it in a variable.

[function]

  1. Variable → SD save
  2. Read SD → Save variable

Well, you have two global arrays totaling 3840 bytes. You have 8k on your Mega so in principle you should be able to get this to work.
As @UKHeliBob implies above: don't use Strings for starters.
Also, please post the error you're apparently getting.

1 Like

I have no idea what that means

Please post the full error message that you get

1 Like

@UKHeliBob
@rsmls

Sketch uses 12730 bytes (5%) of program storage space. Maximum is 253952 bytes.
Global variables use 7108 bytes (86%) of dynamic memory, leaving 1084 bytes for local variables. Maximum is 8192 bytes.
Low memory available, stability problems may occur.

No the arrays occupy 6240 bytes ( 65x32x3 ). One array is int and the other byte.
And the SD lib needs a lot of ram too.
That's too much, even for a Mega. Even worse with the usage of String, which needs ram on the heap ( which is additionally to globals ).

1 Like

When I replied, the array size in the sketch was [40][32]. I think the post was edited.

1 Like

Do you really need a such huge arrays?

The common workaround for a similar memory problems is to divide the data in parts.

As an example, instead of fulfilling the entire 65x32 array and then storing it to the SD, you would work with it row by row: insert a first 32 values to a single-row 1x32 array and write it to SD, then put a next 32 values to the same array and put them to the SD and so on

1 Like

It was

2 Likes

@MicroBahner
@rsmls
@b707
@UKHeliBob

hello. Thanks for your reply.

I was mistaken.
(I was wrong. The problem is simply that there are too many variables and there is not enough memory. The problem is not that the 'for function' was performed...)
This is not a problem with the 'SD library' or 'for function', but a memory problem solely based on variables.

Let's look for improvements.
thank you for the reply.

@MicroBahner
@rsmls
@b707
@UKHeliBob

  1. The reason for changing it to "65" was to display an "error message".

  2. For now, we plan to make the following modifications.

uint8_t WM_MENU[40][32];
uint8_t WM_MENU_D[40][32];
  1. The range of "WM_MENU" values ​​is 0 to 255.
  2. However, in terms of coding, we plan to multiply it by 10 and code the range from 10 to 2550.

I really appreciate your response to my story. thank you so much.
thank you

Why not save it as a uint8_t and do the multiplying only at the moment it's necessary (e.g. when they're being displayed)? There's no sense in storing redundant data; in this case the trialing zeroes of the multiplied integer. For your program, things will work the same if you store values of 1, 2, 3, 10, 255 and then multiply them to 10, 20, 30, 100 and 2550. But if you store the multiplied values (both in an array and on your card), they'll take up twice as much space.

OK, so assuming the actual arrays are [40][32], the root cause of your problem is not so much in these two arrays (they fit easily in your Mega's memory, with room to spare), but also what happens in the rest of your sketch. Memory management is often a balancing act; it's a budget and you have to allocate it to where it's needed the most, and compromise where you can. See the "multiply by 10" issue above.

1 Like

@rsmls

Thanks for the advice.
This method has 0~255 in memory, but
In the code, you can assume that the virtual value is 10 to 2550.

To take a simple example,

float result = 0;
uint16_t
result = (float)X1 * 0.1; // actual calculation expression

float result = 0;
uint8_t
result = (float)X1 * 1.0; // virtual coding, How to bypass

It should be used as assumed above. This seems to be the answer for now.

It may be a matter of how you approach the job. On a PC, tendency is to "grab it all, then process it all". On a micro, it's usually better to grab a bit, process it, iterate until done. If at all possible, rethink your approach that way. Even a menu system can sometimes be partitioned into sections and read when needed, though that can get painful, when it is easier to just push fixed text off into program space.

1 Like

Here you use a 4-byte data type to store 1 byte of actual information. I feel you're juggling data types around without sufficiently realizing the implications. I bet if you remove all such inefficiencies from your code, it'll run just fine.

1 Like

@rsmls

hello. Thanks for the advice.
I know what you're talking about.

uint16_t WM_MENU[40][32];
uint8_t WM_MENU_D[40][32];

The ‘variables’ above are stored values.

  1. I tried to load it from 'EEPROM', but '2K bytes' exceeded, so I tried it through 'SD card'.
  2. 'WM_MENU, WM_MENU_D' values ​​must be loaded and modified in real time.
  3. When driving actual events,
    Processing is based on a specific array value of 'WM_MENU, WM_MENU_D'.
  4. So, we have no choice but to lower the 'WM_MENU' storage memory and use it.

Of course, what I say is not the correct answer.
However, as of now, this seems to be the only solution without hardware replacement.

How 'real'? Which is to say: what kind of actions do you need to perform on the data and how much time do you have for it? I bet there's more leeway than you think. And if there isn't, you've probably selected the wrong platform for the task - if you're doing something that involves really fast interactions with the outside world and moderately large amounts of data, there's not much sense in trying to cram everything into a fairly old-fashioned microcontroller. It seems you're painting yourself into a corner and as a result eliminating solutions that in reality would actually work.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.