Variable Dateinamen für SD-Kartenzugriff

Hallöchen,

Kurzform:
Ich baue eine Steuerung mit einem Mega. Es sollen viele Variablen gespeichert werden können, auch ohne Strom. Dafür hab ich einen SD-Zugang in die Schaltung eingebaut. Erste Tests funktionierten.
Nun soll das Programm mit ca 10 von Grund auf verschiedenen Variablensätzen arbeiten können, ich sag mal einfach Modellspeicher dazu.
Wenn Modellspeicher 1 ausgewählt, dann lade die Variablen dazu von der SD-Karte, bei Modell 2 alle Variablen von 2 usw…

Mein Plan ist, je Modellspeicher 5 Dateien anzulegen, nach dem Schema:
a1.txt
b1.txt
c1.txt
d1.txt
e1.txt

a2.txt
b2.txt
c2.txt

Mein Problem ist, wie kann ich die Dateinamen statt “test.txt” variabel zusammen bauen?

  if (!myFile.open("test.txt", O_RDWR | O_CREAT | O_AT_END)) {
    sd.errorHalt("opening test.txt for write failed");
  }

Ich brauche also einen Weg, im Programm verschiedene Dateinamen dynamisch zu erzeugen, je nach gewähltem Modellspeicher.
Dachte an sowas wie:

char string[7] = "ax.txt";
for (int i = 1; i < 6; i++){
string[1] = i;
...weiterer Code...
}

// oder auch mit:

char x = char(i);
string[1] = x;

// oder sowas auch schon probiert:

for (int i = 1; i < 6; i++){
    String erster = "a";
    String zweiter = erster + i;
    String datei = zweiter + ".txt";
...weiterer Code...
}

…und noch vieles andere aber ich komme einfach nicht auf den richtigen Weg.
Erbarmt sich bitte wer? :slight_smile:

PS: Insgesamt sind es im Moment pro Modellspeicher etwa 120 verschiedene Integers, aufgeteilt in 5 Arrays, pro Modellspeicher.

Sijjim:
...und noch vieles andere aber ich komme einfach nicht auf den richtigen Weg.
Erbarmt sich bitte wer? :slight_smile:

Anbei eine Funktion zum Erzeugen von Dateinamen und ein Demosketch, der ganz viele Dateinamen nach dem Zufallsprinzip bildet.

void setup() {
  Serial.begin(9600);
}


void createFilename(char *str, char index1, char index2)
{
  sprintf(str,"%c%c.txt",index1,index2);  
}


void loop() {
  char kombi1[6]={'a','b','c','d','e','f'}; // Eine Auswahl von Buchstaben
  char kombi2[6]={'1','2','3','4','5','6'}; // Eine Auswahl von Ziffern
  char c1=kombi1[random(0,6)];   // Wähle einen Zufallsbuchstaben aus kombi1
  char c2=kombi2[random(0,6)];  // Wähle eine Zufallsziffer aus kombi2
  char filename[13];                  // Definiere Pufferspeicher für den Dateinamen
  createFilename(filename, c1, c2); // Funktionsaufruf zum Bilden des Dateinamens
  Serial.println(filename);  // Den gebildeten Dateinamen ausgeben
}

Die Funktion bildet den Dateinamen mit der "sprintf" Funktion aus der AVR libc.

Wenn Du damit schon Probleme hast, solltest Du Dich mal ausführlich informieren über

Und um "String-Objekte", die es für mich völlig unbegreiflich teilweise sogar in einige "offizielle" Arduino Demo-Sketche geschafft haben, einen großen Bogen machen!

Alles klar, vielen Dank.
Hab das halbwegs verstanden und mir auch das sprintf angesehen. Deine Infos reichen schon, damit es hier jetzt wie gewünscht funktioniert.
Aber erstmal darauf zu kommen, ein Char-Array mit String-Zahlen anzulegen um dann mit den Int-Zahlen das richtige rauszupicken … beim PHP ist das einfacher 8)

char teil[5]={'a','b','c','d','e'};
char modell[10]={'1','2','3','4','5','6','7','8','9','10'};

void setup(){
  Serial.begin(9600);
}

void createFilename(char *str, char index1, char index2){
  sprintf(str, "%c%c.txt", index1, index2);  
}

void loop(){
  Serial.println("?");
  while (Serial.read() <= 0) {} 

  int speicher = 3;  // Wird nach Bedarf/Modell getauscht
  char datei[10];

  for (int i = 0; i < 5; i++){
    char box1 = teil[i];
    char box2 = modell[speicher];
    createFilename(datei, box1, box2); 
  Serial.println(datei);
// hier dann die Datei laden, Werte den jeweiligen Variablen bzw Arrays zuweisen
  }
}

Die gesamte “string/String/Char” Angelegenheit in C hab ich bisher gekonnt ignoriert, alles läuft auch mit Int, Float usw perfekt aber damit bekomm ich halt keine Dateinamen gebaut XD

Aber gleich noch nen anderes Problem hinterher:
Beim testen hatte ich in den Daten immer ein "  " dazwischen, gefunden hab ich das es wohl an der falschen Codierung der *.txt liegt. Welche ist denn die richtige für Arduino?

Sijjim:
Aber erstmal darauf zu kommen, ein Char-Array mit String-Zahlen anzulegen um dann mit den Int-Zahlen das richtige rauszupicken ...

Das habe ich ja nur für die Zufallszahlenpickerei gemacht, um lauter zufällige Kombinationen aus einem vorgegebenen Kontingent auszuwählen. Du kannst die Funktion genau so gut mit char-Konstanten aufrufen:

void setup() {
  Serial.begin(9600);
}

void createFilename(char *str, char index1, char index2)
{
  sprintf(str,"%c%c.txt",index1,index2);  
}

void loop() {
  char filename[13];                  // Definiere Pufferspeicher für den Dateinamen
  createFilename(filename, 'x', '5');
  Serial.println(filename);  // Den gebildeten Dateinamen ausgeben
  createFilename(filename, 'h', '4');
  Serial.println(filename);  // Den gebildeten Dateinamen ausgeben
  createFilename(filename, 'a', '3');
  Serial.println(filename);  // Den gebildeten Dateinamen ausgeben
  createFilename(filename, 'Z', '9');
  Serial.println(filename);  // Den gebildeten Dateinamen ausgeben
}

Sijjim:
Die gesamte "string/String/Char" Angelegenheit in C hab ich bisher gekonnt ignoriert, alles läuft auch mit Int, Float usw perfekt aber damit bekomm ich halt keine Dateinamen gebaut XD

Im wesentlichen ist ein "char" und ein "byte" in C dasselbe. Eine 8-Bit Variable, in der eine Zahl drin steht. Die Zahl ist der ASCII-Code des Zeichens.

Und ein char-Array ist im wesentlichen dasselbe wie ein Byte-array: Ein ASCII-Code nach dem anderen. Einziger Unterschied: Wenn man das char-Array als "String" interpretieren möchte, muss das letzte Zeichen im Array ein Nullzeichen sein. ASCII-0 erkennt das Stringende. Das ist notwendig, wenn man Stringverarbeitungs- und -ausgabefunktionen verwenden möchte.

Sijjim:
Aber gleich noch nen anderes Problem hinterher:
Beim testen hatte ich in den Daten immer ein "  " dazwischen, gefunden hab ich das es wohl an der falschen Codierung der *.txt liegt. Welche ist denn die richtige für Arduino?

Dem Arduino ist die Codierung vollkommen egal, der arbeitet nur mit Bytes, und da ist ihm ein Byte genauso lieb wie ein anders. Ein Arduino hat keine Tastatur, er hat keinen Bildschirm. Also braucht der Arduino keine Codierung. Die Codierung brauchst eventuell DU, wenn Du Zeichen von einer SD-Karte liest und auf einem Bildschirm darstellen möchtest.

Zur Ausgabe auf dem in der Arduino-Software integrierten "Seriellen Monitor" wird wohl eine an ISO-8859 angelehnte Codetabelle verwendet, soweit es die Zeichen mit ASCII-Code über 127 betrifft.

Wenn Du Texte mit einem modernen Editor schreibst und als Datei abspeicherst, wird wohl oft UTF-8 als Zeichensatz verwendet. Aber das hängt natürlich ganz vom Betriebssystem und der verwendeten Software ab. "Genormt" sind nur die ASCII-Codes bis 127. Bei allen anderen Zeichen mußt Du selber wissen, wo sie herkommen und in welcher Codetabelle sie codiert sind, um zu wissen, welche Zeichen gemeint sind und wie Du sie ggf. umcodieren mußt auf eine andere Codetabelle. Z.B. von UTF-8 auf SD-Karte nach ISO-8859 im seriellen Monitor. Oder vielleicht auch gar nicht, z.B. wenn Du Daten in UTF-8 Code von SD-Karte per Netzwerk an einen Web-Browser sendest, der auch UTF-8 darstellen kann.

Das mit den Arrays ist schon gut so. Mein Beispiel im Antwortpost ist schon so hingebaut wie ich es fürs Projekt brauche, sonst wären das 50 Klarnamen.
Per LCD-Menü wird ua einer der 10 Speicher ausgewählt und die Funktion schreibt dann die jeweiligen Variablen von der SD-Karte ins Array, wie es sein soll.

Der Punkt mit der Zeichnkodierung:
Ich hab die Dateien auffn Rechner mit Notepad erstellt und aus Gwohnheit einfach UTF-8 gewählt. Für meine ganzen Websachen ist das genau richtig. Damit aber keine "Unsichtbaren" Zeichen mitgesendet werden hab ich vorhin ANSI ertestet. Bei Unicode schickt er ebenso irgendwas cryptisches mit.

Vielen Dank dir jedenfalls, Problem gelöst, alles funktioniert.

UTF-8 ist verwirrend benannt. Das sind nicht zwangsläufig 8 Bit! Die ersten 128 Zeichen sind mit ASCII identisch und haben u.U. nur 1 Byte. Aber bei allem darüber macht aus den Zeichen mindestens 2 Byte und das zweite wird dann auf dem Arduino als Müll interpretiert.

Ich hatte einfach am PC drei Dateien erstellt, in diese "111", "222", "333" geschrieben und als a1.txt, a2.txt und a3.txt in UTF-8 auf die SD-Karte gespeichert. Danach in die Schaltung damit und mit obrigen Schnipsel per Arduino - Serial ausgelesen und er schrieb mir dann "111", "222" und "333".

Inzwischen weiß ich, das es das BOM ist und wenn die Datei statt in UTF-8 als ANSI gespeichert wird, tritt es nicht auf.
Problem gelöst 8)