ich spiele gerade mit dem Gedanken mit einem Arduino Pro Micro Ereignisse zu zählen und auf einem Display auszugeben. Bei Stromausfall, bzw. auch bei gezielter Abschaltung sollen die Zählerwerte erhalten bleiben.
Der Zählerstand wird sich voraussichtlich bis zu 1x / Sekunde ändern, sodass es wohl nicht ratsam wäre, jeden Impuls ins EEPROM zu schreiben, sondern nur dann, wenn ein Spannungsabfall erkannt wird.
Gibt es integrierte Spannungsdetektoren/-mechanismen und passende Sketche, über die man das realisieren kann?
Oder muss man die Hard- und Software dafür selbst basteln?
Eine Diode, ein Elko, ein Freier Pin. Damit kannst du den Arduino nach "Abschalten" kurz weiterlaufen lassen und die Zeit nutzen um ins EEPROM zu schreiben.
FRAM: High-endurance 100 trillion (10^14) read/writes
Kannste jede Sekunde 3.170.979 Jahre lang speichern.
Dein zu lösendes Hauptproblem ist die Energieversorgung für den sauberen "letzten" Schreibvorgang vorm abschalten. Die anliegende Spannung kannste mit dem µC eigenen ADC messen. Es gibt auch Voltage Detector ICs.
Du musst die "externe" Versorgungsspannung überwachen.
Nicht die anliegende Spannung am µC, weil die pufferst du zusätzlich unabhängig von extern.
Die Schaltung ist individuell.
Das Programm dazu ist individuell.
Schau einmal in die IDE Beispiele.
Eine andere Möglichkeit ist ein batteriegebuffertes RAM.
entweder als RAM-bausten mit extra Batterie was aber durch die Batterie die Sache kompliziert macht.
oder eine RTC wie zB DS1307 oder DS3232 haben auch noch einige Bytes RAM, das durch die Batterie den Inhalt behält. Da braucht man für die Zeit sowieso eine Batterie.
Ein I2C RAM wie das 47C04 (5V) bzw 47L04 ( 3,3V ) speichert bei Stromausfall die Daten in einem internen EEPROM um und stellt es bei Zurückkehren der Versorgungsspannung automatisch wieder her. 1 000 000 Schreibezyklen.
die Batterie für eine RTC hilft dem µC der die Daten schreiben soll nicht. Ich würde das auch dafür nicht machen. Man hat noch mehr Fehlerquellen die man nicht haben möchte.
Vielleicht noch eine Anmerkung, weil das bestimmt ansonsten falsch verstanden wird. Das EEprom benötigt genau wie der µC eine gepufferte Energieversorgung wenn es die letzten aktuellen Daten noch schreiben soll, bevor die Versorgungsspannung einbricht. Automatisch wiederhergestellt werden die Daten auch nicht. Dazu bedarf es "paar" Codezeilen.
Nein, Tut sie nicht. Aber in ein batteriegebuffertes RAM kannst Du 1000 mal die Sekunde den neuen Wert schreiben und somit den aktuellen Wert jedesmal sichern, wenn der sich ändert.
Natürlich können während des Abschalten der Spannungsversorgung ein Zählerergebnis verloren gehe,n weil ein schon gezähltes Ereignis nicht abgespeichert wird. Aber auch alle Ereignisse während der Spannungsverlustes werden auch nicht gezählt.
Jetzt weiß ich nicht auf was Du Dich beziehst.
Das 47C04 bzw 47L04 macht das automatisch:
Features
Automatic Store to EEPROM array upon power-down (using optional external capacitor)
Automatic Recall to SRAM array upon power-up
Das RAM braucht dazu einen Kondensator (4,7 bzw 6,8 µF)
wie in #2 vorgeschlagen:
Für das Gespann Microcontroller und Internes oder Externes EEprom stimmt das. Der Kondensator muß solange Spannung liefern und die Elektronik am laufen halten, bis der Controller die Spannungsversorgung erkennen kann, und die Daten zum EEprom schicken kann. Das EEprom braucht auch noch Zeit um die Daten zu speichern.
zB ein 24AA256 braucht max 5mS dazu ( wenn man nicht den Blödsinn macht, den Zähler auf 2 Pages zu verteilen).
Dazu muß man aber eine Elektronik so projektiert haben daß siee partiell durch den Kondensator versorgt werden kann und auch nichts kaputtgeht weil der Rest der Schaltung keine Versorgung mehr hat, aber der Controller seine Pins nicht spannungsfrei schaltet. Man kann das aber Programmieren. Per direkt Port Zugriff alle Pins auf Eingang schalten und dann erst den Zähler abspeichern.
Die Option FRAM ist eine mögliche Lösung die ich nicht aufgegriffen habe da bereits gesagt.
Die ist funktional aber gleich wie der 47C04 oder ein batteriegebuffertes RAM in einem bereits in dem Projekt vorhandenen RTC: Man speichert den Zähler bei jeder Änderung ab und hat so beim Einschalten den letzten Wert.
Wenn der Zähler klein bleibt ( 2-3 byte) kann man auch die Register für die Alarmzeit der RTC für das Speichern des Zählers Zweckentfremden. So werden weitere RTC Modelle geeignet wie zB der genaue und weit verbreitete DS3231.
Zusammenfassend:
Entweder speichert man den Zähler bei jeder Änderung Zeitnah ab.
Als Speicher können da FRAM, Batteriegespeichertes RAM oder RAM mit Automatik EEprom (zB 47C04) dienen, die (fast) unbegrenzte Schreibzyklen bieten.
oder man Speichert den Wert bei Erkennen eines Ausschaltens / Power Down in ein weniger Zyklenfestes Speichermedium (EEPROM) ab.
Erst mal vielen Dank für eure Tipps und Vorschläge.
Mir erscheint auf Anhieb die Variante mit dem FRAM am einfachsten zu sein, weil ich mich da hardwareseitig um so gut wie nichts kümmern muss, es sei denn, dass man die Stromversorgungsunterbrechnung ohnehin erkennen muss, damit nicht ein “zeitgleich” auszuführender Schreibbefehl in die Hose geht und unsinnige Daten in den Speicher schreibt.
Auch wenn es für meine Zwecke nur eine theoretische Frage ist, interessiert mich, ob sich die angegebenen Schreibzyklen für FRAM auf den gesamten Baustein beziehen oder auf einzelene Speicherzellen oder Speicherbereiche?
Wenn sich die Angaben auf jede Speicherzelle bzw. einzelne Bereiche beziehen, könnte man z.B. nach jedem Start des uC die erste verfügbare leere Speicherzelle suchen und diese bis zum nächsten Spannungsausfall beschreiben. So würde nicht immer nur die gleiche Speicherzelle beschrieben. Stellt der uC fest, dass alle Zellen beschrieben sind, würde er den letzten Wert verwenden, alle Zellen löschen und wieder bei der ersten Zelle anfangen.
ganz ehrlich, ich hatte mir das Datenblatt nicht angeschaut. Verzeihung. Jetzt bin ich im Bilde. Gut, dann ist eine weitere Option wenn man immer sehr schnell aktuelle Daten speichern möchte. So ein IC kannte ich bis heute noch nicht. Dafür jetzt.
Die Spannungsüberwachung musste ohnehin machen. Ansonsten macht der µC unkontrolliert Mist, wenn er mit externen "Baugruppen" redet. Man sollte sicher stellen, das sich alles in einen sauberen Zustand befindet, wenn mit Daten gearbeitet wird. Einen Led Blinker kann man jederzeit ausschalten. Dann ist eben alles aus. Wenn Daten rumgeschoben werden, sollte man die Kommunikation sauber beenden.
"Uwes" RAM-EEprom hat den Vorteil, man muss dafür keine extra Spannung überwachen. Der notwendige Pufferkondensator an dem IC dient nur dem Backup bei Spannungsausfall. Das heißt der µC muss sich nur um seine vorausschauende Überwachung kümmern. µC und das RAM-EEprom können gemeinsam versorgt werden. Bemerkt der µC das ihm seine Versorgung abhanden kommt, beendet er seine letzte Kommunikation und stellt sich nach außen ruhig. Das RAM-EEprom überlässt man sich selbst.
Du hast viele Optionen. Vielleicht zu viele.
Gilt wie beim EEprom für jede einzelne Speicherzelle.
Gilt das beim EEprom nicht für die ganze Page und icht für die einzelne Speicherzelle, weil immer die ganze Page geschrieben wird?
Beim FRAM weiß ich das nicht, da es aber sehr viele Speicherzyklen aushält würde ich es für unseren Zweck als Unendlich viele Speicherzyklen annehmen.
Wie oft wird der Zähler denn weitergezählt?
Ich glaub nicht, daß es sich lohnt, die Speicherzelle zyklisch zu wechseln. Das ist nur bei EEprom sinnvoll.
Du kannst den Zählerwert mehrfach abspeichern um ein fehlerhaftes Abspeichern ( wegen Abbruch mitten im Abspeichern) erkennen zu können.
Wenn wir pingelig sein wollen und Dich wörtlich nehmen ist das eine Schwachstelle.
Das Löschen dauert je nach Modell pro Page einige mS, Du löscht am besten eine ganze Page gleichzeitig, weil einzelne Zellen löschen ( bzw auf einen gewissen Wert zB 0xFF zu setzen) viele Löschzyklen der Page bedeuten und damit noch länger dauert.
Hab bei einem großen Elektronikversender mal nach I2C EEproms im DIP Gehäuse gesucht und nur 24AA02 ( 256 Byte) und 24AA128 (16kByte) gefunden. Darum schreibe ich beispielhaft von diesen beiden.
Diese haben Page Größen von 16 bzw 64 Byte (also 16 bzw 2048 Pages). Mittels Page Write kannst Du die gesamte Page in einmal schreiben. Das würde bei den beiden genannten Modellen ca 16 mS bzw 10 Sekunden dauern.
Also wenn Du erkennst, daß die letzte Speicherzelle benutzt ist, startest Du einen Schreibzyklus mit 0xff und dann schreibst Du in der ersten Speicherstelle den neuen Zählerwert. Das dauert Sekunden und wenn in der Zeit die Versorgungsspannug ausfällt hast Du keine Zählerstand mehr.
Also mußt Du die Speicherlogik verbessern.
Oder wie gesagt ein FRAM und schreibe den Zählerstand mehrfach in 4 bzw 8 verschiedene Speicherzellen. Beim Einschalten kontrollierst Du ob alle Zählerwerte gleich sind. Sind sie es nicht nimmst Du den Zählerstand den die meisten Speicherzellen haben als richtig.
Frage des Blickwinkels. Letztlich besteht eine Page auch nur aus einzelnen zusammengefassten Speicherzellen. Man kann sie einzeln beschreiben oder als Page. Wenn man sie als Page anfasst, dann werden alle Speicherzellen der betreffenden Page zugleich "abgenutzt". Die Schreibzyklen gelten für jede einzelne Zelle. Ob man mehrere Zellen zusammenfasst, hängt vom Anwender ab.
EEprom: Auf alle Fälle ist Page löschen schneller als das löschen jeder einzelner Speicherstelle der Page oder einen Teil davon. Jeder Löschvorgang/ Speichervorgang einer Speicherzelle oder Page dauert gleich lang.
Grüße Uwe
Weiß nicht wieso, aber externe EEprom (nicht die im Controller) halten sehr viel mehr Schreibzyklen (normalerweise 1 Million gegen die 100000 des ATEmag328) .