Hallo
Lt. Tutorial ist es ja günstig, dieses RS-FlipFlop zu verwenden.
Kann man diese Schaltung auch benutzen, wenn man nur nen simplen Taster
hat? bzw. diese ein wenig abwandeln, damit es klappt?
Danke
Johannes Hofmann schrieb:
> Hallo>> Lt. Tutorial ist es ja günstig, dieses RS-FlipFlop zu verwenden.
Eigentlich macht man Tastenentprellung am besten in Software.
Das ist universeller, kostet nichts und funktioniert absolut
zuverlässig.
Ok, wenn ich mir die Komfortroutine für C anschaue und 2 Taster habe,
die nicht gedrückt und dann gehalten werden, welche Teile des Codes
benötige ich denn dann?
Das Problem ist nämlich, dass ich nen MP3-Player habe, dessen
Spielroutine ich nur für 800us unterbrechen kann, weil der Datenstrom
dann nämlich abreißt.
Deswegen wollte ich das eigentlich mit Hardware-Entprellung machen.
Wie würdest du das machen?
Hi,
die Entprellroutine vom Dannegger besteht doch nur aus ein paar binären
Operationen.
Und wenn du nen Quarz mit z.b. 16 MHz hast, dann sind 800 µs doch ne
Ewigkeit und reichen locker aus, um ein paar Tasten zu entprellen.
Ich hab auch schon nen MP3 Player mit nem VS1053 IC gebaut, an dem ich
12 Taster hatte. Die konnte ich während des MP3-Abspielens ohne Probleme
entprellen.
Gruß
C.H.
Du brauchst
die Timer Overflow Routine
und natürlich die Auswertefunktionen
> Das Problem ist nämlich, dass ich nen MP3-Player habe, dessen> Spielroutine ich nur für 800us unterbrechen kann
800us sind fast 1ms. Also massig Zeit. Solange braucht die Overflow
Funktion ja gar nicht. Und ausserdem wird die ja nur alle heilige Zeiten
aufgerufen (Du kannst auch die Zeitberechnung für das Nachladen des
Timers aus der ISR rausnehmen. Wenn die ISR so alle 5 bis 20ms
aufgerufen wird, dann reicht das. Das muss nicht sonderlich genau sein,
mit dem Prescaler kommt man normalerweise ausreichend gut in einen
vernünftigen Bereich hinein)
Sorry aber etwas kapierre ich hier nicht.
Wenn ich das richtig im Kopf habe dann ist die Prellzeit von
tastern/Schaltern durchaus im Millisekundenbereich, gerne auch mal bei
nicht so hochwertigen mehr als 20 mS.
Wie bitte kann ich die innerhalb von weniger als 0,8yS dann
softwareseitig entprellen????
Dazu müsste ich doch die Tastenausleseroutine in eine zyklisch (Timer)
über Timer aufgerufene Routine machen, die sich die Zustände auch noch
merkt.
Wie schon von Udo geschrieben, ist Entprellen hier der falsche Weg.
Solange hast du nicht Zeit.
Am einfachsten ist es mit der ersten Flanke einen Interrupt auszulösen
und dann alle folgenden für ~20ms zu verwerfen.
Udo. R. S. schrieb:
> Dazu müsste ich doch die Tastenausleseroutine in eine zyklisch (Timer)> über Timer aufgerufene Routine machen, die sich die Zustände auch noch> merkt.
Und genau das macht eben diese Entprellroutine.
Sie tastet 4-mal ab im Abstand von 10ms Timerinterrupt.
Peter
Esko schrieb:
> Wie schon von Udo geschrieben, ist Entprellen hier der falsche Weg.
Udo hat dasnur deswegen geschrieben, weil er noch nicht durchschaut hat,
wie das funktioniert.
> Solange hast du nicht Zeit.
Braucht er auch nicht.
> Am einfachsten ist es mit der ersten Flanke einen Interrupt auszulösen> und dann alle folgenden für ~20ms zu verwerfen.
Äh nein.
Das ist nicht einfacher. Wie machst du das denn 'die folgenden für 20ms
verwerfen'?
Am enfachsten ist es die Entprellroutine zu benutzen.
Die verbraucht minimal Rechenzeit, entprellt zuverlässig, merkt sich
einen gedrückte Taste, erkennt kurze und lange Tastendrücke und kann auf
wunsch auch einen Autorepeat auf die Taste legen. Und das beste am
ganzen: sie verbraucht praktisch keine Rechenzeit.
Udo. R. S. schrieb:
> Wie bitte kann ich die innerhalb von weniger als 0,8yS dann> softwareseitig entprellen????
Musst du auch nicht.
Die Entprellroutine erkennt einen Tastendruck dann als gültig an, wenn 4
mal hintereinander, im Abstand von x Millisekunden die Taste als
gedrückt erkannt wurde. Sobald die Taste das erste mal prellt, beginnt
die 4-er Zähleung erneut zu laufen.
Der Code macht im Grunde nichts anderes als:
Schau alle x Millisekunden die Tasten durch, ob sich etwas verändert
hat. Das geht schnell. Im Grunde ist das wie beim Autofahren: Du
konzentrierst dich auf die Strasse und alle paar Sekunden wirfst du
einen Blick in den Rückspiegel. Das geht schnell genug, damit dir nichts
entgeht.
Genauso hier:
Alle x Millisekunden sieht die Overflow-ISR nach, ob eine Taste gedrückt
wurde. Durch die Konstruktion der ISR gilt aber nicht jeder 1->0
Übergang als Tasterndruck, sondern nur dann, wenn danach bei 4-maligem
erneuten Hinschauen die 0 immer noch anliegt.
Hallo
Wie mach ich das aber, wenn ich bei meinem Player Pause machen will und
dies mittels dieser Schleife tun will:
while(PAUSE){} ?
Da komm ich ja dann nicht mehr raus.
Denn ich wollte über den Interrupt diesen PAUSE-Wert togglen.
Aber das klappt ja dann nicht mehr in Software.
Deswegen würd ich nochmal gern wissen, ob ich mit nem RS-Flip-Flop und
nem Taster arbeiten kann, oder ob das Ding nur bei einem Wechselschalter
benutzbar ist.
Weiterhin noch ne Frage:
In dem Tutorial wird das Timerinterrupt-Intervall so gesetzt.
Zu ersteinmal die Frage, was die beiden uint8 und int16 da zu bedeuten
haben.
Und von denen wird dann der Wert 1,47 (bei 1e+06 als F_CPU) abgezogen.
Daraus werd ich nicht ganz schlau.
TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);
Danke euch
Johannes Hofmann schrieb:
> Hallo>> Wie mach ich das aber, wenn ich bei meinem Player Pause machen will und> dies mittels dieser Schleife tun will:> while(PAUSE){} ?> Da komm ich ja dann nicht mehr raus.
Wer oder was ist PAUSE
Im übrigen:
Du hast es immer noch nicht verstanden. Die Overflow ISR läuft
eigenständig 'im Hintergrund' mit und überwacht die Tasten. Wann immer
es dir passt rufst du get_key_short auf und die liefert der den Wert ob
eine Taste gedrückt wurde.
Deine Schleife ist dann
while( ! get_key_short( 1 << PAUSE_KEY ) )
;
wobei PAUSE_KEY die Pinnummer des Pause Tasters ist
Die musst du natürlich noch richtig konfigurieren. Welche Tasten hast du
und an welchem Port und an welchem Pin sind sie angeschlossen. zb.:
Sobald der Timer läuft, brauchst du dich um nichts mehr kümmern. Du
rufst get_key_short auf und die Funktion teilt dir mit, ob die Taste
seit dem letzten Aufruf gedrückt wurde oder nicht.
> Denn ich wollte über den Interrupt diesen PAUSE-Wert togglen.> Aber das klappt ja dann nicht mehr in Software.
Doch, das klappt wunderbar.
> Deswegen würd ich nochmal gern wissen, ob ich mit nem RS-Flip-Flop und> nem Taster arbeiten kann, oder ob das Ding nur bei einem Wechselschalter> benutzbar ist.
Du machst dir zu viele Sorgen.
Dein main() wird dann in etwa so aussehen
// Tastenbehandlung abgeschlossen, füttere den MP3 Chip mit genügend Daten, sodass
59
// er was zu tun hat, während die while Schleife die nächste Runde
60
// Tastenabfragen macht
61
if(playing){
62
feedMP3Chip(songnr,...);
63
}
64
}
65
}
Die Hauptschleife dreht ständig ihre Runden
Abfragen, ob irgendeine Taste gedrückt wurde und behandeln wenn ja
Dem MP3 Chip wieder ein paar Daten vorwerfen, so dass er spielen
kann, während die nächste Runde Tastenabfragen durchläuft.
Und nein, das Tastenabfragen kostet nicht viel. Das sind ein paar µs die
dafür draufgehen. Die spürst du kaum bis gar nicht.
Johannes Hofmann schrieb:
> Weiterhin noch ne Frage:> In dem Tutorial wird das Timerinterrupt-Intervall so gesetzt.> Zu ersteinmal die Frage, was die beiden uint8 und int16 da zu bedeuten> haben.> Und von denen wird dann der Wert 1,47 (bei 1e+06 als F_CPU) abgezogen.> Daraus werd ich nicht ganz schlau.>> TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);
Das ist die Berechnung des Timerwertes, so dass der Timer zum Hochzählen
von diesem Wert bis auf 255 ziemlich genau 10ms benötigt.
Wie gesagt: das kannst du meistens auch weglassen. Ob das jetzt 10ms
sind oder 20, spielt keine allzugroße Rolle.
@ Karl Heinz
Stimmt, ich habe mir die Routine nicht im Detail angesehen (zumal ich in
AVR assembler mangels Übung etwas eingerostet bin :-)) und nebenbei
arbeiten muss.
Wie ich aber aus den Beiträgen herauslese macht die Routine genau was
ich gesagt habe, nämlich zyklisch über einen Timerinterrupt aufgerufen
werden und sich die Zustände der Taster/Schalter merken (muss er ja
sowiso bei autorepeat). Die eigentliche Portabfrage und der Vergleich
des Istzustandes mit dem vorherigen Zustand braucht dann natürlich nur
ein paar Taktzyklen.
Wenn ich tatsächlich mal wieder den Platz und die Zeit zum Basteln habe
dann schaue ich mir die Routine genau an und bedanke mich schon mal im
Voraus dafür die benutzen zu dürfen.
Hallo Karl-Heinz,
Die Sache mit dem Timer-Interrupt hab ich verstanden, keine Angst ;)
PAUSE wird zwischen 0 und 1 hin und hergesetzt.
Das Problem ist halt, dass ich meinen Player gern mit 2 Tasten steuern
möchte. Mit der einen Taste drücke ich mehrmals, je nachdem, ob ich
Pause(1xdrücken), oder leiser(2x) oder lauter(3x) machen möchte und mit
der anderen Taste bestätige ich diese Folge dann und die gezählten
"Drücker" werden dann an eine Switch-Anweisung weitergegeben und
ausgewertet.
Und diese beiden Taster hängen dann natürlich an den
Interrupt-Eingängen.
Deswegen kann ich für die Pause-Anweisung auch nicht deine Variante
nehmen.
Und deswegen auch nochmal die Frage bzgl. des RS-FFs.
Johannes Hofmann schrieb:
> Das Problem ist halt, dass ich meinen Player gern mit 2 Tasten steuern> möchte. Mit der einen Taste drücke ich mehrmals, je nachdem, ob ich> Pause(1xdrücken), oder leiser(2x) oder lauter(3x) machen möchte und mit> der anderen Taste bestätige ich diese Folge dann und die gezählten> "Drücker" werden dann an eine Switch-Anweisung weitergegeben und> ausgewertet.
Ist damit überhaupt kein Problem:
> Lt. Tutorial ist es ja günstig, dieses RS-FlipFlop zu verwenden.> Kann man diese Schaltung auch benutzen, wenn man nur nen simplen Taster> hat? bzw. diese ein wenig abwandeln, damit es klappt?
Nein.
Deswegen gibt es unterschiedliche Schaltungen, je anch vorhandenm Taster
http://dse-faq.elektronik-kompendium.de/dse-faq.htm#F.29.1> Und diese beiden Taster hängen dann natürlich an den> Interrupt-Eingängen.
Das ist grober Schwachsinn, denn die Pellimpulse von den Tasten können
so schnell kommen, schneller als dein uC den Interrupts folgen kann.
So eine Lösung wird auch nirgends vorgeschlagen.
Mach einen Interrupt der (länger als die Prellzeit der Taster, also
z.B.) alle 20msec nachguckt, wie die Tastereingänge stehen.
on Timer_interrupt:
copy Port -> Tastenzustandvariable aktueller_Zustand
und lass dein Hauptprogramm (in einer Schleife) entscheiden, was es tun
soll, wenn sich der Tastenzustand geändert hat (nun gedrückt, nun nicht
mehr gedrückt)
if alter_Zustand != aktuelle_Zustand
tu was
alter_Zustand:= aktueller_Zustand
Warum habne alle Leute so massive Probleme, zu verstehen, was prellen
ist ?
MaWin schrieb:
> Mach einen Interrupt der (länger als die Prellzeit der Taster, also> z.B.) alle 20msec nachguckt, wie die Tastereingänge stehen.>> on Timer_interrupt:> copy Port -> Tastenzustandvariable aktueller_Zustand>> und lass dein Hauptprogramm (in einer Schleife) entscheiden, was es tun> soll, wenn sich der Tastenzustand geändert hat (nun gedrückt, nun nicht> mehr gedrückt)>> if alter_Zustand != aktuelle_Zustand> tu was> alter_Zustand:= aktueller_Zustand
mit anderen Worten:
nimm die PeDa Tastenentprellung :-)
und freu dich darüber, dass es funktioniert und geniesse den
Zusatzkomfort
MaWin schrieb:
>> Und diese beiden Taster hängen dann natürlich an den>> Interrupt-Eingängen.>> Das ist grober Schwachsinn, denn die Pellimpulse von den Tasten können> so schnell kommen, schneller als dein uC den Interrupts folgen kann.> So eine Lösung wird auch nirgends vorgeschlagen.
Ein im Mikrosekunden Bereich prellender Taster? Hui ;)
> Ein im Mikrosekunden Bereich prellender Taster? Hui ;)
Natürlich, im Moment der Kontaktgabe bzw. des Kontaktöffnens bilden sich
kleine Funken aus, und die sind (das Wort Funkstörungen kommen nicht
ohne Grund daher) sehr schnell am Abreissen und neubilden, auch in
weniger als Mikrosekunden.
Dass neben der Funkenströrung auch noch das mechanische Prellen
hinzukommt, wo der Kontakt, wenn er schliesst, eventuell wieder
"weghüpft" bevor er erneut schliesst, macht die Sache nicht einfacher.
Ich bin ja sehr dankbar für euer Bemühen, aber wenn ich nun in einer
Schleife mit while(PAUSE){} bin, dann komm ich doch gar nicht anders
raus, als wenn PAUSE durch einen Interruptgenerierten Vorgang wieder auf
0 gesetzt wird.
Und natürlich werden die Taster auch nicht direkt an die
Interrupteingänge angeschlossen. Deswegen such ich ja nach so einer
Vorbeschaltung.
Ich hab schon bei Conrad nach so nem Inverter mit
Schmitt-Trigger-Eingängen gesucht, aber konnte keinen finden. Die haben
ja auch eine blöde Suche.
Könnt ihr mir da weiterhelfen?
Sorry Mawin, aber dein Link zu diesem Kompendium lässt meinen FF
abstürzen :(
Johannes Hofmann schrieb:
> Ich bin ja sehr dankbar für euer Bemühen, aber wenn ich nun in einer> Schleife mit while(PAUSE){} bin, dann komm ich doch gar nicht anders> raus, als wenn PAUSE durch einen Interruptgenerierten Vorgang wieder auf> 0 gesetzt wird.
Mit anderen Worten.
Du hast das alles schon fertig aufgebaut, hast festgestellt dass es
nicht so richtig funktioniert und suchst nun nach einer Lösung wie du
das verkorkste Design noch möglichst billig retten kannst.
nenn doch die Dinge beim Namen
Bei einer Liedpause den ganzen Mikrocontroller aufhören lassen zu
rechnen ist nicht gerade klug.
Die Uhrzeit auf dem Display wird nicht mehr geupdatet. Er ist über
Ethernet nicht mehr zu erreichen. Der USB Datenlink bricht ab.. ;)
Quatsch!
Da ist noch nix fertig aufgebaut und wie kommst du auf "Billig
retten"???
Ich hätte es nur gern so gemacht, wie ich es beschrieb. Und dafür
benötige ich die Hardware-Entprellung.
Und somit steht wieder die Frage vom Thread-Anfang.
Doch leider killt ja der Link von MaWin meinen FF.
Johannes Hofmann schrieb:
> Quatsch!> Da ist noch nix fertig aufgebaut und wie kommst du auf "Billig> retten"???
Weil ich lang genug hier im Forum mitlese :-)
Wenn sich jemand standhaft weigert eine Softwarelösung anstelle einer
aufwändigeren Hardwarelösung einzusetzen, dann bedeutet das im Regelfall
nur eines :-)
> Ich hätte es nur gern so gemacht, wie ich es beschrieb. Und dafür> benötige ich die Hardware-Entprellung.> Und somit steht wieder die Frage vom Thread-Anfang.
Im Artikel "Entprellung" ist ja dann auch noch die Hardware-Lösung für
Einfachtaster angegeben. Ausser das die einfacher ist als das FF, was
genau gefällt dir daran nicht?
http://www.mikrocontroller.net/articles/Entprellung#Einfacher_Taster
Weil ich mir bei Pollin grad paar NAND-ICs gekauft habe. Leider hab ich
das mit Wechselschalter und Taster übersehen.
Deswegen die Frage, ob man auch nen Taster mit ner Flip-Flop-Schaltung
entprellen kann.
In jedem anderen Fall hätte ich natürlich sofort die Software-Lösung
benutzt. Gar keine Frage.
Und meine Standhaftigkeit habe ich ja hoffentlich ausreichend erläutert.
Ne ganz harte Variante wäre ja auch die Nutzung eines 2. uC für die
Entprellung. Oder wie war das mit den Kanonen und den Spatzen...
Könnt ihr anderen den Link vom MaWin öffnen?
Johannes Hofmann schrieb:
> Ich bin ja sehr dankbar für euer Bemühen, aber wenn ich nun in einer> Schleife mit while(PAUSE){} bin, dann komm ich doch gar nicht anders> raus, als wenn PAUSE durch einen Interruptgenerierten Vorgang wieder auf> 0 gesetzt wird.
Und wo ist dabei das Problem?
1
while(pause){
2
if(get_key_press(1<<taste1))
3
pause=0;
4
// usw.
5
}
So einfach ist das mit den Entprellfunktionen.
Peter
Aber nichtsdestotrotz probiere ich natürlich grade mit der Routine, auch
zwecks Lerneffekt.
Doch leider will es nicht wie ich wohl will.
Im Moment sieht der Code bei mir so aus:
> Wo hast du denn die Horrorgeschichte her!
Simon, Ball flachhalten, auch wenn du den Blitz nicht geissend hell aus
dem Gehäuse rauskommen siehst, heisst das nicht, dass nicht welche
entstehen. Sie entstehen bei jedem Stromfluss und jeder Spannung.
> Könnt ihr anderen den Link vom MaWin öffnen?
500kB Datei, dauert länger.
taster entprellen mit einem FF geht nicht
allgemein steh ich nich auf hardwareloesungen wenn es auch per software
geht, da die schaltung dann nur unnoetig groesser wird.
Taster hardwaremaesig entprellen noch dazu nicht zuverlaessiger als eine
brauchbare software loesung, ausser das man die hardware hirnlos
nachbauen kann ;-)
Ach das mit der "Horrorgeschichte" stimmt natuerlich, auch bei kleinen
Spannungen entstehen Funken wenn sich kontakte naehern. Das manche
taster mehr und manche weniger prellen haengt daher mit der mechanik und
der beschaffenheit der kontaktflaechen ab. Es gibt natuerlich auch
entprellte schalter aber die sind dann natuerlich nicht rein mechisch
Hello again.
So mein Code sieht jetzt so aus. Klar hatte ich key_state und key_press
als volatile, ich hatte bloß vergessen es in meinem letzten Post
hinzuschreiben.
1
TCCR0 = (1<<CS02)|(1<<CS00); // divide by 1024
2
TIMSK = 1<<TOIE0; // enable timer interrupt
3
4
while(1){
5
if( get_key_press( 1<<KEY1 ))
6
Counter++;
7
if( get_key_press( 1<<KEY2 )){
8
if(Counter){
9
LED_EVENT3(LED1,Counter);
10
Counter=0;
11
}
12
}
13
}
Doch seltsamerweise wird beim Starten des uC einmal ohne mein Zutun KEY1
"gedrückt", sodass natülrich 'Counter' inkrementiert wird.
Habt ihr da ne Idee, was da für "Geister" am Werk sind?
Habe auch den Prescaler auf 8 gesetzt um wirklich eine zuverlässige
Abtastung zu erreichen.Doch das brachte auch keine Besserung.
Auch wenn die Taster gar nicht an den Ports hängen wird ein "Drücken"
detektiert.