SRAM and EEPROM question

Hello,

I have got two questions on which I can't find complete answer (or I am not completely sure) after reading forum and using google.

  1. On some pages I saw that reading from EEPROM is also important but ATmega datasheet says only about write/erase limitations. I am wondering if reading from EEPROM in a loop is also critical or just writing to?

  2. What's the recommended safe amount of free SRAM? I optimized my code as much as I was able (know) to and I have 146 bytes of free SRAM (running on ATmega328, measured with MemoryFree Library). My sketch is running ok but anyway, I am wondering if there is any recommendation of how much free SRAM is good to have.

Br,

Luxy

I am wondering if reading from EEPROM in a loop is also critical or just writing to?

according to datasheet there is limitations on only writing.
Write/Erase Cycles: 10,000 Flash/100,000 EEPROM.

but there is no limitation on reading EEPROM. you can read any number of times.

  1. reading from EEPROM is not critical, the writing is.

  2. SRAM may be consumed up to the last byte, so there is no minimum free needed. However function calls and local variables consume SRAM so you must make your measurement at the right spot.

Be aware that the memFree function needs SRAM too, so to use that you need some free RAM ...

If you want a review of your code just post it to get tips/tricks to reduce memory usage.

luxy:
<...>

  1. What's the recommended safe amount of free SRAM? I optimized my code as much as I was able (know) to and I have 146 bytes of free SRAM (running on ATmega328, measured with MemoryFree Library). My sketch is running ok but anyway, I am wondering if there is any recommendation of how much free SRAM is good to have.

@Luxy... actually a good question and a good portion of the answer will depend on how you code - functions and other objects. Bill Earl has a great writeup here.

On the 8-bit AVR family, you can use the freeRam in the Playground where available memory is also discussed.

Ray

Thank you for all the answers.

I code in functions with local variables and I am measuring SRAM usage in one, where are the most of them.

Br,

Luxy

luxy:
Thank you for all the answers.

I code in functions with local variables and I am measuring SRAM usage in one, where are the most of them.

Br,

Luxy

The trick is to simply make calls from within each of your functions to freeRam and watch for issues... then remark that code prior to deploying the sketch... you can also do it with something like:

# define DEBUG true
<....>

if (DEBUG) Serial.println( freeRam() );

You can scatter the diagnostic routine throughout your sketch, capture the output on the terminal and do a bit of analysis. Then set DEBUG false and recompile.

Honestly, even with 2K on the UNO, one can write some fairly complex code without being concerned about SRAM usage. Just be absolutely certain that you do not throw a bunch of print strings up into SRAM... that is, learn about PROGMEM for constants and the "F" macro for Print.

Serial.print(F("Hello End User..."));

Ray

mrburnette:
Just be absolutely certain that you do not throw a bunch of print strings up into SRAM

Is writing on LCD with "lcd.print("some text")" also concerned as throwing strings to SRAM? If yes, how to reduce this if I need to write on LCD very often?

Also, when I am using equation for calculating with float constants. What is the best way to manage that kind of constant numbers? Is there any difference if I use numbers directly in equation to calculate with them comparing to defining them like constant variables?

Case 1:
const float A = 3.9083E-3;
const float B = -5.775E-7;
float result;

result = A*B;

Case 2:
float result = 3.9083E-3 * -5.775E-7

Which case take more SRAM?

luxy:
Case 1:
const float A = 3.9083E-3;
const float B = -5.775E-7;
float result;

result = A*B;

Case 2:
float result = 3.9083E-3 * -5.775E-7

Which case take more SRAM?

That looks like a very improbable example because it can be reduced to const float result = 3.9... * -5.77.... (which is pretty close to 0)

...R

luxy:
Is writing on LCD with "lcd.print("some text")" also concerned as throwing strings to SRAM? If yes, how to reduce this if I need to write on LCD very often?

Oh, yes!

There is a way to get around that issue, however, with the "F" macro.

Serial.println(F(“Hello World”));

Personally, I much rather use the Streams.h functionality: Streaming.h

Now, those nasty LCD formatting strings can easily be managed in a reasonable manner:

#include <Streaming.h>
<....>
lcd.begin()
lcd << "Hello World" ;        // "Hello World" sits in SRAM
lcd << (F("Hello World")) ;  // "Hello World" sits in Flash

You can also put LCD strings into Flash and leave 'em there this way:

char* msg2[] PROGMEM       = {"Barometer OK"} ;

and you would utilize them this way:

LcdString(*msg2);

Ray
My Projects

Robin2:
That looks like a very improbable example because it can be reduced to const float result = 3.9... * -5.77.... (which is pretty close to 0)

I didn't gave good example. What about this case? Which takes more SRAM? I am wondering how numbers are treated in memory if you don't define them first. Does compiler reserve the same amount of space (4 bytes for float in this case) if I calculate as in Case 1? If I make local constant inside function is also destroyed after function is finished?

Case1:
float result = 3.45 * 6.78;

Case 2:
const float A = 3.45;
const float B = 6.78;

result = A*B;

mrburnette:
There is a way to get around that issue, however, with the "F" macro.

Serial.println(F(“Hello World”));

Personally, I much rather use the Streams.h functionality: Streaming.h

Now, those nasty LCD formatting strings can easily be managed in a reasonable manner:

#include <Streaming.h>

<....>
lcd.begin()
lcd << "Hello World" ;        // "Hello World" sits in SRAM
lcd << (F("Hello World")) ;  // "Hello World" sits in Flash

Thank you Ray, I will manage my code that way because most of the time I am writing to LCD. If I understand correctly "lcd.print" should be treated the same as "Serial.print". Btw, I also reduced buffer size as written on adafruit site because I am sending and receiving only a few bytes of packets through serial connection.

luxy:
I didn't gave good example. What about this case? Which takes more SRAM? I am wondering how numbers are treated in memory if you don't define them first. Does compiler reserve the same amount of space (4 bytes for float in this case) if I calculate as in Case 1? If I make local constant inside function is also destroyed after function is finished?

Case1:
float result = 3.45 * 6.78;

Case 2:
const float A = 3.45;
const float B = 6.78;

result = A*B;

Generally, if any variable is a constant, you should use the const keyword. This informs the GCC compiler and most often these values will stay in Flash memory. I say most often, because the compiler has a mind of her own and will make a liar out of me if I do not qualify the statement!

But, you can find out easily for yourself! If you are using any of the 1.0.x versions, you can analyze the ELF file created in the temp directory to uncover the memory allocation.

On Windows (any version) the following script I wrote will give you the necessary information:
(Edit the first line if your Arduino installation is not standard or on a 32-bit machine):

PATH=%path%;C:\Program Files (x86)\Arduino_106\hardware\tools\avr\bin;
C:
CD %TEMP%
MD %PUBLIC%\ELFtemp
for /R %TEMP% %%f in (*.elf) do XCOPY /D /Y %%f %PUBLIC%\ELFtemp\
DIR %PUBLIC%\ELFtemp\*.elf /s /b /O:-D /T:W >ElfRhere
SET /P ELF= <ElfRhere
ECHO %ELF% >MemUsage.txt
AVR-SIZE -C %ELF% >>MemUsage.txt
NOTEPAD MemUsage.txt
CD %PUBLIC%\ELFtemp
ECHO y | DEL *.* \%1
SET ELF=""

Just create a Windows script ending with the file extension CMD ... mine is "MemoryUsage.cmd" and set up a shortcut icon.

My last compile looks like:

C:\Users\Public\ELFtemp\GLCD5110_BMP085.cpp.elf
AVR Memory Usage

Device: Unknown

Program: 19932 bytes
(.text + .data + .bootloader)

Data: 2800 bytes
(.data + .bss + .noinit)

OR

If you are brave, use the Arduino GUI 1.6.0rc1 which gives you that info automatically after each compile.

Everything you wanted to know about variable types in GCC is here.

But do not get too hung-up on this because when you move to Due or another uC architecture where the core is not 8-bit, things change!

Ray

Ok, I will try this. Thank you again for all the informations!

As an additional note, different versions of Arduino also change the exact flash/SRAM numbers!

So, when I write programs for publication, I include the following in the comments:

  Compiled using Arduino 1.6.0rc1
    Sketch uses 19,212 bytes (17%) of program storage space. Maximum is 108,000 bytes.
    Global variables use 2,800 bytes of dynamic memory.
*/

Ray
My Projects

mrburnette:
As an additional note, different versions of Arduino also change the exact flash/SRAM numbers!

Hi,

I optimized my code as you recommended. Now I have more than 1751 bytes of SRAM free, so almost all available space (measured with memoryFree library) :smiley:

The biggest problem was writing strings on LCD so I used "lcd << (F("text"));" for every example. And I still have approx. 12 Kbytes of free flash memory.

I have one more question about writing on LCD this way. I was not able to figure out how to write degree symbol that way, so I used "lcd.print((char)223);" which still sits in SRAM. Although I have enough memory now, I am wondering why I can't also use F to put it to flash memory anyway. "lcd.print(F((char)223));" doesn't work.

Br,

Luxy

luxy:
Hi,

I optimized my code as you recommended. Now I have more than 1751 bytes of SRAM free, so almost all available space (measured with memoryFree library) :smiley:

The biggest problem was writing strings on LCD so I used "lcd << (F("text"));" for every example. And I still have approx. 12 Kbytes of free flash memory.

I have one more question about writing on LCD this way. I was not able to figure out how to write degree symbol that way, so I used "lcd.print((char)223);" which still sits in SRAM. Although I have enough memory now, I am wondering why I can't also use F to put it to flash memory anyway. "lcd.print(F((char)223));" doesn't work.

Br,

Luxy

Congratulations!

I was not able to figure out how to write degree symbol that way, so I used "lcd.print((char)223);" which still sits in SRAM.

Try 0xDF

LCD << "Temp= " << temp << "0xDF" ;

Or maybe ...

LCD << "Temp= " << temp << "\0xDF" ;

Or maybe ...

LCD << "Temp= " << temp << \0xDF ;

On a tablet, so cannot try same. In theory, you should be able to send anything within your bitmap font matrix.... As any DEC or HEX value.

Ray