How can I reduce the memory usage on my code? I wrote this code to control my christmas tree. It takes up the majority of the memory on my Arduino Uno:

Sketch uses 31822 bytes (98%) of program storage space. Maximum is 32256 bytes.
Global variables use 1882 bytes (91%) of dynamic memory, leaving 166 bytes for local variables. Maximum is 2048 bytes.
Low memory available, stability problems may occur.


Does anyone know how I can reduce the memory usage?

Code:

#include &lt;SPI.h&gt;
#include &lt;SdFat.h&gt;
#include &lt;SdFatUtil.h&gt;
#include &lt;SFEMP3Shield.h&gt;

#define TREEONE 3
#define TREETWO 4
#define TREETHREE 5
#define TREEFOUR 10

SdFat sd;
SFEMP3Shield MP3player;

const uint8_t volume = 10; // MP3 Player volume 0=max, 255=lowest (off)
//10 for basement 50 for testing

const uint16_t monoMode = 1;

int song = 3;
int num = 0;
int count = 0;

//put arrays here
byte arrayTree[] = {17,16,9,8,3,2,5,4,17,16,9,8,3, ...etc };

void setup() {
  initSD();
  initMP3Player();

  pinMode(TREEONE, OUTPUT);
  pinMode(TREETWO, OUTPUT);
  pinMode(TREETHREE, OUTPUT);
  pinMode(TREEFOUR, OUTPUT);

  digitalWrite(TREEONE, HIGH);
  digitalWrite(TREETWO, HIGH);
  digitalWrite(TREETHREE, HIGH);
  digitalWrite(TREEFOUR, HIGH);
}

void loop() {
  if(!MP3player.isPlaying()){
    MP3player.playTrack(song);
    MetallicaChristmas();
  }
}

void initSD() {
  if(!sd.begin(SD_SEL, SPI_HALF_SPEED)) 
    sd.initErrorHalt();
  if(!sd.chdir("/")) 
    sd.errorHalt("sd.chdir");
}

void initMP3Player() {
  uint8_t result = MP3player.begin();
  MP3player.setVolume(volume, volume);
  MP3player.setMonoMode(monoMode);
}

void treeFunc() {
    //delay(arrayTimes[i]);
    num = arrayTree[count];

    //TREEONE
    if(num&gt;15){
      if((num%2)==0){
        digitalWrite(TREEONE,HIGH);
      }else{
        digitalWrite(TREEONE,LOW);
      }
    }
    //TREETWO
    if((num%16)&gt;7){
      if((num%2)==0){
        digitalWrite(TREETWO,HIGH);
      }else{
        digitalWrite(TREETWO,LOW);
      }
    }
    //TREETHREE
    if((num%8)&gt;3){
      if((num%2)==0){
        digitalWrite(TREETHREE,HIGH);
      }else{
        digitalWrite(TREETHREE,LOW);
      }
    }
    //TREEFOUR
    if((num%4)&gt;1){
      if((num%2)==0){
        digitalWrite(TREEFOUR,HIGH);
      }else{
        digitalWrite(TREEFOUR,LOW);
      }
    }
  count = count + 1;
}

void MetallicaChristmas()
{
  //event 1
  delay(670);
  treeFunc();
  delay(248);
  treeFunc();
  //event 2
  delay(116);
  treeFunc();
  delay(248);
  treeFunc();
  //event 3
  delay(100);
  treeFunc();
  delay(248);
  treeFunc();
  //event 4
  delay(132);
  treeFunc();
  delay(248);
  treeFunc();
  //event 5
  delay(125);
  treeFunc();
  delay(248);
  treeFunc();
  //event 6

  ...etc.
As well as PROGMEM (as described in the comments), there are a couple of other efficiencies that you can make:


A function call is expensive (takes a lot of code space), and you are performing a LOT of them!


The repetitious calls to delay() followed by treeFunc() are wasteful. Your commented-out line

//delay(arrayTimes[i]);


looks like you were going to do the right thing, so I’d restore that (use count instead of i) and put the delay() numbers in a new int arrayTimes[] array.

PROGMEM this array too, of course!
Once you’ve done this, you can remove all the calls to delay(). You’ll be left with nothing but repeated calls to treefunc(), which you can replace with a single loop:

for (count=0;count&lt;sizeof(arrayTree);++count) {
   treeFunc();
} // for


Don’t forget to get rid of the count = count + 1; line from treeFunc() - it’s now in the for loop.

Also expensive is calling the same function twice except with different parameters in both sides of the if in treeFunc(). Instead of:

if (&lt;condition&gt;) {
   Function(1);
} // if
else {
   Function(0);
} // else


you can instead do:

Function(&lt;condition&gt;);


For this to work, you need to know that HIGH has the value 1 and LOW has the value 0 - and that a true condition has the value 1 and a false condition has the value 0.

So, you need to change the if () slightly:

digitalWrite(THREEONE, (num%2)&gt;0);

Finally, the mod % operator itself is very expensive, since it is effectively a division, and the Arduino chip doesn’t know how to divide - so the code to do so is large. But the code you’ve written is using binary arithmetic, which the Arduino can do instantly - you just have to write it as such.


Instead of (num%2)&gt;0 use num &amp; B0001.
Instead of (num%4)&gt;1 use num &amp; B0010.
Instead of (num%8)&gt;3 use num &amp; B0100.
Instead of (num%16)&gt;7 use num &amp; B1000.



You’ve probably copied the guts of this code from somewhere else, and while it works it isn’t very efficient. Writing the code as above will greatly reduce your code size, exchanging repeated calls for much smaller PROGMEM arrays.