Arbeitsspeicher sparen in diesem code?

Hallo zusammen,
ich habe folgenden sketch, welcher den Arbeitsspeicher auszureizen scheint. Ich habe keine Erfahrung im programmieren, aber ich bin mir sicher, dass man hier viel Speicher sparen könnte, wenn man nicht alles so oft wiederholen würde. Ich bin jedoch ratlos und viele ergoogelte Sachen verstehe ich schlicht weg nicht.
Hier mein sketch:

#include <DHT.h> // include library
#include <SPI.h>
#include <SD.h>
#include <Wire.h> // Wire Bibliothek einbinden
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"

const int lightRelay = 12;
const int rainRelay = 11;
const int fanRelay = 8;
const int chipSelect = 10;
const int DHTPIN = 7;
float h = 0, t = 0;

int maxTemp = 28;
int coolTemp = 26;
int minHum = 80;

LiquidCrystal_I2C lcd(0x27, 16, 2);

#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);// Initialize DHT sensor
RTC_DS1307 rtc;

File myFile;
char dateBuffer[12];
char sensBuffer[10];

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  lcd.init(); //Im Setup wird der LCD gestartet 
  lcd.backlight();
  if (! rtc.begin()) {
    Serial.println("No RTC"); //Could not fint RTC
    Serial.flush();
    abort();
  }
  if (! rtc.isrunning()) {
    Serial.println("RTC off, set the time");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));


  Serial.print("Initializing SD card...");
  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");
  if (SD.exists("terralog.txt")) {
    Serial.println("terralog.txt exists.");
  } else {
    Serial.println("terralog.txt doesn't exist.");
    Serial.println("Creating terraaaaa.txt");
    myFile = SD.open("terralog.txt", FILE_WRITE);
    myFile.close();
    if (SD.exists("terralog.txt")) {
      Serial.println("terralog.txt was successfully created.");
    } else {
      Serial.println("File creation failed.");
    }
  }

  pinMode(fanRelay, OUTPUT);
  dht.begin();

  Serial.println("date,time,temperature,humidity,fanState,rainState,sun1State");
}

void loop() {
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  if (isnan(h) || isnan(t)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  lcd.setCursor(0, 0);//Hier wird die Position des ersten Zeichens festgelegt. In diesem Fall bedeutet (0,0) das erste Zeichen in der ersten Zeile. 
  lcd.print("Temp: ");
  lcd.print(t);
  lcd.setCursor(0, 1);// In diesem Fall bedeutet (0,1) das erste Zeichen in der zweiten Zeile. 
  lcd.print("Hum: ");
  lcd.print(h); 
  DateTime time = rtc.now();

  sprintf(dateBuffer, "%02u-%02u-%04u", time.day(), time.month(), time.year());
  Serial.print(dateBuffer);
  Serial.print(",");
  sprintf(dateBuffer, "%02u:%02u:%02u", time.hour(), time.minute(), time.second());
  Serial.print(dateBuffer);
  Serial.print(",");
  Serial.print(t);
  Serial.print(",");
  Serial.print(h);
  Serial.print(",");
  
  File myFile = SD.open("terralog.txt", FILE_WRITE);

  if (myFile) {
    sprintf(dateBuffer, "%02u-%02u-%04u", time.day(), time.month(), time.year());
    myFile.print(dateBuffer);
    myFile.print(",");
    sprintf(dateBuffer, "%02u:%02u:%02u", time.hour(), time.minute(), time.second());
    myFile.print(dateBuffer);
    myFile.print(",");
    myFile.print(t);
    myFile.print(",");
    myFile.print(h);
    myFile.print(",");
    myFile.close();
  }
  else {
    Serial.println("error opening terralog.txt");
  }
  if (t >= maxTemp) { // && a == LOW
    digitalWrite(fanRelay, HIGH);
    Serial.print("1");
    File myFile = SD.open("terralog.txt", FILE_WRITE);
    myFile.print("1");
    myFile.close();
  }
  else if (t < maxTemp && t >= coolTemp) {
    Serial.print("1");
    File myFile = SD.open("terralog.txt", FILE_WRITE);
    myFile.print("1");
    myFile.close();
  }
  else if (t < coolTemp) {
    digitalWrite(fanRelay, LOW);
    Serial.print("0");
    File myFile = SD.open("terralog.txt", FILE_WRITE);
    myFile.print("0");
    myFile.close();
  }
  Serial.print(",");

  if (h < minHum) {
    digitalWrite(rainRelay, HIGH);
    Serial.print("1");
    File myFile = SD.open("terralog.txt", FILE_WRITE);
    myFile.print("1");
    myFile.close();
  }
  else if (h >= minHum) {
    digitalWrite(rainRelay, LOW);
    Serial.print("0");
    File myFile = SD.open("terralog.txt", FILE_WRITE);
    myFile.print("0");
    myFile.close();
  }  
  
  Serial.println();
  delay(1000);
}

Viele Grüße und Schönen Sonntag euch allen!

Hallo,
Du konntest erst mal alle

Serial.print("xxxx");

ersetzen durch das F makro ersetzen
Serial.print(F("xxxx"));

dann ist der Text schon mal nicht mehr im Arbeitsspeicher
Heinz

ja F-Makro nutzen für die längeren Textausgaben.

für die einstelligen könntest noch statt einem c-String ein char schicken

```
 Serial.print('0');
```

spart den Nullterminator.

und fürs Auge: jedes int überprüfen und Kontrollfrage stellen: braucht diese Variable werte größer als 255? Wenn nicht --> ein byte Variable (uint8_t oder int8_t) verwenden. Vieles hat dir vermutlich eh der Compiler wegoptimiert, aber trotzdem schaut es bei den Pins nicht notwendig aus.

```
  sprintf(dateBuffer, "%02u:%02u:%02u", time.hour(), time.minute(), time.second());
  Serial.print(dateBuffer);
  Serial.print(",");
  Serial.print(t);
  Serial.print(",");
  Serial.print(h);
  Serial.print(",");
```

wenn du eh schon sprintf verwendest, warum machst du die Ausgabe nicht auch für t und h ?

Wenn ich das richtig sehe ist

char dateBuffer[12];

eh nur ein helper für die Ausgabe. Brauchst nicht global. leg es dir lokal an wenn du es brauchst.

dateBuffer sollte mit 11 Byte auskommen, sensBuffer kann entfallen weil nirgends genutzt.

Die SD Library braucht nun mal 2 * 512Byte RAM für je einen "Sektor" Datei und Dateiverzeichnis der Speicherkarte. Das allein ist die Hälfte des RAM eines 328 (Uno / Nano). Immerhin geht es überhaupt. Und das Feilen an kleinen Ecken und Enden sollte man sich generell von vornherein angewöhnen. Auch wenn da nirgends das Riesen-Einsparpotential schlummert.

(auch @noiasca )
Den sensBuffer wollte ich für t und h benutzen, aber anscheinend kann ich in sprintf keine Werte mit Komma abspeichern. Da hab ich noch nicht rausgefunden wie genau das geht. Grundsätzlich dachte ich mir, dass der Buffer natürlich eine elegantere Lösung sei.

sprintf speichert erstmal garnix.
Aber stimmt, von hause aus kann es kein float auf den AVRs.
Kann man ihm allerdings bei bringen

Wieso nicht? sprintf speichert alles in einem char array :wink: .

Da muss ich drüber nachdenken!
Kommt mir merkwürdig vor, das als "Speichern" zu bezeichnen. Wohl weil man bei printf() ja auch nicht von speichern spricht.
In wenigen Monaten, mehr dazu. (please wait)

Das ist ja auch genau der Unterschied zwischen beiden. sprintf, 'store'-printf speichert das Ergebnis, printf gibt es direkt aus.

Das Argument ist schon angekommen, auch eben schon.
Die "Verarbeitung" steht allerdings noch aus.

Du erstellst die Variablen Global und Lokal. Lokal sollte reichen. Global wird aber bestimmt "wegoptimiert" da nicht verwendet.