Go Down

Topic: reducing the amount of code in ram to free up space (Read 2203 times) previous topic - next topic

Which version of the IDE is in use?

Some simple things such as replacing

 
Code: [Select]
lcd.setCursor(0,0); 
  lcd.print("Saving.     ");
  delay(500);
  lcd.setCursor(0,0);
  lcd.print("Saving..    ");
  delay(500);
  lcd.setCursor(0,0);
  lcd.print("Saving...   ");
  delay(500);
  lcd.setCursor(0,0);
  lcd.print("Saving....  ");
  delay(500);
  lcd.setCursor(0,0);
  lcd.print("Saving..... ");
  delay(500);
  lcd.setCursor(0,0);
  lcd.print("Saving......");
  lcd.setCursor(0,0);
 

with a loop that adds the requisite numbre of dots/spaces will mean you only need 3 string ("Saving","."and," ") so using 1/6 of the storage you currently use might help.

SukkoPera

You can also use the F() macro to avoid copying strings to SRAM when you are print()'ing them, i.e.:

Code: [Select]
lcd.print (F("Saving"));

paulsvang


You know you can attach a file to a forum posting? Click on "Additional Options" below the post and use the Attach option.


I saw it after I copied/pasted the code in so I just left it.

Hopefully someone has an insight progmem with menubackend.

GoForSmoke

Here are pieces of code I used to put menu into PROGMEM. I also put error messages, etc, there.

You need some #includes to use PROGMEM:
Code: [Select]

#include <avr/io.h>
#include <avr/pgmspace.h>


Here I have a 7 line menu (80 characters per line) stored to PROGMEM, and a special pointer to get the data with:
Code: [Select]

const char PROGMEM usageMsg[][80] = { // all this text stored in flash
  "          Piezo touch sensor tuner.",
  "Adjust vertical; enter W to subtract or X to add, and a number 0-255",
  "Adjust timescaler; enter A to subtract or D to add, and 0-16535",
  "to add 250 to vertical enter W250 in Serial Monitor and press enter",
  "seperate multiple commands with spaces; ex: W25 D240",
  "    ** this message stored in flash ram **",
  "    ** and printed with a 1 byte buffer ** :-P"
};

PGM_P Msg; // pointer into flash memory


The full program stores -every- const char string (not C++ String!) in PROGMEM. It has serial user I/O error messages, etc, as well as the menu.

I made this function to print the stored strings one char at a time:
Code: [Select]

void  printMsg( PGM_P FM )
{
  do
  {
    B = pgm_read_byte( FM++ );    // FM++ is pointer math; look Ma, no indexes!
    if ( B )  Serial.print( B );
  }
  while ( B ); // when it reaches the terminating zero, it exits
}


And this function just to print the whole menu:
Code: [Select]

void printHelp(void)
{
  for ( byte i = 0; i < HELPLINES; i++ )
  {
    printMsg( usageMsg[ i ]);
    Serial.println();
  }
  Serial.println();
}
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

paulsvang


You can also use the F() macro to avoid copying strings to SRAM when you are print()'ing them, i.e.:

Code: [Select]
lcd.print (F("Saving"));



I'm going to try this out.   Thanks SukkoPera.

paulsvang

#20
Aug 30, 2012, 04:39 am Last Edit: Aug 30, 2012, 05:09 am by paulsvang Reason: 1
Countrypaul.   I will take a stab at it and you are right; it should reduce the code and sram some more.   I'm using the lastest IDE version on an uno v3.
  thanks



Which version of the IDE is in use?

Some simple things such as replacing

 
Code: [Select]
lcd.setCursor(0,0);  
 lcd.print("Saving.     ");
 delay(500);
 lcd.setCursor(0,0);
 lcd.print("Saving..    ");
 delay(500);
 lcd.setCursor(0,0);
 lcd.print("Saving...   ");
 delay(500);
 lcd.setCursor(0,0);
 lcd.print("Saving....  ");
 delay(500);
 lcd.setCursor(0,0);
 lcd.print("Saving..... ");
 delay(500);
 lcd.setCursor(0,0);
 lcd.print("Saving......");
 lcd.setCursor(0,0);
 

with a loop that adds the requisite numbre of dots/spaces will mean you only need 3 string ("Saving","."and," ") so using 1/6 of the storage you currently use might help.

paulsvang

This really helped alot.  I went from 98 available sram to 477 available.



You can also use the F() macro to avoid copying strings to SRAM when you are print()'ing them, i.e.:

Code: [Select]
lcd.print (F("Saving"));


paulsvang

#22
Aug 30, 2012, 05:07 am Last Edit: Aug 30, 2012, 05:14 am by paulsvang Reason: 1
countrypaul,

I went ahead and took your advice and shorten the code to
Code: [Select]

 lcd.clear();
 lcd.setCursor(0,1);
 lcd.print(used.item.getName());
 lcd.setCursor(0,0);
 lcd.print(F("Saving"));
 //print dots for saving mode
 for (byte i = 0; i < 14;i++ ){
 lcd.print(F("."));



I'm reducing flash memory and sram usage.  Now I need to get progmem working for the menu.  Thanks!  

SukkoPera


I made this function to print the stored strings one char at a time:
Code: [Select]

void  printMsg( PGM_P FM )
{
  do
  {
    B = pgm_read_byte( FM++ );    // FM++ is pointer math; look Ma, no indexes!
    if ( B )  Serial.print( B );
  }
  while ( B ); // when it reaches the terminating zero, it exits
}



This could be actually shortened down to:

Code: [Select]

void  printMsg( PGM_P FM )
{
 Serial.print (reinterpret_cast<__FlashStringHelper *> (FM));
}


It would be better to do the same thing with a macro, thought. Or even always doing the cast explicitly.

PS: Use lowercase - and meaningul - names for variables (i.e.: FM -> str).

GoForSmoke

I don't worry about long names inside such a short, transparent function. If anything, just to not be distracted. It's easier for me to associate the type (the Important Part) with a short name than with a long name for such brief use. When you've done dozens of those a day for weeks it gets to be apparent but a psychology prof or student can tell you the same.
Long names are better for code that runs a screen or more and for globals but are not any kind of universal better IME. Your mileage may vary. I've seen people who won't debug 20 lines of code without a flowchart and a staff meeting; they would long-name everything.

FM is flashMemory... perhaps it should be FMP or full length for finger exercise?

I have never seen the like of reinterpret_cast<__FlashStringHelper *> (FM). Where are docs for that and what-all includes are necessary? Why wouldn't it be better to ditch the printMsg function totally and just inline the print statement?

Will it work with IDE 0022? My Arduino as ISP works with 0022 and I don't feel safe with 1.0.

Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

SukkoPera

#25
Aug 30, 2012, 06:02 pm Last Edit: Aug 30, 2012, 06:04 pm by SukkoPera Reason: 1
The reinterpret_cast thing works because of how serial.Print() is implemented, but it would be too long to explain here :). Ditching the printMSG() function would be great, IMHO! I'm not sure it works with 0022, as I started with 1.0.1 :).

Of course using that name in such a short function won't be a problem, but once you start using clever names, you tend to always do that, and then it never hurts, in particular if other people will be reading your code.

GoForSmoke

Noted. But really I use long names for important things or what isn't right close to see. I went through a couple years of interpreter basic where variables were single letter with number combinations so yeah, I know how bad it can get. But that was over 30 years ago, "I feel Much Better now" (John Aston Night Court line, I'm saying the old var names were a bit insane), LOL!

Some time I should try 1.01 Arduino as ISP and if it works, switch. There were too many maybes for me with 1.0 when it came out. Some of the improvements like what you show are awfully tempting.


Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Go Up