Using Serial.print in nested for loop - why does all my RAM go away?

Hello Arduino community,

I am working on a sketch that have a 128 by 64 array, it is an integer array with 0s and 1s. My goal is to write a pixel on an OLED where there is 1 in the array. From the start this has resulted in all SRAM being consumed and failure to upload the sketch to my arduino uno. It should be said that I can write pixels and other primitives using other 2 by n arrays, as well as other primitives. I concluded that it must be my method that is bad and decided to step back from the OLED and see if it worked with serial.print, the result was the same memory problem. I have pasted the IDE error message below:


Sketch uses 17874 bytes (55%) of program storage space. Maximum is 32256 bytes.
Global variables use 16572 bytes (809%) of dynamic memory, leaving -14524 bytes for local variables. Maximum is 2048 bytes.
Not enough memory; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing your footprint.
Error compiling for board Arduino/Genuino Uno.

I have also attached the ino file below, its called progmem because i first thought i could fix this problem with progmem. Seems rather it is the writing itself that cause the memory to be all gone.

The for loops i use to “scan” the array is that of below (background is a 128 by 64 array):


for (int i = 0; i < 2; i++) {

for (int ii = 0; ii < 5; ii++){

if (background*[ii] == 0) {*

  • Serial.print(“Hej”);*

  • }*

  • }*

}

You probably notice that it does not go to 128 or 64 in either loop, this is because i experimented with using values less than the array size. To see if it helped which it only did in one case - > if ii equals 1 or 2, my interpretation is that it only work if Serialprint only writes once (or twice?) in the nested loop. For the case of ii equal one the IDE report is as below.

Sketch uses 1430 bytes (4%) of program storage space. Maximum is 32256 bytes.
Global variables use 184 bytes (8%) of dynamic memory, leaving 1864 bytes for local variables. Maximum is 2048 bytes.

So if ii is 1 or two it can upload. Some final quirks is that if ii is 1 and i add delay(1000) all RAM is also gone. Same if ii equal 2 and i write serial.println.
I am learning about memory as good as I can but some seasoned insights would be much appreciated. Is it a case of the Arduino trying to write several instances of serial.print where there is only limited memory? I have read that the serial buffer is 64 bytes, I guess that goes quite fast.
progmem.ino (24.8 KB)

it is an integer array with 0s and 1s.

That’s dumb - wasting 16 bits to hold one bit.

You are ABSOLUTELY going to have to learn to to bit manipulation to pack 16 bits into a 16 bit array position. There is NO other way.

Yes I understand that it is overkill, in one iteration i used a boolean array. But that didnt really help, it still consumed all RAM.

The reason you don't see the memory usage if you remove the Serial.print() line is that the compiler sees you don't do anything with the array and optimizes it away.

Thank you for the reply,

But why dies it work for ii equal 1 or 2? It use the array then,

It isn't the attempt to define a stupidly large array that causes problems. It is the attempt to read from/write to an array that can't fit in memory that causes problems. But the problems only occur when you access an element of the array that doesn't fit.

So, apparently you have enough memory for one or two rows (or columns; I always have to work out which way they are actually stored). Working with those two rows is OK. Move into the third row, which doesn't exist, and Bam. All hell breaks loose.

You need to be aware of the memory constraints for your Arduino - 2048 bytes of SRAM in your case.

Attempting to store a 128x64 array using integers in SRAM won’t be possible (that’s 128x64x2 bytes = 16328 bytes, which is 8 times the available memory, as indicated in the output you posted).

As you noted its not an immediate compile-time error defining such an array, but it actually manifests as a runtime error as soon as you read or write an array index outside the available bounds.
(Undefined behaviour will actually occur earlier, memories has some explanations about the Arduinos memory layout)

So what are possible solutions?

  • Use appropriate data types:

Booleans occupy a whole byte, so thats 128x64x1 bytes = 8096bytes and will still not work.

Using bitwise operations you can squeeze your data into the individual bits of an 8-bit datatype like (Arduino defines a type “byte” for this) - this would lead to 1024bytes and fit into SRAM (although using 50% of it).

  • Move data to Flash Memory:

This will only work if your data does not change (since Flash Memory is read-only, at least in the context of a running program).
Info can be found here: PROGMEM

Thank you all for your reply :) I revisited PROGMEM and it works like a charm! Thanks a bunch