dynamischen Speicher schonen?

Hallo,

Zur Feinjustierung meiner Steuerung für Heizung und Rollläden
möchte ich den Programmablauf auf der SD protokollieren.

Das funktioniert auch so wie mir das vorstelle.

Leider verbrauchen meine Texte enorm viel dynamischen Speichers.
Dabei ist es egal ob ich global oder in der Funktion meinen Text definiere.

Hier ein kleiner Ausschnitt, wie ich es jetzt gelöst habe. (Zeile 3)

  if(vTempAussen < paTGrenzeK || vTempAussKLog == true){    //ist die Außentemperatur unter 5°C oder die Hysterese noch nicht erreicht
    if(!bSDPrint[0]){                                       //wurde dieser Text schon gespeichert
      String sLine = "die Außentemperatur ist unter 5°C;Aussentemp. = " + String(vTempAussen); writeProtokollToSD(sLine);
      bSDPrint[0] = true;                                   //als gespeichert markieren
    }

Gibt es eine andere Möglichkeit die zum selben Ergebnis führt aber den dynamischen Speicher schont.
Wenn ich mein Beispiel Zeile 3 auskommentiere habe ich 58 Bytes mehr zur Verfügung.

Gruß Aron

Die Klasse String ist auf einem Arduino ungünstig. Besser ist die Verwendung von Char-Arrays.

Wenn es nur um Ausgabetexte geht, die mit einer print/println()-Funktion ausgegeben werden sollen, kommt noch das F-Macro in Betracht. z.B.:

Serial.print(F("Temperatur (innen): ")); 
Serial.print(temp);

Dabei wird der konstante Text im Flash gespeichert.

Gruß Tommy

Kann ich auch auf SD speichern ohne die Klasse String zu verwenden?

Serial.print benötigt einen angeschlossenen PC. Das kann ich nicht auf Dauer gebrauchen.

print() ist nicht auf Serial beschränkt. Das geht genauso mit SD oder LCDs. Und allen anderen Klassen die von der Print Klasse erben

Ja.
Serial war nur als Beispiel gedacht. Du kannst auch in ein File auf diese Weise printen.

Gruß Tommy

Ja,
ich schreibe schon mit println auf meine SD.

void writeProtokollToSD(String line) {
  String vText = String(TimeString()) + String(line);
    File dataFile = SD.open("datalog.csv", FILE_WRITE);
    if (dataFile) {
     dataFile.println(vText); // Auf die SD-Karte schreiben
     dataFile.close();
     Serial.println(vText); // Zusätzlich auf serielle Schnittstelle schreiben zum Debuggen
    }
    else {
     Serial.println("Error opening datafile");
    }
}

String TimeString() {
 String t = String(day());
 t += String(".");
 t += String(month());
 t += String(".");
 t += String(year());
 t += String(" ");
 t += String(hour());
 t += ":";
 t += String(minute());
 t += ":";
 t += String(second());
 t += ";";
 return t;
}

Aber wie bekomme ich das so flexibel hin, dass ich mal nur Text, mal Text mit einer Variablen
oder Text mit 10 Variablen dazwischen habe kann?

Hier wurde das mal für Variablen vorgestellt.

Aber wie bekomme ich das so flexibel hin, dass ich mal nur Text, mal Text mit einer Variablen
oder Text mit 10 Variablen dazwischen habe kann?

Was jammerst du...
Ich sehe keine 10 Variablen...

Eliminiere alle String Instanzen!
Alle.

void writeProtokollToSD(String line) {

String vText = String(TimeString()) + String(line);

Alleine hier sind mindestens 4 solcher Instanzen im Spiel.
Und mindestens eine davon ist eine überflüssige Kopie.

Suche mal nach sprintf()
Oder nach Streaming.h

Flexibilität nach allen möglichen Richtungen und Speicher sparen stehen sich oft gegenüber. Du musst da einen Mittelweg finden.
Was brauchst Du soviel Text auf der SD?
Wenn Du einen festen Aufbau (z.B. CSV) wählst, dann brauchst Du außer den Spaltenüberschriften überhaupt keinen festen Text und kannst es in einer Tabellenkalkulation Deiner Wahl auswerten..

Gruß Tommy

ar182:
Gibt es eine andere Möglichkeit die zum selben Ergebnis führt aber den dynamischen Speicher schont.

Ja:

  • Texte im Programmspeicher ablegen -> Progmen
  • Texte im EEPROM ablegen: EEPROM
  • Das F-Makro verwenden: Serial.println(F("Error opening datafile")); -> The F() macro

Es gibt nur wenige Bibliotheken bei denen man einen String wirklich an einem Stück senden muss. Ich weiß nicht wieso Anfänger immer auf die Idee kommen alles vor einer Ausgabe verknüpfen zu müssen

Und sowas macht man auch nicht:

void writeProtokollToSD(String line)

Schau dir mal Referenzen an wenn du Objekte an eine Funktion übergeben willst.

Aber vernünftiger ist du machst die Ausgabe direkt in der Funktion. Da einen String zu basteln ist überflüssig. Egal ob Objekte oder char Arrays

Du kannst auch das machen:

void printTime(Print& p)
{
  p.print(...);
}

Da kannst du dann ein File oder ein Serial Objekt übergeben um den Text auf verschiedenen Dingen auszugeben

Wenn man eine schönere und kürzere Schreibweise möchte gibt es wie gesagt das:
http://arduiniana.org/libraries/streaming/
Das überläd den << Operator, wodurch die Ausgabe dann wie Standard C++ aussieht und man nicht jedesmal file.print() schreiben muss

Jetzt einmal ein anderer Ansatz.

Wenn ich datalog.csv auf dauer geöffnet halte.

Dann kann ich doch an beliebiger Stelle im Programm mit print in meine Datei schreiben.

Wenn ich von der SD was lesen will schließe ich die Datei, lese und öffne die Datei wieder.

Funktioniert das bzw kann das Probleme machen?

Die Streaming-Lib wird viel zu wenig gewürdigt. Ich übersehe sie auch leider laufend.
Ich habe gerade mit der SD-Lib das Ganze probiert. Funktioniert problemlos.

Gruß Tommy

ar182:
Funktioniert das bzw kann das Probleme machen?

Wenn dazwischen der Strom weg ist, kann es sein, dass Du die SD nicht mehr lesen kannst.
Im Extremfall ist sie dauerhaft geschädigt.

Gruß Tommy

Tommy56:
Ich habe gerade mit der SB-Lib das Ganze probiert.

Du meinst "SD"?

Danke, ist korrigiert.
Als Anmerkung: SdFat hat Streaming schon drin, da sollte man Streaming.h nicht einbinden.

Gruß Tommy