Hey!
Der Tiny24, den ich in der Mangel habe, raubt mir die Nerven. Er hat
einen low-akiven Taster an einem Eingang. Der Port-Pin PB2 hat den
internen Pull-up aktiviert.
Ich habe eine State Machine programmiert. Der Einfachheit halber habe
ich zunächst auf zwei Zustände reduziert. Sobald der Taster Low-Pegel
hat, zuckt INT0 und bringt seine ISR nach vorne und setzt u.a. das Flag
entsprechend (hier auf 'l'). Wird dieser Zustand wieder verlassen, geht
es zurück zu 'i'. In main() gibt es dann Fallunterscheidungen
hinsichtlich des Zustands des Flags.
Ausgangsseitig sind LEDs im Spiel, die je nach Zustand bespielt werden
sollen.
So weit, so einfach. Nun habe ich ersonnen, daß die LEDs einen
Nachleuchttimer haben sollen. Der Taster wird kurz gedrückt, die LEDs
leuchten daraufhin auf und noch'n paar Sek. nach und gehen dann aus,
Zustand wird auch wieder geändert. Quasi ein Monoflop. Für diese
Nachleuchtung habe ich den Timer1 ins Boot geholt, der im CTC läuft und
der von der ISR des INT0 angeschubst wird.
In der Logik kann ich keinen Fehler mehr finden. Trotzdem läuft die
Kiste kippelig. Nicht-deterministisch. Mal geht alles wie gewünscht.
Dann wieder bleiben die LEDs am leuchten über den Timeout hinaus, als
hätte der Timer was vergessen. Dann geht alles beim ersten Druck wie
gewünscht incl. fristgerechter Dunkelheit, beim zweiten Durchlauf jedoch
passiert nichts mehr. Und dann nie wieder (bis zum Reset). Ich hatte
auch schon Timeouts mit 2T.
So, meine frühen Überlegungen gingen nat. in Richtung Entprellung des
Tasters. Ohne E. müßte das ja alles schrecklich unvorhersehbar und so
sein. Dann sagte ich mir, daß ich ja durch den INT0 und seine ISR mit
der sofortigen Sperrung weiterer INT0s schon eine prima Entprellung
habe. Daran habe ich dann noch etwas getestet, indem ich in die ISR ein
_delay_ms(120); versuchsweise eingefügt habe (jaja, ich weiß :-). Im
Ergebnis das gleiche. Prellen sollte nach meinem Ermessen keine negative
Auswirkung haben.
Meine Bitte an euch: schaut doch mal in den Code. Ist mit dem
Timer-Config was nicht koscher? Fällt euch an den ISRs und den ganzen
Setups was auf? Die Register sind ja zahlreich.
Besten Dank und schöne Grüße, Jan.
Jan R. schrieb:> So, meine frühen Überlegungen gingen nat. in Richtung Entprellung des> Tasters. Ohne E. müßte das ja alles schrecklich unvorhersehbar und so> sein. Dann sagte ich mir, daß ich ja durch den INT0 und seine ISR mit> der sofortigen Sperrung weiterer INT0s schon eine prima Entprellung> habe.
Nö. Hast du nicht.
Nur weil Interrupts gesperrt sind, bedeutet das ja nicht, dass die Pulse
am Eingang nicht trotzdem registriert werden. Die setzen
selbstverständlich das entsprechende Flag im Interrupt
Anforderungsregister und wenn die Interrupts das nächste mal frei
gegeben werden, kommt der nächste Interrupt-
> Meine Bitte an euch: schaut doch mal in den Code. Ist mit dem> Timer-Config was nicht koscher? Fällt euch an den ISRs und den ganzen> Setups was auf? Die Register sind ja zahlreich.
Das kommt mir alles mächtig kompliziert vor.
Karl Heinz Buchegger schrieb:> Jan R. schrieb:>>>> So, meine frühen Überlegungen gingen nat. in Richtung Entprellung des>> Tasters. Ohne E. müßte das ja alles schrecklich unvorhersehbar und so>> sein. Dann sagte ich mir, daß ich ja durch den INT0 und seine ISR mit>> der sofortigen Sperrung weiterer INT0s schon eine prima Entprellung>> habe.>> Nö. Hast du nicht.>> Nur weil Interrupts gesperrt sind, bedeutet das ja nicht, dass die Pulse> am Eingang nicht trotzdem registriert werden. Die setzen> selbstverständlich das entsprechende Flag im Interrupt> Anforderungsregister und wenn die Interrupts das nächste mal frei> gegeben werden, kommt der nächste Interrupt-
Ah, verstehe. Dann half natürlich auch das versuchsweise eingesetzte
Delay() nichts. Der INT kam dann nur später.
>> Meine Bitte an euch: schaut doch mal in den Code. Ist mit dem>> Timer-Config was nicht koscher? Fällt euch an den ISRs und den ganzen>> Setups was auf? Die Register sind ja zahlreich.>> Das kommt mir alles mächtig kompliziert vor.
Hmja, ich finde die ganze Registerklaviatur des t24 im Vergleich zu
früheren auch kompliziert. Besonders beim Timer/Counter.
Viele Grüße,
Jan.
> Für diese Nachleuchtung habe ich den Timer1 ins Boot geholt,> der im CTC läuft und der von der ISR des INT0 angeschubst wird.
Würd ich gar nicht machen.
Ich würde den Timer ständig durchlaufen lassen, der zb alle 100ms seine
ISR ausführt.
Dazu noch eine globale Variable, die als Countdown-Uhr fungiert.
volatile uint8_t ledAus;
In der ISR dann
ISR( ... )
{
if( ledAus > 0 ) {
ledAus--;
if( ledAus == 0 )
Led abschalten
}
}
bei Tastendruck wird einfach ledAus auf 30 gesetzt und 3 Sekunden später
dreht dann die ISR tatsächlich die LED ab.
(Ich verstehe, dass du deine Taste auf einen INterrupt legst, weil du
später irgendwann mal einen Sleep-Modus aktivieren willst und der Taster
den da rausholen soll)
ISR( INT0 )
{
Led einschalten
ledAus = 30;
}
Das Prellen ist in dem Fall relativ egal. Ob die Zeit mit dem ersten
Niederdrücken oder mit dem 3. Preller losläuft, ist auch schon wurscht.
Jan R. schrieb:> So, meine frühen Überlegungen gingen nat. in Richtung Entprellung des> Tasters.
Das wäre der einzig richtige Ansatz gewesen.
Warum hast Du ihn aber nicht weiter verfolgt?
Jan R. schrieb:> Ohne E. müßte das ja alles schrecklich unvorhersehbar und so> sein.
Das hast Du nun ja eindrucksvoll bewiesen.
Hier mal ein Beispiel mit Entprellung:
Beitrag "AVR Sleep Mode / Knight Rider"
Peter
Karl Heinz Buchegger schrieb:>> Für diese Nachleuchtung habe ich den Timer1 ins Boot geholt,>> der im CTC läuft und der von der ISR des INT0 angeschubst wird.>> Würd ich gar nicht machen.> Ich würde den Timer ständig durchlaufen lassen, der zb alle 100ms seine> ISR ausführt.>> Dazu noch eine globale Variable, die als Countdown-Uhr fungiert.
[...]
> bei Tastendruck wird einfach ledAus auf 30 gesetzt und 3 Sekunden später> dreht dann die ISR tatsächlich die LED ab.
Hallo Karl Heinz,
ah, gute Idee. Die hat ggü. meinem on-demand-Timer noch den Vorteil, daß
der immerlaufende 100 ms-Timer auch ggf. für andere Timeout-Bedarfe
genutzt werden könnte (mit dann eigenen Variablen, nat.).
> (Ich verstehe, dass du deine Taste auf einen INterrupt legst, weil du> später irgendwann mal einen Sleep-Modus aktivieren willst und der Taster> den da rausholen soll)
Genau.
[...]
> Das Prellen ist in dem Fall relativ egal. Ob die Zeit mit dem ersten> Niederdrücken oder mit dem 3. Preller losläuft, ist auch schon wurscht.
Stimmt. So hatte ich mir das ja auch mit dem INT0 und dem Sperren
weiterer INTs gedacht, aber nicht berücksichtigt, daß auf jeden Fall ein
Nachtritt vom während der Sperre gesetzten I-Flag kommt.
Sehr gut, das setze ich mal so um. Dir vielen Dank für Rat und Tat!
Viele Grüße, Jan.
Peter Dannegger schrieb:> Jan R. schrieb:>> So, meine frühen Überlegungen gingen nat. in Richtung Entprellung des>> Tasters.>> Das wäre der einzig richtige Ansatz gewesen.> Warum hast Du ihn aber nicht weiter verfolgt?
Hallo Peter,
das hatte zwei Gründe: ich wollte keinen weiteren Timer für die
Entprellung einbinden, um möglichst wenig im t24 am rennen zu haben
(Perspektive Strom sparen). Das ist/war aber eher eine
Bauchentscheidung, berechnet in mW bzw. µW hatte ich das noch nicht. Und
dann eben die Annahme, mit dem ersten LOW des Pins in der ISR zu sein,
die weiteres Zappeln des Tasters verpuffen lassen würde.
> Jan R. schrieb:>> Ohne E. müßte das ja alles schrecklich unvorhersehbar und so sein.>> Das hast Du nun ja eindrucksvoll bewiesen.
:-) Hier mußte ich mehr als grinsen.
> Hier mal ein Beispiel mit Entprellung:> Beitrag "AVR Sleep Mode / Knight Rider"> Peter
Den Thread werde ich mir mal ansehen. Besten Dank für den Tip, denn den
kannte ich noch nicht. Wohl aber andere und vor allem auch die vielen
sehr guten Artikel, ohne die µC.net nur halb so wertvoll wäre.
Viele Grüße,
Jan.
Jan R. schrieb:> das hatte zwei Gründe: ich wollte keinen weiteren Timer für die> Entprellung einbinden, um möglichst wenig im t24 am rennen zu haben
Viele Programme haben einen Timer ausschliesslich dafür abgestellt, im
Programm eine Zeitbasis zu haben, wobei der tatsächliche Zeitschritt
(millisekunden) gar nicht mal so wichtig ist, sondern viel wichtiger ist
es, eine definierte 'Uhr' im System zu haben
So auch beim Entprellen.
Beim PeDa Entrprellen ist es nicht so wichtig, ob der ISR Aufruf
tatsächlich alle 5 Millisekunden kommt oder nicht. Du hast da viel
Spielraum, d.h. man könnte die Entprellung und diese Timeout Counter
ruhig in eine ISR zusammenlegen, die vom selben Timer gespeist wird. Ob
der Timeout Counter alle 5 oder 10 oder 50 Millisekunden aufgerufen
wird, ist ja wiederrum nur ein Zahlenwert, der bei der Vorbelegung zum
Runterzählen interessant ist.
Und wenn dann noch was dazu kommt (systeminterne Uhr oder so was), dann
kommt das dann eben auch da mit dazu.
Wie gesagt: Einen Timer als interne Zeitbasis, das ist etwas, was sich
sehr bewährt hat. Wohingegen das ständige Timer-ein, Timer-aus, und wenn
dieses oder jenes der Fall ist, dann wird der Timer auf 0 gesetzt, etc.
etc. ... das wird alles schnell unübersichtlich.
Karl Heinz Buchegger schrieb:> Viele Programme haben einen Timer ausschliesslich dafür abgestellt, im> Programm eine Zeitbasis zu haben, wobei der tatsächliche Zeitschritt> (millisekunden) gar nicht mal so wichtig ist, sondern viel wichtiger ist> es, eine definierte 'Uhr' im System zu haben
[...]
> Wie gesagt: Einen Timer als interne Zeitbasis, das ist etwas, was sich> sehr bewährt hat. Wohingegen das ständige Timer-ein, Timer-aus, und wenn> dieses oder jenes der Fall ist, dann wird der Timer auf 0 gesetzt, etc.> etc. ... das wird alles schnell unübersichtlich.
Ja, das stimmt. Ich habe den Timer mittlerweile auf Dauerlauf gestellt
und meine Kausalkette etwas entschlackt. Und ich habe auch gleich eine
weitere Verwendung für den Puls im Hintergrund gefunden. Der Tip war für
mich hilfreich.
Am Wochenende komme ich dann hoffentlich zu Peters Link mit dem
sinnvollen Umsetzen des Sleep Modes. Zuvor muß ich aber noch ein, zwei
Routinen fertigbekommen, sonst scheppert da wieder was.
Viele Grüße,
Jan.