Hallo allerseits! Ich habe ein kleines Problem mit meinem Programm. Und zwar will ich eine LED über ein Poti dimmen. Dazu verwende ich den Mega8 und dessen ADC Eingang. Außerdem will ich haben, dass nach dem Einschalten der Spannungsversorgung die LED in der Helligkeit leuchtet, wie beim Ausschlalten. Dazu schreibe ich alle 8 sek. den Helligkeitswert in das EEprom. NUR: Beim Schreiben in das EEprom flackert die LED, d.h. alle 8 Sekunden. Kann mir jemand sagen, warum das so ist? Mache ich irgendwo einen Fehler? Ich habe die Datei im Anhang (BASCOM). Vielen Dank für Eure Hilfe!! mfg Andy
Beim EEprom schreiben muss eine bestimmte Sequenz eingehalten werden und das Timing ist eher kritisch. Daher wird BASCOM wahrscheinlich die Interrupts kurzzeitig abschalten was dein Timing durcheinander bringt.
Schau mal ins Datenblatt, wie lange ein Schreibzugriff (ein Byte) auf das EEPROM dauert. Das ist afaik im ms-Bereich. Wenn Du einen long-Wert (sind das bei BASCOM auch 32 Bit?) hineinschreibst, dann dauert das entsprechend länger. Der Compiler muss natürlich auch dafür sorgen, dass während des Schreibens ins EEPROM keine Interrupts auftreten, so dass das Programm an sich komplett unterbrochen wird, wenn geschrieben wird. Und Störungen im Bereich einiger ms kann man durchaus schon optisch wahrnehmen. Da ich allerdings von BASCOM keine Ahnung habe, habe ich mir das Programm jetzt nicht genauer angesehen und weiß deshalb nicht, wie die LED genau angesteuert wird....
Hab grad mal nachgeschaut: Die (typ.) Schreib-Zugriffszeit für das EEPROM liegt bei sage und schreibe 8,4 ms! Wenn man da mehrere Bytes direkt hintereinander ablegt, dann ist das Programm entsprechend lange unterbrochen...
Erstmal danke für Eure Antworten. OK, d.h. wenn ich eine Long-Variable ins EEprom schreibe, nimmt das schon ca. 32ms in Anspruch. Ist klar, dass das dann flackert. Wie könnte ich dann eine sinnvolle Sicherung der Helligkeit vornehmen? Ich wollte schon den ADC-Interrupt nehmen. Aber wenn ich das Poti dann von null auf hundert drehe, dann wird das EEprom ja 100x beschrieben, oder? Das wäre auch nicht sinnvoll! Ich bin für jeden Tipp dankbar!! mfg Andy
Ich weiß nicht, ob ich das Programm richtig verstehe, aber versuchst Du da, so was wie eine Software-PWM zur Helligkeitssteuerung zu machen? Wenn ja, dann wird sich das Problem wahrscheinlich nur mit einer Hardware-PWM umgehen lassen. Die ist nämlich unabhängig vom Programmablauf, da der Timer den zugehörigen Pin selber toggelt.
Du könntest die Betriebsspannung überwachen, und sobald diese unter einen bestimmten Wert fällt, deine Helligkeit sichern. Weiterhin könntest du überprüfen, ob sich die Potistellung geändert hat. Das wird in relativ grossen Abständen gemacht, und dann muß der Poti-Wert auch über einen gewisesn Zeitraum konstant bleiben, um gesichert zu werden.
Ja, ich mache die Helligkeitssteuerung über Software-PWM. OK, dann muss ich es wohl über HW-PWM machen. Nur habe ich damit keine Erfahrungen. Gibt es irgendetwas, was ich beachten muss? Ist das sehr schwierig?? THX
Das ist im Prinzip leichter als eine Soft-PWM, weil Du den Timer einmal startest und nur von Zeit zu Zeit mal einen neuen Wert ins Compare-Register schreiben musst und ansonsten keine Aktionen im Programm durchführen musst. Ansonsten macht der Timer nämlich alles selber. Du müsstest Dir "nur" im Datenblatt die entsprechenden Infos zusammensuchen... Das ist da allerdings recht ordentlich tabellarisch zusammengefasst. BTW: > Incr Zaehler > If Zaehler = 1 Then > Zaehler = 0 Das kommt mir selbst als BASCOM-Unwissender etwas komisch vor. Wenn Zaehler beim Einsprung in die Routine 0 ist, wird um 1 erhöht, abgefragt, ob 1 ist (was ja dann immer der Fall sein dürfte) und wieder auf 0 gesetzt. Die drei Zeilen kannste also vermutlich weglassen, es sei denn, ich habe das Konzept irgendwie nicht durchschaut...
Ach ja, Du musst die LED dann natürlich auch an den entsprechenden Pin hängen. Timer 0 hat beim Mega8 leider keine Compare-Einheit, deshalb müsstest Du dann entweder Timer 1 oder 2 nehmen. Dann die LED an den entsprechenden Compare-Ausgang (OC1A, OC1B oder OC2), den jeweils korrekten PWM-Modus einstellen und los gehts...
@ johnny: Du hast schon recht: Diese Abfrage ist sinnlos. Ich habe hier vorher einen anderen Wert als 1 stehen gehabt, um das EEprom nicht zu oft zu beschreiben. Ich habe dann nur "testhalber" 1 hingeschrieben. OK, dann werde ich das ganze mit HW-PWM versuchen! Vielen Dank für die Hilfe!!! mfg Andy
Während des EEPROM-Schreibens muß überhaupt kein Interrupt disabled werden, sondern nur für die Dauer der 2 Befehle, die das Schreiben einleiten. Du brauchst also nur das EEPROM-Schreiben selber programmieren. Ich würde allerdings auch noch vor dem Schreiben erstmal vergleichen, ob schon das richtige drinsteht, dann sparst Du massig Schreibzyklen. Peter
@ PeDa Und wie kann ich das EEprom-Schreiben selber programmieren? Hab davon überhaupt keine Ahnung! Wäre toll, wenn du mir helfen könntest! Andy
>Und wie kann ich das EEprom-Schreiben selber programmieren? Hab davon >überhaupt keine Ahnung! Da könnte ein Blick ins Datenblatt helfen. Dort ist beschrieben, wie man sowas macht; allerdings in Assembler oder C.
Da müsstest Du das Datenblatt bemühen, da steht das detailliert drin. Ich gehe aber mal davon aus, dass das Problem ein ganz anderes ist (nachdem ich mir Dein Programm doch mal näher angeschaut habe): Du schreibst innerhalb eines Interrupt-Handlers mehrere Bytes direkt hintereinander ins EEPROM, was, wie oben schon angedeutet, einige -zig Millisekunden dauert. Da während eines Interrupt-Handlers die Bearbeitung aller anderen Interrupts (inklusive desjenigen, der die LED umschaltet) deaktiviert ist, ist es nicht der EEPROM-Zugriff an sich, der das Flackern verursacht, sondern eben die Tatsache, dass Du Dir durch den Zugriff im Interrupt-Handler das Programm blockierst. Ich vermute auch, dass BASCOM so schlau ist wie Peter und nach den Schreib-Befehlen die Interrupts wieder freigibt. Wenn Du das EEPROM im Hauptprogramm schreibst, dürfte sich das Problem erledigen.
Nun, ganz genau so, wie es im Datenblatt angegeben ist: - Adreßregister setzen - Datenregister setzen - Interrupt sperren - Schreibbefehle ausgeben - Interrupt freigeben - pollen bis Schreibbit auf fertig steht Und das für jedes Byte, d.h. einen mehrbytigen Wert erst in ein Bytefeld schreiben, unter C nennt sich das ne Union. Peter
Da hat Johnny voll recht. EEPROM schreiben im Interrupt ist natürlich verboten ! Peter
@Johnny Daran hab ich auch schon gedacht, aber nur wird mir dann das EEprom nach ein paar Stunden verrecken, oder. Es hält ja nur 100.000 Schreib- und Lesezyklen aus, oder? Oder ich lasse im Hauptprogramm ein Zählvariable mitlaufen, und erst bei Erreichen eines Wertes schreibe ich ins EEprom. Was sagst du??
Du brauchst nur in der Interrupt-Routine, in der Du sonst das EEPROM geschrieben hast, eine (Bit-) Variable zu setzen, die Du im Hauptprogramm abfragst. Wenn sie gesetzt ist->EEPROM schreiben und Variable wieder löschen.
BTW:
> Es hält ja nur 100.000 Schreib- und Lesezyklen aus, oder?
Nein, es hält mindestens 100000 Schreib- Lösch- Zyklen aus. Das
Lesen hat keinen Effekt auf die Lebensdauer, wäre auch schlimm. Das
heißt aber auch nur, dass ATMEL diese Anzahl garantiert, in der
Realität der Wert aber sicher weit darüber liegt. Wenn Dein EEPROM
schon nach 99999 Lösch-Schreib-Zyklen den Geist aufgibt, dann muss
ATMEL Dir einen neuen µC schenken, vorausgesetzt, Du kannst das
nachweisen, dass es tatsächlich nur 99999 waren....
Und die Schreib-Löschzyklen beziehen sich auf "eine" Zelle. Wenn du nach X Schreibzyklen auf eine andere Zelle wechselst, hast du bei der auch wieder 100000 Schreib-Löschzyklen. MW
> ... flackert trotzdem!
Dann ist BASCOM wohl doch nicht so schlau wie ich dachte. Ich weiß
schon, warum ich in C und Assembler programmiere (Tschulligung, der
Kommentar musste jetzt sein;-). Also deaktiviert BASCOM anscheinend
tatsächlich für die komplette Dauer des Schreibvorganges das I-Bit...
Dann wirst Du wohl doch nicht umhin kommen, es entweder mit einer
HW-PWM zu versuchen, oder tatsächlich dass EEPROM-Schreiben selber zu
programmieren. Beides bedeutet allerdings ein Studium des Datenblattes
an den entsprechenden Stellen.
Übrigens: Eine Soft-PWM ist zwar nett zum Lernen, wird aber eigentlich
i.d.R. nur dann eingesetzt, wenn eine HW-PWM aus irgendwelchen Gründen
nicht möglich ist (keine Compare-Einheit frei, zu viele Kanäle
erforderlich...). Der Mega8 hat 3 PWM-Kanäle (1 8-Bit vom Timer 2 und
zwei mit je max. 16 Bit vom Timer 1). Da sollte doch was möglich
sein...
@Michael:
Genau! Man muss dann nur irgendwo (natürlich ebenfalls im EEPROM)
ablegen, in welcher Zelle man grad ist (Zähler).
Mal nur interessehalber... wenn der Poti eh den Wert der PWM vorgibt, warum musst du dann den alten wert speichern? Wenn du beim Programmstart den Potiwert einliest, hast du ja den "alten" Wert wenn der Poti nicht bewegt wurde... wurde es bewegt, änderst du den Wert eh beim nächsten inlesen auf den neuen Wert...
Das ist das eine. Das andere ist: Bevor man einen neuen Wert schreibt, sollte man den alten Wert erst mal auslesen und feststellen ob ein Schreiben überhaupt notwendig ist. Sowas verlängert die Lebensdauer des EEprom ungemein.
und ins EEPROM schreiben braucht man auch erst wenn das µC abgeschalten werden soll. Ich würde es so machen Poti-Wert vom ADC ins SRAM schreiben und den ADC auch die Betriebsspannung messen lassen wenn diese dann runtergeht weil die Spannungsversorgung ausgeschalten wurde schreibts du die Daten erst ins EEPROM. Die Abfrage ob sich was geändert hast kannste dir dann auch sparen, weil das Schreiben ins SRAM auch so lange dauern wird wie die Abfrage mit dem Sprungbefehl selbst.
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.