Array typ struct, casted als int8_t pointer: Erfahrung mit Sd-Fat

Hallo zusammen,

ich möchte mal in die Runde fragen, wer von euch schon etwas mit Hilfe dieser Bibliothek (Sd-Fat Beta von Bill Greiman) programmiert hat? Vielleicht kann mir jemand von euch helfen. Hinweise und Tipps werden sehr willkommen.

Als Basis für mein Programm habe ich das Beispielprogramm "bench" genommen. Ich habe ein struct definiert, wo die Daten bei jedes Ablesen gespeichert werden. Von gleichen Typ ein Array (dataToSd) große 512 (BUF_SIZE).

struct sample{
float x; char tab1='\t';
float y; char tab2='\t';
unsigned long stamp;
bool stateIE;
};

In bench wird ein Pointer der Typ uint8_t definiert und direkt zu (uint8_t*)buffer32
Bei mir würde es so aussehen: uint8_t* buffertest = (uint8_t)* dataToSd. Da wird mir natürlich ein Fehler angezeigt. Daher habe ich der Pointer, der an die write-Funktion übergeben wird, von Typ sample* definiert.

Hier werden die Daten künstlich generiert :

for(i=0; i < (BUF_SIZE-1);i++)
{
dataToSd[i].stamp = millis();
dataToSd[i].x = i*2;
dataToSd[i].y = i*7;
}

Um die Werte in der Sd zu schreiben:

buffertest = &dataToSd[0];
if (file_race.write(buffertest, BUF_SIZE) != BUF_SIZE) 
{error("write failed");}
else{ Serial.println(" wrote in Sd");}
delay(50);
if(file_race.fileSize()>=FILE_SIZE)
{file_race.sync();file_race.close();Serial.println("File is full");while(1){;}}

Wenn ich die "Aufnahme" in der SD-Karte überprüfe kommt nur mist raus. Man erkennt aber, dass die gleichen Werte gespeichert worden sind. Deswegen denke ich, dass das Problem bei der Definition von buffertest liegt aber wenn ich dataToSd "casted" die Info komplett verloren geht.

Entschuldige ich mich für grammatische Fehler. Deutsch ist nicht meiner Muttersprache.

Besten Dank

Von gleichen Typ ein Array (dataToSd) große 512 (BUF_SIZE).

Huh? Irgendwie bringst du da was durcheinander. Ein Array vom gleichen Typ ist ein Array aus Strukturen. Das ist etwas ganz anderes als ein Byte Array. Das Byte Array in dem Beispiel hat 512 Bytes, weil das die Größe eines SD Blocks ist. Deine Struktur hat aber schon mehrere Bytes!

Strukturen und Klassen fangen übrigens überlicherweise mit Großbuchstaben an

Du willst vielleicht eher sowas:

sample data;

...

file_race.write((uint_8t*)&data, sizeof(sample));

Serenifly:
Das Byte Array in dem Beispiel hat 512 Bytes, weil das die Größe eines SD Blocks ist.

Ahhh ok! Das habe ich so nicht kapiert.

Serenifly:
Deine Struktur hat aber schon mehrere Bytes!

Genau. Es sind 32 Bytes.

Zwischen jeden Sensormessung habe ich etwas 600µs um in der SD-Karte zu speicher, daher habe ich ein kleines Array definiert.

const bool PRE_ALLOCATE = true;
bool skipLatency = false;
#if SD_FAT_TYPE == 0
SdFat sd_race;
File file_race; // @suppress("Abstract class cannot be instantiated")
#endif
// Store error strings in flash to save RAM.
#define error(s) sd_race.errorHalt(&Serial, F(s))
// Set SKIP_FIRST_LATENCY true if the first read/write to the SD can
// be avoid by writing a file header or reading the first record.
const bool SKIP_FIRST_LATENCY = true;
// Size of read/write.
const size_t BUF_SIZE = 512;
const uint32_t FILE_SIZE_MB = 1;
const uint32_t FILE_SIZE = 1000000UL*FILE_SIZE_MB;
// Serial output stream
ArduinoOutStream cout(Serial);
/*
 */
unsigned long pick = 0;
struct Sampleacc{ //32Bytes
 float x; char tab ='\t';
 float y; char tab2='\t';
 unsigned long stamp;
 bool stateIE;
};
const size_t WBUF_SIZE = 1024;
const size_t WRITE_GAP = 32;
Sampleacc dataToSd[WRITE_GAP]; //
uint8_t* buffer = (uint8_t*)dataToSd;

int16_t i=0;
int16_t idxRData = 0;
int16_t idxWData = 0;
void setup()
{
 Serial.begin(BaudRate);
  while (!Serial) {
    SysCall::yield();
  }
 pinMode(LED_R, OUTPUT);
 pinMode(LED_G, OUTPUT);
 pinMode(LED_B, OUTPUT);
 do{
    delay(10);
 } while (Serial.available() && Serial.read() >= 0);
 if (!sd_race.begin(SD_CONFIG)) {
    sd_race.initErrorHalt(&Serial);
 }
 if (!file_race.open("race1.dat", O_RDWR | O_CREAT | O_TRUNC)) {
 error("open failed");}
}
void loop()
{
 Serial.println("loop in");
 for(i=0; i < (BUF_SIZE-1);i++)
 {
 dataToSd[i].stamp = millis();
 dataToSd[i].x = i*2;
 dataToSd[i].y = i*7;
 }
 if (file_race.write((uint8_t*)&dataToSd[0], WBUF_SIZE) != WBUF_SIZE) {error("write failed");}else{ Serial.println(" in Sd wrote");}
 delay(50);
 if(file_race.fileSize()>=FILE_SIZE){file_race.sync();file_race.close();Serial.println("File is full");while(1){;}}
 loop();
}

Mit der Sd-Fat beta Version habe ich gemessen, dass man etwas über 2MB/s schreiben kann.
Da ich nur 600µs habe, habe ich als Arraygroße 1024 Byte genommen. Nun möchte ich bei der Speichervorgang die 32 Messungen in der SD speichern.

Es gibt da mit LowLatencyLogger auch noch ein Beispiel für performantes Schreiben. Das ist aber nicht trivial, da da das alles per Hand macht was einem die Bibliothek normal abnimmt

Ich habe dies mal so ausprobiert aber leider ohne Erfolg... Als Bild habe ich die Datei race1 hinzugefügt.

const size_t WBUF_SIZE = 1024;
const size_t WRITE_GAP = 32;
const uint32_t SIZE_P = 32;
Sampleacc dataToSd[SIZE_P]; 
//...

for(i=0; i < (SIZE_P-1);i++)
{
dataToSd[i].stamp = millis();
dataToSd[i].x = i*2;
dataToSd[i].y = i*7;
}
//...


if (file_race.write((uint8_t*)&dataToSd, sizeof(dataToSd)) != (sizeof(dataToSd))) {error("write failed");}else{ Serial.println(" in Sd wrote");}
if(file_race.fileSize()>=FILE_SIZE){file_race.sync();file_race.close();Serial.println("File is full");while(1){;}}
//...

Ich weiß nicht woran das liegt oder wie ich das lösen kann. :confused:

Dir ist schon klar dass das keine Text Datei, sondern Binär-Daten sind?

Serenifly:
Dir ist schon klar dass das keine Text Datei, sondern Binär-Daten sind?

Nicht bis vorhin. Danke, werde mich da schlau machen