Daten von SD-Karte lesen und verarbeiten

Hallo Leute,

ich bin neu im Forum und bei der Arduino Programmierung, auch in C oder C++ bin ich nicht Fit.
Ich habe einen Uno, und die Arduino IDE 2.2.1 Version.
Ich habe jetzt viel gelesen und ausprobiert aber manches ist mir nicht klar. Da würde ich gerne um Eure Unterstützung bitten.

Ich möchte Daten nach dem Ausschalten beibehalten dazu sollen diese auf einer SD-Karte in einer Textdatei gespeichert werden.

SD-Karte schreiben lesen erst einmal kein Problem. Aber die Weiterverarbeitung funktioniert nicht so wie ich es mir wünsche.

Eine Zahl die in eine txt-Datei geschrieben ist wird als String eingelesen, diesen String möchte ich wieder als Zahl einer Variablen zuweisen je nach größe Integer oder Long.

Ich lese den String ein, char für char wandle jedes char in einen int Wert und möchte diese dann mit der zugehörigen Potenz multiplizieren und die Summe bilden. Bin mir nicht sicher ob dies der richtige Weg ist aber ein anderer hat sich mir nicht erschlossen.

Gespeicherte Zahl in Text-Datei = 12345

char TEST[10];

while (myFile.available()) {
      TEST[i] = myFile.read(); 
      ++i;
    }

Serial.print("Jetzt Test : ");
Serial.println(TEST);
Serial.print("Jetzt -500 : ");
Serial.print(TEST - 500);

Das gibt auf dem Serial Monitor ausgegeben folgendes Ergebnis:

Serial.print("Jetzt Test : "); & Serial.println(TEST); -> Jetzt Test : 12345
Serial.print(TEST - 500); -> Jetzt -500 : u5���0

Somit ging die Suche los was man da machen kann um eine Zahl zu gewinnen
toint() und atoi() hat nicht funktioniert

Dann habe ich folgendes angefangen:

int b = 0;
int c = 0;
int d = 0;
int Lange = 0;
int expo = 0;

for (int zaehler=0; zaehler<Lange; zaehler = zaehler+1) {
    Serial.print("TEST = ");
    Serial.println(TEST[zaehler]);
    b = atoi(TEST[zaehler]); //dies scheint nicht zu funktionieren??
    Serial.print("b = ");
    Serial.println(b);
    Serial.print("Lange = ");
    Serial.print(Lange);
    Serial.print("; zaehler = ");
    Serial.print(zaehler);
    expo = Lange - 1 - zaehler;
    Serial.print("; expo = ");
    Serial.print(expo);
    c = pow(10, expo);
    Serial.print("; c = ");
    Serial.println(c);
    d = d + b * c;
    Serial.print("d = ");
    Serial.println(d);
    Serial.println(pow(10, Lange - 1 - zaehler));
    Serial.println(c); //Berechnet = Berechnet +
  }

Ergebniss der Schleife:

alles Gedruckt
dat1.txt geschlossen
--> erster Schleifendurchgang
TEST = 1
b = 0
Lange = 5; zaehler = 0; expo = 4; c = 9999
10000.00
9999
--> zweiter Schleifendurchgang
TEST = 2
b = 0
Lange = 5; zaehler = 1; expo = 3; c = 999
d = 0
1000.00

Also Warum ergibt

-> Serial.println(c); = 999 -> mit c = pow(10, expo);
aber
-> Serial.println(pow(10, Lange - 1 - zaehler)); = 10000.00 -> warum?

und warum ergibt: b = atoi(TEST[zaehler]); immer = 0 (TEST kann immer nur 0,1, 2, 3.... oder 9 sein)

Wie kann ich in eine Textdatei eine Zahl speicher und wieder auslesen?? Ich komme da einfach
nicht weiter, da ich nicht weiß ist der Fehler im C-Programm, bei den Befehlen oder liegt es an etwas anderem?

Wäre SUPPER wenn Ihr mir helfen könnt oder einen Tipp geben könnt.

Vielen Dank und LG
Hampo

Versuch mal an Stelle

Serial.print(atoi(TEST) - 500);

Du suchst zur Umwandlung atol() für long bzw. atoi() für int.

Gruß Tommy

Danke! da hätte ich noch lange gesucht,

-> Serial.print(atoi(a)); -> mit a = 12345

wird anstatt 12345 -> 123450 im Serial Monitor angezeigt

schreibe ich aber -> b = atoi(a);

Serial.print(b); -> wird 12345 ausgegeben

Die angehängt Null nur ein Anzeigeproblem ?

Mit der Variante in eine Variable zu übergeben lässt sich rechnen das ist das was ich gesucht habe!

Top vielen Dank

Hallo Tommy,

vielen Dank für die schnelle Antwort ok das Leuchtet ein! Hätte ich auch selbst darauf kommen können. Manchmal sieht man den Wald vor lauter Bäumen nicht.

Nochmals vielen Dank hat mir sehr weiter geholfen!
Ich denke ich habe jetzt alles um weiter zu machen!

Wenn mein Projekt fertig ist stelle ich es mal vor! Kleine Überraschung hoffe nur dass es auch so funktioniert wie ich es mir vorstellen.

LG und Vielen Dank
Hampo

vermutlich spielt Dir char TEST[10] einen Streich.
Mach mal vor dem befüllen des Array das array richtig leer.
memset(TEST, '\0', sizeof(TEST)/sizeof(TEST[0]));

du meinst bestimmt
memset(TEST, 0, sizeof(TEST));

Es reicht übrigens, nach dem Einlesen ein Endezeichen ( 0 oder '\0' ) anzufügen. und möglichst nicht über den definierten Variablenbereich hinaus zu gehen.

char TEST[10] = "12345";
Serial.println(TEST-500);  // Gibt aus, was irgendwo ganz woanders gespeichert ist
Serial.println(TEST+2); // liefert den Text "345", vielleicht erklärt das @papanos Denkfehler.

memset füllt Byte weise, also muss die Länge in Bytes angegeben werden, nicht in Elementen (auch wenn das Element hier 1 Byte groß ist, sollte man nicht diese falsche Berechnung nutzen):

memset(TEST, '\0', sizeof(TEST));

Gruß Tommy

1 Like

Vermutlich wird es egal sein, wie das gelöst wird. Ich vermute, das da dann noch immer ein 0 angehangen wird :wink:

In der zweiten Variante hast du eine Variable mehr in deinem Sketch. Dadurch verändert sich eventuell, was hinter a "zufällig" im Speicher steht.

char TEST[10];
int i = 0;
while (myFile.available()) {
      TEST[i] = myFile.read(); 
      if (i < sizeof(TEST) -1 ) i++ ;
}
TEST[i] = 0; // das hat gefehlt

Hallo michael_x,

sollte es zum Schluss nicht

}
i++;
TEST[i] = 0;

sein? Denn sonst würde ja das letzte char mit der Null überschrieben werden oder?

Hab leider jetzt gerade keine Zeit es auszuprobieren.

Vielen Dank für die intensive Diskussion (das war eigentlich nicht beabsichtigt).
Da ich in einer Zeit Programmiert habe wo man noch E-Proms gebrannt hat bin ich mit den Möglichkeiten und den "Hochsprachen" noch etwas überfordert. Ich bin mir nicht sicher
wie die einzelnen Befehle den Speicher füllen und auslesen. Und gleichzeitig wird noch die Umwandlung von Bit-Werten in char automatisiert. Die Übertragung zum PC-Monitor usw. das geht alles von alleine. Früher hat man sich um alles gekümmert. Speicherplatz zuweisen, Schnittstellen öffnene Werte Bit- bzw. Byte-Weise übertragen usw. war viel handarbeit. Aber da
hat man eben gewusst ob und wie der Speicherplat belegt ist usw.. Nun ja das ist schon eine weile her. Da hat noch der PC 5 1/4Zoll Laufwerke gehabt :smile: .

Ich denke auch dass man den Speicherplatz erst einmal leeren muss und nicht zuviel einlesen und die Datensatzendenull muss auch her.

(Doch wieder mal mehr geschrieben als gewollt)

Nochmals ALLEN Vielen Dank LG
Hampo

hab's nicht getestet, und überlegt:

  • Im Normalfall wird nach jedem in TEST[i] abgelegten Zeichen i erhöht,
    also ist am Ende TEST[i] = 0; richtig.
  • Bei drohendem Puffer-Überlauf darf i nicht weiter erhöht werden, die 0 darf und sollte auf sizeof(TEST) -1 kommen.
  • Wenn mehr Zeichen gelesen werden und nicht alles in den Puffer passt, ist auch egal, was man dann wohin (innerhalb des zu kleinen Puffers) speichert.

Das Schöne an Arduino-Programmierung ist doch, dass es immer noch auf jedes Byte und Bit ankommt.