Hallo Zusammen,
ich werfe hier mal eine eher algorithmische Frage in die Runde:
Ich habe mir mit einem ESP32, L76X, ePaper und einem SD card Modul einen
GPS-Tracker gebastelt bzw. ich bin dabei.
Ist alles noch early stage, PCB ist auch noch in Arbeit, aber soweit
funktioniert er erstmal grundsätzlich und speichert brav die gewünschten
GPS-Daten auf der SD Karte als CSV.
So weit so gut. Nun würde ich die Daten aber gerne auch als GPX-Datei
speichern um sie - später auf dem Rechner - direkt in einer Karte zu
zeigen. Für die die GPX nicht kennen, das Dateiformat ist im Prinzip wie
eine XML-Datei gestrickt.
Ein vereinfachtes Beispiel mit 2 Trackpoints:
1
<gpx>
2
<trk>
3
<trkpt lat=\"0.0000"\" lon=\"0.00000\">" </trkpt>
4
<trkpt lat=\"1.0000"\" lon=\"2.00000\">" </trkpt>
5
</trk>
6
</gpx>
Nun ist es so, dass der Tracker einfach logged sobald er Strom bekommt
(USB-Powerbank). Es gibt keinen Schalter oder Knopf zum Starten und/oder
Stoppen. Keep it simple eben.
Das Problem ist nun, dass die Datei - um gültig zu sein - immer die
entsprechenden "Closing-Tags" braucht, also im o.g. Beispiel die letzten
2 Zeilen. Die muss man aber erst anhängen, wenn der letzte Trackpoint
eingefügt und die Datei 'fertig' ist.
Das Ende einer Datei wird aber nie geschrieben, wenn man einfach den
Stecker zieht. Die trkpt-Zeilen werden einfach in unendlichen Loop
zeileweise angehängt.
---
Das Problem sollte eigentlich nicht neu sein. Insbesondere da es auf
alle XLM-strukturierten Dateiformate zutrifft. Daher hoffe ich, dass ich
einfach noch etwas übersehe und hier vielleicht jemand eine Idee hat.
Bisherige Möglichkeiten die ich sehe:
1. CSV auf dem Tracker und GPX später daraus mit einem Script erstellen
(mit Python simple) => Doof, weil ich auf der SDcard direkt GPX zum
anschauen haben will.
2. Bei jedem Loop, die existierende Datei ohne die Closing-Tags in eine
Temp-Datei kopieren, den nächsten trkpt anhängen, und mit Closing-Tag
versehen wieder zurück kopieren. => Wird mühsam wenn die Datei grösser
wird (zB mehrere Monate in einer Datei), auch eine Speicherfrage
irgendwann. Zudem viel Geschreibe auf der SD im Hinblick auf die
Lebensdauer. ABER, damit könnte man jeder Zeit den Stecker ziehen und
die Datei sollte i.O, sein.
3. Immer nur den den Header und die trkpt schreiben, ohne Closing-Tag,
und dann bei jedem Boot bei der "vorherigen" oder "letzten GPX-Datei"
die Closing-Tags anhängen. => Minimaler Aufwand da man einfach wie bei
CSV immer die Zeile anhängt, aber die letzte Datei auf der SDcard wäre
immer "korrupt" - bis zum nächsten Boot. Irgendwie auch doof.
4. Oder eben einen Knopf dran und damit "Close-File" signalisieren bevor
man den Stecker zieht. => Rettet einen Fall von Powerloss auch nicht.
Sehe ich eher als Wörkaround.
Ich habe nun schon eine Weile rumgeschaut, aber so die "beste Lösung"
suche ich noch. Fallen noch jemandem andere denkbare Optionen ein?
Bin für jeden Input dankbar. Wie löst man sowas???
Gruss, Patric
Eine Möglichkeit:
Nach dem jeweils ersten Anlegen der Datei am Ende etliche kByte Spaces
anhängen, gefolgt vom XML-Dateiende.
Dann werden die folgenden Zeilen immer auf die Spaces geschrieben, wenn
die letzte Zeile dann keinen Platz mehr hätte, wird diese dennoch
geschrieben und wieder etliche kB Spaces angehangen und ein neuer
Schluß.
Sinnvoll ist hierbei auf die Blockgröße des Dateisystems zu achten.
Weiterhin sinnvoll wäre es, nicht jede Zeile gleich zu schreiben,
sondern 10 oder 20 Zeilen in einem Rutsch, weniger Zeilen nur, wenn seit
einer gewissen Zeit keine neuen Zeilen dazukommen. Klar steigt hierbei
das Risiko, die letzten Zeilen u.U. zu verlieren, die Lebensdauer eine
Speicherkarte dankt es aber.
Hallo Nick, danke für Deinen Input.
Wenn ich dich richtig verstehe, dann meinst Du man soll zum Beispiel
sowas hier machen:
1
<gpx>
2
<trk>
3
<trkpt lat=\"0.0000"\" lon=\"0.00000\">" </trkpt>
4
5
... hier ganz viele Leerzeilen ...
6
7
</trk>
8
</gpx>
und dann die nächsten trkpt-Zeilen in die "Leerzeilen schreiben",...
Von der Logik bin ich bei Dir, aber das funktioniert mMn nicht mit einem
SD card Modul. Da fehlen die Datei-Informationen zu. Sprich, man kann
nicht ohne eine Komplettkopie der Datei etwas an Zeile X einfügen.
Und mit einer Kopie wären wir wieder bei o.g. Option 2.
Zumindest ist das soweit mein Verständnis der Problematik.
Lasse mich aber natürlich gerne eines Besseren belehren.
Gruss
Brownout-Detection und ausreichend großen Pufferelko, um beim
Stromausfall die Datei in einem sauberen Zustand zu hinterlassen.
Wenn beim ESP32 das WLAN nicht aktiv ist (wozu sollte das bei einem
GPS-Tracker auch gut sein?), sollte man den Stromverbrauch davon ja
irgendwie in Grenzen halten können. Dazu kommt der Strombedarf der
SD-Karte.
Rüdiger B. schrieb:> Die ESP32 gibt es auch mit Batterie Lade und Überwachungchip, z.B.> LilyGo t-Beam.
Danke Rüdiger.
Ich weiss. Habe sogar USB-Lademodule und kleine LiPos hier, aber das ist
nicht die Idee.
PowerOn => Tracken/Loggen
PowerOff => Aus
Aber ich gebe zu, Dein Vorschlag würde es immerhin ermöglichen die
Spannung zu monitoren und dann "kurz vor Ende" die Closing-Tags zu
schreiben. Andererseits, dann braucht es auch einen Knopf, denn mit
einer internen Batterie logged der ja weiter bis die Leer ist, auch wenn
ich die Powerbank abziehe.
Ich sehe das mal als eine "extended Version" von o.g. Option 4 mit dem
Knopf. ;)
Es gibt noch die Strategie "Safe-on-powerloss". Elko einbauen der so
groß ist, dass er so viel Zeit überbrücken kann, wie der Controller
braucht, den gezogenen Stecker zu detektieren und die Abschlusszeile zu
schreiben.
Du darfst einer SD Karte eh nicht einfach die Stromversorgung kappen,
während sie aktiv ist. Das Risiko für Datenverlust wäre enorm hoch. Du
brauchst einen Pufferakku, so eine Art USV, um kontrolliert runter
fahren zu können.
Harald K. schrieb:> Brownout-Detection und ausreichend großen Pufferelko, um beim> Stromausfall die Datei in einem sauberen Zustand zu hinterlassen.>> Wenn beim ESP32 das WLAN nicht aktiv ist (wozu sollte das bei einem> GPS-Tracker auch gut sein?), sollte man den Stromverbrauch davon ja> irgendwie in Grenzen halten können. Dazu kommt der Strombedarf der> SD-Karte.
Harald, Danke! Das klingt nach einer Idee.
Eine Art mini-USV nur zum Dateiabschluss wenn Strom weg.
Momentan benutze ich weder Bluetooth not Wifi (aber wer weiss).
Ich vermute momentan wird das GPS-Modul wohl am meisten weglutschen.
Generell finde ich Deinen Vorschlag - zumindest ist der Theorie - nicht
uninteressant. Schauen ob Spannungsversorgung weg ist, und dann zusehen,
dass man in dem Fall noch genug Energie (=Zeit) hat die Datei zu
schliessen. Genau das ist ja alles was es braucht.
Ist "Brownout-Detection" einen Fachbegriff dafür?? Noch nie gehört. Ich
schau mal...
P. Z. schrieb:> mit einer internen Batterie logged der ja weiter bis die Leer ist, auch> wenn ich die Powerbank abziehe.
Du kannst die externe Spannungsversorgung überwachen und bei einem
Ausfall sauber in den Deep-Sleep Midus herunterfahren
Uwe schrieb:> Es gibt noch die Strategie "Safe-on-powerloss". Elko einbauen der so> groß ist, dass er so viel Zeit überbrücken kann, wie der Controller> braucht, den gezogenen Stecker zu detektieren und die Abschlusszeile zu> schreiben.
Hey Uwe, Danke.
Damit bist Du auf der selben Spur wie Harald. ;)
Wenn das schon von 2 Quellen kommt, dann muss ich mir das wohl man
genauer anschauen. Die Idee an sich finde ich in der Theorie jedenfalls
überzeugend.
Irgendwelche lesenswerte Empfehlungen zu so einer Schaltung? Hier oder
im Netz?
P. Z. schrieb:> Ist "Brownout-Detection" einen Fachbegriff dafür??
Nein. Die löst einen Reset aus, wenn die Stromversorgung zu niedrig ist
oder kurz einbricht. Du willst aber sauber/kontrolliert herunter fahren.
Sherlock 🕵🏽♂️ schrieb:> P. Z. schrieb:>> mit einer internen Batterie logged der ja weiter bis die Leer ist, auch>> wenn ich die Powerbank abziehe.>> Du kannst die externe Spannungsversorgung überwachen und bei einem> Ausfall sauber in den Deep-Sleep Midus herunterfahren
Ok. Aber dann bleibt die Datei doch trotzdem "korrupt"...
Sherlock 🕵🏽♂️ schrieb:> Du darfst einer SD Karte eh nicht einfach die Stromversorgung kappen,> während sie aktiv ist. Das Risiko für Datenverlust wäre enorm hoch. Du> brauchst einen Pufferakku, so eine Art USV, um kontrolliert runter> fahren zu können.
Ja, da gebe ich Dir Recht. In der Theorie hat man das Risiko.
Aber ich logge alle 15 Sekunden, und bisher habe ich noch nie (wirklich
noch NIE) den kurzen Moment getroffen wo gerade die eine Zeile angehängt
wird. Habs noch nicht gemessen, aber ich vermute das Fenster wird im
Bereich von ms sein.
klopf auf Holz
Sherlock 🕵🏽♂️ schrieb:> P. Z. schrieb:>> Aber dann bleibt die Datei doch trotzdem "korrupt"...>> Sauber herunter fahren beinhaltet, die Datei abzuschließen.
Ok, dann wären wir doch aber auch wieder bei dem Elko als mini-USV,
oder?
P. Z. schrieb:> In der Theorie hat man das Risiko.
Auch in der Praxis.
Läufst du bei rot über die Ampel, so lange du Glück hast?
Geräte die nur mit Glück funktionieren, machen irgendwann übel Ärger.
Sherlock 🕵🏽♂️ schrieb:> P. Z. schrieb:>> In der Theorie hat man das Risiko.>> Auch in der Praxis.>> Läufst du bei rot über die Ampel, so lange du Glück hast?>> Geräte die nur mit Glück funktionieren, machen irgendwann übel Ärger.
Ja, ich gebe zu: Robustiness habe ich bisher noch nicht berücksichtigt.
Hatte offensichtlich die letzten Jahre dann immer sehr viel Glück.
Bisher ist mein Tracker immer gut über die rote Ampel gekommen. ;)
Habe bis vor einigen Monaten noch meine erste Version auf Basis eines
RPi Zero genutzt um beim Segeln zu tracken. Ja, mit Linux ist nochmal
was anderes, aber auch da war es so eingerichtet, dass man einfach Strom
dran macht, Linux bootet und anfängt zu loggen. Und aus ging einfach mit
"Strom weg". Mag Linux auch nicht unbedingt, aber das OS hat das immer
gut weggesteckt.
Anyway. Du hast schon Recht. Und ich finde die Idee mit der Elko-USV zum
sauberen Shutdown durchaus sympathisch. Ich hoffe ich finde da was für
den Anfang.
Sherlock 🕵🏽♂️ schrieb:> Die löst einen Reset aus, wenn die Stromversorgung zu niedrig ist
Das ist eine Möglichkeit davon, aber es gibt auch die Möglichkeit, einen
Interrupt auszulösen. Der ESP32 kann das. Bei dem kann auch der
Spannungspegel konfiguriert werden.
Harald K. schrieb:> Sherlock 🕵🏽♂️ schrieb:>> Die löst einen Reset aus, wenn die Stromversorgung zu niedrig ist>> Das ist eine Möglichkeit davon, aber es gibt auch die Möglichkeit, einen> Interrupt auszulösen. Der ESP32 kann das. Bei dem kann auch der> Spannungspegel konfiguriert werden.
Ja, einen IRQ zum Spannungsüberwachung nutzen klingt logisch. Irgendwas
muss man ja eh zum Triggern des "sauberen Shutdown" nutzen.
Ich muss mir generell erstmal einen überblick verschaffen wie der Elko
dimensioniert sein muss. Ich hab hier noch ein paar Monster-Elkos, aber
die sind eher aus dem Bereich >50V, also eher ungeeignet.
P. Z. schrieb:> Ich muss mir generell erstmal einen überblick verschaffen wie der Elko> dimensioniert sein muss.
Stromaufnahme ohne GPS-Empfänger beim Schreiben auf die SD-Karte messen.
Harald K. schrieb:> P. Z. schrieb:>> Ich muss mir generell erstmal einen überblick verschaffen wie der Elko>> dimensioniert sein muss.>> Stromaufnahme ohne GPS-Empfänger beim Schreiben auf die SD-Karte messen.
Ja, leichter gesagt als getan. ;)
Für den Strombereich fehlt mir das Equipment. Gabs da nicht mal so
USB-Module zum Zwischenstecken?
P. Z. schrieb:> Gabs da nicht mal so> USB-Module zum Zwischenstecken?
Die dürften weder genau genug sein noch die erforderliche zeitliche
Auflösung haben.
Ausreichend kleiner Serienwiderstand (Shunt) und mit Oszilloskop
Spannungsverlauf darüber messen.
Vielleicht hat ja einer der ein Oszilloskop besizenden Mitforisten einen
ESP32 mitsamt einer SD-Karte im Betrieb und mag hier helfend
einspringen?
Ich schlage Soft-Power On und Off vor, wie beim Telefon. Also ein
Taster, der das Gerät ein- und ausschaltet. Beim Ausschalten alles
abschliessen, SD-Karte abmelden und dann in den Powerdown gehen.
Wie wichtig sind die GPX Datensätze, ist es verschmerzbar, wenn z.B.
immer die letzten 5 Datensätze nicht aufgezeichnet sind aber trotzdem
die Datei richtig abgeschlossen ist?
Mein Gesanke (noch nicht vollständig durchdacht) :
Du schreibst mit jedem Datensatz auch das Dateiende. Mit dem nächsten
Datensatz überschreibst du das Dateiende und hängst es neu an. Ich hoffe
das ist verständlich wie ich das meine. Oder dieses Vorgehen erweitern,
so dass immer ein ganzer Sektor / Cluster auf die SD-Karte geschrieben
wird. Es wird aber immer das Dateiende geschrieben und mit dem nächsten
Schreibvorgang überschrieben und neu angehängt. Der Spannungswegfall
müsste trotzdem dedektiert werden und ein gerade laufender
Schreibvorgang beendet werden.
Matthias S. schrieb:> Ich schlage Soft-Power On und Off vor, wie beim Telefon. Also ein> Taster, der das Gerät ein- und ausschaltet. Beim Ausschalten alles> abschliessen, SD-Karte abmelden und dann in den Powerdown gehen.
Hallo Matthias,
stimmt. Das wäre noch eine Variante mit dem Knopf.
Das liesse sich auch relativ einfach umsetzen ohne Elko-USV. Dann würde
es wirklich nur noch im Falle einen "unerwarteten Powerloss" (i.e.
Powerbank leer) zu korrupten Dateien kommen.
Also die Garmins von vor 20 Jahren konnten sowas schon problemlos. Denen
konnte man im laufenden Betrieb die Batterien rausziehen, trotzdem war
der GPX-Track intakt.
Meine Vermutung: sie haben immer eine syntaktisch korrekte XML-Datei
geschrieben auf die Karte. Wenn ein Datensatz angehängt werden sollte,
sind sie die paar Bytes der letzten schließenden Klammern zurück
gegangen und haben ab dort neu geschrieben, dann aber wieder mit dem
kompletten Ende der Datei.
P. Z. schrieb:> Das Problem sollte eigentlich nicht neu sein. Insbesondere da es auf> alle XLM-strukturierten Dateiformate zutrifft. Daher hoffe ich, dass ich> einfach noch etwas übersehe und hier vielleicht jemand eine Idee hat.
Ist es auch nicht.
Schreibe hinter einen trkpt-Record immer den Abschluss für trk und gpx.
Bevor du den nächsten trkpt-Record schreibt, positionierst du den
Schreib-Pointer vor das Closing-Tag "</trk>".
Obelix X. schrieb:> Wie wichtig sind die GPX Datensätze, ist es verschmerzbar, wenn z.B.> immer die letzten 5 Datensätze nicht aufgezeichnet sind aber trotzdem> die Datei richtig abgeschlossen ist?
Stillos
Rainer W. schrieb:> P. Z. schrieb:>> Das Problem sollte eigentlich nicht neu sein. Insbesondere da es auf>> alle XLM-strukturierten Dateiformate zutrifft. Daher hoffe ich, dass ich>> einfach noch etwas übersehe und hier vielleicht jemand eine Idee hat.>> Ist es auch nicht.> Schreibe hinter einen trkpt-Record immer den Abschluss für trk und gpx.> Bevor du den nächsten trkpt-Record schreibt, positionierst du den> Schreib-Pointer vor das Closing-Tag "</trk>".
Unter Linux, mit den entsprechenden Tools ist das klar.
Aber mit nem ESP32 auf ner SD card geht "Einfügen in/nach Zeile X" mMn
nur indem man die bestehende Datei kopiert. Siehe oben Option 2.
Jörg W. schrieb:> Also die Garmins von vor 20 Jahren konnten sowas schon problemlos. Denen> konnte man im laufenden Betrieb die Batterien rausziehen, trotzdem war> der GPX-Track intakt.>> Meine Vermutung: sie haben immer eine syntaktisch korrekte XML-Datei> geschrieben auf die Karte. Wenn ein Datensatz angehängt werden sollte,> sind sie die paar Bytes der letzten schließenden Klammern zurück> gegangen und haben ab dort neu geschrieben, dann aber wieder mit dem> kompletten Ende der Datei.
Ja, logisch ist das einfach zu realisieren in dem man die Datei beim
"anhängen" eines neuen Datenpunktes stets kopiert. Rein logisch lässt
sich das lösen. Aber eben zu Lasten der Schreibzyklen der SD card.
Den Elko-Mini-USV-Ansatz finde ich schon attraktiv. Aber ist auch
deutlich mehr Aufwand. Ähnliches liesse sich sicherlich auch mit nem
LiPo realisieren...
Eventuell sollte ich auch einfach mal überschlagen wie lange man eine SD
card so malträtieren muss, dass sie die Grätsche macht. Alle paar Jahre
mal ne neue SD Card wäre dann auch nicht so tragisch.
P. Z. schrieb:> Aber mit nem ESP32 auf ner SD card geht "Einfügen in/nach Zeile X"
Welches Betriebssystem verwaltet Dateien nach Zeilennummer?
Schreibpointer zeigen auf Byte Positionen. Die Datei muss dazu
gewöhnlich als Binärdatei mit random Zugriff geöffnet sein.
Rüdiger B. schrieb:> Zum Dateiende und x Bytes zurück geht problemlos.
Beziehungsweise nach dem Schreiben der letzten "richtigen" Daten ein
ftell(), dann die schließenden Klammern schreiben, und bei den nächsten
Daten wieder zum vorigen Punkt zurück.
P. Z. schrieb:> Ja, logisch ist das einfach zu realisieren in dem man die Datei beim> "anhängen" eines neuen Datenpunktes stets kopiert.
Das werden die Garmins ganz gewiss nicht gemacht haben. Schon deshalb,
weil dann ja bei einem langen Track die SD-Karte riskiert hätte voll zu
sein. Damals zählten SD-Karten noch nach 1 oder 2 GB – für die 4er
Karten brauchte man schon einen Firmwareupgrade.
Jörg W. schrieb:> Damals zählten SD-Karten noch nach 1 oder 2 GB – für die 4er> Karten brauchte man schon einen Firmwareupgrade.
Bist du sicher, dass sie nicht nach 128ern MB gezählt wurden?
Selbst 128 MB reichen bei sekündlicher Aufzeichnung der Position für um
die 30 Tage.
Wieviel RAM hast du denn?
Hier die nächste Idee: Im RAM eine komplette Kopie der GPX Datei halten
und per Blockwrite die aktuelle Kopie auf die Karte schreiben.
Rainer W. schrieb:> Jörg W. schrieb:>> Damals zählten SD-Karten noch nach 1 oder 2 GB – für die 4er>> Karten brauchte man schon einen Firmwareupgrade.> Bist du sicher, dass sie nicht nach 128ern MB gezählt wurden?
Ja, denn schließlich war ja das Kartenmaterial mit drauf. Die 2 GB
wurden dann schon ziemlich schnell zu knapp, sodass man die
Firmwareerweiterung benötigte für 4 GB (eigentlich ein Bugfix, weil
davor offenbar beim Einlegen einer 4er Karte eine negative Zahl als
Größe ermittelt worden ist). Ziemlich schnell wuchsen die OSM-Daten dann
volumenmäßig so weit an, dass man für diese älteren Garmins abgespeckte
OSM-Daten produziert hat, die noch in 4 GB passten.
Trotzdem hätte sich in dieser Zeit natürlich keiner erlaubt, ganze
Dateien auf einer SD-Karte umzukopieren, nur um einen Datensatz
anzuhängen.
Rüdiger B. schrieb:> Auch der ESP32 hat in der FS.H die Seek Funktion. Zum Dateiende und x> Bytes zurück geht problemlos.
Ja, sowas hatte ich auch gehofft, aber bisher hat meine Recherche
ergeben, dass man immer Kopieren muss.
Hast Du ein Code-Snipped oder eine Referenz wo sowas gemacht wird?
P. Z. schrieb:> ich logge alle 15 SekundenP. Z. schrieb:> ESP32-C6FH4 as the main chip, with RISC-V 32-bit single-core processor,> support up to 160 MHz, and built-in 320KB ROM, 512KB HP SRAM
Wenn wirklich nur alle 15 Sekunden ein Wegpunkt geschrieben wird, passen
die Daten¹ von knapp 3 Tagen bis 1 Woche ins RAM. Da müsste es doch
möglich sein, die komplette Datei in einem Stück zu schreiben. Oder wie
lange muss man ununterbrochen loggen? Die Lebensdauer der SD-Karte würde
sich vervielfachen.
Oder kann man GPX-Dateien nachträglich aneinander hängen? Dann könnte
man mehrere kleinere Dateien jeweils am Stück schreiben.
1) Länge und Breite passen sehr gut in 32 Bit, dazu evt. ein 32-Bit
Zeitstempel plus ganz vielleicht noch Statusbits, Akkuspannung usw.
Bauform B. schrieb:> Oder kann man GPX-Dateien nachträglich aneinander hängen? Dann könnte> man mehrere kleinere Dateien jeweils am Stück schreiben.
Natürlich kann man das (Datenformat s.o.)
P. Z. schrieb:> Ein vereinfachtes Beispiel mit 2 Trackpoints:
Nur der TO möchte die Daten direkt als GPX lesen können, ohne
irgendetwas aneinanderhängen zu müssen:
P. Z. schrieb:> ... später daraus mit einem Script erstellen (mit Python simple) => Doof,> weil ich auf der SDcard direkt GPX zum anschauen haben will.
P. Z. schrieb:> Ja, sowas hatte ich auch gehofft, aber bisher hat meine Recherche> ergeben, dass man immer Kopieren muss.
ftell() und fseek() gibt es schon seit Äonen in C. Wo hast du denn
recherchiert? Relative Suche zum Dateiende kann auf manchen Plattformen
ggf. nicht funktionieren (wenn die Plattform nämlich im Textmode aus
jedem "\n" noch ein CR-LF machen möchte), aber absolute Suche (also
SEEK_SET zum Dateianfang) sollte überall machbar sein. Daher der
Hinweis, sich die Position, bei der man im nächsten Schritt
weiterschreiben möchte, mit ftell() zu merken.
Rainer W. schrieb:> P. Z. schrieb:>> Hast Du ein Code-Snipped oder eine Referenz wo sowas gemacht wird?>> https://www.tutorialspoint.com/c_standard_library/c_function_fseek.htm> https://esp32.com/viewtopic.php?t=10439>> Oder welche Sprache hättest du gerne?
Danke für den Schubs! Da haben wir das nötige Buzzword!
Correct me if I'm wrong:
fseek() ist scheinbar was ich suche, allerdings für plain C.
Ich benutze die Arduino IDE für die ESP-Programmierung, daher habe ich
die entsprechenden libs SD.h und SPI.h eingebunden.
Momentan ist mein Denkansatz folgender (PseudoCode):
1
#define CLOSING_TAG_BYTES 15
2
3
File file = fs.open(gpxDateiName, FILE_APPEND);
4
file.seek(file.size()-CLOSING_TAG_BYTES);
5
file.print(trackpointDatenMitClosingTags);
Also, CLOSING_TAG_BYTES muss der Anzahl Bytes entsprechen die die
Closing-Tags verbrauchen (15 ist hier nur als Beispiel zu verstehen).
Dann mit file.seek() vom Ende zurück zählen um den Pointer an die
richtige Stelle zu brinegn, und dann an der Stelle den nächsten
Trackpoint samt ALLER Closing-Tags schreiben. Man überschreibt dann
jedes mal einfach die Closing-Tags.
Ich muss das jetzt mal ausprobieren ob das auch in der Praxis so hinhaut
wie ich das im Kopf hab.
Bauform B. schrieb:> P. Z. schrieb:>> ich logge alle 15 Sekunden>> P. Z. schrieb:>> ESP32-C6FH4 as the main chip, with RISC-V 32-bit single-core processor,>> support up to 160 MHz, and built-in 320KB ROM, 512KB HP SRAM>> Wenn wirklich nur alle 15 Sekunden ein Wegpunkt geschrieben wird, passen> die Daten¹ von knapp 3 Tagen bis 1 Woche ins RAM. Da müsste es doch> möglich sein, die komplette Datei in einem Stück zu schreiben. Oder wie> lange muss man ununterbrochen loggen? Die Lebensdauer der SD-Karte würde> sich vervielfachen.>> Oder kann man GPX-Dateien nachträglich aneinander hängen? Dann könnte> man mehrere kleinere Dateien jeweils am Stück schreiben.>>> 1) Länge und Breite passen sehr gut in 32 Bit, dazu evt. ein 32-Bit> Zeitstempel plus ganz vielleicht noch Statusbits, Akkuspannung usw.
Danke für den Denkanstoss. Unter der Annahme, es gäbe keinen
unerwarteten Powerloss wäre das definitiv der beste Weg. Insbesondere
wenn man auf die SD Karte achten will.
Bei Powerloss hat man dann aber eben auch maximalen Datenverlust wenn
noch alles im RAM war.
Dateien stückeln hatte ich ehrlicherweise auch schon dran gedacht. Geht
auch tatsächlich problemlos was das Loggen angeht. Aber dann hab ich
eben keine GPX-Datei mit dem ganzen Track auf der SD card liegen.
(Soll später entweder einfach in ein Tablet oder PC, oder sogar Cloud
mit GPX-Viewer.)
Sprich, da wäre auch wieder nachträgliches Skripten nötig.
Jörg W. schrieb:> P. Z. schrieb:>> Ja, sowas hatte ich auch gehofft, aber bisher hat meine Recherche>> ergeben, dass man immer Kopieren muss.>> ftell() und fseek() gibt es schon seit Äonen in C. Wo hast du denn> recherchiert? Relative Suche zum Dateiende kann auf manchen Plattformen> ggf. nicht funktionieren (wenn die Plattform nämlich im Textmode aus> jedem "\n" noch ein CR-LF machen möchte), aber absolute Suche (also> SEEK_SET zum Dateianfang) sollte überall machbar sein. Daher der> Hinweis, sich die Position, bei der man im nächsten Schritt> weiterschreiben möchte, mit ftell() zu merken.
Bin scheinbar in den falschen Ecken des Interwebs gelandet. Zugegeben,
hatte immer nach einem ESP- oder Arduino IDE/lib-Zusammenhang geschaut.
Ist schon über ne Dekade her, dass ich mal was seriös mit C/C++ gemacht
habe. (Arduino zähle ich da unfairerweise nicht wirklich dazu.) Aber als
ich fseek() las da hat was geklingelt. Muss jetzt nur mal zusehen wie
das in der entsprechenden SD-library implementiert ist, die ist wohl
nicht ganz so mächtig wie das was man auf anderen Plattformen zur
Verfügung hat. Ich nehme an ftell() ist dann ein INT, da wo der Pointer
grade steht, richtig? Wäre vielleicht sogar besser als mein "Bytes
zurück zählen"...
P. Z. schrieb:> Ich nehme an ftell() ist dann ein INT, da wo der Pointer grade steht,> richtig?
Offiziell ist es (aus eher historischen Gründen) ein long, denn auch
fseek() nimmt einen long für den Offset – in der Zeit, in der C
entstanden ist, konnte man mit einem long halt mehr an Dateigröße
abdecken als mit einem int, und vorzeichenbehaftet muss es sein, weil
fseek() ja auch vom Dateiende mit negativen Werten hantieren kann.
Klasse! Ich liebe dieses Forum!
Danke für die Denkanstösse, Unterstützung und so weiter. Auf dieses
Forum ist Verlass. :)
Ich mach mich dann mal ran zu schauen wie weit ich damit komme.
EDIT/UPDATE:
So, an der Stelle noch eine kurze aber essentielle Info, da ich daran
gerade fast verzweifelt bin:
Beispiel: Datei wird mit 5 Zeichen (ABCDE) initialisiert.
Dann:
1
File file = fs.open(gpxDateiName, FILE_APPEND);
2
file.seek(2);
3
file.print("X");
aber das X wird immer am Ende angehängt. Nach file.seek(2) kann man
sogar file.position() aufrufen und via Serial ausgeben (ist auch 2).
Aber, file.print() schreibt immer ans Ende. Man bekommt: ABCDEX
Nun, Lösung ist statt FILE_APPEND, die Datei mit FILE_WRITE öffnen.
Also:
1
File file = fs.open(gpxDateiName, FILE_WRITE);
2
file.seek(2);
3
file.print("X");
Dann bekommt man: ABX
Das Ende wird also scheinbar gestripped, aber so kann man scheinbar an
einer definierten Position schreiben. Was ja gewünscht war.
Wollte dieses wichtige Detail, FILE_WRITE statt FILE_APPEND mit seek()
verwenden, nicht unterschlagen, falls nochmal jemand hier reinschaut.
P. Z. schrieb:> Bei Powerloss hat man dann aber eben auch maximalen Datenverlust wenn> noch alles im RAM war.
Wieso denn? Die Datei im RAM zu haben bedeutet ja nicht, das du sie
nicht regelmässig (z.B. jede Minute) als Block auf die SD Karte
schreiben kannst. Die Datei auf der Karte ist dann auf jeden Fall
valide.
Das kann ein Timer zünden. Wenn du eine Woche oder so voll hast,
startest du dann eine neue Datei, ehe der RAM knapp wird. So sparst du
dir auch die aufwendigen File Operationen mit ihren Eigenarten.
Ahja, da hast Du natürlich Recht.
Bin grade dran die Variante mit file.seek() zu implementieren.
Momentan sieht es so aus als würde mich das zum Ziel zu führen.
So, kurz um das hier abzuschliessen:
Ich habe das nun, wie oben vorgeschlagen, via seek() auf die Datei
gelöst.
Für ESP32 in der Arduino IDE die FS.h, SD.h und SPI.h includen, und dann
mit
1
file.seek(POINTER);
2
file.print("Text der an dieser Stelle eingefügt wird.")
den Zeiger zum schreiben an die richtige Stelle (POINTER ist dann eine
Zahl, zB 12) bringen um dann dorthin zu schreiben.
Ferner kann man mit
1
file.position();
an der richtigen Stelle die Pointerposition wegschreiben um dort später
wieder zu schreiben.
Ich muss damit zwar jedes Mal die Closing-Tags mitschreiben, aber das
nehme ich hin.
ERGO: Problem ist damit für mich gelöst. VIELEN DANK!
PS: Die Idee mit der Mini-ELKO-USV habe ich aber noch im Hinterkopf.
Falls ich jemals einen Powerloss in den paar ms habe wo ich grade ein
Log geschrieben habe, dann bau ich das ein. Lernen durch Schmerz
(=Datenverlust).
Bis dahin, viel Spass.
P. Z. schrieb:> Ich muss damit zwar jedes Mal die Closing-Tags mitschreiben, aber das> nehme ich hin.
Klaro, das ist das Prinzip dabei.
Ich habe mich damals auch gefragt, wie sie das bei dem Garmin geschafft
haben, wird aber das gleiche Prinzip gewesen sein. Ich habe jedenfalls
bei dem Teil nie eine korrupte GPX-Datei erlebt.
P. Z. schrieb:> Die Idee mit der Mini-ELKO-USV habe ich aber noch im Hinterkopf
Wenn man die Stromaufnahme vom ESP32 und der SD Karte berücksichtigt,
könnte der Elko etwas größer als "mini" werden.
Sherlock 🕵🏽♂️ schrieb:> könnte der Elko etwas größer als "mini" werden.
So groß sind die 1-F-Elkos aus einem alten Fahrrad-Rücklicht nun auch
wieder nicht. :-)
Jörg W. schrieb:> So groß sind die 1-F-Elkos aus einem alten Fahrrad-Rücklicht nun auch> wieder nicht.
Was mich auf den Gedanken bringt, dass man bei diesen hoch-kapazitiven
Elkos auf die Stromstärke achten muss. Manche liefern und laden nur
einstellige mA. Die anderen will man wahrscheinlich mit einer
Strombegrenzung laden.
Sherlock 🕵🏽♂️ schrieb:> Wenn man die Stromaufnahme vom ESP32 und der SD Karte berücksichtigt,> könnte der Elko etwas größer als "mini" werden.
Wenn man auf WLAN verzichtet, wird der ESP32 wohl auch etwas
zurückhaltender.
(Es dürfte für die Aufgabe sicherlich auch besser µCs geben, bei denen
man nicht ein riesiges IDF benötigt ...)