Forum: Mikrocontroller und Digitale Elektronik Taster an Int0


von Michael (Gast)


Lesenswert?

Hallo,

ich habe das Forum nach Entprelltipps für Taster durchsucht und auch
einiges gefunden.

Jetzt vielleicht eine dumme Frage:

Wenn ich einen Taster an INT0 (ATTiny12) benutze und der Interrupt bei
steigender Flanke ausgelöst werden soll, muss ich dann den Taster noch
entprellen?

Meiner (noch formbaren) Meinung nach müsste doch der Interrupt bei der
ersten steigenden Flanke ausgelöst werden, egal ob danach der Taster
noch prellt, oder?

Ich lasse mich aber auch belehren.

Danke, Michael.

von Jürgen Berger (Gast)


Lesenswert?

natürlich, durch das Prellen kann es sein, dass deine Interrrupt
Routine mehrfach durchlaufen wird.

Gruss
Jürgen

von Hubert (Gast)


Lesenswert?

Bei der ersten Flanke und bei der nächsten und nächsten und .....

von pripri (Gast)


Lesenswert?

hallo michael,
guckst du hier
http://www.mikrocontroller.net/wiki/Entprellung
mfg ip

von Benedikt (Gast)


Lesenswert?

Quick&dirty Lösung: Pullups aktivieren, 10-100nF parallel zum Taster

von Quark (Gast)


Lesenswert?

ich würde auch die Entprellroutine von Peter D.
nehmen.

Farge:
Was passiert denn, wenn ich als erstes in der ISR den
Int. sperre und vor dem reti das Int.-Flag lösche;
natürlich dann den Int. wieder freigebe?
In der Zeit müsste sich das Prellen doch erledigt haben?
Natürlich wird jetzt jdede noch so kleine Störung einen
Tastendruck Int. auslösen.

Quark

von crazy horse (Gast)


Lesenswert?

ich nehme für Tasten überhaupt keinen Interrupt. Alle 10ms mal
vorbeischaun, ein Timer läuft doch sowieso in fast Programm.

von ...HanneS... (Gast)


Lesenswert?

Richtig...

Das Problem ist nur, dass es immer wieder welche gibt, die sich wehren
wie die Zicke am Strick, einen Timer zur globalen Programmsteuerung
einzusetzen.

...

von Michael (Gast)


Lesenswert?

Tja,

Danke erstmal für die angeregte Diskussion.

Der Interrupt soll deswegen genommen werden, damit der Tastendruck den
Tiny auch aus dem Sleepmode weckt.

Oder hat da jemand eine bessere Methode?
Da würde ich nämlich auf die Timerlösung umschwenken...

Das "Projekt" sieht folgendermassen aus:
Taster soll LED 5 oder 10 Sekunden einschalten. Wenn in dieser Zeit der
Taster nicht gedrückt wird, soll die LED ausgehen und der Sleepmodus
aktiviert werden.(Welcher mit dem nächsten Druck auf den Taster wieder
verlassen werden soll.


Gruß, Michael.

von Sebastian (Gast)


Lesenswert?

hi,
da ich genau an diesen Punkt mich auch gerade befinde, schreibe ich
auch mal ein paar zeilen dazu.
Ich habe genau wie Michael vor per externem Interrupt, über einen
Taster, den µC in den schlafmodus zu versetzen und ihn auch daraus
wieder zu wecken. Dazu habe ich den Port auf "eingang" und internem
"pull up" konfiguriert und den Taster auf der anderen seite an Masse
geschlossen(Low-level interrupt). Bei meinem ATmega169, mit 4MHz
getaktet, (*1) ist hierbei laut Datenblatt zu beachten, daß der zum
wecken verwendete externe Interrupt INT0 nur durch "LOW Level
detection" asynchron aufgerufen werden kann. D.h., daß gerade mal im
"idle" Modus der benötigte Takt "I/O clk" für eine
Flankengesteuerte Interrupterkennung vorhanden ist. Beim ATmega169
heißt das (*1), alle sleep modies erfordern eine Level gesteuerte
Interrupterkennung.
Leider hat dies auch zur Folge, daß der Interrupt fortwährend erkannt
wird wie ein "Low Level" vorhanden ist, sprich: der Taster gedrückt
ist. Dazu habe ich als Experiment mal nur eine globale Variable in der
ISR inkrementieren lassen "int_counter++;" und sie dann ausgeben
lassen. Ergebnis: durch ein normales Taster betätigen, wird die ISR
rund 10000 mal aufgerufen. Hierbei spielt das Taster Prellen eher
weniger die Rolle, dafür ist das entstehende Problem, der immer wieder
aufrufen der ISR, aber umso gravierender.
Zur Lösung fallen mir nur 2 Ansätze ein:
a) das verhindern des wiederholten Aufrufes der ISR , oder
b) das verhindern des wiederholten Codeausführen in der ISR .

Ich habe mich für zweiteres entschieden. Dazu später evtl. mehr.

mfg Sebastian

(*1): wahrscheinlich bei den anderen AVRs auch
ISR: Interrupt Service Routine, Interrupt handler

von ...HanneS... (Gast)


Lesenswert?

Und wenn man den Low-Level-Int "nur" zum Wecken nimmt??

Also der AVR macht seine Arbeit, gesteuert vom Timer-Int. Wenn er
hinterher ist und nix mehr anliegt (Erkennung folgt weiter unten),
löscht die "Gute-Nacht-Prozedur" das Int-Flag für Ext-Intin GIFR ,
aktiviert danach den Int in GIMSK und schickt den AVR schlafen.

Bei Tastendruck wird der AVR geweckt und die zugehörige ISR aufgerufen.
In dieser wird der ext-Int erstmal wieder deaktiviert (GIMSK). Das Flag
in GIFR wird dann vor dem nächsten Aktivieren erst wieder gelöscht.

Dann kann der Timer wieder arbeiten und in seinen nächsten "Runden"
die Taste sicher erkennen und entprellen und das zugehörige Flag für
das Hauptprogramm setzen. Weiterhin zählt der Timer ein weiteres
Register runter, das bei Erreichen von 0 die "Gute-Nacht-Prozedur"
aufruft. Dieses Register wird von allen aktiven Teilen des Programms
gelöscht (oder auf einen definierten Wert gesetzt, falls 256
Warterunden zu "verschwenderisch" sein sollten), so dass es nur dann
0 werden kann, wenn 256 (oder so) Timerrunden stattgefunden haben, in
denen das Hauptprogramm nix mehr zu tun hatte.

Somit hat man eine sauber entprellte Taste und kann den AVR trotzdem
schlafen schicken.

Da der Schlafmodus ja zum Stromsparen genutzt wird, kommt nun die
Frage, ob denn auch der Analogcomparator deaktiviert wurde...

...

von Michael (Gast)


Lesenswert?

Das hört sich ja interessant an.
Aber wenn ich das aber richtig verstanden habe, dann kann ich - während
meine LED-Prozedur läuft - keine weiteren Tastendrücke (sprich
Interrupts) erkennen, sondern erst, wenn die Prozedur durchlaufen wurde
und der AVR auf den Schlafmodus wartet ?!?

und ja ... er wurde... er wurde... ;)

von ...HanneS... (Gast)


Lesenswert?

Während dein Programm (was immer es auch tut) läuft, löscht es immer
wieder das Register, was zum "Einschlafen" Null werden muss. Daher
kann der AVR nicht pennen gehen, solange "Arbeit anliegt". Und
solange tuckert auch der Timer und kann mit einer in dem Timer-ISR
laufenden Entprellroutine weitere Tastendrücke abfragen.

Erst wenn dein Programm fertig ist wird der "Einschlafzähler" nicht
mehr gelöscht und kann ablaufen.

Wenn dann schonmal eine Timer-ISR periodisch aufgerufen wird, dann kann
sie auch die gesamte LED-Steuerung übernehmen. Dinge wie Lauflicht,
Ausgabe von Zuständen über blinkende LEDs usw. mach ich grundsätzlich
in der Timer-ISR. Viele meiner Programme haben als Main nur RJMP main,
da das gesamte Hauptprogramm in der Timer-ISR läuft.
Dort kann man auch ein weiteres Zählregister mitlaufen lassen, welches
darüber entscheidet, welche Programmteile in der jeweiligen "Runde"
ausgeführt oder übersprungen werden. Damit erreicht man eine
"Zeitscheibe", die die anliegenden Arbeiten halbwegs gleichmäßig
verteilen kann. Z.B. Multiplexen eines mehrstelligen
LED-Zifferndisplay, Tastaturabfrage, PWM-Erzeugung ADC-Auslesen... -
Alles in der Timer-ISR, aber alles zu seiner Zeit. Sollten
zeitaufwendige Berechnungen nötig sein, dann kann man diese im
Hauptprogramm (zwischen den ISR-Aufrufen) ausführen, gesteuert über
Flags, die von der Timer-ISR gesetzt werden und vom Hauptprogramm nach
Erledigung des Jobs wieder gelöscht werden.

...

von MSE (Gast)


Lesenswert?

@CrazyHorse:
"ich nehme für Tasten überhaupt keinen Interrupt. Alle 10ms mal
vorbeischaun, ein Timer läuft doch sowieso in fast Programm."

Es gibt auch Leute, bei denen alle Timer mit anderen Dingen beschäftigt
sind. Die Idee, asynchrone spodradisch auftretende Vorgänge mit einem
Interrupt zu behandeln, ist guter Programmierstil. Genau für so etwas
sind Interrupts schließlich da! ;)


Gruß, Michael

von Michael (Gast)


Lesenswert?

Danke, danke. So langsam dämmerts.
Ich werde wohl mein Programmdesign komplett überarbeiten müssen, aber
das scheint mir doch sinnvoll zu sein.

Nochmal eine Frage zum externen INT0:

(Ich kenne nur den Tiny12, denke aber, dass das bei den "größeren"
genauso ist...)
Ich hatte vor, den ext. INT über die steigende Flanke zu triggern.
Sebastian (s.o.) hat einen Low-level. Macht das einen Unterschied?
Gibts da Vor- oder Nachteile?
Bei Sebastian müsste doch der INPUT dann (Wenn der Taster nicht
gedrückt ist) an Vcc liegen, oder?
Nimmt der AVR dann im Schlafmodus hier auch Strom auf?

Danke und Gruß, Michael.

von ...HanneS... (Gast)


Lesenswert?

Flanke kann nicht wecken, da Flanke Takt voraussetzt. Takt ist aber
abgeschaltet wenn der AVR schläft...

Du musst also den Low-Level nehmen.

Da der AVR Spannung hat, nimmt er keinen zusätzlichen Strom auf, wenn
Pins auf H liegen.

...

von crazy horse (Gast)


Lesenswert?

@MSE
Über "guten Programmierstil" kann man sicher streiten.
Externe Ints sind für mich wertvolle Resourcen, die ich nicht an einen
Taster verschwende (den hier beschriebenen Fall zum Aufwecken nehme ich
davon mal aus).
Ich baue ein Programm meist folgendermassen auf:
Ein Timer (der Timer0) liefert den Grundtakt für das gesamte Programm,
welche Zeit man dafür nimmt, hängt vom konkreten Fall ab. Daraus leite
ich über Zähler in der main diverse Aktionen aus, im einfachsten Fall
ist das ein linearer Ablauf in main.
while (!timer_ready);   //wird vom Timer0-Int gesetzt
timer_ready=0;
.
.
.Der Rest der Programms
Vorteil der Sache: definierte, konstante Abarbeitungszyklen, auch nach
Änderungen im Programm. Das ist mir wichtiger als min. mögliche
Programmlaufzeit.
Und in dem Zuge frage ich auch  Schalter/Taster mit ab, die
Prozessorbelastung dafür ist minimal. Wie du das siehst, ist mir
herzlich egal, ich bin damit immer gut gefahren. Und es ist ja auch
kein Dogma - wenn es wirklich mal so schnell wie möglich sein muss,
kann man es ja auch weglassen. Aber eigentlich ist es immer so, dass
der MC sowieso irgendwo warten muss.

von MSE (Gast)


Lesenswert?

@CrazyHorse:
Bei mir wartet der MC oft nicht sondern arbeitet durch. Es kommt auf
die Anwendung an, was gerade am günstigsten ist. Dein Ansatz hat sicher
in vielen Fällen Vorteile.

Gruß, Michael

von crazy horse (Gast)


Lesenswert?

Sag mir mal ein Beispiel, in welchem du 100% Auslastung hast. Ich kann
mir keins vorstellen bzw. würde zu dem Schluss kommen, dass ich den
falschen MC/zu geringe Taktfrequenz/zu hohe Programmlaufzeit habe.

von MSE (Gast)


Lesenswert?

Du hast recht, 100 % sind es nicht. Er hat aber trotzdem gut zu tun.

von crazy horse (Gast)


Lesenswert?

Tja, ~90% komme ich auch manchmal, das ist aber schon fast der
Grenzwert, den ich noch tolerieren würde, ich mag es nicht, im
Grenzbereich zu arbeiten, kleine Erweiterungen können dann das ganze
Design kippen.
Und wenn die Abarbeitung der main max. 9ms dauert, was spricht dann
dagegen, die mit 10ms zu synchronisieren? Baue ich noch Kleinkram ein,
bleibt es bei den 10ms, zur Not könnte ich problemlos auf 15 oder 20ms
wechseln. Oder aber aufteilen, wenn grössere Berechnungen anzustellen
sind. In den ersten 10ms läuft eine Berechnung, beim nächsten Mal die
andere. Es gibt auch Fälle, bei denen die Laufzeit von Programmteilen
abhängig ist von den Eingangsparametern, das kann auch sehr unschöne
Effekte hervorbringen
Allgemeingültig kann man das alles nicht sagen, es gibt sicher Fälle,
wo man davon abweichen muss, ist aber relativ selten. Wie gesagt,
persönliche Vorlieben tun auch einiges zur Sache, mir persönlich ist
ein geordnetes Zeitregime viel Wert.
Und zur Anzahl der Timer: 10.000ende von Projekten mussten sich mit
einem Timer (Standard-8051, der 2. ging meist für die serielle
Schnittstelle drauf) zufrieden geben, und das ging und geht auch heute
noch. Insofern bin ich mit dem AVR mit freiem Timer1 und (meist
vorhanden Timer2) gut bestückt, wenn der Timer0 das Programm steuert.
Und nebenbei kann er ja weiterhin übliche Timeraufgaben übernehmen, das
entfällt ja deswegen nicht.

von Michael (Gast)


Lesenswert?

@HanneS : ok. Low-level-int

nur um da nichts falsch zu machen:
Ich gebe also (Beim TINY12) die Vcc auf Pin 6 (IN2) und 8 und schalte
den internen Pullup dazu.

Dann Taste ich die Vcc gegen Masse und der AVR erwacht.
Alles richtig so?


Nochmals Danke. Das ist alles sehr aufschlussreich für mich.
Michael.

von ...HanneS... (Gast)


Lesenswert?

Quatsch! - hätte ich beinahe gesagt...

Du legst Vcc auf Pin 8, dein interner Pullup zieht den Int-Eingang auf
H, dein Taster beim Betätigen auf L.

Würdest du da Vcc anlegen, würde dein Taster einen Kurzschluss
verursachen.

...

@Crazy: Es gibt Controller, deren Rechenzeit zu 100% ausgelastet ist.
Und zwar mit Warteschleifen, da man sich vor der Verwendung eines
Timers drückt (kennichnich, essichnich...)

;-)

...

von Michael (Gast)


Lesenswert?

Na, Danke! Das hätte bestimmt schön gekokelt...
Wie sieht denn dann das ganze aus, wenn man statt eines Schließers
einen Öffner nimmt?

Dann sollte doch der interne Pullup abgeschaltet sein, damit er nicht
direkt an Vcc liegt, sondern nur, wenn der Öffner in Ruhestellung ist,
oder?
Dann müsste man einen externen Widerstand zwischen Vcc und Öffner-Pin6
packen. Aber wie kommt dann die Masse ins Spiel?

Ich hoffe, dann habe ichs gerafft...

Gruß, Michael.

von ...HanneS... (Gast)


Lesenswert?

Wenn der Schalter/Tester einen Pegelwechsel verursachen soll, dann muss
durch den geschlossenen Kontakt Strom fließen. Strom kostet meist Geld,
also wäre es töricht, den Strom im unbetätigten Zustand zu verheizen.

von MSE (Gast)


Lesenswert?

@CrazyHorse:
Da wir neulich darüber sprachen:
Ich habe jetzt ein Problem, bei dem der Controller 24 h am Tag fleißig
vor sich hin arbeiten soll und alle paar Tage wird vielleicht einmal
eine Taste betätigt. In so einem Fall scheint es mir nicht
unvernünftig, die Eingabe über einen Interrupt zu detektieren und nicht
irgendwelche Polling-Abfragen durchzuführen, die zu 99,99% der Laufzeit
stets mit negativem Ergebnis enden.


Gruß, Michael

PS: Ich will damit nichts gegen die von Dir aufgeführten Konzepte
sagen, die lesen sich durchaus schlüssig und sind bestimmt bei Geräten,
die häufig bedient werden, nicht verkehrt!

von Santa Klaus (Gast)


Lesenswert?

>der Controller 24 h am Tag fleißig
>vor sich hin arbeiten soll und alle paar Tage wird vielleicht einmal
>eine Taste betätigt. In so einem Fall scheint es mir nicht
>unvernünftig, die Eingabe über einen Interrupt zu detektieren und
nicht
>irgendwelche Polling-Abfragen durchzuführen, die zu 99,99% der
Laufzeit
>stets mit negativem Ergebnis enden.

Solange eine Abfrage praktisch überhaupt keine Rechenleistung benötigt,
wie das bei Tastenpolling der Fall ist (*), ist es doch völlig wurscht,
wie groß der Anteil an positiven und negativen Ergebnissen ist!?

(*) Abschätzung: Tasten mögen alle 10 ms abgefragt werden; die
Abfrageroutine hat 50 Instruktionen --> ca. 100 Taktzyklen --> bei 8
MHz Systemtakt ist die Routine innerhalb 12.5 µs abgearbeitet.  12.5 µs
/ 10 ms = 0.00125.  Ergebnis: Das Tastenabfragen kostet stolze 0.125 %
der gesamten Rechenleistung.

von ...HanneS... (Gast)


Lesenswert?

Richtig... Aber:

Er möchte doch den Controller in den Tiefschlaf versetzen um Strom zu
sparen (Batterie). Deshalb auch der Low-Level-Int zum Wecken.

...

von crazy horse (Gast)


Lesenswert?

ich zitiere mich mal selbst:
"Externe Ints sind für mich wertvolle Resourcen, die ich nicht an
einen
Taster verschwende (den hier beschriebenen Fall zum Aufwecken nehme
ich
davon mal aus)."

@MSE:

-Du musst den Schalter entprellen  (dann wartest du in der ISR und
blockierst die restlichen Ints??)
-ansonsten kann dir ein einziger Tastendruck ganz viele Interrupts
auslösen (was dann wiederum einen Timer oder Warteschleifen verlangt,
um die zu umgehen).
-was machst du, wenn ein 2. oder 3. oder noch mehr Taster hinzukommen?

Summa summarum: nichts gewonnen, Vorteile verspielt, schlechtes
Geschäft gemacht.
Und, wie schon gesagt, kann doch jeder machen, wie er will, solange es
funktioniert. Ich will dich nicht bekehren, aber deine Lösung hat keine
Vorteile.

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
Noch kein Account? Hier anmelden.