Forum: Mikrocontroller und Digitale Elektronik Datei von SD-Karte zeilenweise lesen und gelesenes Löschen


von Chris (Gast)


Lesenswert?

Hi!

Meine Schaltung schreibt alle 4 Minuten Sensorwerte auf eine SD-Karte. 
Die Daten sollen nun von einem PC abgerufen werden, wobei die ältesten 
Messwerte, die am Anfang der Datei stehen, zu erst kommen sollen.

Meine Idee ist, dass der PC die Daten anfordert und pro Anforderung eine 
Zeile aus der Logdatei übermittelt bekommt, die der PC dann bestätigt. 
Der Mikrocontroller soll nach der Bestätigung die Zeile löschen.

Problem ist nun: Um am Anfang der Datei eine Zeile zu löschen, müsste 
ich die Datei ja jedes mal komplett neu schreiben, oder?

Gruß,
Chris

von Martin (Gast)


Lesenswert?

ja.

von Chris (Gast)


Lesenswert?

Hm, das ist schlecht. Welche Alternativen gibt es denn?

Eventuell könnte ich in einer Variable speichern lassen, welche Zeile 
als letztes ausgelesen wurde und die komplette Datei löschen / leeren, 
sobald alle Zeilen übertragen wurden. Das würde zumindest die 
Schreibzugriffe reduzieren.

In der Regel wird beim Abruf durch den PC die ganze Datei gelesen. Im 
Fehlerfall (Verbindung weg, PC abgestürzt usw.) würde der "Zeilenzeiger" 
halt stehen bleiben, so dass beim nächsten Abruf einfach fortgesetzt 
werden würde. Nur, wenn der Mikrocontroller resettet würde, wäre der 
Zeilenzeiger verloren und beim nächsten Lesen würde erneut die ganze 
Datei gelesen werden. Das ist aber auch kein Beinbruch.

=> Lösung gefunden:)
Oder hat noch jemand eine bessere Idee?

von _elko_ (Gast)


Lesenswert?

Bau dir nen Ringpuffer?

von Karl H. (kbuchegg)


Lesenswert?

Chris schrieb:
> Hm, das ist schlecht. Welche Alternativen gibt es denn?

Du könntest zb am Anfang jeder Zeile ein Sonderzeichen vorsehen, welches 
den Status der Zeile darstellt.
 '+' bedeutet: Zeile wurde noch nicht abgeholt
 '#' bedeutet: Zeile wurde bereits abgeholt und ist als gelöscht zu
               betrachten.

Ab und an wird dann die Datei reorganisiert, indem bereits gelöschte 
Datensätze beim Umkopieren in ein neues File nicht mitgenommen werden.

Ein bereits in einer Datei vorhandenes Zeichen durch ein anderes zu 
ersetzen, stellt auch in Textdateien kein Problem dar.

von Stephan (Gast)


Lesenswert?

Du könntest auch z.B.

- ohne Dateisystem anstatt einer Zeile jeweils einen Block schreiben
- den Blöcken "Seriennummern" geben und laufend hochzählen
- wenn die karte voll ist vorne wieder anfangen
- den PC eine Startseriennumer beim Anfordern senden lassen
- oder eine "Sammelquittung" für mehrere Datensätze schicken lassen und 
im EEprom speichern
...

Bei jeder Zeile wieder auf die Karte zu schreiben halte ich für 
überflüssig.

von cskulkw (Gast)


Lesenswert?

Jede Messwertezeile als eigene Datei speichern?

Die kann dann individuell gelöscht werden.

von Matthias (Gast)


Lesenswert?

Was spricht dagegen, jedemal die ganze Datei an den PC zu übertragen und
dann nach Quittierung die ganze Datei zu löschen?
So ein "Einzelgefrickel" würde ich prinzipiell meiden.
Das verursacht nur Overhead und macht die Sache unnötig kompliziert!

Wie groß kann die Datei maximal werden?
(Die soll hoffentlich nicht die ganze SD-Karte ausfüllen ;-) )

Wird während des Übertragens zum PC was in die Datei geschrieben?

von Chris (Gast)


Lesenswert?

Hi!
Danke für die vielen Antworten!

Im Moment landen in 4-Minuten-Intervallen rund 500 Bytes (!) in der 
Datei, + Zeilenumbruch). Das lässt sich aber sehr stark reduzieren da 
die Ausgabe im Moment Klartext ist und für die Ausgabe mit Excel gedacht 
ist. Am Ende werden es nur noch 150 Bytes sein, und selbst das kann 
reduziert werden wenn man nicht alles in Zahlen wandelt sondern das Byte 
direkt schreibt.

Problem ist, dass das Auslesen der Karte recht lange dauern kann wenn 
sich dort z.B. ein halbes Jahr lang was angesammelt hat. Daher die 
Überlegung mit der häufigen Bestätigung. Dass das natürlich auch wieder 
stark bremst, ist klar.

Die Datei kann "unendlich" groß werden, die SD-Karte hat aber nur 32MB, 
was reichen sollte. Eine Abfrage, ob der Speicher voll ist, steht auf 
der Todo-Liste.

Während des Lesens muss außer ein paar ISRs nichts anders gemacht 
werden, es wird definitiv nicht auf die Karte geschrieben.

von Lukas T. (tapy)


Lesenswert?

Schreib' dir doch einfach mehrere Dateien mit bspw. je 10 Zeilen. Dann 
kannst du jeweils eine der 10 Zeilen übertragen und als übertragen 
markieren und dann, wenn du alle zehn einer Datei übertragen hast, 
löschst du die Datei.

von Hans-Georg L. (h-g-l)


Lesenswert?

Wenn die Datei nur beim PC Absturz nicht vollständig gelesen wird und 
während dieser Zeit kein Schreiben vom MC erfolgt, dann würde ich dem PC 
beim Lesen ein Timout verpassen.

Ist das Timeout überschritten wird die Datei reorganisiert = gelesenes 
gelöscht. Sonst wird die Datei nach dem vollständigen Lesen gelöscht.

Wenn auch der MC Absturz abgefangen werden soll wirst du um ein 
Timestamp für jeden Datensatz im File und Überprüfung auf doppel 
Übertragung durch den PC nicht herum kommen.

HG

von Stephan (Gast)


Lesenswert?

Eine Datei und laufend anhängen, damit verbunden auch die FAT laufend 
aktualisieren und beim auslesen noch vorne abschneiden wollen ist 
definitiv Käse.

Eine einzelne Datei, alle 4 Minuten erweitert und das ganze über ein 
halbes Jahr sind schon mal ca. 65.000 Schreibzugriffe auf den 
FAT-Eintrag. Das würd ich so niemals machen. Wear-Leveling hat auch 
irgendwann Grenzen.
Mindestens jeden Tag/Woche gesondert, bringt aber Verwaltungsaufwand mit 
sich.

Wie schon geschrieben:
Geh auf die rohen Blocks. Je Datensatz ein Block mit laufender 
Seriennummer. Und dann quasi als Ringpuffer.
Die Karte einmalig mit genullten Blocks initialisieren.
Bei jedem Reset der Schaltung die letzte Seriennummer mittels 
"Halbierungstaktik" ermitteln (der letzte geschriebene Block ist der mit 
einer höheren Seriennummer als der darauffolgende).
Den Startdatensatz fürs Auslesen je nach Gusto im EEprom speichern oder 
durch die Anwendung verwalten. Quittierung nicht nach jedem Datensatz, 
sondern vielleicht alle 500 (Schreibzugriffe EEprom).

Das wird hinsichtlich Speicherbedarf und Datensicherheit das einfachste 
werden und es hat immer noch fast ein halbes Jahr auf den 32MB Platz.

von Ingo W. (Gast)


Lesenswert?

Chris schrieb:

> Im Moment landen in 4-Minuten-Intervallen rund 500 Bytes (!) in der
> Datei, + Zeilenumbruch).

Mir schwebt für die nächste Zukunft in einem Projekt etwas ähnliches 
vor.
Da werde ich es wohl so machen, das die Datei einmal mit fester Größe 
erstellt (genullt?) wird, die dann als Ringpuffer mit 2 Zeigern (für 
lesen und schreiben) genutzt wird. Dann wird außer den Datensektoren 
nichts mehr beschrieben. Bei 500 Bytes würde ich sogar immer ganze 
Sektoren nutzen, das vereinfacht die Verwaltung noch einmal und hat noch 
den Vorteil, das bei einem Überlauf, die ältesten Daten überschrieben 
werden. Einen Zeitstempel sollten sie ohnehin haben. Einzige Frage wäre 
jetzt, wo die beiden Zeiger (persistent gegen Ausfälle) liegen, auf 
einem Sektor der Karte wäre ja auch tödlich. In meinem Prj werde ich 
evtl eine batteriegepufferte RTC haben, die dort befindlichen RAM-Zellen 
sind der fast ideale Platz dafür. Wenn normaler RAM genutzt wird, der 
beim Init genullt wird, würde dann immer mit leerem Puffer begonnen 
werden.
mfG ingo

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.