Low Memory Problem

Hello,

I am getting this message after verification:

Sketch uses 11886 bytes (36%) of program storage space. Maximum is 32256 bytes.
Global variables use 1889 bytes (92%) of dynamic memory, leaving 159 bytes for local variables. Maximum is 2048 bytes.
Low memory available, stability problems may occur.

I am actually having stability problems after several hours of operation of the Arduino due to low memory. I would appreciate any help on getting the 92% Global Variable memory usage down. I’m trying to not use a Mega at this point, as there is a bit of a deadline on this project.

Using:
Arduino Uno
Adafruit Wave Shield
Green LEDs
Red LEDs

Idea: If no outside signal, things blink while the sounds go off at the same time

Code (not all of it because of the 9000 max characters allowed in a forum post, see first reply for rest):

//Wave 5 ~jULY 2017 //
#include <WaveHC.h>
#include <WaveUtil.h>

SdReader card;    // This object holds the information for the card
FatVolume vol;    // This holds the information for the partition on the card
FatReader root;   // This holds the information for the volumes root directory
FatReader file;   // This object represent the WAV file for a pi digit or period
WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time

uint8_t dirLevel; // indent level for file/dir names    (for prettyprinting)
dir_t dirBuf;     // buffer for directory reads
uint8_t countStateGood = 0;
uint8_t countStateBad = 0;

#define error(msg) error_P(PSTR(msg))

int Good_G = 6;
int Bad_B = 7;
int GLED = 8;
int RLED = 9;

int i = 0;
int j = 0;

int buttonPusherCounterGood = 0;
int buttonStateGood = 0;
int lastButtonStateGood = 0;

int buttonPusherCounterBad = 0;
int buttonStateBad = 0;
int lastButtonStateBad = 0;

unsigned long previousMillis1 = 0;
long OnTime1 = 250;
long OffTime1 = 750;
unsigned long previousMillis2 = 0;
int TimeState1 = 0;
int prevTimeState1 = 0;
int TimeState2 = 0;
int prevTimeState2 = 0;
long intervalRandom = 180000; //30,000 = 30sec 60,000 = 1 min 120,000 = 2 min 180,000 = 3min 300,000 = 5 min


void setup() 
{ Serial.begin(9600);

PgmPrintln("Wave_5");
  
  if (!card.init()) {
    error("Card init. failed!");
  }
  if (!vol.init(card)) {
    error("No partition!");
  }
  if (!root.openRoot(vol)) {
    error("Couldn't open dir");
  }

  PgmPrintln("Files found:");
  root.ls();

  pinMode(Good_G, INPUT_PULLUP);
  pinMode(Bad_B, INPUT_PULLUP);
  pinMode(GLED, OUTPUT);
  pinMode(RLED, OUTPUT);

  //Start Up/ Reset Acknowledgement
   //  Serial.println(F("Start Up Cycle"));
     digitalWrite(GLED, HIGH);
     playcomplete("GOOD2.WAV");
     digitalWrite(GLED, LOW);     
}

void loop() {
  
unsigned long currentTime1 = millis();

 buttonStateGood = digitalRead(Good_G);
 if (buttonStateGood != lastButtonStateGood){

   if(buttonStateGood == LOW){ 
     buttonPusherCounterGood++;
  //   Serial.println(F("Begin Good button increment"));
  //   Serial.print(F("Number of Count:  "));
  //   Serial.println(buttonPusherCounterGood);
  
   if (buttonPusherCounterGood % 3 != 0){
     digitalWrite(GLED, HIGH);
   //  Serial.println(F("Playing Good Wav"));
     playcomplete("GOOD.WAV");
     digitalWrite(GLED, LOW);
       }
   else if (buttonPusherCounterGood % 3 == 0  && buttonStateGood == LOW){
   //  Serial.println(F("Randomized Good activated"));
     digitalWrite(GLED, HIGH);
     RandomizedGood();
     digitalWrite(GLED, LOW);
       }
   else {
   //  Serial.println(F("End Good button increment"));
      }
    }
    previousMillis1 = currentTime1;
  }
lastButtonStateGood = buttonStateGood;


buttonStateBad = digitalRead(Bad_B);    
if (buttonStateBad != lastButtonStateBad){

    if((buttonStateBad == LOW) && (buttonStateGood == HIGH)){
      buttonPusherCounterBad++;
   //   Serial.println(F("Begin Bad button increment"));
   //   Serial.print(F("Number of Count:  "));
   //   Serial.println(buttonPusherCounterBad);
      
    if(buttonPusherCounterBad % 3 != 0 ){
   //   Serial.println(F("Playing playbad void"));
      playbad ("BAD.WAV");
      digitalWrite(RLED, LOW);
    }
    else if ((buttonPusherCounterBad % 3 == 0) && (buttonStateBad == LOW) && (buttonStateGood == HIGH)){
     // Serial.println(F("Randomize Bad activated"));
      RandomizedBad();
      digitalWrite(RLED, LOW);
    }

    else {
      Serial.println(F("End Bad button increment"));
    }
  }
   previousMillis1 = currentTime1;
}
  lastButtonStateBad = buttonStateBad;

if ((buttonStateBad == HIGH)  && (buttonStateGood == HIGH) && (currentTime1 - previousMillis1 >= intervalRandom)){
        RandomizedRandom();
        previousMillis1 = currentTime1;
      }
       if (TimeState1 != prevTimeState1){
        previousMillis1 = currentTime1;
       }
 
    prevTimeState1 = TimeState1;
 }


void error_P(const char *str) {
  PgmPrint("Error: ");
  SerialPrint_P(str);
  sdErrorCheck();
  while(1);
}

void sdErrorCheck(void) {
  if (!card.errorCode()) return;
  PgmPrint("\r\nSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  PgmPrint(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}

void playcomplete(char *name) {
  
  playfile(name);
  while (wave.isplaying);
  sdErrorCheck();
  
}

void playfile(char *name) {
  if (wave.isplaying) {
    // already playing something, so stop it!
    wave.stop(); // stop it
  }
  if (!file.open(root, name)) {
    PgmPrint("Couldn't open file ");
    Serial.print(name); 
    return;
  }
  if (!wave.create(file)) {
    PgmPrintln("Not a valid WAV");
    return;
  }
  // ok time to play!
  wave.play();
}


void RandomizedBad(){
   //Serial.println(F("Playing Randomized Bad wave via RandomizedBad void"));
      i = random (3);
      if ( i == 0){
    //    Serial.println(F("Playing BAD1"));
        playbad("BAD1.WAV");
           }
      else if (i == 1) {
      //  Serial.println(F("Playing BAD2"));
        playbad("BAD2.WAV");
            }
      else {
       // Serial.println(F("Playing BAD3"));
        playbad("BAD3.WAV");
            }
      }

void RandomizedGood(){
   //Serial.println(F("Playing Randomized Good wave via RandomizedGood void"));
      j = random (3);
      if ( j == 0){
        //Serial.println(F("Playing GOOD1"));
        playcomplete("GOOD1.WAV");
              }
      if (j == 1) {
        //Serial.println(F("Playing GOOD2"));
        playcomplete("GOOD2.WAV");
              }
      if (j == 2) {
        //Serial.println(F("Playing GOOD3"));
        playcomplete("GOOD3.WAV");
              }
      }
void RandomizedRandom(){
   j = random (28);
   
      if ( j == 0){
        //Serial.println(F("Playing RANDOM1 - Vader's Theme Song"));
        playVader("RANDOM1.WAV");
             }
       if (j == 1) {
        //Serial.println(F("Playing RANDOM4 - Crickets"));
        playY("RANDOM4.WAV");
              }
       if (j == 2) {
        //Serial.println(F("Playing RANDOM8 - YMCA Minion Style"));
        playR("RANDOM8.WAV");
              }  
      if (j == 3) {
        //Serial.println(F("Playing RANDOM9 - Phone Ring Then RANDOM2 - Dun Dun Dun"));
        playcomplete("RANDOM9.WAV");
        delay(4000);
        playbad("RANDOM2.WAV");
              }
      if (j == 4) {
        //Serial.println(F("Playing CAR6 Then RANDOM10 - We will rock you"));
        playcomplete("CAR6.WAV");
        delay (2500);
        playbad("RANDOM10.WAV");     
              }
      
      if ( j == 5){
        //Serial.println(F("Playing CAR1 Then RANDOM12 - Jeopardy Timer"));
        playcomplete("CAR1.WAV");
        delay (2000);
        playJeopardy("RANDOM12.WAV");
              }
  
      if (j == 6) {
      //  Serial.println(F("Playing CAR2 Then RANDOM8 - Mocking Jay"));
        playcomplete("CAR2.WAV");
        delay (3000);
        playMocking("RANDOM28.WAV");
              }
        
      if (j == 7) {
     //   Serial.println(F("Playing CAR3 Then RANDOM11 - PacMan Fail "));
        playcomplete("CAR3.WAV");
        delay (3500);
        playbad ("Random18.WAV");
              }
    
      if (j == 8) {
     //   Serial.println(F("Playing CAR4 Then RANDOM29 Transformers Transforming"));
        playcomplete("CAR4.WAV");
        delay (1500);
        playbad("RANDOM29.WAV");
             }
    
      if (j == 9) {
      //  Serial.println(F("Playing CAR5 Then RANDOM9 Phone Ring Then RANDOM21 Mario's coin"));
        playcomplete("CAR5.WAV");
        delay (1000);
        digitalWrite(RLED, HIGH);
        digitalWrite(GLED, HIGH);
        playcomplete("RANDOM9.WAV");
        digitalWrite(GLED, LOW);
        digitalWrite(RLED, LOW);
        delay (4500);
        digitalWrite(GLED,HIGH);
        digitalWrite(RLED,HIGH);
        playcomplete("RANDOM21.WAV");
        digitalWrite(RLED, LOW);
        digitalWrite(GLED, LOW);
              }
     
      if (j == 10) {
      //  Serial.println(F("Playing RANDOM16 Then RANDOM5 - Bubbles"));
        playJeopardy("RANDOM16.WAV");
        delay (2500);
        playY("RANDOM5.WAV");
              } 
              
      if (j == 11) {
      //  Serial.println(F("Playing RANDOM15 - BB-8"));
        playbad("RANDOM15.WAV");
        delay(600);
        playbad("RANDOM37.WAV");
        delay(800);
        playbad("RANDOM38.WAV");
              }

      if (j == 12) {
       // Serial.println(F("Playing RANDOM22 - R2D2 1"));
        playcomplete("RANDOM22.WAV");
              }

      if (j == 13) {
      //  Serial.println(F("Playing CAR3 Then RANDOM23 - R2D2 2"));
        playcomplete("CAR3.WAV");
        delay (3500);        
        playgood("RANDOM23.WAV");
             }
             
      if (j == 14) {
       // Serial.println(F("Playing RANDOM26 - StarTrek Beeping"));
        playBeep("RANDOM26.WAV");     
             }
             
     if (j == 15) {
      //  Serial.println(F("Playing RANDOM24 - R2D2 3"));
        playbad("RANDOM24.WAV");
             }   
                      
     if (j == 16) {
        //Serial.println(F("Epic Lightsaber Fight"));
        digitalWrite(RLED,HIGH);
        playcomplete("RANDOM19.WAV");
        digitalWrite(RLED,LOW); 
        delay(300);
        digitalWrite(GLED,HIGH);
        playcomplete("RANDOM36.WAV");
        digitalWrite(GLED,LOW);
        delay(100);
        playbad("RANDOM31.WAV");
        delay(700);
        playR("RANDOM20.WAV");
        delay(400);
        playR("RANDOM32.WAV");
            }
            
      if (j == 17) {
       // Serial.println(F("Playing RANDOM3 - JAWS"));
        playJAWS("RANDOM3.WAV");
              }                          

         //-----//                   
      if (j == 18) {
       // Serial.println(F("Playing RANDOM21 - Mario's Coin"));
        digitalWrite(GLED,HIGH);
        digitalWrite(RLED,HIGH);
        playcomplete("RANDOM21.WAV");
        digitalWrite(RLED, LOW);
        digitalWrite(GLED, LOW);
              }
      if (j == 19) {
      //  Serial.println(F("Playing RANDOM2 - Dun Dun Dun"));
        playbad("RANDOM2.WAV");
              }
                     
      if (j == 20) {
       // Serial.println(F("Playing RANDOM5 - Bubbles"));
        playY("RANDOM5.WAV");
              }
          
      if (j == 21) {
       // Serial.println(F("Playing RANDOM6 - Bike Spokes"));
        playR("RANDOM6.WAV");
              }
         
      if (j == 22) {
       // Serial.println(F("Playing RANDOM7 - Piano"));
        playR("RANDOM7.WAV");
              }
                  
      if (j == 23) {
       // Serial.println(F("Playing RANDOM16 - Car Door Adjar Beeping Then Playing RANDOM8 - YMCA Minion Style"));
        playJeopardy("RANDOM16.WAV");
        delay (4000);
        playR("RANDOM8.WAV");
              } 

      if (j == 24) {
       // Serial.println(F("Playing RANDOM18 - PacMan Fail"));
        playR("RANDOM18.WAV");
              }

      if (j == 25) {
       // Serial.println(F("Playing RANDOM25 - StarTrek Tansporter"));
        digitalWrite(GLED,HIGH);
        playcomplete("RANDOM25.WAV");
        digitalWrite(GLED, LOW);
              }

      if (j == 26) {
       // Serial.println(F("Playing RANDOM27 - Mario Gets Bigger"));
        playR("RANDOM27.WAV");
             } 

      if (j == 27) {
       // Serial.println(F("Playing RANDOM29 - Transformers Transforming"));
        playbad("RANDOM29.WAV");     
             }

}
 
void Bblinky(){
  digitalWrite(RLED,HIGH);
  delay(200);
  digitalWrite(RLED, LOW);
  delay(100);
}

void playbad(char *name) {
  playfile(name);
  do{Bblinky();}
  while (wave.isplaying);
  sdErrorCheck();
}


void Gblinky(){
  digitalWrite(GLED,HIGH);
  delay(200);
  digitalWrite(GLED, LOW);
  delay(100);
}

void playgood(char *name) {
  playfile(name);
  do{Gblinky();}
  while (wave.isplaying);
  sdErrorCheck();
}


void Rblinky(){
  digitalWrite(GLED,HIGH);
  delay(200);
  digitalWrite(GLED, LOW);
  delay(100);
  digitalWrite(RLED,HIGH);
  delay(200);
  digitalWrite(RLED, LOW);
  delay(100);
  digitalWrite(GLED,HIGH);
  digitalWrite(RLED,HIGH);
  delay(200);
  digitalWrite(RLED, LOW);
  digitalWrite(GLED, LOW);
  delay(100);
}

void playR(char *name) {
  playfile(name);
  do{Rblinky();}
  while (wave.isplaying);
  sdErrorCheck();
}


void Yblinky(){
  digitalWrite(GLED,HIGH);
  delay(200);
  digitalWrite(GLED, LOW);
  delay(100);
  digitalWrite(GLED,HIGH);
  digitalWrite(RLED,HIGH);
  delay(200);
  digitalWrite(RLED, LOW);
  digitalWrite(GLED, LOW);
  delay(100);
}

void playY(char *name) {
  playfile(name);
  do{Yblinky();}
  while (wave.isplaying);
  sdErrorCheck();
}


void JAWSblinky(){
  delay(500);
  digitalWrite(RLED,HIGH);
  delay(850);
  digitalWrite(RLED, LOW);
  delay(3100);
  digitalWrite(RLED,HIGH);
  delay(750);
  digitalWrite(RLED, LOW);
  delay(4000);
}

void playJAWS(char *name) {
  playfile(name);
  do{JAWSblinky();}
  while (wave.isplaying);
  sdErrorCheck();
}


void Vaderblinky(){
  digitalWrite(RLED,HIGH);
  delay(400);
  digitalWrite(GLED, HIGH);
  delay(200);
  digitalWrite(GLED, LOW);
  digitalWrite(RLED, LOW);
}

void playVader(char *name) {
  playfile(name);
  do{Vaderblinky();}
  while (wave.isplaying);
  sdErrorCheck();
}


void Jeopardyblinky(){
  digitalWrite(GLED,HIGH);
  delay(1000);
  digitalWrite(RLED, HIGH);
  delay(1000);
  digitalWrite(RLED, LOW);
  digitalWrite(GLED, LOW);
}

void playJeopardy(char *name) {
  playfile(name);
  do{Jeopardyblinky();}
  while (wave.isplaying);
  sdErrorCheck();
}


void Mockingblinky(){
  delay(200);
  digitalWrite(RLED,HIGH);
  digitalWrite(GLED,HIGH);
  delay(100);
  digitalWrite(RLED, LOW);
  delay(100);
  digitalWrite(RLED,HIGH);
  digitalWrite(GLED,LOW);
  delay(100);
  digitalWrite(RLED, HIGH);
  digitalWrite(GLED,HIGH);
  delay(300);
}

void playMocking(char *name) {
  playfile(name);
  do{Mockingblinky();}
  while (wave.isplaying);
  sdErrorCheck();
}

Thank you!

Since you are already aware of the F() macro, why not use it on all those filenames too then load them into RAM on demand. Low hanging fruit.

int Good_G = 6; // a byte will hold a pin number, good practice is to mark it “const”

All those ints that will probably never be more than 16, can by bytes.

If you're only going to play ".WAV" files, then lose the file extension in the strings too.
Error messages are good candidates for flash.

Thank you, arduarn and KeithRB changing int to byte compiled.

AWOL,

AWOL:
If you're only going to play ".WAV" files, then lose the file extension in the strings too.

Do you mean literally deleting the '.WAV' from the code as in "BAD1.WAV" goes to "BAD1"? Doing that, the Arduino can't read the file. How would you indicate that WAV files are what is being read?

arduarn,

arduarn:
Since you are already aware of the F() macro, why not use it on all those filenames too then load them into RAM on demand. Low hanging fruit.

Could you point me in the right direction? I've been trying to figure out how to do that today, and haven't been successful.

Thanks again for your time!

Clickity:
AWOL,

Do you mean literally deleting the '.WAV' from the code as in "BAD1.WAV" goes to "BAD1"? Doing that, the Arduino can't read the file. How would you indicate that WAV files are what is being read?

He means take it off all the filename strings that you will wrap with the F() macro. Then in the playFile() function, append the extension back on before using the filename to access the file.
You could alternatively just store the files on the SDcard without any extension.

Clickity:
Could you point me in the right direction? I've been trying to figure out how to do that today, and haven't been successful.

Sure, you need to use the AVR's *_P or *_PF functions.
So you would really just need to allocate an appropriately sized buffer in playFile() (just a local char array), use strcpy_P() to copy the string from flash in to the buffer, append the file extension, then open the file.

strcpy_P() just works like the ordinary strcpy, but the source parameter is a pointer to program space in flash.