Hey Leute,
ich hatte schonmal einen ähnlichen Thread erstellt, in dem es um die
genaue Funktionsweise der Tastenentprellung (Komfortroutine in C) von
Peter Dannegger ging.
Jetzt habe ich aber ein Atmel ATXmega xplained A1 Board mit einem xmega
128A1 der bei 32 MHz läuft.
Ich wollte fragen, wie die folgende Zeile genau funkioniert, um zu
verstehen, wie ich meinen Counterstand nach der Taktfrequenz des MC
berechnen muss, um eine von mir gewünschte "Abtastrate" zu bekommen.
1
TCNT0=(uint8_t)(int16_t)-(F_CPU/1024*10e-3+0.5);// preload for 10ms
Ich dachte ich kann mir den Counterwert x mit der folgenden Formel
berechnen:
(Preload = 1ms, Takt = 32MHz, Timer-Prescaler = 1024)
Kann das so überhaupt stimmten? Wäre super wenn ihr da ein paar
Ratschläge für mich hättet ;)
Viele Grüße
Hallo,
im Datenblatt steht doch immer eine schöne Formel.
Wenn man dann einen CTC Mode wählt folgt mit aufrunden.
Zaehler = (uint16_t)(1.0* F_CPU/ PRESCALER/ 1000 -1 + 0.5)
Wobei 1000Hz 1ms entspricht.
Also ganz einfach und natürlich.
Beim Xmega ganz einfach, da kannst du den Timer so einstellen dass er
nur bis zu einem von dir eingestelltem Wert zählt und dann einen
Overflow auslöst.
Danke für eure Hilfe.
@Uwe S.:
Hmmm... ich scheine nicht sorgfältig genug gelesen zuhaben, muss mir
entgangen sein :)
@Timmo H.:
Danke für deine Mühe, den Code hatte ich schon ;)
Ich wollte in der ISR zunächst eine LED toggeln, an der ich dann die
Frequenz messen kann, die ich mit dem Zählwert eingestellt habe. Wusste
aber nicht wie man auf die Formel kommt, weiß ich jetzt immer noch
nicht, aber ich weiß wenigstens, dass sie im Manual bzw. Datenblatt
gegeben ist, also kommt man da vermutlich nicht so schnell alleine
drauf?
Warum. Ganz einfach. Der Timer Tickt mit dem Peripheral-Takt (meist
F_CPU). Diesen kann mit mit einem Presclaler runterteilen (hier 256).
Dann Tickt der Timer mit 32MHz/256 = 125 kHz. Damit dauert ein Takt 8ns.
Damit du auf 10ms kommst musst du also 10ms/8ns Takte bzw. 10e-3s/8e-9s
warten. Also 1250 Takte. Steht eigentlich alles im Timer-Kapitel im
Datenblatt beschrieben.
Willy M. schrieb:> Frequenz messen kann, die ich mit dem Zählwert eingestellt habe. Wusste> aber nicht wie man auf die Formel kommt, weiß ich jetzt immer noch> nicht,FAQ: Timer
ist ganz einfach und logisch
Wie ist die Taktfrequenz und wie ist der Prescaler eingestellt?
Aus den beiden Angaben folgt, wie weit der Timer in 1 Sekunde zählen
könnte, wenn ich ihn lasse und er ohne Rücksicht auf Bitanzahl zählen
könnte.
Und dann dreht man das einfach um: Bis zu welcher Zahl kann(muss) er
zählen, wenn ich haben will, dass er das in x Zeiteinheiten schafft (x
ist vorgegeben).
Kommt da dann eine Zahl raus, die zu gross für die Bitbreite des Zählers
ist, dann muss man eben den Prescaler größer machen, damit der Timer
langsamer zählt.
Letzten Endes ist das nur eine Variation von:
Ein Arbeiter kann in 1 Stunde 45 Werkstücke fertig machen. Wieviele
Werkstücke muss er fertig machen, wenn er damit in 35 Minuten fertig
sein soll? Wieviele Werkstücke muss er fertig machen, wenn er damit in x
(x gegeben) Minuten fertig sein soll?
Gewöhn dich an den 3-Satz. Mehr als die Hälfte aller Berechnungen mit
denen du es zu tun hast, sind im Kern nichts anderes als dieser berühmt
berüchtigte 3-Satz.
Oh man.... Ich hab einfach nur einen Denkfehler gehabt -.-
Ich habe gerechnet
1ms/( (1/32Mhz)/1024 ) und nicht
1ms/( 1/(32Mhz/1024) )
Ick raste aus !!!!!!!!!! :D
Soviel dazu -.-
Ich habe jetzt allerdings noch eine Frage. In dem damaligen Thread wo es
um die Funktion der ganzen Routine ging hatte ich den Tipp bekommen,
dass ich für einen Drehgeber lieber 1ms anstatt 10ms Abtastrate nehmen
sollte. Das habe ich jetzt hiermit gemacht, die Frequenz beträgt 1,12
kHz, was in etwa 900us Abtastrate entspricht.
Dennoch kommt es relativ häufig vor, dass wenn ich den Taster drücke die
LED nicht weiter getoogelt wird.
Hier vielleicht nochmal der simple Code der while-Schleife:
Willy M. schrieb:> um die Funktion der ganzen Routine ging hatte ich den Tipp bekommen,> dass ich für einen Drehgeber lieber 1ms anstatt 10ms Abtastrate nehmen> sollte.
Für die Auswertung des Drehgebers. Also den Knopf, den du links/rechts
drehst.
Wenn das ein Drehgeber mit eingebautem Taster ist, bleibst du für die
Auswertung des Tasters selber bei den ungefähr 10ms
(Tasterauswertung nur bei jedem 10-ten ISR Aufruf machen, wenn du die
ISR auf ca 1ms eingestellt hast)
Okay, danke für den Hinweis, mein Drehencoder hat auch einen
integrierten Taster.
Aber vielleicht nochmal zum eigentlichen Problem. Die Abtastung scheint
nicht so gut zu funktionieren.
Manchmal reagiert der Mikrocontroller nicht, wenn ich den Taster drücke
dann bleibt die LED im ein- oder auch ausgeschalteten Zustand.
Ich kann mir nicht erklären wie das passiert....
Innerhalb von 900us den Taster zu drücken und wieder loszulassen ist ja
Schwachsinn, dass schafft niemand so schnell, also müsste auch die
Zustandsänderung bemerkt werden... Tut sie aber halt manchmal nicht
Habt ihr eine Idee wie diese Aussetzer zustande kommen und wie ich sie
beheben kann?
Ich kann mich nicht daran erinnern, dass das auf dem MSP430G2553 kein
Problem war, der hat das gemacht ohne zu mucken...
Willy M. schrieb:> Innerhalb von 900us den Taster zu drücken und wieder loszulassen ist ja> Schwachsinn, dass schafft niemand so schnell, also müsste auch die> Zustandsänderung bemerkt werden... Tut sie aber halt manchmal nicht
Oder sie wird doppelt registriert.
Der PeDa Code macht eine 4-fach Abtastung. 4*900 us macht ca. 3.6ms.
Wenn der Taster langsamer als 3.6ms prellt, dann wertet der Code das
dann daher als 2 Tastendrücke.
Effekt: Die LED wird zwar eingeschaltet, aber gleich darauf wieder aus.
Wenn das schnell genug geht, merkst du das nicht wenn du nicht gaaaaaanz
genau in die LED schaust um das kurze Aufblitzen zu sehen.
> Habt ihr eine Idee wie diese Aussetzer zustande kommen und wie ich sie> beheben kann?
Soll ich dir den enstprechenden Zähler und die if Abfrage in deine ISR
einbauen? Oder machst du das jetzt ganz einfach alleine und wir
überlegen weiter, wenn das das Problem nicht löst.
Da fehlt ja der ganze Drehencoder-Teil!
Kannst du mir mal erklären, warum du dann hier
> TCC0.PER = (uint8_t)(int16_t)-(F_CPU / 1024 * 1e-3 -1 + 0.5); // preload for
1ms
auf 1 ms gehst?
Wie oft soll ich dir das jetzt eigentlich noch erklären?
Um den Drehencoder auszuwerten, das ist das Teil an dem du mit dem
Patschehändchen drehst (!), benutzt du 1ms.
Wenn du mit dem Patschehändchen draufdrückst, also den Taster im
Drehencoder betätigst, benutzt du so wie im Original die 10ms. Der
Draufdrück-Knopf ist doch auch nichts anderes als ein Taster! Taster ist
Taster. Ob der jetzt eigenständig ist oder in einen Drehencoder als
zusätzliches Bedienelement eingebaut ist, ist doch Jacke wie Hose! Der
Taster prellt doch nicht weniger, nur weil er in einen Encoder eingebaut
ist.
So ein Encoder hat 3(!) Ausgänge
Spur A - Abtastung mit dem 1ms Timer
Spur B - Abtastung mit dem 1ms Timer
Taster - <---- Abtatsung wie jeden anderen Taster auch mit ca. 10ms
Okay stoppppppp!!!!
Bevor hier Emotionen hochkochen muss ich nochmal was aufklären... ;)
Der jetzige Code bezieht sich nicht auf den Drehencoder :S
Sondern nur auf einen Taster, der auf dem xplained Board montiert ist.
Wenn ich den drücke, passiert das oben beschriebene Problem!
Den Drehgeber hatte ich noch gar nicht angeschlossen, den Code bekomm
ich dafür aber auch alleine hin, wenn nicht melde ich mich desewegen
auch nochmal, dann wird das vermutlich aber nur an Kleinigkeiten liegen
:)
Entschuldigt, wenn ich mich vorher nicht klar ausgedrückt habe...
Also suche ich jetzt erstmal nach der Lösung für das Problem, dass nicht
alle Tasterdrücke erkannt werden.
Willy M. schrieb:> Also suche ich jetzt erstmal nach der Lösung für das Problem, dass nicht> alle Tasterdrücke erkannt werden.
Dann setze doch mal um, was dir Karl-Heinz jetzt schon 5 Mal erklaert
hat.
Willy, kann es sein, dass dir nicht klar ist, dass es eine UNTERGRENZE
gibt, unter die du mit dem Entprellcode nicht gehen darfst?
Denn das Prellen eines Tasters ist nicht beliebig schnell! Das bewegt
sich so um die 5 bis 20ms rum. Kann auch ein bischen weniger oder ein
bischen mehr sein.
D.h. wenn der Code zu schnell immer wieder auf den Taster schaut, dann
kriegt der das Prellen nicht mit! Der Code sieht dann 2 Tastendrücke,
anstatt nur 1 verprellten.
Entprellen bedeutet nichts anderes, als einen Zeitraum festlegen, indem
mehrfache detektierte Tastendrücke nicht als mehrfach gewertet werden,
weil sie physikalisch als gewollter Tastendruck nicht möglich sind. Wenn
du diese Grenze zu niedrig ansetzt, dann passiert genau das, das das
Programm ein einmaliges Drücken mit Prellen mit mehreren schnell
hintereinander abgegebenen Tastendrücken verwechselt. Der einzige
Unterschied: selbst bei Training wird es dir als Mensch kaum gelingen,
einen Taster in weniger als 100ms 2-mal hintereinander zu drücken. D.h.
wenn du die Entprellzeit auf 3ms festlegst, dann bist du von dieser
Grenze unnötig weit entfernt. Und was noch viel schlimmer ist, du kommst
dann in den Zeitbereich in dem ein prellender Taster tatsächlich 2 mal
anschlägt.
Fazit. Mit deinen 1ms tust du dir KEINEN Gefallen. Das bringt ganz
einfach nichts. Denn die Tastenbetätigung wird deswegen auch nicht
besser. Sie wird höchstens schlechter, wie du ja am eigenen Leib
erfahren hast.
Also: Rauf mit der Entprellzeit für den Taster!
Ob das jetzt alle 10ms statt findet, oder alle 20ms, oder alls 30ms,
oder meinetwegen auch noch alle 5ms, spielt nicht die große Rolle.
Aber weniger darf es nicht werden! Sonst entprellt der Code nicht mehr
richtig.
Länger darf es theoretisch werden, aber auch da gibt es eine sinnvolle
Obergrenze, weil man ja als Benutzer nicht ewig warten will, bis das
Programm dann endlich irgendwann mal den Tastendruck akzeptiert. Aber:
Diese Grenze ist weit jenseits von 10 oder 20ms. 10ms ist eine
Hunderstelsekunde. 100ms ist eine Zehntelsekunde. Wenn du eine Taste
drückst und das Programm reagiert 1 Zehntelsekunde später, dann fällt
dir das kaum auf. Noch länger und der Effekt wird merkbar.
d.h. sinnvolle Entprellzeiten liegen irgendwo in diesem Bereich zwischen
20ms und sagen wir mal 80ms. Wo genau, ist nicht so wichtig. Aber in der
Größenordnung muss es stimmen. Dein Code hat eine 4-fach Abtastung, also
wird das Polling dann in den Bereich 20/4 ca. 5ms bis 80/4 ca. 20ms
gelegt. Und wenn es mehr als 20ms sind, dann ist das auch noch kein
Beinbruch.
> dass nicht alle Tasterdrücke erkannt werden.
Kann natürlich auch sein, dass dein Taster ein Kontaktproblem hat.
Aber davon geh ich erst mal nicht aus, sondern davon, dass es eben nicht
so ist, dass ein Tastendruck nicht ewrkannt wird, sondern dass ein
falscher Tastendruck (wegen Prellen) zusätzlich erkannt wird. Der sorgt
dann dafür, dass die gerade eben eingeschaltete LED wieder ausgeschaltet
wird. Und da sich das im Millisekundenbereich abspielt, kriegst du das
optisch nicht mit.
Nein, dass war mir nicht so ganz bewusst, ich dachte wirklich, dass je
kleiner ich die Zeit mache, desto genauer wird das ganze...
Okay, Entprellzeit liegt bei 10,76ms... Passiert aber immer noch, wenn
ich die Zeit ein WENIG niedriger mache (7-8ms), hilft es auch nicht, bei
16ms auch keine Besserung...
Eigentlich will ich nur, dass der Entprellcode 100% funktioniert, bevor
ich dann den Code für den Drehgeber erweitere, weil wenn beim langsamen
Drücken schon Fehler auftreten, dann doch erst Recht beim Entprellen vom
Drehcoder oder ist das schon wieder ein Irrtum?
TCC0 ist auf deinem Prozessor was für ein Timer? Welche Bitbreite hat
der?
Denn
1
32000000 / 1024 = 31250
2
31250 * 10e-3 = 312
einen 8 Bit Timer kannst du aber nicht mit 312 vorladen!
Mal ein bischen rumrechnen. Was ist wenn du den Timer einfach
durchlaufen lässt?
1
32000000 / 1024 / 256 = 122 Überläufe pro Sekunde
2
1/122 = 0.008 Sekunden, oder 8ms
d.h. wenn du nichts tust und den Timer einfach machen lässt, dann
kriegst du ca alle 8ms einen Overflow. Das sollte reichen. Länger
kriegst du bei einem 8 Bit Timer, einem Vorteiler von 1024 und 32Mhz
nicht hin.
Leg doch mal diese ganze TCC0 Zuweisung still.
Hmmm... Also bei dem XMega 128A1 hat man 8x 16bit Timer.
Welche TCC0 Zuweisung?
Meinst du, dass ich die Zuweisung aus der ISR einfach zur
Initialisierung des Timers schreiben soll, sodass nicht bei jedem ISR
Durchlauf das TCC0.PER beschieben wird?
Das period Register brauchst du nur beschreiben wenn du die zeit/ticks
ändern willst. In deinem Fall willst du aber ja nichts ändern. Es soll
doch immer alle 10ms ein overflow Interrupt ausgelöst werden. Du
brauchst das PER-Register nur einmal mit dem Wert beschreiben der deinen
10ms entspricht und dann kannst du es so lassen und musst nicht bei
jedem Interrupt das Register neu beschreiben.
Jo, hab ich geändert, verändert sich aber leider auch nichts, das Ding
ist, dass ich jetzt alle auf dem Board befindlichen Taster durchprobiert
habe und das bei jedem die Aussetzer aufgetreten sind... Ich habe sogar
schon externe Taster angeschlossen, bei denen das gleiche passiert...
Das passiert sogar, wenn ich die Pins direkt mit einem Kabel verbinde,
manchmal erkennt er das einfach nicht und nichts passiert...
Leider hab ich kein Oszilloskop hier, mit dem ich vielleicht sehen
könnte, ob die LEDs vielleicht doch einmal kurz aufblitzen, allerdings
kann ich mir das jetzt nicht mehr vorstellen, habe eine Entprellzeit von
16ms eingestellt.
Ah, ok - 16 Bit
Ich seh schon, du weißt hier ja ans Period Register zu
1
TCC0.PER=(uint8_t)(int16_t)-(F_CPU/1024*1e-3-1+0.5);// preload for 1ms
ja, das geht aber so nicht.
Zum einen braucht das nicht bei jedem ISR Aufruf gemacht werden, sondern
nur einmalig beim Programmstart.
Zum anderen ist diese Berechnung falsch, für deinen Zweck
(die Berechnung im Original ist für die 'alten' 8 Bit AVR gemacht, die
einen 8 Bit Timer haben, bei denen man ins Zählregister einen Wert
schreibt, von dem aus an der Timer bis 255 zählt, ehe der Overflow
kommt. Daher auch das - in der Berechnung.
Bei dir muss das lauten
1
TCC0.PER=(uint16_t)(F_CPU/1024*10e-3-1+0.5);
und diese Berechnung kommt einmalig in main() rein und flíegt aus der
ISR raus
Willy M. schrieb:> Leider hab ich kein Oszilloskop hier, mit dem ich vielleicht sehen> könnte, ob die LEDs vielleicht doch einmal kurz aufblitzen, allerdings> kann ich mir das jetzt nicht mehr vorstellen, habe eine Entprellzeit von> 16ms eingestellt.
In dem Fall sind wir (ich?) von falschen Voraussetzungen ausgegangen.
Mit der Originalberechnung hast du tatsächlich eine Entprellzeit
jenseits von gut und böse erhalten.
Daher ein gut gemeinter Rat:
WEnn du Timer aufsetzt und du bei den ISR Aufrufen auf eine bestimmte
Zeit aus bist, dann überprüfe das! zb indem du in der ISR eine LED
toggeln lässt. WEnn die Zeit zu kurz ist, als das du das Blinken siehst,
dann verlängere dir die Zeit, zb auf das 1000-fache
1
ISR(....)
2
{
3
staticintcnt=0;
4
5
cnt++;
6
if(cnt==1000)
7
{
8
cnt=0
9
LEDtoggeln;
10
}
11
}
dann brauchst du auch kein Oszi um das zu sehen. Eine gewöhnliche
Armbanduhr reicht. Du zählst einfach die Sekunden und die ISR
Aufrufhäufigkeit ist dann 1/1000 davon. So kannst du auch einzelne
Millisekunden noch gut unterscheiden.
Aber gerade am Anfang ist es wichtig, alles und jedes zu überprüfen. Vor
allen Dingen dann, wenn der Code ursprünglich gar nicht für deinen
µC-Typ geschrieben war.
Edit:
Ich würde das sogar jetzt noch überprüfen, ob die 10ms jetzt stimmen.
genau nach diesem Muster. Vielleicht nicht mit 1000, aber mit 500. Die
LED muss dann 5 Sekunden brennen und 5 Sekunden dunkel sein. Jegliche
ABweichung von diesen Zeiten bedeutet, dass irgendwo in der
Konfiguration was nicht stimmt.
Und erst dann, wenn ich sicher bin, dass die ISR Zeiten korrekt sind,
gehts weiter mit der Entprellung.
Hey Karl,
also ich toogle in meinem Code den ich gepostet habe in der ISR eine
LED, um zu sehen, ob der Timer beim Overflow auch wirklich die ISR
aufruft. Dann messe ich mit meinem Multimeter die Frequenz an der LED
und nehme den Kehrwert davon, deswegen konnte ich auch Aussagen wie
meine Entprellzeit ist 10,76ms machen (abgesehen mal davon, dass die
Genauigkeit meines Multimeters das garnicht zulässt ;) )
Und das mit dem Oszilloskop stimmt auch nicht ganz, ich habe zwar ein
gaaaaaanz altes Grundig 20MHz Oszilloskop, aber damit kann ich mir nur
noch Signalverläufe anschauen, leider nichts genauers mehr messen,
allerdings weiß ich nicht wie ich ein so kurzes aufblitzen einer LED
aufnehmen sollte, ich habe ja kein WafeformRecording.
Willy M. schrieb:> Nein, dass war mir nicht so ganz bewusst, ich dachte wirklich, dass je> kleiner ich die Zeit mache, desto genauer wird das ganze...
Du hast also das Prinzip wohl schon nicht richtig verstanden.
> Okay, Entprellzeit liegt bei 10,76ms...
Definitiv zu wenig für schlechte Schaltkontakte. Die prellen schonmal
20, 30ms oder noch mehr.
Sinnvolle Werte für die Entprellung liegen so zwischen 50 und 100ms,
wobei man mit 100ms leider schon in dem Bereich ist, der durchaus auch
Nutzsignal sein könnte. Die Fire-Tasten von guten Joysticks aus der
Homecomputer-Zeit z.B. erlaubten tatsächlich "Eingabe"raten in dieser
Größenordnung. Allerdings gibt's sowas heute offensichtlich nicht mehr.
Da wurde wohl massiv kostenoptimiert, sowohl bei der Kontaktgeometrie
als auch bei der Wahl der Werkstoffe...
Wirklich schnelle, zuverlässige und langzeitstabile Mikrotaster kriegt
man heute nur noch im Industriebereich (und auch dort nur mit etwas
Glück oder Hintergrundwissen) und die kosten dann wirklich unanständig
viel Geld. Wahrscheinlich, weil der Billichscheiß die guten Sachen zu
Exoten mit sehr geringen Produktionszahlen gemacht hat.
> Eigentlich will ich nur, dass der Entprellcode 100% funktioniert, bevor> ich dann den Code für den Drehgeber erweitere
Jetzt ist sicher: Du hast es nicht verstanden. Das coole an Drehencodern
ist nämlich, daß die überhaupt nicht entprellt werden müssen...
Willy M. schrieb:> @Jörg:>> Hatte ich schon, war bei 2s. War ganzschön nervig die 8s zu warten bis> die LEDs angegangen sind ;)
Ich denke es ist wieder mal an der Zeit, den Code in seiner jetzigen
Form zu sehen :-)
c-hater schrieb:>> Okay, Entprellzeit liegt bei 10,76ms...>> Definitiv zu wenig für schlechte Schaltkontakte. Die prellen schonmal> 20, 30ms oder noch mehr.
wenn ich ihn richtig verstehe, dann meint er damit die ISR
Aufruffrequenz. Die Entprellzeit ist dann im Minimum das 4-fache davon.
Karl Heinz Buchegger schrieb:> Willy M. schrieb:>> @Jörg:>>>> Hatte ich schon, war bei 2s. War ganzschön nervig die 8s zu warten bis>> die LEDs angegangen sind ;)>> Ich denke es ist wieder mal an der Zeit, den Code in seiner jetzigen> Form zu sehen :-)
Vor allen Dingen weil Timmo gestern abend schon die korrekte Formel
gepostet hat und der Code von heute Nachmittag wieder die falsche drinn
hatte.
Okay, 50...100 ms habe ich ausprobiert, erstmal fang ich an die in der
ISR getoogelte LED blinken zu sehen und bei 100 muss ich anfangen etwas
länger gedrückt zu halten, damit er das wirklich erkennt, aber auch hier
besteht weiterhin das Problem, dass manche Tastendrücke??? nicht erkannt
werden. Ich habe mir einfach mal versucht die Pegel mit dem Oszilloskop
anzuschauen und zu gucken, ob der Taster jedes mal beim Drücken den Pin
auf Masse zieht und das Tut er, trotzdem scheint der MC diesen Wechsel
manchmal nicht mitzubekommen...
c-hater schrieb:> Jetzt ist sicher: Du hast es nicht verstanden. Das coole an Drehencodern> ist nämlich, daß die überhaupt nicht entprellt werden müssen...
Das kann gut sein, so dachte ich, dass der Drehencoder funktioniert:
Mein Drehencoder hat 12 Stellung, und ist 360° drehbar mit zusätzlicher
Tasterfunktion. Wenn ich nun den Drehencoder nach Rechts drehe, wird am
Pin A eine steigende Flanke erzeugt, phasenverschoben z.B. dem Pin A
nacheilend wird an Pin B enbenfalls eine positive Flanke erzeugt. Durch
den Phasenwinkel zwischen Pin A und Pin B kann ich feststellen in welche
Richtung der Drehencoder gedreht wurde, d.h. wenn ich den Drehencoder
nach links drehen würde, dann würde Pin B Pin A vorrauseilen...
Ist das so korrekt?
Und nun dachte ich, das es bei den Übergängen von einer Stellung zur
nächsten unsaubere Flanken geben kann, die entprellt werden müssen...
> TCC0.CCA = 1.0*F_CPU /1024 /2 *30e-3 -1;
wieso auf einmal CCA?
Bitte, mach keine unmotivierten Änderungen!
WIe soll man denn da als Aussenstehender, der nicht sieht, was du sonst
noch so alles änderst noch mitkommen.
Jetzt muss ich erst mal nachlesen, was eigentlich das CCA Register
macht.
Entschuldige, ich habe den zählmodus geändert, weil für den die
Frequenzberechnung genau angegeben war.
TCC0.CCA ist für den FRQ Mode das gleiche wie TCC0.PER für den Normal
Mode, also die obere grenze, mit der die Periodendauer T festgelegt
wird.
Stimmt ihr mir zu, das wenn man davon ausgeht, das der Taster ideale
Flanken (eindeutig zu interpretierende Signale) produziert, der MC bei
jedem Tasterdruck die LEDs toggeln müsste?
Hmm
Der weigert sich hartnäckig.
Hast du eigentlich 8 Pins am bewussten Port mit den LED?
Lass dir mal key_state so wie es ist dort ausgeben.
Eigentlich solltest du dort sehen können, wie nach kurzer Zeit der
Tastendruck von der ISR registriert wird
Ich kenne diese XMega Sache nicht.
ABer.
Geht das überhaupt?
PORTE.OUT ^= 0x01; // Hier wird die LED getoogelt, an der ich die
Frequenz messe
Kann man mittels des OUT den aktuellen Zustand der Ausgangspins
zurücklesen?
Timmo H. schrieb:> Das geht schon,
ok.
nicht dass er sich unabsichtlich in der ISR die LED wieder abschaltet,
die er in main getoggelt hat.
Ich seh im Code jetzt nämlich auch nichts mehr.
Drum falle ich in den Modus "Hinterfrage alles und zieh alles in
Zweifel" zurück.
Karl Heinz Buchegger schrieb:> Hast du eigentlich 8 Pins am bewussten Port mit den LED?
Ja, genau. Auf dem Board sind an PORTE acht LEDs angeschlossen, die
neben den 8 Tastern die an PORTD angeschlossen sind liegen.
Erstmal zum Verständnis, die Funktionen aus P. Danneggers Code dienen
nur dazu um z.B. einmal abzufragen, ob ein Taster gedrückt wurde oder ob
der Zustand länger gehalten wird (für die Repeat Funktion), dass ganze
müsste aber auch ohne die Funktionen funktionieren?
Ich könnte z.B. anstatt
1
if(get_key_press(Pin4_bm))
auch
1
if(key_state&Pin4_bm)
schreiben?
Folgendes passiert wenn ich den Taster drücke:
Taster gedrückt halten: Die LED toggelt gedimmt immer hin und her, auf
dem Osilloskop sieht man ein "schönes" 50% PWM Signal
Taster kruz drücken: Für kurze Zeit sieht man das oben beschriebene PWM
Signal, es ist Zufall in welchem Zustand (Ein,Aus) die LED bleibt.
Ich habe das Bild mal mit angehängt.
>> schreiben?
Ist aber eine andere Funktionalität.
> Folgendes passiert wenn ich den Taster drücke:>> Taster gedrückt halten: Die LED toggelt gedimmt immer hin und her, auf> dem Osilloskop sieht man ein "schönes" 50% PWM Signal>> Taster kruz drücken: Für kurze Zeit sieht man das oben beschriebene PWM> Signal, es ist Zufall in welchem Zustand (Ein,Aus) die LED bleibt.
Das ist interessant.
Das sollte nämlich nicht so aussehen.
Wenn du die Taste drückst, dann sollte key_state am bewussten Pin mit
ein wenig verzögerung den Zustand des Input Port Pins annehmen.
Kann es sein, dass dein µC zwischendurch Resettet?
Willy M. schrieb:> Okay... Das kann wirklich sein, aber wie finde ich das heraus?
Na zum Beispiel
1
intmain()
2
{
3
....
4
5
Portsinitialisieren
6
7
LEDeinschalten
8
1Sekundewarten
9
LEDausschalten
10
11
...
12
13
while(1)
14
{
15
...
16
}
wenn die LED immer wieder für 1 Sekunde an geht, dann läuft main()
offenbar wieder von vorne an.
Auf der anderen Seite sind mir die Pulse zu regelmässig. Aber einen
Versuch ist es wert.
key_state sollte eigentlich stabile Pegel zeigen, je nachdem ob die
Taste gedrückt ist oder nicht. Im Grunde ist das nur eine bereinigte
Version von KEY_PIN (die könnte man auch mal ausgeben und nachsehen ob
sich da dieselben Toggler zeigen)
@Karl:
Der MC resetet nicht, ~KEY_PIN zeigt das gleiche verhalten wie
key_state...
Ich glaube ich habe den Fehler gefunden...
Ich habe die Zeilen cli(); und sei(); aus den Funktionen rausgenommen,
und das auch nur, weil ich als ich wieder mit den Atmels angefangen habe
vergessen hatte, dass man die interrupts.h braucht, deswegen hat der mir
ne Fehlermeldung ausgespuckt, dass er die nicht kennt, habe sie aber
vergessen wieder reinzuschreiben.... vielleicht klappst ja jetzt
Ohnein... Sorry Leute... Was für ein dummer Fehler :S
Jetzt funktioniert alles so wie es soll... Na toll!!!
Dann können wir ja gleich nochmal meine Frage klären, ob der Drehencoder
sehr saubere Signale liefert oder ob man den doch entprellen muss :)
Und danke das ihr mir so tapfer geholfen habt :)
Ist doch schon alles fertig: Drehgeber
Kannst auch die gleiche Timer ISR dafür verwenden. Einfach auf 1ms
Intervall verkürzen und nur jedes 10. mal die Taster abfragen.
Häng doch fix jeweils die Drehencoderkanäle an dein Oszi.
Wenn du dir überlegst, wie so ein Drehencoder arbeitet, solltest du
darauf kommen, das der recht saubere Signale liefern sollte. Du hast ja
quasi ne Optokopplerstrecke, auf der zwischen LED und Optotranse einfach
ne Lochscheibe bzw Schlitzscheibe liegt. Schlitz geht auf, Licht trifft
auf den Transistor, dein Signal schaltet sauber auf LOW/HIGH(je nach
Architektur), Schlitz geht zu, Licht weg, Signal wechselt sauber auf den
anderen Pegel=).
MfG Chaos
P.S. von den Schlitzscheiben hast du dann natürlich die 2 versetzten
Spuren, um dein phasenverschobenes Signal auf den beiden Kanälen zu
erhalten.
P.P.S. wenn du natürlich n mechanischen Drehencoder hast.... dann
solltest du dir schon Gedanken ums Entprellen machen. Das Prellen ist
halt ein Abart der Elektromechanik =), mit sowas hast du bei der
LED-Optostrecke nicht zu kämpfen