Die Variable wird ja während der Fahrt andauern geschrieben.
Echte, real eingesetzte Speicherkonzepte verwenden da EEPROMs (mit 100000 Schreibzyklen) und dazu ein halbwegs taugliches Wearleveling, dass der Tachostand über mehr als 1Mio km auf 100m genau abgespeichert werden kann.
Die Frage ist lege ich das im NVS ab, oder besser auf einer SSD?
Bei deinem aktuellen Wissensstand: nimm ein externes FRAM (I²C oder SPI). Da musst du dir die Gedanken um das Wearleveling nicht machen.
ich schreib mir gerade einen Kilometerzähler für meinen Oldtimer.
Der Kilometerstand muss natürlich nonvolatil sein.
VW hat damals in den ersten Tagen der Digitalen Kilometerzähler alles in einem EEPROM abgelegt. Aber auf intelligente Art und Weise. Kann man googlen wie das geht.
Vergiss es. Das Ding ist schneller kaputt als du dir vorstellen kannst.
Es reicht vermutlich, den aktuellen Kilometerstand am Ende der Fahrt auf der SD zu aktualisieren, also vielleicht zweimal am Tag. Hinzu kommt, dass der Oldtimer gewiss nicht jeden Tag ausgeführt wird.
Wenn man da eine 16GB-Karte reinsteckt, die einigermaßen Wear-Leveling beherrscht, sollte das für ein paar zehntausend Schreibzugriffe reichen.
Vergiss es. Das Ding ist schneller kaputt als du dir vorstellen kannst.
Ein 16MB Karte hat ~31250 Sektoren.
Zu Beginn einmal vollständig löschen.
Dann, zum Abspeichern einen leeren Sektor suchen, den Stand dort hineinschreiben und den nächsten Sektor prüfen. Falls schon beschrieben sind wir einmal außen herum. Also diesen nächsten Sektor löschen. Für das nächste Mal.
Das Ding macht er in seinem Leben nicht mehr kaputt.
Du kannst dir bei so einer microSD irgendwas logisches wie z.B. einen Sektor wünschen. Was die in der Hardware dann tatsächlich macht, in welchem Flashblock die diesen Sektor dann tatsächlich abspeichert, das bestimmt die Firmware der Karte. Da ist dann der selbe logische Sektor im Idealfall (wenn das Wearleveling gut funktioniert) immer woanders abgespeichert.
Du kannst dir bei so einer microSD irgendwas logisches wie z.B. einen
Sektor wünschen. Was die in der Hardware dann tatsächlich macht, in
welchem Flashblock die diesen Sektor dann tatsächlich abspeichert, das
bestimmt die Firmware der Karte. Da ist dann der selbe logische Sektor
im Idealfall (wenn das Wearleveling gut funktioniert) immer woanders
abgespeichert.
Wenn sie kein ›wear-leveling‹ hat, ist's gut so.
Sollte sie jedoch ›wear-leveling‹ haben, dann ist's ebenfalls gut so.
Doppelt ›gelevelt‹ hält besser.
Außer der wear-leveling Algorithmus wäre von einem Australopithecus geschrieben, dann wär's schlecht. ;-)
Das Ding macht er in seinem Leben nicht mehr kaputt.
Nimm mal eine Karte von Intenso, dann ist die Weltreise noch nicht mal halb um und er weiß nicht mehr, wie weit er schon gefahren ist.
Wenn mich mein Chef zwingen würde, diese Aufgabe mit einer microSD zu lösen, dann nähme ich (aufgrund langjähriger und immer weiter laufenden Tests) eine Karte von Xmore oder Flexxon.
Wenn ich die freie Wahl hätte, dann ein serielles EEPROM mit geeigneter Schreibstrategie.
Und wenn man sich mit Brownout beschäftigt und dem Ding einen ausreichend dimensionierten Pufferkondensator spendiert, muss das nur beschrieben werden, wenn die Versorgungsspannung flöten geht.
Nächste obskure Idee:
Wenn 262.144km für einen Kilometer Umbruch reichen könnte man 32kB reservieren/löschen. Ich glaub beim ESP sind die Sektoren 4kB groß. Also 8 Sektoren.
Bei jedem Kilometer der dazu kommt wird ein weiteres Bit auf 0 geschrieben.
Die Anzahl 0en im reservierten Bereich ist dann der Kilometerstand 😄
Spaß bei Seite:
Nimm einen kleinen FRAM. Gibt's als fertiges Board für ein paar Euro. Dann kannst du sogar immer auf die gleiche Adresse schreiben.
Die Sache ist die, der ESP32 hängt am Dauerplus, allerdings
schalte ich den LKW stromlos wenn ich den verlasse
Aber schon 'lange' vorher drehst Du wohl die Zündung ab, das ist Dein 'jetzt bitte mal speichern'-Signal.
Alternativ, ganz ohne externes Signal: gespeichert wird immer dann, wenn der km-Stand für eine gewisse Zeit (kurz genug, um sicher nicht früher nach dem Anhalten schon die Batterie abzuklemmen) unverändert bleibt (und noch nicht gespeichert wurde).
Die Übersicht genügt mir schon. Da sehe ich allein fünf mal RasPi.
Der nutzt die SD nämlich auf eine Art und Weise, welche meiner Methode diametral gegenübersteht. Dort wird geschrieben bis der Arzt kommt.
Hier wird jeder Sektor nur ein einziges Mal alle 32500km beschrieben. Mit nur einem winzigen Datensatz. Der Rest des Sektors bleibt frei und wird auch nicht genutzt. Nächster Kilometer, nächster Sektor.
Aber ist auch egal, wird wohl sowieso eine völlig andere Methode zum Einsatz kommen. Wenn überhaupt.
Die Übersicht genügt mir schon. Da sehe ich allein fünf mal RasPi.
Der nutzt die SD nämlich auf eine Art und Weise
Ich habe gesagt: Lies die Threads. Dort siehst du, dass ich die SD-Karten nicht mit einem eigenartigen Betriebs- und Filesystem teste. Sondern mit einem Windows-System und FAT32.
Der nutzt die SD nämlich auf eine Art und Weise, welche meiner Methode
diametral gegenübersteht. Dort wird geschrieben bis der Arzt kommt.
Das mache ich zum Test auch. Da wird ständig die gleiche Datei geschrieben, gelesen, geändert und dann wieder von vorn. Zwischendurch ein Powerfail, um die Karte noch mehr zu stressen. Die Intenso-Karte ist beim Dauerschreiben nach 1 Woche kaputt. Mit überaus urigen Fehlerbildern bis zum Totalausfall der Karte, weil ja die Software des Flashcontrollers auch auf dem Flash gespeichert ist.
Dort finden sich ein paar der "Fehlerumgehungsstrategien" der Hersteller:
Und wie merkst du dir, welcher der "nächste Sektor" ist? Du liest beim Einschalten die ganze Karte nach&nach ein und suchst den diesen "nächsten freien Sektor"?
Hier wird jeder Sektor nur ein einziges Mal alle 32500km beschrieben.
Wenn du den grade gepostetn Link mal anschaust, dann siehst du, dass nicht du als Anwender entscheidest, was tatsächlich auf dem Flash passiert. Aus diesem Grund kannst du auch einfach immer den selben Sektor beschreiben. Und dich darauf verlassen, dass der Hersteller seine Firmware schon ordentlich programmiert hat.
wird wohl sowieso eine völlig andere Methode zum Einsatz kommen.
Ich würde einfach einen GPS-Tracker von Garmin kaufen, der speichert dann die gefahrene Route viertelstündlich fein säuberlich ab. Und funktioniert dank Satellit auch dann als Kommunikationsmittel, wenn grade kein WLAN in der Nähe ist.
So in der Art wird das bei Kilometerzählern mit EEPROM gemacht.
Aber nicht Bit für Bit, weil im EEPROM die kleinste unteilbare Einheit 1 Byte ist. Und beim EEPROM beinhaltet auch jeder Schreibzyklus automatisch einen verschleißenden Löschzyklus.
Beim Flash muss immer ein Block auf '1' gelöscht werden, das kostet dann einen Schreibzyklus. Das Programmieren kann dann Bit für Bit passieren und bringt keinen zusätzlichen Verschleiß auf die nicht geänderten Bits.
Und das funktioniert ausgezeichnet.
Ich mache solche fortlaufenden "Betriebsstundenzähler" im EEPROM so, dass z.B. 64 Bytes in einem Ringpuffer geschrieben werden. Mit jedem Umlauf wird der Wert des Bytes um 1 erhöht. Wenn dann grade beim Abschalten ein Powerfail ist, dann beim nächsten Einschalten schlimmstenfalls 1 Byte korrupt, die anderen 31 zeigen an, was da gerade zu schreiben versucht wurde. Damit kann so ein Fehler leicht erkannt und dann leicht korrigiert werden. Wenn alle 100m geschrieben wird, dann passen in diese 32 Bytes also 256640,1km = 1638 km. Und jede EEPROM-Zelle wurde in dieser Strecke 256 mal beschrieben. Für 800.000 km wären das dann also knapp 500 Durchläufe und somit rund 256*500 = 128000 Schreibvorgänge pro EEPROM-Zelle. Übliche EEPROMs sind heute mit ca. 1 Mio Schreibzyklen spezifiziert. Da ist dann genug Reserve...
Aber nicht Bit für Bit, weil im EEPROM die kleinste unteilbare Einheit 1
Byte ist. Und beim EEPROM beinhaltet auch jeder Schreibzyklus
automatisch einen verschleißenden Löschzyklus.
Das ist eben falsch. Du kannst in einem EEPROM jederzeit ein Bit von 1 auf 0 kippen. Ohne löschen. Auch wenn du dafür das ganze Byte nochmal neu schreiben musst.
Wie gesagt: Genau so wird (oder wurde) das in echten Kilometerzählern in Autos gemacht. Daher ist allein schon die Behauptung das ginge nicht Unsinn.
Eventuell gehst du von bestimmten seriellen EEPROMs aus, welche Löschen und Schreiben in einem Arbeitsgang, untrennbar zusammen implementiert haben?
Das ist aber nur eine Implementierungsentscheidung, die es z.B. bei parallelen EEPROMs so nicht gibt.
Ist also kein Naturgesetz sondern eher eine praktische Sonderlocke bei seriellen EEPROMs.
Bei Flash ist es sogar ganz normal dass löschen und schreiben völlig getrennte Anweisungen sind. Und man kann fast immer auch einfach schreiben ohne zuvor zu löschen. Was dann ähnlich funktioniert: Ein Bit kann so nur in eine Richtung gekippt werden.
Wenn ich die freie Wahl hätte, dann ein serielles EEPROM mit geeigneter
Schreibstrategie.
Ich werfe mal die Serial EERAM von Microchip in den Raum.
Solange der Strom da ist, wird der Wert ins SRAM geschrieben. Wenn der Strom fehlt, wird der SRAM Inhalt automatisch ins EEPROM geschrieben. Die Energie muss dann ein Kondensator am Chip zur Ver0fügung stellen.
Im speziellen Fall hier wird wohl keiner auf die Ideee kommen, ein
paralleles bitweise adressierbares EEPROM dranzustricken.
Verstehs doch bitte mal. Es geht nicht um bitweise EEPROMs. Der EEPROM muss nur erlauben zu schreiben ohne vorher zu löschen. Byteweise ist ok. Dann funktioniert das.
Und zum 3. mal: Solche EEPROM wurden in Tachos eingesetzt zu genau diesem Zweck.
Dass es auch andere Verfahren gibt, welche ganz normale serielle EEPROMs nutzen sollte klar sein. Dann ist man aber wieder bei Tricks wie "Schreiben vor Power-Down" mit Pufferelko und solchen Geschichten. Eher unschön.
Kann es sein, dass ST hier anders als Microchip vorgeht?
Zumindest bietet er ein explizites "Erase" Kommando und in der Tat kein zwingendes Erase vor dem Schreiben.
Mit diesem Baustein kann man ziemlich einfach so einen Tacho realisieren der im Betrieb keinen einzigen Löschzyklus braucht.
Allerdings hat er laut Hersteller auch 1 Mio. Löschzyklen. D.h. damit könnte man sogar einen trivialen Lösch/Schreib Vorgang für jeden einzelnen Kilometer machen.
Ich frage mich schon die ganze Zeit: "Wie dumm oder klug ist der 'Automatic Erase' denn umgesetzt?"
Klug wäre es, vor dem Schreiben zu testen, ob ein Erase überhaupt notwendig ist. Werden nur Bits von 1 nach 0 gekippt, entfällt der Erase komplett. Weiß jemand, wie dumm oder klug die Dinger den 'Automatic Erase' behandeln? Bekommt man das vielleicht durch eine Messung der Busy-Zeit heraus?
Genau so kenne ich das. Ich weiß kein übliches serielles EEPROM, das byteweises Schreiben ohne automatischen Löschzyklus erlaubt. Wegen dieses automatischen Löschvorgangs dauert das Schreiben dort auch immer relativ lange. Aber ich lasse mich gerne vom Gegenteil überzeugen.
Und beim Flash ist Autoerase beim Schreiben eines Bytes schon deshalb nicht drin, weil dort ja immer ganze Blöcke mit vielen Bytes gelöscht werden. Da dauert das Löschen lange, das Schreiben geht ratzfatz.
Na ja, das vergleichen könnte man ja tatsächlich selbst machen, aber wie vermittle ich einem EEPROM mit Auto-Erase bei jedem Write, mir bitte nur ein paar Bits zu kippen, so ganz ohne Write (oder zumindest ohne Erase)?
Bei den AVRs wurden Bits hinzu gefügt, mit denen man das Autoerase abschalten kann. Dann verringert sich die Schreibzeit von 8ms auf 4ms.
Das ist nützlich, wenn man bei Power-Fail noch ein paar Bytes aus dem SRAM in den EEPROM sichern will.
Testablauf:
Eine Page wurde abwechselnd mit 0x00 / 0xFF beschriebeben.
Danach ausgelesen und verglichen.
Nach 10.000 Durchgängen immer noch alles OK.
Nimmst du dir jetzt nur 1MB von der Karte und für dein KM Zähler eine uint32 Variable, dann kannst du bei jeder Änderung schreiben.
Mit einmal füllen, wären das 262144 KM.
Und da hast du jede Page nur 1x voll beschrieben, bzw. 128 Schreibzugriffe, wobei sich immer nur 4 Byte geändert haben. (Kommt auf die SD Karte an wie die damit umgeht)
Aber da brauch man sich keine Gedanken machen das man an die 100.000 Schreibzugriffe kommt.