Forum: Compiler & IDEs Stromausfall, Parameter speichern, eeprom.h


von Jochen Ruf (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Forum,

ich möchte bei einem Ausfall der Versorgungsspannung den Zustand von 
PORTB im EEPROM abspeichern. Ich habe hierfür den internen 
Analog-Komparator verwendet. Am ADC1 ist im Moment ein Poti 
angschlossen, mit dem ich das Absinken der Spannung simuliere. Später 
hängt dann die 24V Versorgung über einem Spannungsteiler daran. Fällt 
die Spannung unter 1,1V, wird die analog-comp ISR aufgerufen und der 
Zustand von PORTB wird mit der Funktion eeprom_write_byte der AVRlibc 
abgespeichert. Ich habe das EEPROM mehrfach ausgelesen und es 
funktionier einwandfrei. Soweit so gut. Bei einem Power-up wird geprüft, 
ob im EEPROM ein Wert abgespeichert wurde. Wenn ja, wird der Wert an 
PORTB gegeben und das Byte im EEPROM wieder "rückgesetzt" (s. BOOKMARK 1 
im Quelltext). Im Simulator funktioniert alles bestens, in der Realität 
leider nicht. Der Wert 0 wird nicht ins EEPROM geschrieben. Ich hab dann 
den Write-Befehl auskommentiert und die komplette if-Abfrage weiter 
unten ( nach sei() ) reinkopiert (s. BOOKMARK 2). Jetzt wird der Wert 0 
geschrieben, allerdings funktioniert hier der Read-Befehl nicht - also 
habe ich ihn wieder auskommentiert. Sprich: so wie das Programm im 
Moment aussieht, macht es genau das was ich will. Nur, warum 
funktioniert einmal eeprom_write_byte (BOOKMARK 1) und einmal 
eeprom_read_byte (BOOKMARK 2) nicht? Bin vollkommen verwirrt und hoffe 
auf Antworten. Leider habe ich über die Suchfunktion nichts in Erfahrung 
bringen können. Mit den neusten Versionen von AVRStudio und WINavr haut 
es übrigens auch nicht hin.

Das ganze läuft auf einem ATmega168. Ich benutze AVRStudio 4.12 SP4 und 
WinAVR 20060421.

von holger (Gast)


Lesenswert?

Verzwickte Geschichte nicht war ;) Simulation und Realität
sind meistens zwei unterschiedliche Dinge.

Eine konkrete Lösung hab ich für dich jetzt nicht, aber
vieleicht ein paar Tips.

eeprom_write_byte(); wartet nicht auf das Ende des Schreibvorganges.
Man sollte aber besser darauf warten:

    eeprom_write_byte(EEP_VOLUME,volume);
    eeprom_busy_wait();

Hast du den Brown-Out Reset aktiviert ?
Evtl. schlägt der zu bevor du in die Analog-Komparator ISR kommst.

Das schreiben ins EEPROM dauert ein paar Millisekunden.
Wenn die Versorgungsspannung zu schnell fällt kann das
Probleme machen.

Das hier ist auch problematisch:

ISR ( ANALOG_COMP_vect)
{
  eeprom_write_byte(&output_backup, PINB);
}

Da fehlt auf jeden Fall das eeprom_busy_wait();
Das Programm kann bei langsam fallender Spannung auch
SEHR oft hier reinspringen. Das ist nicht gut fürs EEPROM !
Evtl. einfach ne Endlosschleife hinter eeprom_write_byte();
setzen und hoffen das entweder der Brown-Out Reset oder
der WDT einen sauberen Reset hinlegt. Oder die ISR abschalten.

von Jochen Ruf (Gast)


Lesenswert?

Hallo Holger,

vielen Dank für deine Antwort. Leider verbessert sich durch 
eeprom_busy_wait() nichts. Brown-out ist die ganze Zeit deaktiviert. Mir 
ist klar, dass der Komparator am Schwellwert etwas zu klappern anfängt 
und dann evtl. mehrfach das gleiche Byte beschrieben wird. Das 
wollte/will ich noch korrigieren. Unverständlich bleibt für mich, dass 
die read/write Funktionen an den Stellen, wo ich sie verwende so 
merkwürdige Dinge veranstalten. In der ISR funktioniert das Schreiben in 
100% der Fälle. Ok, vielleicht ist das so, weil durch mein Poti die ISR 
mehrmals getriggert wird und der Wert in die Zelle reingehämmert wird 
:-) Ich habe zwischenzeitlich herausgefunden, dass häufiges reseten 
machnmal den Wert 0 ins EEPROM schreibt. Also manchmal klappts. Delays 
haben mich auch nicht weiter gebracht :-(

von Falk B. (falk)


Lesenswert?

@  Jochen Ruf (Gast)

>eeprom_busy_wait() nichts. Brown-out ist die ganze Zeit deaktiviert. Mir

Das ist eher schlecht. Welche AVR Fuses hast du denn gesetzt? Du 
sollte auf jeden Fall die längste Startup-zeit einstellen, Brown Out 
wäre noch besser.

>ist klar, dass der Komparator am Schwellwert etwas zu klappern anfängt
>und dann evtl. mehrfach das gleiche Byte beschrieben wird. Das

Nöö. Wie holger schon sagte, nach dem Erkennen des Spannungsausfalls 
muss deine CPU auf ihre Ende warten. So.

1
ISR ( ANALOG_COMP_vect)
2
{
3
  eeprom_write_byte(&output_backup, PINB);
4
  while(1);
5
}

Hier wird ggf. der Compiler mosern, muss man aber ignorieren. Denn 
wenn die Schaltschwelle einmal unterschritten ist, darf das Programm 
keinen Schritt weiter laufen sondern muss auf das Ende aller Tage 
warten. Mit Brown Out wird das Solide, ohne eine Zitterpartie.

>wollte/will ich noch korrigieren. Unverständlich bleibt für mich, dass
>die read/write Funktionen an den Stellen, wo ich sie verwende so
>merkwürdige Dinge veranstalten. In der ISR funktioniert das Schreiben in

Das sind wahrscheinlich sporadische Resets, wenn die Spannung fällt. 
IOhne Brouwn Out kann die CPU komische Dinge veranstalten.

>machnmal den Wert 0 ins EEPROM schreibt. Also manchmal klappts. Delays
>haben mich auch nicht weiter gebracht :-(

Daran liegt es selten.

MfG
Falk

von Jochen Ruf (Gast)


Lesenswert?

Ahhh... jetzt hab ich's kapiert. Jungs ihr seid spitze! Ist ja 
eigentlich logisch, dass der Controller nach der Unterspannungserkennung 
definiert hängen bleiben muss/sollte. Holger hats ja schon geschrieben, 
bei Falks Erklärung ist dann der Groschen gefallen.

Ich habe gestern nach meinem Post die ANALOG_COMP ISR mal komplett 
deaktiviert und siehe da, die read/write Funktionen machen genau was sie 
sollen, egal wo sie im Programm vorkommen. Hätte mich auch gewundert. 
Mit der Endlosschleife in der ISR und der Brown-out Abschaltung sollte 
es jetzt funktionieren. Vielen Dank und schönes Wochenende.

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.