Hi, ich hab ein Problem mit dem Power Down Modus.
Ich krieg meinen Tiny da einfach nicht raus.
Meine schaltung:
attiny13 steuert ein paar leds.
An Pin6 (PB1 / INT0) hab ich einen einen Taster, der gegen Masse
schaltet.
Der interne Pull-Up ist aktiviert.
Das schalter auslesen und ansteuern der LEDs klappt alles Prima.
Auch in den Power Down-Modus versetzen kann ich ihn:
1
LED_OFF(LED_R);
2
LED_OFF(LED_G);
3
LED_OFF(LED_B);
4
set_sleep_mode(SLEEP_MODE_PWR_DOWN);// aus avr/sleep.h
5
GIMSK|=(1<<INT0);
6
sleep_mode();// aus avr/sleep.h
7
GIMSK&=~(1<<INT0);
Vor dem Schlafen schicken aktiviere ich Int0.
Aber wenn ich dann auf den schalter drücke passiert rein gar nix, er
bleibt aus.
Hoffe jemand hat ne idee
da ich das MCUCR register nirgends beschreibe, sollte das der Fall
sein,werds heut abend noch mal explizit probieren.
Mir ist aber nicht ganz klar, was der Unterschied zwischen Low-Level und
fallende Flanke ist.
Beides ist active-low. LowLevel wird nur immer wieder aufgerufen,
solange der pin auf masse liegt, oder wie? wie ist da die wiederholrate?
sobald er aus der ISR raus ist?
Meine schaltung ist aber nicht das Problem?
>// externer Interrupt INT0>>// Die Interruptroutine kann leer sein, ABER sie muss existieren!>// Sonst springt der AVR nach dem Aufwachen zum Reset, weil kein sinnvoller>// Interruptvektor eingetragen ist!>>ISR(INT0_vect) {>}
Bei mir ist die ISR leer.
kann es sein, dass der Compiler ne leere Routine wegoptimiert?
vlad schrieb:
> Aber wenn ich dann auf den schalter drücke passiert rein gar nix, er> bleibt aus.
Man könnte jetzt versuchen, Dir alle Würmer aus der Nase zu ziehen.
Du könntest aber auch ganz profan nen compilierfähigen Code (*.c) als
Anhang posten, geht deutlich schneller.
Allgemein kann man nur die sleep.h zitieren:
"the sleep_mode() macro might cause race conditions in some situations"
Oder deutlicher: Das sleep_mode() gehört verboten!
Peter
So habe ein Problem gefunden Hatte tatsächlich vergessen die interupts
wieder zu aktivieren.
Nu hab ich aber ein neues Problem.
Hab das ganze auf beigefügten Code reduziert (hoffe habe nix vergessen
reinzukopieren)
wenn ich das cli weglasse, geht alles, außer dass mir hin und wieder der
Timer dazwischenfunkt und die leds wieder anschaltet.
um das zu verhindern, will ich nach dem Tastendruck bis zum sleep_cpu
die Interupts sperren.
jedoch wacht der tiny sofort wieder auf.
Weiß da jemand rat?
>//cli(); // <-- wenn das aktiv ist, dann geht er sofort aus dem
4
>powerdownraus
5
>
Ist doch richtig, denn der Pin ist ja low, sonst wäre ja das while()
nicht verlassen worden.
Die Delays kannst Du in der Pfeife rauchen.
Tastendruck entprellen und Flanke erkennen sieht anders aus.
Mach Dir mal nen PAP, wie das Sleep gestartet und wie es wieder
verlassen werden soll.
Beides mit dem Zustand Pin = low kann nicht gehen. Dann machst Du nur
beides schnell hintereinander.
Es müssen unterschiedliche Bedingungen sein.
Peter
P.S.:
Wenn Du schon Delays benutzt, was stört Dich daran, es lesbar zu machen,
d.h. die Zeit direkt in µs oder ms anzugeben?
>Ist doch richtig, denn der Pin ist ja low, sonst wäre ja das while()>nicht verlassen worden.
Was hat das mit dem cli zu tun?
es läuft kein anderer Int als der Timer und der Int0, der später gesetzt
wird.
die delays sind bloß für des minimalbeispiel da, in meinem Programm sind
die Tasten "ordentlich" entprellt
> Mach Dir mal nen PAP, wie das Sleep gestartet und wie es wieder> verlassen werden soll.
Was bitte ist PAP
das sleep soll beginnen, wenn taste lang gedrückt wurde.
dann wird ein blinksignal ausgegeben (da ist genug zeit die Taste
loszulassen)
dann power down.
bei erneuten tastendruck soll er wieder aufwachen.
das einschläfern und aufwecken funktioniert auch, bis auf das
Blink-signal , da hier der Timer dazwischen funkt und die LEDs
verstellt.
deaktiviere ich die Interrupts, dann sehe ich das Blinken aber er läuft
direkt weiter aus dem PowerDwon raus, obwohl der Taster schon seit ner
sekunde nicht mehr gedrückt wird.
folgendes kommt dem orignal näher:
vlad schrieb:
> Was bitte ist PAP
Programm-Ablauf-Plan
> das sleep soll beginnen, wenn taste lang gedrückt wurde.
Schön das endlich zu wissen.
Jedoch sehe ich nirgends Code für Langerkennung.
> folgendes kommt dem orignal näher:
Das ist nicht schön, daß Du uns so verscheißerst.
Mit nur "näher kommen" ist keinem gedient.
Schreibe einen Code, lasse ihn laufen und erst dann poste Fragen, die
auch auf diesen getesteten Code passen!
Wenn Du immer nur irgendwas ausgedachtes hinschreibst, brauchst Du Dich
nicht zu wundern, daß die Antworten nicht auf Deinen unbekannten Code
passen.
Peter
>Jedoch sehe ich nirgends Code für Langerkennung.
die Langerkennung funktioniert und ist nicht teil des Problems deswegen
ist sie in der Kurzvariante nicht drin.
>Schreibe einen Code, lasse ihn laufen und erst dann poste Fragen, die>auch auf diesen getesteten Code passen!
der Code, den ich gepostet habe ist der, an dem ich grad rumprobiere.
Bei ihm tritt das selbe Problem auf, wie in meiner eigendlichen
Anwendung.
Warum also willst du den gesammten Code (der Tiny13 ist bei 95%), wenns
in dieser Minimalvariante genauso ersichtlich ist?
Die neue Variante habe ich nur gepostet, damit ersichtlihc ist, dass es
kein Problem des Tasters ist, der noch gedrückt ist, wenn in den
sleep-mode gegangen wird, ansonsten ist die Problematik die selbe, wie
bei der ersten Code-Variante.
Wenn du dir den Code angeschaut oder gar ausprobiert hättest (mehr als
ne LED und ein Taster ist dafür ja nicht nötig), wüstest du das
Ich habe alles was ich poste getestet.
Das einzige was an meinem Code anders ist, ist, dass ich nicht
angesprungene Funktionen entfernt habe.
vlad schrieb:
> Die neue Variante habe ich nur gepostet, damit ersichtlihc ist, dass es> kein Problem des Tasters ist, der noch gedrückt ist, wenn in den> sleep-mode gegangen wird
Du mußt ihn nach dem Drücken innerhalb von 2s loslassen (100*20ms
Warteschleife), dann sollte es funktionieren. Es ist also höchstens ne
Kurzdruckerkennung.
> Wenn du dir den Code angeschaut
Das habe ich, sonst hätte ich ja nicht erkannt, daß da garkeine
Langerkennung drin ist.
Das Du eine Routine postest, die nicht das macht, was Du erklärst, ist
zumindest verwirrend, auch wenn da nicht der Fehler ist.
Wenn Dich der Timerinterrupt stört, dann deaktiviere ihn einfach vor dem
Sleep.
Deaktiviere alle Interrupts, die nicht zum Aufwachen benötigt werden.
Dem Sleep ist es nämlich wurscht, welcher Interrupt es beendet.
Peter
> Du mußt ihn nach dem Drücken innerhalb von 2s loslassen (100*20ms> Warteschleife), dann sollte es funktionieren.
es funktioniert ebend nicht, bzw nur, wenn ich die Interupts NICHT
deaktiviere.
Wenn das cli() weg ist, gehts, aber der timer fummelt halt bei dem
Blink-signal dazwischen, dafür bleibt der tiny aber im power down.
wenn das cli() da ist, mag er nicht schlafen.
>Dem Sleep ist es nämlich wurscht, welcher Interrupt es beendet.
nur der int0 (und der wachhund, den ich nicht hab) kann den aufwecken
So, ich habs mal selber ausprobiert.
Es funktioniert alles bestens, wenn man ne ordentliche Entprellroutine
nimmt.
Die Taste wechselt zwischen Schlafen und Wachen hin und her. Das
Schlafen darf natürlich erst nach Loslassen erfolgen.
Und hier der komplette Code:
es liegt nicht an der Entprellung!
wenn ich anstatt des cli() auch nur den timer deactiviere dann gehts bei
mir auch. Das ist zwar ein Workaround, aber mich interessiert dennoch wo
das Problem seinen Ursprung hat.
Mach mal nach der Erkennung des Tastendrucks ein
cli() anstatt den Timer-Int abzustellen.
direkt vor dem sleep muss ein sei()
>wenn ich anstatt des cli() auch nur den timer deactiviere dann gehts bei>mir auch
wobei das nicht am timer liegt.
Es wird damit ja nur verhindert, dass der Timer die LEDs verstellt.
Es geht ja auch mit aktiviertem timer und er bleibt im sleep, nur sieht
man das Blinken nicht
die cli/sei müssen irgendwelche seiteneffecte haben, die ich übersehe.
vlad schrieb:
> es liegt nicht an der Entprellung!
Aber die Entprellung macht das Ganze erst richtig testbar.
Außerdem bewirkt sie, daß die Schaltung nicht gleich durch Störimpulse
wieder aufwacht (z.B. Einschalten einer Leuchtstofflampe in der Nähe).
Der AVR wacht kurz auf, macht die Entprellung, merkt, es ist nur ne
Störung und geht sofort wieder schlafen.
> Mach mal nach der Erkennung des Tastendrucks ein> cli() anstatt den Timer-Int abzustellen.> direkt vor dem sleep muss ein sei()
Warum sollte ich, es ist falsch.
Wie schon gesagt, jeder freigegebene Interrupt verläßt das Sleep.
Das Power-Down verhindert nur, daß der Timer weiterzählt und einen
weiteren Interrupt erzeugt.
Aber das interessiert nicht, da Du durch das cli() den Timerinterrupt am
Ausführen gehindert hast.
Das Interrupt-Pending-Bit des Timers ist also schon längst gesetzt und
reißt Dich natürlich nach dem sei() sofort wieder aus dem Sleep raus.
Peter
>Wie schon gesagt, jeder freigegebene Interrupt verläßt das Sleep.
Das ist falsch!
Der Timer kann den AVR nicht aus dem Schlaf holen!
Das kann nur der INT0 und der Watchdog.
Datenblatt Tabelle 7-1 Seite 30
vlad schrieb:
>>Wie schon gesagt, jeder freigegebene Interrupt verläßt das Sleep.> Das ist falsch!
[Goldwaagemodus an]
Wie schon gesagt, jeder freigegebene pending Interrupt verläßt das
Sleep.
[Goldwaagemodus aus]
Nun zufrieden?
> Der Timer kann den AVR nicht aus dem Schlaf holen!
Er kann nur keinen neuen Interrupt auslösen, da er nicht weiter zählt.
Die Interruptlogik ist im Power-Down voll aktiv und damit verläßt jeder
freigegebene pending Interrupt das Sleep. Das Sleep dauert dann genau
einen CPU-Zyklus.
Man könnte auch sagen, es wird ja kein Sleep ausgeführt, es wird wie ein
NOP ausgeführt.
Stelle Dir das einfach mal in Hardware vor:
Das Signal zum Interrupteinsprung liegt parallel auch an der
Aufwachschaltung an.
Es gibt keine extra Schaltung mit ANDs und ORs von jeder Interruptquelle
und jedem Freigabebit speziell für die Sleep-Schaltung.
> Das kann nur der INT0 und der Watchdog.> Datenblatt Tabelle 7-1 Seite 30
Darum geht es überhaupt nicht.
Es geht um beim Sleep-Befehl bereits anhängige Interrupts.
Peter
>[Goldwaagemodus an]>Wie schon gesagt, jeder freigegebene pending Interrupt verläßt das>Sleep.>[Goldwaagemodus aus]
Du hast scheinbar Recht. Steht aber nicht im Datenblatt.
Ist jetzt auch egal, es funktioniert jetzt alles.
Ich danke für eure Hilfe,
Gruß,
Vlad
vlad schrieb:
> Du hast scheinbar Recht. Steht aber nicht im Datenblatt.
Das Datenblatt schreiben auch nur Menschen, muß also nicht immer 100%
verständlich sein.
Indirekt steht es doch drin:
Table 7-1 Seite 30 sagt, daß die "Clock Domain" CLK_IO abgeschaltet
wird, d.h. der Timer zählt nicht weiter.
Daß damit auch sein Interrupt Pending Flag gelöscht wird, steht aber
nirgends.
Peter
Ich habe dieses Beispiel hier ausgegraben weil es ganu das machen soll
was ich benötigen würde.
Mit einer Taste den Sleep-Modus EIN/AUS zu schalten.
Was mir jedoch hier fehlt ist, wo wird denn der Interrupt-PIN zum
aufwecken definiert?
Also der PCMSK0?
Also ich habe mein program damit jetzt fast so zum laufen bekommen wie
ich es gern haben möchte.
Jedoch sind noch 2 seltsame Verhalten:
.) Ich kann den AVR in den Schlafmodus schicken aber mit der gleichen
taste nicht mehr aufwecken
.) Bei jedem Tastendruck des Encoders (#define TASTER (1 << PB2)) wird
der AVR aufgeweckt (und nur dann) und beginnt den main-Vorgang
abzuarbeiten.