Forum: Mikrocontroller und Digitale Elektronik ESP32 to SD-Card Datalogging Problem


von hudlbergaJoe (Gast)


Lesenswert?

Hallo Community,

ich würde gerne verschiedene Sensordaten (Temperatur, Druck, 
Feuchtigkeit, etc.) mit einer ESP32 auf eine micro-SD Karte loggen.

Dazu verwende ich eine Adafruit HUZZAH32 
(https://www.adafruit.com/product/3405) und ein breakout board für die 
SD (https://www.adafruit.com/product/254) mit der Arduino IDE.

Aktuell ist es nicht möglich die Daten für eine längere Zeit bzw. viele 
Daten in kurzer Zeit in eine .csv zu speichern. Der letzte Code lässt 
sich ohne Probleme kompilieren und lässt die ESP via SPI mit der 
SD-Karte kommunizieren. Der Code ist aus einem Tutorial und wurde von 
mir nur etwas modifiziert, um zunächst Konstanten als Strings 
abzuspeichern (noch keine Messung, aktuell sind nur ESP und SD-Board 
verbunden. (Beispiel Tutorial: 
https://iotdesignpro.com/projects/logging-temperature-and-humidity-data-on-sd-card-using-esp32

1
#include "FS.h"
2
#include "SD.h"
3
#include "SPI.h"
4
5
float Temperature;
6
float Humidity;
7
String formattedDate;
8
String dayStamp;
9
String timeStamp;
10
String dataMessage;
11
12
unsigned int count = 0;
13
#define SD_CS 33
14
15
void setup() {
16
  Serial.begin(115200);
17
18
  pinMode(13, INPUT_PULLUP);  //manuell switch
19
20
  SD.begin(SD_CS);  
21
 
22
  uint8_t cardType = SD.cardType();
23
24
  File file = SD.open("/data.csv");
25
  if(!file) {
26
    writeFile(SD, "/data.csv", "Date; Time; Temperature; Humidity \r\n");
27
  }
28
  file.close();
29
}
30
31
void loop() {
32
    if(digitalRead(13) == HIGH){
33
    count = count + 1;
34
    Humidity = 44.2;
35
    Temperature = 24.2;
36
    logSDCard();
37
  }
38
}
39
40
41
void logSDCard() {
42
  dataMessage = String(count) + ";" + String(Temperature) + ";" + String(Humidity);
43
  for(int i=0;i <= 20; i++){
44
  dataMessage = dataMessage + ";" + String(Temperature) + ";" + String(Humidity);
45
  dataMessage = dataMessage + ";" + String(Temperature) + ";" + String(Humidity);
46
  dataMessage = dataMessage + ";" + String(Temperature) + ";" + String(Humidity);
47
  dataMessage = dataMessage + ";" + String(Temperature) + ";" + String(Humidity);
48
  dataMessage = dataMessage + ";" + String(Temperature) + ";" + String(Humidity);
49
  dataMessage = dataMessage + ";" + String(Temperature) + ";" + String(Humidity);
50
  dataMessage = dataMessage + ";" + String(Temperature) + ";" + String(Humidity);
51
  dataMessage = dataMessage + ";" + String(Temperature) + ";" + String(Humidity);
52
  dataMessage = dataMessage + ";" + String(Temperature) + ";" + String(Humidity);
53
  dataMessage = dataMessage + ";" + String(Temperature) + ";" + String(Humidity);
54
  dataMessage = dataMessage + ";" + String(Temperature) + ";" + String(Humidity);
55
  dataMessage = dataMessage + ";" + String(Temperature) + ";" + String(Humidity)
56
  dataMessage = dataMessage + ";" + String(Temperature) + ";" + String(Humidity) + "\r\n";
57
  }
58
  Serial.print("Save data: ");
59
  Serial.println(dataMessage);
60
  appendFile(SD, "/data.csv", dataMessage.c_str());
61
}
62
63
// Write to the SD card (DON'T MODIFY THIS FUNCTION)
64
void writeFile(fs::FS &fs, const char * path, const char * message) {
65
  Serial.printf("Writing file: %s\n", path);
66
  File file = fs.open(path, FILE_WRITE);
67
  if(!file) {
68
    Serial.println("Failed to open file for writing");
69
    return;
70
  }
71
  if(file.print(message)) {
72
    Serial.println("File written");
73
  } else {
74
    Serial.println("Write failed");
75
  }
76
  file.close();
77
}
78
// Append data to the SD card (DON'T MODIFY THIS FUNCTION)
79
void appendFile(fs::FS &fs, const char * path, const char * message) {
80
  Serial.printf("Appending to file: %s\n", path);
81
  File file = fs.open(path, FILE_APPEND);
82
  if(!file) {
83
    Serial.println("Failed to open file for appending");
84
    return;
85
  }
86
  if(file.print(message)) {
87
    Serial.println("Message appended");
88
  } else {
89
    Serial.println("Append failed");
90
  }
91
  file.close();
92
}

PIN 13 ist mit einem Schalter verbunden, mit dem ich das Loggen starten 
bzw. stoppen kann.

Wenn ich den Schalter umlege und 60 Sekunden warte, ist die .csv 471 KB 
groß, nach weiteren 20 Sekunden 642 KB, nach weitern 20 Sekunden 816 KB, 
und nach weitern 20 Sekunden nur noch 110 KB (alte Zeilen überschrieben 
bzw. gelöscht).

Wenn ich hingegen das Programm 80 Sekunden ununterbrochen laufen lasse, 
dann sind die Daten auf der SD korrupt und lassen sich am PC nicht mehr 
lesen.

Egal was ich versuche (i variieren, delay einfügen), es ist mir nicht 
möglich über längere Zeit bzw. viele Daten auf der SD zu speichern 
(Dateigröße 1 MB noch nie erreicht).

Hat jemand von euch eine ähnliche Erfahrung gemacht, oder Ideen an was 
es liegen könnte?
Vielen Dank schon mal für eure Zeit!

Liebe Grüße

von John P. (brushlesspower)


Lesenswert?

welches Filesystem ist auf der SD Karte?
kannst du überhaupt eine lesbare datei mit hello World schreiben?


Habe hier einen ESP32 mit SD Karte über SPI als datenlogger.
geht einwandfrei.

von Johannes K. (hudlbergajoe)


Lesenswert?

Wurde mit FAT32 formatiert.
Ja kann ich, die Beispiele aus 
https://github.com/espressif/arduino-esp32/tree/master/libraries/SD 
funktionieren auch, nur wenn ich diese anpasse und über etwas längere 
Zeit oder viele Daten speichern will, dann entstehen erst korrupte 
Dateien, bis schließlich der Inhalt der SD-Karte komplett korrupt ist.

Funktioniert der obige Code von mir bei euch über längere Zeit?

: Bearbeitet durch User
von John P. (brushlesspower)


Lesenswert?

Da passe es stück für stück an und gucke ab wann der Fehler auftritt

Meine Vermutung ist, dass dataMessage zu lang ist

von Johannes K. (hudlbergajoe)


Lesenswert?

Vielen Dank!

Für mein Vorhaben muss ich entweder viele Daten selten speichern, oder 
weniger Daten öfter (Beschleunigungsdaten mit 100 Hz).
Wie könnte ich es alternativ machen? Ich wollte es vermeiden die Daten 
in zu kurzen Zeitabständen abzuspeichern.

: Bearbeitet durch User
von Bernhard S. (b_spitzer)


Lesenswert?

mit file.print(message) schreibst du zunächst in den internen Puffer der 
SD-Karte. Wenn da ein Datenblock voll ist, schreibt das die Karte 
irgendwann weg. Du kannst mal mitzählen und nach etwas über 500 Bytes 
mit file.flush() den Schreibvorgang auf die Karte erzwingen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.