Hallo, ich versuche den Drehregler ans Laufen zu kriegen. Anfänger Level! Benutzt wird ein STM32F103 Mikrocontroller. Ich habe mir bereits den Code von Peter D. angeguckt leider konnte ich ihn nicht nachvollziehen. Es ist verwirrend, wo die Funktionen reingeschrieben worden. Ich habe es erst selber versucht den Drehregler ans Laufen zu kriegen mit 2 Timer und 2 Interrupts aber das ganze funktioniert nicht perfekt manchmal werden Impulse Doppelt und manchmal gar nicht erkannt. Vielleicht hat jemand mit STM Erfahrung gehabt.
AA schrieb: > STM32F103 Soweit mir bekannt, hat der STM32F103 (Alle STM32F103 ?) einen (oder mehrere?) Timer(Hardwaredecoder), welcher direkt mit einem solchen Drehencoder umgehen kann. Den Code von Peter wirst du also gar nicht brauchen.
Arduino Fanboy D. schrieb: > Den Code von Peter wirst du also gar nicht brauchen. Wobei man sagen muss, das der evtl. vorhandene Quadraturdekoder (so heisst das Ding) nicht ganz einfach zu initialisieren ist. Ich habe jedenfalls dann doch PeDas Code implementiert, der ja lediglich einen 1ms Timerinterrupt voraussetzt. AA schrieb: > Benutzt wird ein STM32F103 Mikrocontroller. Ich habe mir bereits den > Code von Peter D. angeguckt leider konnte ich ihn nicht nachvollziehen. Eigentlich ist es nicht so schlimm: 1. Timer auf 1ms mit Interrupt initialisieren. Das ist beim STM32 mit Prescaler und Periodendauer nicht so schwer hinzukriegen, obwohl man evtl. gleich uin32_t statt uint8_t für die Zwischen- und Ergebnisvariablen verwenden könnte. 2. In der Hauptschleife nur eine der drei Ergebnisabfragen verwenden, also nur 'encode_read1' oder nur 'encode_read2','encode_read4' etc. verwenden. Welche am günstigsten ist, hängt vom Drehgeber ab. Beim STM32 ist es günstig, mit den Bitmustervorgaben der Libraries zu arbeiten. Also z.B.
1 | #define PHASE_A GPIO_Pin_12
|
2 | #define PHASE_B GPIO_Pin_13
|
3 | |
4 | #define ENCODER_GPIO_PORT GPIOD
|
da ja beim STM32 Bitposition und Portpin nicht 1:1 liegen.
:
Bearbeitet durch User
Ja ich denke mir ist nicht klar, wo ich den Code reinschreiben soll. Ich habe jetzt TIM1 auf 1 ms eingestellt Prescaler auf 7200 somit habe ich 10kHz und Period auf 65525. Jetzt zählt er nur 10 Schritte = 1mS
1 | static void MX_TIM1_Init(void) |
2 | {
|
3 | TIM_ClockConfigTypeDef sClockSourceConfig; |
4 | TIM_MasterConfigTypeDef sMasterConfig; |
5 | |
6 | htim1.Instance = TIM1; |
7 | htim1.Init.Prescaler = 7200; |
8 | htim1.Init.CounterMode = TIM_COUNTERMODE_UP; |
9 | htim1.Init.Period = 65525; |
10 | htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; |
11 | htim1.Init.RepetitionCounter = 0; |
12 | htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; |
13 | }
|
Jetzt habe ich in der Interrupt Service Routines folgendes einen Interrupt und ein Timer. Ich müsste dann jetzt seine "void t0_interrupt" Funktion in EXTI1 und "gray_width get_gray_delta" Funktion in TIM1 schreiben richtig? Aber dennoch ich sehe nicht das Gesamtbild, habe den Code von Peter nicht zu 100% verstanden.
1 | void EXTI1_IRQHandler(void) |
2 | {
|
3 | |
4 | }
|
und
1 | void TIM1_UP_IRQHandler(void) |
2 | {
|
3 | |
4 | }
|
AA schrieb: > ich versuche den Drehregler ans Laufen zu kriegen. Gib es nur einen Typ davon? Wie regelt er die Drehung? Das sollte doch zuerst geklärt werden.
AA schrieb: > Aber dennoch ich sehe nicht das Gesamtbild, habe den Code von Peter > nicht zu 100% verstanden. Wenn du so einen einfachen Drehgeber nicht zu verstehen in der Lage bist, warum wagst du dich dann an so ein Projekt? Versuche zu allererst, die Funktion dieser Dinger zu verstehen, dann ergibt sich alles Weitere wie von selbst! Die allermeisten heutigen Drehgeber funktionieren so, daß sie 2 Kontakte besitzen, die mit einem Winkel-Versatz öffnen und schließen. Also etwa so: 1. k1 geht auf 2. k2 geht auf 3. k1 geht zu 4. k2 geht zu dann wiederholt sich das Spiel 1..4 in der gleichen Reihenfolge. Wenn man anders herum dreht, dann geht es ganz genau so, bloß in umgekehrter Reihenfolge. Bei den meisten Drehgebern gibt es auch eine Raststellung, die ganz häufig mit einem oder mit zweien der Ereignis-Punkte 1 bis 4 zusammenfällt. Also etwa so: 1. k1 geht auf und Rastpunkt A 2. k2 geht auf 3. k1 geht zu und Rastpunkt B 4. k2 geht zu Wenn du also einen rastenden DG hast, dann mußt du das Ereignis herausfinden, wo k2 auf oder zu geht und zu diesem Zeitpunkt feststellen, welchen Zustand k1 gerade hat. Aus dem Ereignis "k2 hat sich geändert" folgt das controllerinterne Ereignis, daß jemand dran gedreht hat. Aus dem Zustand von k1 hingegen erkennst du, ob der vorwärts oder rückwärts gedreht hat. Ist doch EASY, sowas! Nun kannst du dir überlegen, ob du den ganzen Mist pollen willst, oder ob du das durch einen Interrupt auf beide Flanken von k2 erfassen willst. Der Interrupt ist die weitaus elegantere Variante, setzt aber voraus, daß du das Signal zuvor analog entprellst. Dafür braucht's nen 22nF Kondensator und fertig. Obendrein ist diese Variante weniger ressourcenfressend. Hier gibt's jedoch eine Riege militanter Verfechter des Pollings. Kann man auch machen, aber dann muß man eben softwaremäßig entprellen, was den Programm-Overhead erhöht. Den beiden Kontakten nen Kondensator zu spendieren ist wesentlich einfacher. W.S.
AA schrieb: > void EXTI1_IRQHandler(void) Den EXTI Handler brauchst du, wenn du die von W.S. beschriebene Methode benutzt, bei dem der Drehgeber selber einen IRQ auslöst. Bei der PeDa Methode wird er nicht benötigt. Hier ist AA schrieb: > void TIM1_UP_IRQHandler(void) die richtige ISR. AA schrieb: > seine "void t0_interrupt" > Funktion in EXTI1 und "gray_width get_gray_delta" Funktion in TIM1 > schreiben richtig? Ich bin mir nicht klar, von welchen Routinen du redest. Ich beziehe mich immer auf die 'Solide Lösung' von hier: https://www.mikrocontroller.net/articles/Drehgeber#Solide_L.C3.B6sung:_Beispielcode_in_C Ausserdem nicht vergessen, den NVIC auf die Interrupts zu programmieren, sonst passiert nix.
:
Bearbeitet durch User
W.S. schrieb: > Hier gibt's jedoch eine Riege militanter Verfechter des Pollings. Kann > man auch machen, aber dann muß man eben softwaremäßig entprellen, was Nicht ganz richtig. Beim Polling muß man gar nicht Entprellen, weil das Prellen eben durchs Zeitraster fällt. Hab ich jedenfalls nie gebraucht.
batman schrieb: > Nicht ganz richtig. Beim Polling muß man gar nicht Entprellen, weil das > Prellen eben durchs Zeitraster fällt. Hab ich jedenfalls nie gebraucht. Bei einer Abtastrate von ~1kHz korrigiert sich das von selbst, weil eine Schalterstellung immer mehrfach abgefragt wird, bevor zur nächsten geschaltet wird. Dank des Gray-Codes springt das beim Prellen nur zwischen einem Schritt hin und her (+/-). Falls beim schnellen kurbeln mal ein Schritt verlorengeht, merkt das eh keiner. Der Einsatz von Pin-Change-INTs ist völlig unnötig und bringt nur zusätzliche Probleme. [Nachtrag] Bzw. bei Einsatz von INTs ist dann wirklich eine aktive Entprellung notwendig. Was heißt den INT sperren bis das Prellen vorbei ist....
:
Bearbeitet durch User
Matthias S. schrieb: > Eigentlich ist es nicht so schlimm: > 1. Timer auf 1ms mit Interrupt initialisieren. Das ist beim STM32 mit > Prescaler und Periodendauer nicht so schwer hinzukriegen, obwohl man > evtl. gleich uin32_t statt uint8_t für die Zwischen- und > Ergebnisvariablen verwenden könnte. Oder noch simpler den viel einfacher zu konfigurierenden Systick nutzen. Vermutlich wird der eh schon für andere Zwecke gebraucht. Hat den weiteren Vorteil, dass die Routine dann auch auf allen Cortex-M Controllern läuft.
Doctor Snuggles schrieb: > Oder noch simpler den viel einfacher zu konfigurierenden Systick nutzen. Klar, geht natürlich auch. Ob man Polling oder IRQ Methode benutzt, sei jedem selber überlassen. Ich habe mit Polling auch bei übelsten Drehgebern gute Erfahrungen gemacht und habe sowieso immer irgendwelche Timer über bei den STM32. Auf AVR nutze ich den Timer dann sowohl für den Encoder als auch für etwaige Tasterroutinen, Multiplexing oder Uhrenkram gleichzeitig.
:
Bearbeitet durch User
batman schrieb: > Beim Polling muß man gar nicht Entprellen, weil das > Prellen eben durchs Zeitraster fällt. Wenn das nicht so unsäglich falsch wäre, könnte man sich vor Lachen .. ROTFL Nein, beim Polling muß man auch entprellen, entweder wieder mal analog mit nem simplen C oder durch mehrfaches Abfragen und "Mehrheits-Entscheidung". Obendrein muß man beim Polling das per Software nachbilden, was die Hardware - nämlich das Erkennen des Flanken-Wechsel Ereignisses - einem sonst an Arbeit abnimmt. W.S.
batman schrieb: > Beim Polling muß man gar nicht Entprellen, weil das > Prellen eben durchs Zeitraster fällt. Zumindest PeDas Routine kann man unter 'ich frage zweimal und dann ist es wahr' zusammenfassen. Beim ersten Durchlauf mit geänderten Phasenzuständen wird erstmal ein Bit gekippt. Ist beim nächsten Durchlauf die Zustand immer noch so, wird das übernommen und als gültig erklärt. Es kann also schon mal prellen, rutscht aber beim nächsten Durchlauf durch den Test.
W.S. schrieb: > batman schrieb: >> Beim Polling muß man gar nicht Entprellen, weil das >> Prellen eben durchs Zeitraster fällt. > > Wenn das nicht so unsäglich falsch wäre, Das ist bei einem Drehgeber etwas anders, als bei einem Taster mit nur einem Kontakt -> Gray-Code. Das entprellt sich da wirklich von selbst, da du dir den alten Zustand ja eh merken musst und wesentlich schneller pollst. Das muss man halt bei einem Taster extra zum Endprellen programmieren. In SW Endprellen heißt doch nur 'Oh da war doch was, sehen wir etwas später noch mal nach, ob da wirklich was is....' Bei solch immensen Aufwand, könnte man schon auf die Idee kommen, daß das zeitgesteuerte Abfragen bereits das komplette entprellen darstellt. :)
Wo hat das was mit einer "Mehrheits-Entscheidung" zu tun? Die (pollende) EA-Methode, die ich kenne, übernimmt den ersten gültigen Zustandswechsel. Nagut, mag es auch andere Varianten geben.
batman schrieb: > Wo hat das was mit einer "Mehrheits-Entscheidung" zu tun? Die (pollende) > EA-Methode, die ich kenne, übernimmt den ersten gültigen > Zustandswechsel. Tust du doch automatisch! Oder wertest du die Drehgeber Ereignisse so schnell aus wie sie auftreten können (1kHz -> 500Hz bei 28âTurn -> ~1000RPM!), bzw. änderst du Einstellungen im Programm? Du Oversampelst den Drehgeber sowieso und dank des Gray-Codes summieren sich die Fehler durchs Prellen nicht auf.
Teo D. schrieb: > Oder wertest du die Drehgeber Ereignisse so schnell aus wie sie > auftreten können Ja wieso nicht, worauf willst du denn warten. Man muß jeden Zustandswechsel doch nur einmal erkennen. Nichtsdestowenigertrotz kann der schon im nächsten Intervall wieder rückgängig gemacht werden, ob durch Kippeln (auf dem Rastpunkt), Prellen oder schlicht Zurückdrehen ist ja im Prinzip gleich.
Teo D. schrieb: > Das entprellt sich da wirklich von selbst,.. eben nicht. Du hast ja Recht mit der Annahme, daß sich das nach einigem Prellen von selbst auf den richtigen Zustand einspielt (vorausgesetzt, dein Polling ist schnell genug, um alle Prell-Zustände korrekt zu erfassen), aber bedenke mal, was quasi hintendran losgeht. Nimm mal an, dein DG prellt dreimal, also dabei stellst du fest: vor-rück-vor-rück-vor-rück-vor und jetzt stabil. Willst du jetzt z.B. im angezeigten Menü auf dem kompliziert und langsam anzusteuernden grafischen Display insgesamt 7 mal binnen einiger zehn Millisekunden sämtlichen Schmonzes neu zeichnen? Wohl eher nicht. Also mußt du entweder zuvor analog entprellen um nur 1 Ereignis "vor" zu kriegen - oder du mußt nach all dem gepollten vor-zurück-vor Krempel das Ganze softwaremäßig entprellen, um dir die 7 Zustandswechsel zu ersparen. Ist das jetzt ein bissel klarer geworden? W.S.
W.S. schrieb: > Willst du jetzt z.B. im angezeigten Menü auf dem kompliziert und langsam > anzusteuernden grafischen Display insgesamt 7 mal binnen einiger zehn > Millisekunden sämtlichen Schmonzes neu zeichnen? Teo D. schrieb: > Oder wertest du die Drehgeber Ereignisse so schnell aus wie sie > auftreten Das meinte ich damit. In der IRQ wird ein Var aufsummiert und alle xx-ms dieser Wert im Programm aktualisiert und die Var auf 0 gesetzt. So Prellt nichts und verloren geht auch nichts. Wie meist bei dem Thema, reden wir nur ein wenig aneinander vorbei...
ich konnte nur feststellen der Peter D Code war einfach zu nutzen, ich musste nur die 3 möglichen Subroutinen durchprobieren bis es passte! int8_t encode_read1( void ) // read single step encoders int8_t encode_read2( void ) // read two step encoders int8_t encode_read4( void ) // read four step encoders bei meinem Drehecoder war es encode_read4( void )! ISR mit 1ms
:
Bearbeitet durch User
W.S. schrieb: > Teo D. schrieb: >> Das entprellt sich da wirklich von selbst,.. > > eben nicht. Du hast ja Recht mit der Annahme, daß sich das nach einigem > Prellen von selbst auf den richtigen Zustand einspielt (vorausgesetzt, > dein Polling ist schnell genug, um alle Prell-Zustände korrekt zu > erfassen), aber bedenke mal, was quasi hintendran losgeht. > Falsch, man braucht eben nicht jeden Prell-Zustand erfassen. Dafür reichen die üblichen Tastraten auch nicht => kann irgendwie schon nicht sein. Der Trick ist hier grob, daß verpaßte Wechsel zu ungültigen Folgen führen, die nicht gezählt werden. > Nimm mal an, dein DG prellt dreimal, also dabei stellst du fest: > vor-rück-vor-rück-vor-rück-vor und jetzt stabil. > > Willst du jetzt z.B. im angezeigten Menü auf dem kompliziert und langsam > anzusteuernden grafischen Display insgesamt 7 mal binnen einiger zehn > Millisekunden sämtlichen Schmonzes neu zeichnen? > > Wohl eher nicht. Also mußt du entweder zuvor analog entprellen um nur 1 > Ereignis "vor" zu kriegen - oder du mußt nach all dem gepollten > vor-zurück-vor Krempel das Ganze softwaremäßig entprellen, um dir die 7 > Zustandswechsel zu ersparen. > Falsch, dafür gibts die 2-4 Phasen Abstand zwischen den Rastpunkten. Erst wenn der Phasenzyklus korrekt durchgelaufen ist, triggert man eine Reaktion im Hauptprogramm. Prellen bleibt i.d.R. in Phase 1 hängen, weil nur 1 Bit sich ändert. Ohje, die Grundlagen..
irgendwie wird hier "Prellen" und "kippeln zwischen 2 gültigen Zuständen" vermischt.
Ich hatte mir den Peter-D-Code ausgedruckt und durchgearbeitet, als meine Frau mit ihren Freundinnen im Wald Pilze suchte. Alles sehr logisch und nachvollziehbar, ohne das hard-/soft-Entprellen, ohne Polling, ohne INT vom DG ausgelöst???, das Prinzip muss man verstehen... Ich habe das dann (ohne Abzugucken) auf mein PIC in ASM umgesetzt, läuft sehr gut - muss ja. Man muss es verstehen! initialisieren, ISR, Verwendung im HP, beim Lesen der Variablen im HP die ISRs sperren. Ich habe dann gleich noch die Drehgeschwindigkeit dynamisiert. mfG fE_wob
batman schrieb: > dafür gibts die 2-4 Phasen Abstand zwischen den Rastpunkten. > Erst wenn der Phasenzyklus korrekt durchgelaufen ist, triggert man eine > Reaktion im Hauptprogramm. Prellen bleibt i.d.R. in Phase 1 hängen, weil > nur 1 Bit sich ändert. so isses. W.S. schrieb: > Annahme, daß sich das nach einigem > Prellen von selbst auf den richtigen Zustand einspielt (vorausgesetzt, > dein Polling ist schnell genug, um alle Prell-Zustände korrekt zu > erfassen), aber bedenke mal, was quasi hintendran losgeht. > > Nimm mal an, dein DG prellt dreimal, also dabei stellst du fest: > vor-rück-vor-rück-vor-rück-vor und jetzt stabil. > > Willst du jetzt z.B. im angezeigten Menü auf dem kompliziert und langsam > anzusteuernden grafischen Display insgesamt 7 mal binnen einiger zehn > Millisekunden sämtlichen Schmonzes neu zeichnen? Selbstverständlich nicht. Betrachte bitte die tatsächliche mechanisch erreichbare Auflösung (aka Drehwinkel) mal als Zyklus im Greycode. Und erst nach einem Zyklus wird die Richtung erkannt+auegewertet, und erst dann als Winkeländerung weitergereicht. (von mir aus nenne das "halbe Auflösung" aka "gröbere Winkel" und nenne deine bisherige Methode "oversampling"). Da(nn) prellt lange nix mehr; an dem Punkt (in dem Winkel) ist ja sogar schon der nächste Kontakt geschaltet (und der kann prellen wie er will) und damit die Position erkannt. HTH P.S. W.S. schrieb: > Hier gibt's jedoch eine Riege militanter Verfechter des Pollings LOL der war gut. Yodaspeech: Ertappt du mich hast :D
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.