How much sram ?

I am trying to workout how much sram I have left using :-

int availableMemory() {
int size = 1024;
byte *buf;
while ((buf = (byte *) malloc(--size)) == NULL);
free(buf);
return size;

it says 388 bytes left !!!

My variables should only use around 98 bytes.
4+9+9+2+2+14+3+18+18+1+4+2+2+1=98 byte

Where is my sram going ?, and how can ? can I change my code to reduce this.

#include <Wire.h>
long clock_delay = 0;
char bcd_string[]="12:34:56";
char clock_string[]="??:??:??";
int rtc_address = B1101000;
int io_address = B100001;
int rtc_bcd[7];
boolean alarm_set[3];
int alarm_on[3][3];
int alarm_off[3][3];
boolean knight_run = false;
long knight_time = 0;
int knight_delay = 30;
int x = 0;
boolean forward = true;

void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
// start_ball(); // set the rtc arrary , not needed now I have a battery
// clock_save();
int_alarm();

// alarm_set[0] = true;
set_alarm(0 , true , "22:20:00");
set_alarm(0 , false , "22:25:00");

alarm_set[1] = true;
set_alarm(1 , true , "00:55:00");
set_alarm(1 , false , "00:57:00");

// alarm_set[2] = true;
set_alarm(2 , true , "12:00:00");
set_alarm(2 , false , "12:00:01");

display_alarms(0);display_alarms(1);display_alarms(2);

io_int();
Serial.print ("Bytes of available Memory = ");
Serial.println (availableMemory(), DEC);
}

void loop()
{
clock_read();
bcd2string();
if (strcmp(bcd_string , clock_string) != 0)
{
// Serial.println(clock_string);
strcpy(clock_string , bcd_string);
check_alarms();

}

if ( millis() >= knight_time )
{
knight_time = millis() + knight_delay;
if ( knight_run == true ) knight();
}

} // end of loop

void clock_save()
{
Wire.beginTransmission(rtc_address); Wire.send(0x00); // reset register pointer
for(int i=0; i<7; i++) { Wire.send(rtc_bcd*);} Wire.endTransmission();*
}
void clock_read()
{

  • Wire.beginTransmission(rtc_address);*
  • Wire.send(0x00); Wire.endTransmission(); Wire.requestFrom(rtc_address, 7);*
    for(int i=0; i<7; i++) { rtc_bcd*=Wire.receive();}
    _
    }_
    void start_ball()
    _
    {_
    rtc_bcd[0]=B00000000; // Second -- 0 --
    rtc_bcd[1]=B01000101; // Minites -- 45 --
    rtc_bcd[2]=B00001010; // Hours -- 2 --
    rtc_bcd[3]=B00000001; // Sunday 1 , Monday 2 , Tuesday 3 etc in BCD -- Saturday -- 7 --
    rtc_bcd[4]=B00000001; // Date -- 1 --
    rtc_bcd[5]=B00000001; // Month -- 1 --
    rtc_bcd[6]=B00000001; // Year -- 1 --
    } // end of start_ball*

    void string2bcd()
    {
    * rtc_bcd[2] = (bcd_string[1]-48) + (bcd_string[0]-48 << 4); //hours 12:12:12*
    * rtc_bcd[1] = (bcd_string[4]-48) + (bcd_string[3]-48 << 4); //mins*
    * rtc_bcd[0] = (bcd_string[7]-48) + (bcd_string[6]-48 << 4); //sec*
    } // end of string2bcd
    void bcd2string()
    {
    * int rtc_dec = 0 ;int j = 0 ;int i = 2 ;
    rtc_dec = (( rtc_bcd & B0111000) >> 4) * 10 + (rtc_bcd & B00001111); // hours 2 , mins 1 , sec 0
    if ( rtc_dec <= 10 ) bcd_string[j] = 48;
    bcd_string[j]=(rtc_dec / 10 )+48;
    j++,bcd_string[j]=(rtc_dec % 10)+48,j++,bcd_string[j] = 58,i--, j++ ;
    rtc_dec = (( rtc_bcd & B1111000) >> 4) * 10 + (rtc_bcd & B00001111); // hours 2 , mins 1 , sec 0
    if ( rtc_dec <= 10 ) bcd_string[j] = 48;
    bcd_string[j] = (rtc_dec / 10 )+48;j++;bcd_string[j]=(rtc_dec % 10)+48;j++;bcd_string[j] = 58,i--, j++ ;
    rtc_dec = (( rtc_bcd & B1111000) >> 4) * 10 + (rtc_bcd & B00001111); // hours 2 , mins 1 , sec 0
    if ( rtc_dec <= 10 ) bcd_string[j] = 48;
    bcd_string[j] = (rtc_dec / 10 )+48;j++;bcd_string[j]=(rtc_dec % 10)+48;
    _} // end of bcd2string*
    int availableMemory() {
    * int size = 1024;
    byte buf;
    while ((buf = (byte ) malloc(--size)) == NULL);
    free(buf);

    return size;
    }
    void int_alarm()
    {_

    strcpy(bcd_string , "12:00:00");
    _ string2bcd();
    for(int j=0; j<3; j++) {
    for(int i=0; i<3; i++) {_

    alarm_on[j] = rtc_bcd;
    alarm_off[j] = rtc_bcd;
    } alarm_set[j] = false; }
    } // end of int_alarm*

    void display_alarms(int j) // 0 1 2
    { for(int i=0; i<3; i++) rtc_bcd = alarm_on*[j];
    _ Serial.print("Alarm "),Serial.print(j,DEC);_
    if ( alarm_set[j] == true ) { Serial.print(" - on - "); } else { Serial.print(" - off - "); }
    _ Serial.print("Alarm on time ");_
    bcd2string(),Serial.print(bcd_string);
    for(int i=0; i<3; i++) rtc_bcd = alarm_off[j];
    _ Serial.print(" - Alarm off time ");_
    bcd2string(),Serial.println(bcd_string);
    } // end of display_alarm*

    void check_alarms()
    * { clock_read(); bcd2string(); strcpy(clock_string , bcd_string);
    _ for(int j=0; j<3; j++)_
    { if ( alarm_set[j] == true ) {
    for(int i=0; i<3; i++) { rtc_bcd = alarm_on[j] ; }
    _ bcd2string();_
    if (strcmp ( bcd_string , clock_string ) == 0) alarm_trigger_on(j);
    for(int i=0; i<3; i++) { rtc_bcd = alarm_off[j] ; }
    _ bcd2string();_
    if (strcmp ( bcd_string , clock_string ) == 0) alarm_trigger_off(j);
    }}} //end of check_alarm*

    void set_alarm(int alarm , boolean on_alarm , char alarm_time[] )
    * { strcpy(bcd_string , alarm_time); string2bcd();
    _ for(int i=0; i<3; i++)_
    { if ( on_alarm == true ) { alarm_on[alarm] = rtc_bcd;
    } else { alarm_off[alarm] = rtc_bcd;
    }} }// alarm_set[alarm] = true; } // end of set_alarm*

    void alarm_trigger_on(int alarm)
    { switch (alarm) {
    * case 0:*
    * //do something when var == 1*
    * break;*
    * // break is optional*
    * case 1:*
    * //do something when var == 2*
    * knight_run = true;
    _ break;
    case 2:
    //do something when var == 2*

    * break;
    }}
    void alarm_trigger_off(int alarm)
    { switch (alarm) {
    case 0:
    //do something when var == 1*

    * break;
    // break is optional*

    * case 1:
    //do something when var == 2*

    * knight_run = false;*
    * break;
    case 2:
    //do something when var == 2*

    * break;
    }}
    void io_int()
    {
    do { _

    x = read_io(6),write_io(6,0);
    _ } while ( x != 0 );
    do {_

    x = read_io(6),write_io(6,255);
    _ } while ( x != 255 );
    do {_

    x = read_io(6);
    write_io(6,0),write_io(7,0);
    _ } while ( x != 0 );_
    write_io(0,1),write_io(1,0);
    } // end of int_io*

    int read_io(int cmd_reg)
    {
    *int tmp; *
    Wire.beginTransmission(io_address);
    Wire.send(cmd_reg); // 0 or 1 -- GP0 or GP1
    Wire.endTransmission();
    Wire.requestFrom(io_address, 1);
    tmp=Wire.receive();
    return tmp;
    } // end of read_io
    void write_io(int cmd_reg, int push_this)
    {
    * Wire.beginTransmission(io_address);
    Wire.send(cmd_reg),Wire.send(push_this); // reset register pointer then set GP0 to push_this // use (0,??)
    _ Wire.endTransmission();_
    } // end of write_io*

    void knight()
    {
    x = read_io(0);
    if (forward == true)
    {
    * if ( x == B10000000 )*
    * {*
    * // forward = true & x = B10000000*
    * forward= false;*
    * write_io(1,255);
    _ }
    else*

    * {
    // forward = true & x not B10000000*

    * x = x << 1;_
    write_io(0,x);
    _ }
    }
    else
    {
    if ( x == B00000001 )
    {
    // forward = false & x = B00000001*

    * forward=true;_
    write_io(1,0);
    _ }
    else*

    * {
    // forward = false & x not B10000000*

    * x = x >> 1;_
    write_io(0,x);
    _ }
    }
    } // end of knight*_

Well, just counting your own variables only tells part of the story, right? There are instance variables for the Wire object you're using, it needs to keep track of its internal state and maintain an input buffer and an output buffer and the Serial object likewise needs a buffer, and ... You get the idea.

You could save bytes here and there by not using all those strings for internal representation of the time and just count time in terms of "seconds since midnight " or what have you. For small numbers (less than 255) you can use an unsigned char instead of an int and for 'variables' that don't actually vary at all you can replace them with #defines, ...

Serial uses a 128 byte buffer and Wire allocates two 32 byte buffers. The runtime code and those two classes use RAM and you seem to allocate a lot of variables in your functions (BTW, its hard to read your code – you loose the formatting if you don't put it into a code block)
fjornir gave some advice on how to save some space.

So 388 bytes left may be correct.

variables' that don't actually vary at all you can replace them with #defines

You mean use #define for :-

int rtc_address = B1101000;
int io_address = B100001;

knight_delay was the one that I saw that you're not actually changing anywhere but I didn't audit all of your code looking for how you used each variable.

Good luck!

Thanks .

I`ll try using define on what does not change and see if the free ram goes up.

I can see that in my programs , ram is going to be the bigger problem than the flash ram / eprom

I would focus first on the ~150+ bytes of static string data, which can easily be moved to PROGMEM space.

Also, just a cursory glance at the code suggests that nearly all the int arrays and variables could be made half as big by using byte or uint16_t.

Mikal

Keep in mind that your math shows how much you're using personally. The most you can possibly reclaim is those 98bytes - and you're not going to get ALL of those back unless your device stops doing anything at all.

You can reclaim some of the memory from the Serial buffer by decreasing its size (you never read from the Serial port in your application so why do you need a big buffer? ). And yes, PROGMEM may help.

nearly all the int arrays and variables could be made half as big by using byte or uint16_t.

I think Mikal meant byte or uint8_t.

Oops! Yes, I mean uint8_t. Thanks, mem.

The most you can possibly reclaim is those 98bytes

This is not really true. The 98 bytes are just the global variables. RAM is also consumed by local variables, function return addresses, buffers in libraries, and, most importantly, as I mentioned above, STRINGS. Every time you write something like

Serial.print("Oh man, my program has only ");
Serial.print(avail());
Serial.println("bytes left!");

you have just consumed another 40 bytes of that precious 1K.

Mikal

nearly all the int arrays and variables could be made half as big by using byte or uint16_t.

I think Mikal meant byte or uint8_t.

Moving to a smaller datatype ignores the bigger win available by just changing the data model. You do not need a three element array to store the time to start/stop an alarm - rework the code to track seconds since noon and a small helper function to change that into BCD hours/minutes/seconds when needed and you lose two dimensions off that array, check_alarms() becomes trivial, and so on.

This is not really true. The 98 bytes are just the global variables. RAM is also consumed by local variables, function return addresses, buffers in libraries, and, most importantly, as I mentioned above, STRINGS. Every time you write something like...

Sorry. I spoke with a lack of precision there. I meant "...reclaim by attacking those variables..." :slight_smile:

Sorry. I spoke with a lack of precision there.

After my uint16_t gaffe, I'm hardly one to criticize on that point! :slight_smile:

@peter, another thing to consider is that your program is running the whole show, so as long as you don't actually run OUT of RAM, everything is perfectly fine. 300+ bytes left is plenty, unless you are planning to expand your program in the future.

M

Thanks for all for all your comments.

At the present time, my program is a means to the ends, I`m just learning.

But I guess it just like learning to drive a car, the best way is to learn the right way first, because it`s so hard to get out from bad habits.

Sorry Im from VB / PC where memory is no limit, so normally I just dont care .

So if I get you all right I should go from :-

Serial.println(“sorry this is using lots of sram so don`t do it”);

To
#define str1 “sorry this is using lots of sram so don`t do it”
Serial.println(str1);

Tried this :- Using #defined strings and direct strings and finish with the same figure 70 bytes used .

//#define test1 "This is a test to see how much space I can space"
//#define test2 "or to see if it does"

void setup()
{
Serial.begin(9600);
//Serial.println(test1);
//Serial.println(test2);
//Serial.println( "This is a test to see how much space I can space");
//Serial.println( "or to see if it does" );

Serial.print ("Bytes of available Memory = ");
Serial.println (availableMemory(), DEC);

}

void loop()
{

}
int availableMemory() {
int size = 1024;
byte *buf;
while ((buf = (byte *) malloc(--size)) == NULL);
free(buf);
return size;
}

Hi...

The #define suggestion applies to numbers only.

For strings/text you'll want learn to use PROGMEM.

--Phil.