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
@ 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