Hallo zusammen, ich lese durch das encoder interface die Daten eines Encoders ein. Zur Konfiguration des Interfaces verwende ich folgenden Befehl: TIM_EncoderInterfaceConfig(TIM_ENC, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Falling); Was ist hierbei die ICPolarity? Und warum benötige ich einmal Rising und einmal Falling. Ich habe gedacht mit TIM_EncoderMode_TI12 wähle ich aus, dass ich zwei Eingänge habe und mit der Polarity wähle ich die Flanke aus? Laut Reference Manual soll es am besten sein, beide Flanken auszuwerten, weshalb ich bei beiden TIM_ICPolarity_BothEdges verwenden wollte. Danach hat das TIM_Register allerdings nicht mehr korrekte Werte angegeben. **********************STM32F4 Reference Manual****************************** It also shows how input jitter is compensated where both edges are selected. ******************************************************************
> Was ist hierbei die ICPolarity? Und warum benötige ich einmal Rising und > einmal Falling. Du kannst auch beide rising oder beide falling setzen. Insgesamt gibt es 4 Möglichkeiten, aber nur zwei Richtungsveränderung durch Änderung... Bothedge bedeutet hier, dass pro PPR 4 Puls gezählt werden, anstatt nur 2.
aSma>> schrieb: > Du kannst auch beide rising oder beide falling setzen. Insgesamt gibt es > 4 Möglichkeiten, aber nur zwei Richtungsveränderung durch Änderung... > > Bothedge bedeutet hier, dass pro PPR 4 Puls gezählt werden, anstatt nur > 2. Was soll denn ICPolarity genau bedeuten? Mit Polarity wird die Art der Flanke gemeint sein, also rising/falling/both. Aber wofür steht das IC? Was meinst du mit PPR? Also laut dem Reference Manual und deiner Erläuterung sollte es auch klappen, wenn ich zwei mal bothedges verwende. Dann kommen bei mir aber immer zufällige Werte und es klappt überhaupt nicht mehr.
Ein Quadratur Encoder gibt zwei Impulse aus (Index Impuls nicht mitgezählt). Diese zwei Pulse sind um 90 Grad verschoben. Beim Encoder gibt man die Umdrehung in PPR (pulse per revolution). Es hätte nicht wehgetan das mal zu googlen. Armes Folk. Jetzt gibt es die einfache Genauigkeit, dann wird nur die Flanke eines Kanals gez#hlt. Pro Periode 2 Flanken. Bei bothedge werden 4 Flanken gezählt. Bei 400 PPR hätte man bei bothedge 1600 Pulse/360 grad... > Also laut dem Reference Manual und deiner Erläuterung sollte es auch > klappen, wenn ich zwei mal bothedges verwende. Dann kommen bei mir aber > immer zufällige Werte und es klappt überhaupt nicht mehr. Wie zweimal bothedges? Poste dein Code. Ich hatte schon mal einen defekten Encoder gehabt. Ohne ein Oszi hätte ich den Fehler nie gefunden.
Also mein Code ist wie auf dieser Homepage beschrieben: http://www.micromouseonline.com/2013/02/16/quadrature-encoders-with-the-stm32f4/ Aber hauptsächlich geht es mir um diesen Befehl.
1 | TIM_EncoderInterfaceConfig (ENCL_TIMER, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); |
Als erstes wähle ich den Timer und mit TI12, dass ich zwei Kanäle auswerte. Danach werde ich vermutlich zuerst für Kanal1 die Flanke auswählen und dann für Kanal 2. Laut meinem Anhang aus dem Reference Manual sieht es für mich so aus, als würde ich mit TIM_ICPolartiy_Bothedges das beste Ergebnis bekommen.
Mit TIM_EncoderMode_TI12 wählst du "count bothedge". Alternative: -TIM_EncoderMode_TI1 -TIM_EncoderMode_TI2 > Laut meinem Anhang aus dem Reference Manual sieht es für mich so aus, > als würde ich mit TIM_ICPolartiy_Bothedges das beste Ergebnis bekommen. Du erhälst eine höhere Genauigkeit pro Periode. Nämlich die doppelte.
Das Problem besteht oftmals, dass ein Counter zu geringe Auflösung besitzt. Hier macht der Autor aus 16bit eine 32bit absolute Position mithilfe ein paar Hilfsvariablen:
1 | void encodersRead (void) |
2 | {
|
3 | oldLeftEncoder = leftEncoder; |
4 | leftEncoder = TIM_GetCounter (ENCL_TIMER) ; |
5 | oldRightEncoder = rightEncoder; |
6 | rightEncoder = -TIM_GetCounter (ENCR_TIMER) ; |
7 | leftCount = leftEncoder - oldLeftEncoder; |
8 | rightCount = rightEncoder - oldRightEncoder; |
9 | fwdCount = leftCount + rightCount; |
10 | rotCount = - (leftCount - rightCount); |
11 | fwdTotal += fwdCount; |
12 | rotTotal += rotCount; |
13 | leftTotal += leftCount; //absolut pos |
14 | rightTotal += rightCount; //absolut pos |
15 | }
|
Alle Variablen sind als Integer initialisiert (16 und 32bit). Da aber die Funktion:
1 | uint16_t TIM_GetCounter (ENCL_TIMER) ; |
vom Typ unsigned ist, da müsste schon der Kompiler merkern... Ich bin mir nicht sicher, ob dies überhaupt so fkt. Wenn du deine Encoder testen willst, dann mach folgendes:
1 | uint16_t Encoder_1, Encoder_2; |
2 | |
3 | while(1) |
4 | {
|
5 | Encoder_1 = TIM_GetCounter (TIMx) ; //ich glaub timer2 und 4 waren es |
6 | Encoder_2 = TIM_GetCounter (TIMx) ; |
7 | }
|
Dann müssest du einen Wert von 0..2^16-1 bekommen.
aSma>> schrieb: > Mit TIM_EncoderMode_TI12 wählst du "count bothedge". Das glaube ich nicht. Ich habe das so verstanden, dass ich mit TI12 auswähle, dass ich die Flanken der beiden Channel auswähle und dann mit der Polarität für jeden Kanal die Flanke auswählen kann. Aus dem Reference Manual: To select Encoder Interface mode write SMS=‘001’ in the TIMx_SMCR register if the counter is counting on TI2 edges only, SMS=’010’ if it is counting on TI1 edges only and SMS=’011’ if it is counting on both TI1 and TI2 edges. Select the TI1 and TI2 polarity by programming the CC1P and CC2P bits in the TIMx_CCER register. When needed, the user can program the input filter as well. CC1NP and CC2NP must be kept low Und warum klappt es dann nicht, wenn man von beiden Kanälen beide Flanken auswählt?
Glauben kannst du in der Kirche. Der Text aus dem Manual sagt dasgleiche wie ich zurvor! Der Code vom Autor ist einfach Murks. Man muss schon ein wenig mehr Gehirnschmalz investieren, damit man aus 16bit Timer 32bit Var erstellen kann. Ich habe es damals mit UIF gemacht... Vorallem es sind ein paar Variablen vorhanden wie: rotCount, rotTotal so ein Schwachsinn ohne der Angabe PPR. > Und warum klappt es dann nicht, wenn man von beiden Kanälen beide > Flanken auswählt? Was klappt bei dir nicht? Hast du einen zweiten Encoder zum Testen? Nehme diesen Code:
1 | leftCount =(int16_t)TIM3->CNT; |
2 | TIM3->CNT=0; //reset timer cnt |
3 | rightCount=(int16_t)TIM4->CNT; |
4 | TIM4->CNT=0; //reset timer cnt |
5 | leftTotal +=(int32_t)leftCount; |
6 | rightTotal+=(int32_t)rightCount; |
Ich habe schon somit eine Instabile Strecke ohne Schrittverlust geregelt gehabt! Wobei ich gerade sehe, dass Timer2/5 32bit groß sind. Ändere dafür mal in: TIM_SetAutoreload (TIM2/5, 0xffffffff); leftTotal=(int32_t)TIM2/5->CNT ... mfg
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.