Forum: Mikrocontroller und Digitale Elektronik String in EEPROM speichern bevor Strom aus


von Klaus (Gast)


Lesenswert?

Hallo zusammen,
ich überwache derzeit ein Pumpsystem via Arduino Mega Board(ATmega 
2560). Bei einer Warnmeldung erhöhe ich einen Counter. Bei 13 
detektierten Meldungen soll eine LED leuchten.

Die Sache ist jetzt nur: Wenn ich mein Board mal vom Gerät entferne oder 
es zu einem Stromausfall kommt, sollten mein gezählten Alarmmeldungen 
nicht einfach verschwunden sein.

Allerdings kann ein EEPROM nur begrenzt beschrieben werden und das Ganze 
soll lange, sehr lange funktionieren. Eine direkte Speicherung in den 
EEPROM kommt daher wohl nicht in Frage.

Wie kann ich einen bevorstehenden Spannungsabbruch softwaretechnisch 
detektieren und wie muss ich meine zuvor in den SRAM gespeicherten 
Variablen modifizieren, sodass ich diese in den EEPROM speichern kann 
und bei wieder vorhandener Spannung wieder aufrufen kann.

ICH HAB NULL PLAN und würde mich freuen, wenn mir jemand weiterhelfen 
könnte.
Grüße,
Klaus

von Egberto (Gast)


Lesenswert?

Prinzipiell:

Spannung für uC muss gepuffert werden  (Akku oder Goldcap), denn du 
brauchst ja noch Zeit, wenn der Strom weg ist.

Der uC muss erkennen, wenn der Strom weg ist, und dann die Werte ins 
Eeprom schreiben. Geeignet sind hierfür AD Wandler oder Comparator, die 
an der ungepufferten Spannung "lauschen".

Du kannst ja mal im Code der diversen Uhren hier stöbern, da haben viele 
eine Gangreserve nach diesem Prinzip.

Viele Grüsse,

egberto

von Guru (Gast)


Lesenswert?

Der Grundwiderspruch ist, das einerseits eine Aktion erfolgen soll, wenn 
der Strom abgeschaltet wird, aber andererseits für die diese Aktion auch 
Strom benötigt wird.

Je nach den Umständen kann dieser Widerspruch wie folgt aufgelöst 
werden.

Es gibt dabei zwie Ansätze denen folgender Gedanke zugrunde liegt: Die 
Stromquelle wird in eine "eigentliche" und eine "uneigentliche" 
aufgeteilt.

Die eigentliche Stromquelle kann bzw. wird hart abgeschaltet. Wenn Strom 
weg, dann weg.
Die "uneigentliche" Stromquelle liefert aber noch eine Zeitlang Strom 
wenn die eigentliche Quelle abgeschaltet ist.

Im einfachsten Falle ist die uneigentliche Quelle ein grosser 
Kondensator. Es kann sich auch um einen Akku oder eine Batterie handeln.

Die Schaltung wird nun neben der "uneigentlichen" Quelle um einen Teil 
erweitert, der detektiert das die eigentliche Quelle abgeschaltet wurde.

Mit einem Kondensator oder eine Batterie bleibt dann noch Zeit um die 
Daten in das EEPROM abzuspeichern.

Die RAM-Variablen brauchen dafür nicht verändert zu werden.

Je nachdem ob sehr viele oder sehr weniger Daten gespeichert werden 
müssen ist entweder die kondensatorlösung ausreichend oder es muss die 
Batter/Akku-Lösung genommen werden.

---

Was die Frage betrifft wie oft im EEPROM geschrieben werden kann und wie 
man damit umgeht, so gibt es dazu Application Notes von Atmel.

Grundsätzlich sollte man erstmal feststellen wie oft der Stromausfall 
(absichtlich/gewollt) auftritt bzw. wie oft er wahrscheinlich 
(unabsichtlich) auftritt .

Im Datenblatt steht die Anzahl der zulässigen Schreibzyklen (ich weiss 
sie jetzt nicht auswendig). Diese beiden Zahlen setzt man in Relation zu 
den oben ermittelten Häufigkeiten und kann daraus die Laufzeit errechnen 
wie lange das EEPROM speichern klappt. Falls das so nicht ausreicht gibt 
es eine Reihe von Strategien von denen eine in der genannte Application 
Note beschrieben ist. Falls diese nicht passt, frag hier bitte nochmal 
und beschreibe das Problem dabei.

Zuerst muss man aber mal feststellen wieviele Daten gespeichert werden 
sollen. Es lohnt sich oft auch einmal festzustellen welche Bits der in 
Frage kommenden Variablen sich überhaupt verändern. Läuft z.B. ein Index 
ohnehin nur von 0 bis 15, dann kann man diese geschickt umverteilen oder 
mit anderen Werten kombinieren.

von holger (Gast)


Lesenswert?

>Allerdings kann ein EEPROM nur begrenzt beschrieben werden und das Ganze
>soll lange, sehr lange funktionieren. Eine direkte Speicherung in den
>EEPROM kommt daher wohl nicht in Frage.

Auch dafür gibt es Lösungen. Ein externes SPI FRAM ist unbegrenzt
schreibbar. Das geht verdammt schnell. Eine frühzeitige Erkennung
das die Stromversorgung ausfällt muss man da aber auch implementieren.

von Falk B. (falk)


Lesenswert?


von Thorsten (Gast)


Lesenswert?

Mit wie vielen Fehlern rechnest du denn pro Tag in etwa?

Grund meiner Frage: Im Datenblatt werden die Schreibzyklen des EEPROMs 
mit 100.000 angegeben. Bei 10 Fehlern am Tag würde es mehr als 13 Jahre 
dauern bis du 50.000 Mal ins EEPROM geschrieben hast, falls du jedes Mal 
direkt schreiben würdest und nicht erst bei Wegfall der Spannung.

Falls dir das nicht reicht und du genügend EEPROM zur Verfügung hast, 
nimmst du einfach mehrere Adressen. Du schreibst deinen Fehler ins 
EEPROM und speicherst dir wie oft du diese Stelle schon beschrieben 
hast. Bei einem bestimmten Wert fängst du an, an eine andere 
EEPROM-Adresse zu schreiben. Dadurch kannst du das ganze noch länger 
hinauszögern.

von Erich R. (riedi)


Lesenswert?

Prinzipiell würde ich einen interrupt-fähigen GPIO nehmen und diesen 
(ggf. über Spannungsteiler, Schutzbeschaltung etc.) an den 
Versorgungsspannungseingang hängen. Nach diesem Abgriff kann man z.B. 
eine Diode hängen, welche nachfolgende Pufferkondensatoren vom Eingang 
entkoppelt (bei Ausfall der Versorgung).
In der SW musst du dann nur noch beim Auftreten eines externen 
Interrupts die Daten in den EEPROM schreiben. Natürlich solltest du die 
Gesamtkapazität der Kondensatoren so auslegen, dass sie für die hierfür 
benötigte Zeit dein System noch versorgen können.

Beste Grüße...

von Erich R. (riedi)


Lesenswert?

Ups... hätte wohl auf den Link vom Falk klicken sollen :-)

von Klaus (Gast)


Lesenswert?

Hallo,
zunächst einmal vielen Dank für die Antworten!

Mein Hauptproblem bei der ganzen Sache ist eigentlich das 
softwaretechnische detektieren des Spannunsabbruchs und das Schreiben 
und Holen der Variable in bzw. aus den EEPROM.

Wenn die Spannung wieder vorhanden will ich wieder mit dem zuvor 
gespeicherten Wert weiter arbeiten, ohne sie dabei immer wieder in den 
EEPROM schrieben zu müssen.

Spannungsabbruch -> Detektieren -> Speichern in EEPROM --> Spannung 
wieder da -> gespeicherter Wert aus EEPROM holen und wieder in SRAM 
speichern

Gibt es hierzu Codebeispiele in C? Ich stelle mir das nicht so einfach 
vor.

VG

von Michel (Gast)


Lesenswert?

Nochmal die Frage von Thorsten:

Thorsten schrieb:
> Mit wie vielen Fehlern rechnest du denn pro Tag in etwa?
Bei 4 kByte EEPROM kannst du, falls nicht tausende von Warnmeldungen pro 
Tag auflaufen, ausreichend Schreibzugriffe "frei", um über dutzende von 
Jahren deine Warnungen sofort im EEPROM zu verewigen. Bei passendem 
Wear-out Management sollte das normalerweise kein Problem sein.

Warum also der Aufwand mit "Notstromversorgung" für's Schreiben. Oder 
möchtest du das aus "sprotlichem Ehrgeizt" über NSV lösen? Wieviele 
Warnungen kommen denn bei deinere Anlage und wieviel EEPROM hättest du 
für die Warnungen frei.

MfG

von Marco S. (Gast)


Lesenswert?

Das selbe Problem habe ich bei einem Alarmanlagenprojekt auch gehabt.
Weil die Sensoren und ein Teil der Schaltung mit 12 funktionieren, habe 
ich die Speisung auf 12V ausgelegt.
Über eine Diode wird ein Elko geladen, welcher den Controller nach einem 
Stromausfall noch ein Weilchen am Leben hält. Der Rest der Schaltung ist 
aber sofort ausser Betrieb.
Über einen Optokoppler (kann auch ein Spannungsteiler sein) werden die 
"direkten" 12V aus dem Netzgerät überwacht und bei deren Ausfall 
schreibe ich die Zählerwere und Statusbits ins EEPROM.
Beim nächsten Start lese ich die Daten ins RAM und arbeite damit weiter 
bis zum nächsten Stromausfall...

Wenn Du einiges an EEPROM-Speicher verfügbar hast (nicht für andere 
Zwecke brauchst) dann wäre vielleicht folgendes eine Lösung.
Ich weiss nicht wie hoch Dein Zählerstand werden kann, sollten 32768 
reichen, dann kannst Du die Daten in Words ins EEPROM ablegen.
Wenn Du z.B. 80 Bytes frei hast, kannst Du also 40 Words ablegen => bei 
40 ändernden Zählerständen wäre jede Speicherzelle einmal beschrieben 
worden.
Bei mir läuft es folgendermassen. Ist bei der ersten Word-Speicherstelle 
das 16.Bit = 0 so fahre ich weiter bis an die erste Adresse mit einem 
gesetzten Bit.
Tritt ein Ereigniss ein, so lege ich dort den inkrementierten 
Zählerstand mit GELÖSCHTEM Bit ab. dies geschieht, bis die letzte 
Adresse ebenfalls mit einem gelöschten Bit versehen ist.
Bei erneut eintretendem Ereignis wird dann der aktuelle Zählerstand mit 
gelöschtem Bit an der ersten Stelle abgelegt und das ganze beginnt von 
vorne.
So kannst Du die Anzahl der Schreibzyklen runterbrechen, wenn genügen 
EEPROM-Speicher verfügbar ist.

von Thisamplifierisloud (Gast)


Lesenswert?

Ich weiss nicht, wie die atmels das lösen, aber bei den zilogs
gibt es ein "Voltage brown out". Das ist ein hochpriorer Interrupt,
der ausgelöst wird, sobald die Spannung unter eine Schwelle rutscht.
Wenn die Spannung entsprechend gepuffert ist und langsam genug
abfällt (gold-cap), kann man in der irq-Routine noch gemütlich alles 
aufräumen.

von Marco S. (Gast)


Lesenswert?

Wenn Dein Problem nur das Detektieren eines Stromausfalles ist, dann 
würde ich wie folgt vorgehen.
Die ungepufferte Spannung über einen Spannungsteiler oder Optokoppler 
auf einen Eingang verbinden.
Wenn Du nicht sinnlos lange Routinen programmiert hast und die 
Programmzyklen einigermassen kurz sind, kannst Du den Eingang zyklisch 
abfragen und bei je nach Beschaltung bei einer 1 oder einer 0 die Daten 
ins EEPROM schreiben und auf den Spannungsausfall warten.
Sollte dies nicht der Fall sein, könnstest Du das ganze auf einen 
Eingang mit Interrupt schalten.
Dann würde ich nach dem Initialisieren der Controller Hardware (im 
ersten Zyklus => beim Hohfahren) kurz die gewünschten Daten aus dem 
EEPROM ins RAM laden und dann kannst Du weiterarbeiten.

von Klaus (Gast)


Lesenswert?

Hallo,
danke für die Antworten.
Es hat sich nun noch zusätzlich was ergeben: Ich muss noch weitere Daten 
untersuchen und speichern.

Sprich, ich muss den Counter-Wert und ein ca. 34 Zeichen ,langer String 
speichern.

Nach dem Spannungsabbruch sollen die letzten empfangen Daten und der 
Counter-Wert noch vorhanden sein.

Ich verwende den ATmega 2560 mit 4 kBytes EEPROM. Die Daten empfange ich 
mit 9600 bps und je nach Situation kann an es an einem Tag gut zu 100 
Alarmmeldungen kommen. Allerdings soll nach 13 detektieren Ereignissen 
der Counter wieder auf Null gesetzt werden und von vorne gezählt werden.

Gibt es da schon fertige Baugruppen mit der ich einen Offsetwert 
einstellen kann und mir eine log 1 oder 0 an meinen Eingang sendet und 
ich die Daten in den EEPROM speichern.

Mit dem Speichern in den EEPROM hab ich noch Null Ahnung...

Das speichern in den EEPROM erfolgt das nach den Bsp. im Datenblatt, 
also so?

void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
/* Wait for completion of previous write */
while(EECR & (1<<EEPE))
;
/* Set up address and Data Registers */
EEAR = uiAddress;
EEDR = ucData;
/* Write logical one to EEMPE */
EECR |= (1<<EEMPE);
/* Start eeprom write by setting EEPE */
EECR |= (1<<EEPE);
}

Was muss ich aber als uiAddress angeben?

von Thomas E. (thomase)


Lesenswert?

Klaus schrieb:
> Das speichern in den EEPROM erfolgt das nach den Bsp. im Datenblatt,
> also so?

Geht viel einfacher:

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#EEPROM

mfg.

von Frank K. (fchk)


Lesenswert?

Ich weiß nicht, warum Du Dir so viel Stress machst.

Wenn Du nicht in ein EEPROM schreiben willst, dann nimm doch einfach ein 
batteriegepuffertes RAM: Microchip 23K640. Kapazität 8k. Ansteuerung 
über SPI, Pinout wie ein SPI-EEPROM.

Das Ding hat einen Standby-Verbrauch von 1 uA gemäß Datenblatt. Wenn Du 
eine normale CR2032 Knopfzelle als Backup nimmst, hat diese 
üblicherweise eine Kapazität von etwa 200 mAh. Das heißt, diese 
Knopfzelle könnte 200h lang 1 mA liefern, oder eben 200000h lang 1uA. 
200000h sind über 20 Jahre. Selbst wenn es nur die Hälfte ist 
(Selbstentladung), dürfte das für Dich gut ausreichen.

Zur Versorgung des Speicherbausteins hängst Du deine normale 
Stromversorgung und die Knopfzelle über eine BAT54C Doppeldiode an VCC 
vom Speicher. Einmal 100n gegen Masse und Pullups an alle Eingänge 
(damit der Chip wirklich passiv ist, wenn er über die Batterie versorgt 
wird), und das wars dann.

Es gibt ansonsten auch FRAMs. Die werden wie EEPROMs verwendet, aber das 
Schreiben geht so schnell wie bei RAM, und die Schreibzyklen sind fast 
unbegrenzt, aber der Speicherinhalt bleibt auch ohne Strom erhalten.

fchk

von Tobias (Gast)


Lesenswert?

Der EEPROM des ATmega 2560 hat 4KB.
Ein 13 Zeichen String hat 13 Byte, dazu ein 8 Bit Zähler sind wir bei 14 
Byte.

Dem fügen wir noch ein 2 Byte Counter für ein Wear-Level-Managing hinzu, 
umsetzen dann folgendermaßen:
Der 4KB Speicher wird logisch in 256 Zellen geteilt (4KB / 16Byte = 
256), in die die genannten Werte passen.
Nun speicherst du bei jedem Alarm deinen String und deinen Counter in:
a) eine freie Speicherzelle (16 Bit Counter = 0)
b) in eine Speicherzelle mit dem kleinsten Wear-Level-Counter
Auf den größten Counter-Wert (65535) folgt als nächstes die 1, da die 0 
für ungenutzte Stellen steht (noch nie beschrieben).

Dies hat den Vorteil, dass du beim Schreiben von neuen Daten nicht die 
alten Daten löschen musst (weitere Schreiboperation) sondern diese 
automatisch ungültig werden, wenn es einen Eintrag mit einem höheren 
Wear-Level-Counter gibt.

Hast du nun also den Strom verloren, sind alle Daten trotzdem immer 
persistent im EEPROM (ohne Zusatzschaltung für die Stromsicherung), 
bekommt dein Mikrocontroller nun wieder Strom suchst du einfach linear 
in den 256 Zellen nach dem Eintrag mit dem höchsten Wear-Level-Counter 
und du hast deine Daten wieder.
Zusätzlich hast du auch noch alle 255 älteren Eintrage, ist das nicht 
wunderbar ;)


Die Lebenszeit davon ist auch gigantisch, du hast 256 Zellen mal 100.000 
Schreibzyklen, dies entspricht 25.600.000 Alarmmeldungen die du 
speichern kannst ;)
Damit du den EEPROM in der Produktlebenszeit (10 Jahre) kaputt bekommst, 
müssten es 7.013 Alarmmeldungen sein, also alle 12 Sekunden ein Alarm, 
unmöglich :)

von Tobias (Gast)


Lesenswert?

Ich habe eben gerade noch festgestellt, dass der Ansatz nicht ganz 
reibungslos funktioniert:
Bei einem Überlauf haben die neuen Werte natürlich einen kleineren 
Wear-LEvel-Counter und würden somit ignoriert, also vereinfach den 
Ansatz und nimm ein 4 Byte unsigned Counter, der EEPROM ist viel 
schneller kaputt als dass der Counter die 4,2 Milliarden Grenze 
erreicht.

Zusätzlich lässt sich das finden der Speicherzelle vereinfachen indem 
nur nach dem kleinsten Counter gesucht werden muss, denn die Methode b) 
implimiziert bereits die Methode a) da 0 die kleinste unsigned Zahl ist.

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.