Go Down

Topic: Kann man den Code Speicher(SRAM) sparsamer machen ? (Read 959 times) previous topic - next topic

Shojo

Jan 05, 2013, 01:20 pm Last Edit: Jan 05, 2013, 01:22 pm by Shojo Reason: 1
Hallo,

ich habe es nun endlich geschafft das ich auch größere *.htm Seiten von der SD-Card anzeigen kann.
Nun stehe ich aber vor den Problem wenn ich nun noch eine Lib (RCSwitch) einbinde und sie nutze macht mein Speicher nicht mehr mit ...
Wenn ich mir dagegen mein MultiWiiCopter ansehe was da alles auf den 328p gemacht wird mag ich kaum glauben das mein kleines Vorhaben nicht gehen soll ..

Gibt es da eine Möglichkeit das alles zu optimieren?

Ich bin dankbar für jede Teilnahme ;)  

Code: [Select]
//This is the basic SDFat Webserver sketch, without any modifications
#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <Ethernet.h>
#include <RCSwitch.h>

// Ethernet configuration
byte mac[] = {
 0x90,0xA2,0xDA,0x00,0x26,0xEB};
byte ip[] = {
 192,168,0,87};
char rootFileName[] = "index.htm";  //root file name is what the homepage will be.
EthernetServer server(80);

// RCSwitch configuration
RCSwitch mySwitch = RCSwitch();
int RCTransmissionPin = 7;

Sd2Card card;  //SD Stuff
SdVolume volume;
SdFile root;
SdFile file;

#define error(s) error_P(PSTR(s))  //SD card errors stored in Program memory
void error_P(const char* str) {  //Error function
 PgmPrint("error: ");
 SerialPrintln_P(str);
 if (card.errorCode()) {
   PgmPrint("SD error: ");
   Serial.print(card.errorCode(), HEX);
   Serial.print(',');
   Serial.println(card.errorData(), HEX);
 }
 while(1);
}

void setup() {  //setup stuff
 Serial.begin(115200);
 PgmPrint("Free RAM: ");
 Serial.println(FreeRam());
 pinMode(10, OUTPUT);
 digitalWrite(10, HIGH);
 if (!card.init(SPI_FULL_SPEED, 4)) error("card.init failed!");  //If you are having errors when reading from the SD card, change FULL to HALF
 if (!volume.init(&card)) error("vol.init failed!");
 PgmPrint("Volume is FAT");
 Serial.println(volume.fatType(),DEC);
 Serial.println();
 if (!root.openRoot(&volume)) error("openRoot failed");
 PgmPrintln("Files found in root:");
 root.ls(LS_DATE | LS_SIZE);
 Serial.println();
 PgmPrintln("Files found in all dirs:");
 root.ls(LS_R);
 Serial.println();
 PgmPrintln("Done");
 Ethernet.begin(mac, ip);
 server.begin();
}
#define BUFSIZ 100  //defines the buffer size.  100 gives plenty of room.  reduce size if more ram is needed.

void loop()
{
 char clientline[BUFSIZ];
 char *filename;
 int index = 0;
 int image = 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;
       filename = 0;
       Serial.println(clientline);
       if (strstr(clientline, "GET / ") != 0) {  //If you are going to the homepage, the filename is set to the rootFileName
         filename = rootFileName;
       }
       if (strstr(clientline, "GET /RC=") != 0){
         if (!filename) filename = clientline + 8;
         (strstr(clientline, " HTTP"))[0] = 0;        
         Serial.print("Paket Inhalt: ");
         Serial.println(filename);
         Serial.print("Ausgeloeste Funktion: ");
         //-------------------------------------Housecode 01000------------------------------------//
         if (strcmp(filename, "110") == 0){
           mySwitch.switchOff("01000", 1);
           Serial.println("Dose 1 OFF");
           ////ReplyBufferlyBuffer = "Dose 1 OFF";
         }
         else if(strcmp(filename, "111") == 0){
           mySwitch.switchOn("01000", 1);
           Serial.println("Dose 1 ON");
           //ReplyBuffer = "Dose 1 ON";
         }  
         //-----------------------------------------------//
       }
       if (strstr(clientline, "GET /") != 0) {
         if (!filename) filename = clientline + 5;  //gets rid of the GET / in the filename
         (strstr(clientline, " HTTP"))[0] = 0;  //gets rid of everything from HTTP to the end.
         Serial.println(filename);
         if (! file.open(&root, filename, O_READ)) {  //if the file doesn't exist a 404 is sent
           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");
         if (strstr(filename, ".htm") != 0)  //Sets content type.
           client.println("Content-Type: text/html");
         else if (strstr(filename, ".css") != 0)
           client.println("Content-Type: text/css");
         else if (strstr(filename, ".png") != 0)
           client.println("Content-Type: image/png");
         else if (strstr(filename, ".jpg") != 0)
           client.println("Content-Type: image/jpeg");
         else if (strstr(filename, ".gif") != 0)
           client.println("Content-Type: image/gif");
         else if (strstr(filename, ".3gp") != 0)
           client.println("Content-Type: video/mpeg");
         else if (strstr(filename, ".pdf") != 0)
           client.println("Content-Type: application/pdf");
         else if (strstr(filename, ".js") != 0)
           client.println("Content-Type: application/x-javascript");
         else if (strstr(filename, ".xml") != 0)
           client.println("Content-Type: application/xml");
         else
           client.println("Content-Type: text");
         client.println();
         int16_t c;
         while ((c = file.read()) >= 0) {
           client.write((char)c);  //sends file to website client
         }
         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();
 }
}



Gruß
Dennis

paulinchen

Hallo,
Du kannst z. Bsp. das "F-Makro" verwenden:

statt:
Serial.println("Dose 1 OFF");

besser:
Serial.println(F("Dose 1 OFF"));

Viele Grüße, paulinchen


olikraus

Ich sehe folgende Möglichkeiten:
* PROGMEM, F() verwenden
* Globale und lokale statische Variablen vermeiden: Ablage von berechneten Daten vermeiden sondern vielmehr Funktionen schreiben, die die Berechnung "on demand" durchführt (Austausch SRAM gegen Geschwindigkeit)
* Die SW Architektur so ausrichten, dass nur der tatsächlich benötigte Funktionsumfang im Speicher landet.

Auf der anderen Seite kann ich aus eigener Erfahrung sagen, dass es einem niemand dankt, wenn man seine Lib (bei mir u8glib und m2tklib) auf Speicherplatz oder SRAM Verbrauch optimiert. Klar, das merkt man ja auch normalerweise nie, solange die Lib problemlos läuft. Auf der anderen Seite fragen dann die Nutzer eher nach neuen Funktionen und natürlich sollte alles viel schneller sein.

Fazit: Die Lib-Entwickler bauen lieber schnell neue Features rein, als sich mal um Code-Cleanup und Optimierung zu kümmern.

Die SdFat ist durchaus so ein Beispiel. Natürlich eine geniale Lib. Und sicher hinsichtlich ROM Verbrauch und Geschwindigkeit besser als die Arduino SD Lib, aber wenn man beispielsweise nur lesenderweise auf die Dateien zugreifen will, wird trotzdem der ganze Code dazugelinkt.

Grüße,
Oliver



Shojo

Danke schon mal für die Tipps!

Mal sehen was ich davon umsetzten kann ;)

sui

Ethernet + Webserver sind halt schon ganz gewaltige Speicherfresser, da bleibt nicht mehr viel für was anderes übrig ;)

Ich hab' die RCSwitch Library mal auf ein absolutes Minimum zum Schalten der gängigsten Steckdosen (die 10DIP Baumarktdinger) reduziert. Ist echt schlank geworden, vieleicht sollte ich das auch als Lightversion im nächsten RCSwitch Release dazulegen:

Code: [Select]

int RCLpin = 7;

void setup() {
    pinMode(RCLpin, OUTPUT);
}

void loop() {
    RCLswitch(0b010001000001);  // DIPs an Steckdose: 0100010000 An:01
    delay(2000);

    RCLswitch(0b010001000010);  // DIPs an Steckdose: 0100010000 Aus:10
    delay(2000);   
}

void RCLswitch(uint16_t code) {
    for (int nRepeat=0; nRepeat<6; nRepeat++) {
        for (int i=4; i<16; i++) {
            RCLtransmit(1,3);
            if (((code << (i-4)) & 2048) > 0) {
                RCLtransmit(1,3);
            } else {
                RCLtransmit(3,1);
            }
        }
        RCLtransmit(1,31);   
    }
}

void RCLtransmit(int nHighPulses, int nLowPulses) {
    digitalWrite(RCLpin, HIGH);
    delayMicroseconds( 350 * nHighPulses);
    digitalWrite(RCLpin, LOW);
    delayMicroseconds( 350 * nLowPulses);
}

Go Up