Webserver SD Card Logger - uses too much RAM

Hi everybody,

this is my first post here.
So please be gentile.
I "wrote" this Code by copying components from differnet sources.
Every component runs perfect by itself, but unfortunatelly the sketch uses too much RAM.

I Use a Arduino Ethernet Board. (not the ethernet shield)

Can someone please give me hints, how and where i can optmize the code for RAM usage?

Sadly I had to remove most of the comment due to the limited posting size in here.

Thanks alot so far.

#include <SD.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <string.h>
#include <SPI.h>
#include <Time.h>
#include <EEPROM.h>
#include <EEPROMAnything.h>
#include <avr/pgmspace.h>

/************** NTP STUFF ***************/
unsigned int localPort = 8888;        
IPAddress timeServer(132, 163, 4, 101); 
                                       
 
const int NTP_PACKET_SIZE= 48;
byte packetBuffer[ NTP_PACKET_SIZE]; 
EthernetUDP Udp;
 
/*** DATA LOGGER AND TIMER CONTROLS ****/
const int analogPin = 0;
unsigned long lastIntervalTime = 0; 
#define MEASURE_INTERVAL 30000     
unsigned long newFileTime;        
#define FILE_INTERVAL 604800      

/************ ETHERNET STUFF ************/
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 125 };
EthernetServer server(80);

//A structure that stores file config variables from EEPROM
typedef struct{                    
    unsigned long newFileTime;   
    char workingFilename[19];      
} configuration;
 

configuration config;               //Actually make our config struct

void setup() {
  File root;
  Serial.begin(9600);
  pinMode(4, OUTPUT);

  SD.begin(4);

  root = SD.open("/data/");

  

  Serial.println("done!");
  
  pinMode(10, OUTPUT); // set the SS pin as an output (necessary!)
  digitalWrite(10, HIGH); // but turn off the W5100 chip!

  Ethernet.begin(mac, ip);
  server.begin();
  Udp.begin(localPort);
  root.close();
}
void printDirectory(EthernetClient client, File dir, int numTabs) {
   while(true) {

     File entry =  dir.openNextFile();
     if (! entry) {
       // no more files
       // return to the first file in the directory
       
       dir.rewindDirectory();
       break;
     }
     client.print("<li><a href=\"HC.htm?file=");
     client.print(entry.name());
     client.print("\">");
     client.print(entry.name());
     client.print("</a></li>");
       delay(100);
     for (uint8_t i=0; i<numTabs; i++) {
       Serial.print('\t');
     }
     Serial.print(entry.name());
     
     entry.close();
    
   }
}

 
unsigned long getTime(){
  sendNTPpacket(timeServer); // send an NTP packet to a time server
 
 
  delay(1000); 
  if ( Udp.parsePacket() ) { 
   
    Udp.read(packetBuffer,NTP_PACKET_SIZE);  
 
    
    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); 
    
    unsigned long secsSince1900 = highWord << 16 | lowWord; 
  
    const unsigned long seventyYears = 2208988800UL;    
  
    unsigned long epoch = secsSince1900 - seventyYears; 
 
    return epoch;
  }
}
 

unsigned long sendNTPpacket(IPAddress& address){
   

  memset(packetBuffer, 0, NTP_PACKET_SIZE);
 
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
 
     
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer,NTP_PACKET_SIZE);
  Udp.endPacket();
}


#define BUFSIZ 40

void loop()
{ if ((millis() % lastIntervalTime) >= MEASURE_INTERVAL){ //Is it time for a new measurement?
  
    char dataString[15] = "";
    int count = 0;
    unsigned long rawTime;
    rawTime = getTime();
 
    while((rawTime == 39) && (count < 12)){     
      delay(5000);                             
      rawTime = getTime();                      
      count += 1;                               
    }                                           
    
    if (rawTime != 39){                         
      Serial.println("got Ntp Server Time");
      
      if (rawTime >= config.newFileTime){
        int dayInt = day(rawTime);
        int monthInt = month(rawTime);
        int yearInt = year(rawTime);
        char newFilename[18] = "";
        char dayStr[3];
        char monthStr[3];
        char yearStr[5];
        char subYear[3];
        strcat(newFilename,"/data/");
        itoa(dayInt,dayStr,10);
        if (dayInt < 10){
          strcat(newFilename,"0");
        }
        
        strcat(newFilename,monthStr);
        strcat(newFilename,"-");
        itoa(yearInt,yearStr,10);
        
        memcpy( subYear, &yearStr[2], 3 );
        strcat(newFilename,subYear);
        strcat(newFilename,".csv");
        
        config.newFileTime += FILE_INTERVAL;
        strcpy(config.workingFilename,newFilename);
       
        
         EEPROM_writeAnything(0, config); 
      }
      
     
      int sensor = analogRead(analogPin); 
      char timeStr[12];
      char sensorStr[6];
       
      ultoa(rawTime,timeStr,10);
      itoa(sensor,sensorStr,10);
       
      strcat(dataString,timeStr);
      strcat(dataString,",");
      strcat(dataString,sensorStr);
      
      
      File dataFile = SD.open("/data/05-08-13.CSV", FILE_WRITE);
   
     
      if (dataFile) {
        dataFile.println(dataString);
        dataFile.close();
        
        Serial.println(dataFile);
        Serial.println(dataString);
        
      } 
      
      else {
        Serial.println("Error opening datafile for writing");
      }
   
    }
    else{
      Serial.println("Couldn't resolve a time from the Ntp Server.");
    }
 
    lastIntervalTime = millis();
    Serial.println(lastIntervalTime);
  }
 
  else{
  File root;
  root = SD.open("/data/");
  
  char clientline[BUFSIZ];
  int index = 0;
  
  EthernetClient client = server.available();
  if (client) {
   
    boolean current_line_is_blank = true;
    
   
    index = 0;
    
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        
        
        if (c != '\n' && c != '\r') {
          clientline[index] = c;
          index++;
          
          if (index >= BUFSIZ)
            index = BUFSIZ -1;
          
          
          continue;
        }
        
        
        clientline[index] = 0;
        
       
        
        Serial.println(clientline);
        
        
        if (strstr(clientline, "GET / ") != 0) {
          
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
          
          
          client.println("<h2>Files:</h2>");
        
         
         printDirectory(client, root, 0);
         PgmPrint("Free RAM: ");
  Serial.println(FreeRam()); 
         
        } else if (strstr(clientline, "GET /") != 0) {
          
          char *filename;
          
          filename = clientline + 5; // look after the "GET /" (5 chars)
          
          (strstr(clientline, " HTTP"))[0] = 0;
          
         
          Serial.println(filename);

       /*   if (! file.open(&root, filename, O_READ)) {
            client.println("HTTP/1.1 404 Not Found");
            client.println("Content-Type: text/html");
            client.println();
            client.println("<h2>File Not Found!</h2>");
            break;
          }
          
          Serial.println("Opened!");
         */           
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/plain");
          client.println();
          
          int16_t c;
       /*   while ((c = file.read()) > 0) {
             
              client.print((char)c);
          }*/
         // file.close();
        } else {
          
          client.println("HTTP/1.1 404 Not Found");
          client.println("Content-Type: text/html");
          client.println();
          client.println("<h2>File Not Found!</h2>");
        }
        
        break;
      }
    }
    
    delay(1);
    client.stop();
  }
  root.close();
  }
}

Every place you .print() or .println() a string constant, like this:

     client.print("<li><a href=\"HC.htm?file=");

change it to use the F() macro, like this:

     client.print(F("<li><a href=\"HC.htm?file="));

The F() macro will keep that string constant from being copied from FLASH to SRAM. Every byte of string constant you can do that with will save a byte of SRAM.

Also strcat_P(newFilename,".csv");