Hallo zusammen nach langer Zeit programmiere ich nun wieder was mit dem AVR Studio. Bei meinem derzeitigen Projekt will ich meinen ATmega88 in den PowerDown versetzen, wenn die Leuchtstärke einer Fotodiode unter einen bestimmten Wert fällt. Die Leuchtstärke bestimme ich mittels eines A/D-Wandlers. Befindet sich der uc nun im SleepMode soll er wieder aufwachen, wenn es hell wird. Ich hab im Datenblatt auch gelesen, dass man die ext. Interrupts so definieren kann, dass sie entweder bei pos. Flag, neg. Flag, low level, logical change auslösen. Desweiteren hab ich mir überlegt zwischen Sensor und ATmega eine Z-Diode zu schalten, das es aber einer bestimmten Spannung ein Durchbruch kommt und somit ein Signal an den ATmega kommt. Welche Interrupteinstellung sollte ich denn in diesem Fall nehmen? Am besten das er bei pos. Flag aufwacht oder? Kann die Interruptroutine überhaupt ausgeführt werden, wenn sich der uc im Powerdown befindet? Was muss ich dann beachten? Hab irgendwo gelesen, dass ich dem Quarz eine Zeit zum Einschwingen lassen muss, damit keine Programmfehler auftreten. Was passiert überhaupt im PowerDown Mode? Schläft da im Grunde alles? So, jetzt ist erstmal genug mit Fragen :P Danke schonmal im Voraus für eure Antworten ^^ Grüßle Alex
@ Sacx (Gast) >Wert fällt. Die Leuchtstärke bestimme ich mittels eines A/D-Wandlers. >Befindet sich der uc nun im SleepMode soll er wieder aufwachen, wenn es >hell wird. Naja, dann darf er aber nicht zu fest schlafen. In allen wichtigen Sleep Modi ist der ADC tot. >Ich hab im Datenblatt auch gelesen, dass man die ext. Interrupts so >definieren kann, dass sie entweder bei pos. Flag, neg. Flag, low level, >logical change auslösen. Ja. >Desweiteren hab ich mir überlegt zwischen Sensor und ATmega eine Z-Diode >zu schalten, das es aber einer bestimmten Spannung ein Durchbruch kommt >und somit ein Signal an den ATmega kommt. Nicht sonderlich sinnvoll. Alles sehr ungenau und stromfressend. >So, jetzt ist erstmal genug mit Fragen :P Fast alle Antworten findest du im Artikel Sleep Mode. MfG Falk
>>Desweiteren hab ich mir überlegt zwischen Sensor und ATmega eine Z-Diode >>zu schalten, das es aber einer bestimmten Spannung ein Durchbruch kommt >>und somit ein Signal an den ATmega kommt. > > Nicht sonderlich sinnvoll. Alles sehr ungenau und stromfressend. Die Sache ist ja die... der Sensor sollte standardmäßig am A/D-Wandler hängen. Mit diesem messe ich die Leuchtstärke alle paar Minuten und bearbeite den Wert dann programmintern. Wenn der Sensor nun irgendwann einen zu geringen Wert liefert, möchte ich den PowerDown-Mode einschalten. Davor muss ich ja noch den A/D-Wandler deaktivieren oder? Wenn die Lichstärke nun wieder über einen Schwellenwert steigt, soll der Prozessor wieder aufwachen. Da die A/D-Wandlung ja deaktiviert ist, muss ich den Sensor gleichzeitig auch noch an INT0 oder INT1 (Eingang für ext. Int.) anschließen, damit der Prozessor wieder aufgeweckt wird. Wenn ich nun nichts zwischen Sensor und uc schalte, könnte ja schon ein schwacher Lichteinfall für eine Flag sorgen oder? Deswegen hab ich mir überlegt was davorzuschalten, das wirklich erst aber einer bestimmten Lichtstärke ein Flag kommt. Oder habt ihr eine Idee das iwie anders zu lösen?
Ich denke was Du brauchst ist ein Komparator mit Hysterese am Int-Pin. Damit kannst du Dir den Helligkeitswert einstellen und du bekommst auch ne gescheite Flanke. Gruß Bad Urban
Du kannst den Watchdoginterrupt zum Aufwachen nehmen, z.B. alle 2s, dann ne Messung machen und wieder schlafen gehen. Peter
@ Sacx (Gast) >hängen. Mit diesem messe ich die Leuchtstärke alle paar Minuten und Alle paar Minuten? Da kann der uC ja 1.000.000mal dazwischen schlafen gehen. >bearbeite den Wert dann programmintern. Wenn der Sensor nun irgendwann >einen zu geringen Wert liefert, möchte ich den PowerDown-Mode >einschalten. Viel zu spät, siehe Sleep Mode. >Davor muss ich ja noch den A/D-Wandler deaktivieren oder? Wenn du Strom sparen willst. >Wenn die Lichstärke nun wieder über einen Schwellenwert steigt, soll der >Prozessor wieder aufwachen. Da die A/D-Wandlung ja deaktiviert ist, muss >ich den Sensor gleichzeitig auch noch an INT0 oder INT1 (Eingang für >ext. Int.) anschließen, damit der Prozessor wieder aufgeweckt wird. kann man machen, ist hier aber wahrscheinlich nicht sinnvoll. Schick deinen uC in den Power Save Mode und miss alle paar Minuten das Signal, so wie sonst auch. Das spart genug Strom. >Wenn ich nun nichts zwischen Sensor und uc schalte, könnte ja schon ein >schwacher Lichteinfall für eine Flag sorgen oder? Deswegen hab ich mir >überlegt was davorzuschalten, das wirklich erst aber einer bestimmten >Lichtstärke ein Flag kommt. ??? Licht macht erstmal gar kein Flag, sondern bestenfalls eine Spannung an deinem Sensor. Die kann man per ADC oder Komparator auswerten. Die Software macht dann ggf. ein Flag draus. MFG Falk
Vielen Dank für eure Antworten. Ich ziehe es jetzt glaub vor einen Power Save Mode zu benutzen. Dieser wird ja über den Timer2 Interrupt aufgeweckt. Nun könnte ich mit einem 32,768khz Quarz das Auftreten eines Interrupt alle 8Sekunden erreichen. Was für meinen Fall ausreichend ist. Der uc sollte nämlich die ganze Nacht "schlafen" bis ihn morgens die ersten Sonnenstrahlen komplett aus dem Schlaf reißen ^^ Wenn ich nun bei einem bestimmten Ereignis (z.b. das Verfahren eines Motors) die Interruptzeit für ein paar Sekunden auf 125ms setzen will, was muss ich dann machen? Muss ich in diesem Fall dann die Interrupts ausschalten, den Timer2 neu definieren, die Interrupts einschalten... warten bist der Motor verfahren ist, dann wieder ausschalten, alten Wert einstellen und wieder einschalten? würde das so in etwas funktionieren? oder gäbe es da noch einfachere Möglichkeiten?
@ Sacx (Gast) >Wenn ich nun bei einem bestimmten Ereignis (z.b. das Verfahren eines >Motors) die Interruptzeit für ein paar Sekunden auf 125ms setzen will, >was muss ich dann machen? Man könnte den Presclaer von Timer 2 ändern. Wenn man den nicht als Zeitbasis braucht, ist das OK. Einfacher und besser, weil dann nämlich Timer 2 normal mit konstanter Frequenz weiterläuft, ist die Nutzung eines anderen Timers, z.B, Timer 0. Für die paar Sekunden schickt man den uC auch nicht mehr in den Sleep Mode, sonder arbeitet erst die "schnellen" Aufgaben ab. > Muss ich in diesem Fall dann die Interrupts >ausschalten, den Timer2 neu definieren, die Interrupts einschalten... >warten bist der Motor verfahren ist, dann wieder ausschalten, alten Wert >einstellen und wieder einschalten? würde das so in etwas funktionieren? Ja, ist aber unnötig kompliziert und fehleranfällig. MFG Falk
Okay das klingt vernünftig :) Soweit ich das mitbekommen habe wird der Sleep Mode ja ständig neu in der Hauptschleife (while(1)) aufgerufen oder? Die Konfiguration des Timers2 mache ich schon davor. Genauso wie die Ausschaltung des ADC Wandlers, weil dieser anscheinend einiges an Strom zieht. Wenn nun der Timer2 überläuft, wird der Interrupt ausgeführt und ich wollte i inkrementieren lassen, damit ab nem bestimmten Zeitpunkt (ein paar Minuten) eine ADC Messung durchgeführt wird. Beispiel:
1 | ISR(TIMER2_OVF_VECT) //mit Prescaler auf 4s pro OVF eingestellt |
2 | |
3 | {
|
4 | i++; |
5 | |
6 | if(i==150) //d.h nach 600s sprich 10min eine Messung |
7 | |
8 | {
|
9 | LDR_Messung(); //Unterprogramm zur Messung von 4LDRs und Vergleich |
10 | } //der Werte. In diesem Unterprogramm müsste ich ja |
11 | } //zu Beginn den ADC aktivieren und nach der Messung |
12 | //wieder deaktivieren oder?
|
Falls diese zwei von diesen vier Werten nicht "annähernd" übereinstimmen, soll der Motor gestartet werden und die Sensoreinheit wieder in Position bringen, weshalb dabei auch viele Messungen aufeinander folgen sollen um den Motor richtig zu verfahren. Ich würde im Falle einer Abweichung also in ein weiteres Unterprogramm springen in dem dann, solange der Motor verfährt, mehrere Messungen durchgeführt werden. Dies könnte ich ja entweder mit dem Timer0 machen, den ich dann zu Beginn der Messung initialisieren müsste oder was ich mir grad überlegt habe einfach eine if-Schleife zu nehmen, die wenn alle 4 Messwerte ungefähr den gleichen Wert liefern, den Motor stoppt und das Programm wieder in die while-Schleife lässt, wo das System wieder in den Power Save Mode gelangt. Könnte das ungefähr so hinkommen? Noch ne Frage: Wenn nun der OVF-Interrupt ausgelöst wird und er meine Unterprogramme abarbeitet, läuft dann im Hintergrund der OVF weiter, also könnte während des einen Interrupts ein weiterer auftreten? Wenn ja, kann ich das ganze dann mit den Befehlen cli(); (Interrupts deaktivieren) zu Beginn der LDR Messung und sei(); (Interrupts aktivieren) am Ende der Messung bzw des Verfahrens des Motors unterbinden? Grüße sacx
Ich finde da könnte man schon einen kleinen Zustandsautomaten draus machen: Zustand 1: Schalfen Der Microcontroller legt sich schlafen und wird über einen Timerinterrupt mit langsamer Zeitbasis gelegentlich geweckt um dann alle 2 min (oder so ähnlich) in den Zustand 2 zu wechseln. Zustand 2: Kontrollmessung es wird eine ADC durchgeführt, Timerinterrupt kann dafür ja deaktiviert sein. Je nachdem ob der Schwellwert erreicht wird oder nicht, wird danach zurück in den Zustand 1 gewechselt, oder der Zustand 3 aufgerufen. Zustand 3: Ausrichten Hier wird abwechselnd das Verfahrprogramm und ein Messprogramm aufgerufen. Hier muß die Zeitbasis schneller sein als in Zustand 1, un das ist meine ich der Vorteil der Statemachine - Abhänging vom zustand werden z.B. die Timer anders eingestellt. Ist das Ausrichten zufridenstellend abgeschlossen, wird wieder in Zustand 1 gewechselt. Gruß, Jan
@ Sacx (Gast) >Soweit ich das mitbekommen habe wird der Sleep Mode ja ständig neu in >der Hauptschleife (while(1)) aufgerufen oder? Ja. >Die Konfiguration des Timers2 mache ich schon davor. Ja. > Genauso wie die Ausschaltung des ADC Wandlers, weil dieser anscheinend einiges an Strom >zieht. Nein, der wird IN der Hauptschleife an- und ausgeschaltet, natürlich gesteuert duch Bedingungen. > { > LDR_Messung(); //Unterprogramm zur Messung von 4LDRs und Vergleich > } //der Werte. In diesem Unterprogramm müsste ich ja >} //zu Beginn den ADC aktivieren und nach der Messung //wieder deaktivieren oder? Nicht gut. Solche Sachen gehören nicht in einen Interrupt, das macht man in der Hauptschleife. Steht alles im Artikel. >4 Messwerte ungefähr den gleichen Wert liefern, den Motor stoppt und das >Programm wieder in die while-Schleife lässt, Das Programm läuft fast immer in der Hauptschleife. Im Interrupt wird nur minimal Arbeit verrichtet und Flags gesetzt. >Könnte das ungefähr so hinkommen? Grob ja, im Detail nein. Siehe oben. >Wenn nun der OVF-Interrupt ausgelöst wird und er meine Unterprogramme >abarbeitet, läuft dann im Hintergrund der OVF weiter, also könnte Ywährend des einen Interrupts ein weiterer auftreten? Ja, wenn dein Unterprogramme zu lange dauern. Deshalb macht man das nicht so. > Wenn ja, kann ich >das ganze dann mit den Befehlen cli(); (Interrupts deaktivieren) zu >Beginn der LDR Messung und sei(); (Interrupts aktivieren) am Ende der >Messung bzw des Verfahrens des Motors unterbinden? Unsinning, im Interrupt sind diese beim AVR sowieso gesperrt. Lies den Artikel Interrupt. MFG Falk
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.