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
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
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.
>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.
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.
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...
Ups... hätte wohl auf den Link vom Falk klicken sollen :-)
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
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
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.
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.
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.
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?
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.
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
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 :)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.