STM32 - Quadratur Encoder

Gast #6028716
Lesenswert?

Guten Tag zusammen,

folgendes Szenario liegt mir vor:
Ich möchte mit einem Getriebemotor mit integriertem Inkremental 
Drehgeber an meinem STM32L152 die Umdrehungen der Welle messen. Der 
Motor ist ein billig Teil aus China und besitzt zwei Hallsensoren, 
welche ein um 90° versetztes Rechtecksignal ausgeben. Die zwei Leitungen 
der Signale habe ich an den Encoder(Timer 4) des µC angeschlossen. Der 
Counter wird in Uhrzeigerrichtung hoch und gegen den Uhrzeiger 
runtergezählt.
Soweit funktioniert auch alles, allerdings verschieben sich meine 
Endlagen der Welle, womit ich bei mehrmaligen hin und herfahren mit dem 
gleichen Counterwert für bei Richtungen, nicht mehr an den Positionen 
stoppe wo ich es eigentlich möchte.
Im Grunde möchte ich die Drehrichtung gar nicht ermitteln, sondern 
wirklich nur ein genaues anfahren von zwei Endlagen erreichen.
Dazu sei noch gesagt dass ich CubeMX und die HAL Library verwende.
Kann mir damit jemand weiterhelfen?
Habe ich evtl. den Sinn hinter dem Encoder oder den Signalen des Motors 
falsch verstanden?

Vielen Dank im Voraus!

MFG,
DerHasenHerbert
Gast #6028728
Lesenswert?

Anhand der Fehlerbeschreibung brauchst Du doch nur noch checken wann der 
Zählerstand/Positionswert nicht mehr mit der realen IST Position überein 
stimmt.

Vermutlich läuft das beim Wechsel der Richtung aus dem Ruder.

Einzelstep vor zurück - und genau hinschauen.
Gast #6029267
Lesenswert?

Vielen Dank erstmal für die vielen Antworten in der kurzen Zeit!

Zunächst mal die Init des Timers für den Encoder (Controller wird mit 
der MSI auf 4,193 MHz betrieben):
static void MX_TIM4_Init(void){
  TIM_Encoder_InitTypeDef sConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 419;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 65535;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
  sConfig.EncoderMode = TIM_ENCODERMODE_TI1;
  sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
  sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC1Filter = 0;
  sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
  sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC2Filter = 0;
  if (HAL_TIM_Encoder_Init(&htim4, &sConfig) != HAL_OK) {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig)
     != HAL_OK) {
    Error_Handler();
  }
}

@NichtWichtig: Werde ich mal testen. Allerdings verwundert es mich, dass 
die Verschiebung der Endlagen immer nur in eine Richtung geschieht.
--> Evtl noch ein Wichtiger Hinweis <---

@Nico: Ich verwende den internen, die Funktionen für die Initialisierung 
habe ich von CubeMX generieren lassen. Ich muss dann nur noch den 
Encoder an der passenden stelle starten und stoppen und TIM4->CNT 
auslesen.

@Georg: Das hab ich schon gemacht, die Signale sind m.M.n. einwandfrei, 
lediglich beim stoppen des Motors "zieht" sich das Signal über ein paar 
ms auf dem jeweiligen high oder low stand des Signals. -> hier könnte 
ich mir die Fehlerquelle vorstellen, würde zu NichtWichtig´s Vermutung 
passen, das der Fehler beim Richtungswechsel stattfindet...

@Schorsch: Diese Vermutung hab ich auch, falls ich heute nicht weiter 
komme, werde ich mal noch einen höherwertigen Motor bestellen...

@MaWin: Wie könnte ich das denn Abfangen? Im Anhang meine 
Motorschaltung, an dem 1x2 Header werden die Stromversorgungsleitungen 
des Motors angeschlossen.
Gast #6029406
Lesenswert?

Kann leider nicht zur Lösung des Problems beitragen, und es ist nur ein 
frommer Wunsch von mir, mal mit dem STM32 umzugehen und Motorsteuerungen 
zu bauen, ich möchte aber an dieser Stelle schon mal eine 
Verständnisfrage stellen:

Ist es so, daß der STM32 einen ausgewiesenen Harware-Quadraturencoder 
hat?
Also daß sich ein Zähler und zwei Eingangspins so konfigurieren lassen, 
daß sie ohne wenn und aber, ohne Interrupt, ohne Programmcode, ohne 
Polling den Positionswert zählen, der dann im Programm nur aus einem 
bestimmten Register rausgelesen werden muß?

Das ganze Konfigurieren, Setzen von Flankenauswertungen und Timings 
verunsichert mich jetzt etwas...
Gast #6029440
Lesenswert?

@Nico: Habe ich alles schon ausprobiert, nur ein Channel Rising, Falling 
und Both und beide Channels mit Rising, Falling und Both.... Alles mit 
dem gleichen Resultat

@Tom: Wie Johannes schon geschrieben hat, ja haben sie. Du kannst dir 
mal das PDF AN4013 - STM32 cross-series timer overview anschauen, da 
steht die Funktionsweise des Encoders unter 4.3.4 beschrieben.
#6029643
Lesenswert?

Wenn du genug RAM hast kannst ja einmal Testweise bei jedem Interrupt 
die Position abspeichern und dir nach jeder Runde auslesen lassen.

Ich lege dann gerne einfach den Debugger an und schreib mir den Speicher 
direkt in eine Datei. Kann man dann sehr einfach z.b. mit Python 
analysieren.
Gast #6033891
Lesenswert?

Guten Morgen,

zunächst einmal vielen Dank nochmal an alle!

Ich habe jetzt mal den Richtungswechsel, bzw. das stoppen des Motors 
genauer betrachtet. Das Problem ist wohl tatsächlich, dass die 
Magnetscheibe des Drehgebers zu viel spiel hat. Beim stoppen dreht die 
noch ein paar runden, was an sich nicht schlimm wäre, wenn sie in beide 
Richtungen nicht verschieden lange ausdrehen würde.... Selbst wenn ich 
per PWM die letzten Drehungen minimal laufen lasse, schafft es der Motor 
nicht exakt zu stoppen.
Werde es jetzt mit einem selbst gebastelten Drehgeber aus einem 
Minimagneten in einer Spule und einem Reedkontakt probieren.
Gast #6034010
Lesenswert?

Rund schrieb:
> Mach doch mal bitte ein Foto des mechanischen Aufbaus. Ein paar
> "Runden", was soll das sein?

Die Welle dreht vorwärts und rückwärts leicht verschieden, der 
Unterschied wird später durch das Gewicht welches der Motor hochziehen 
soll wahrscheinlich noch größer. Und die schwarze Magnetscheibe an der 
Platine des Motors dreht noch einige Runden nach, dadurch zählt der 
Sensor weiter, daher ist über den Sensor auch keine 100%ig genaue 
Position festzustellen.
Angehängte Dateien:
Gast #6034020
Lesenswert?

die Position sollte damit trotzdem exakt erfasst werden, nur beim 
Stoppen hält der Motor nicht da an wo du möchtest weil der nachläuft. 
Das kann man veringern indem man den beim Abschalten kurzschließt.
Gast #6034032
Lesenswert?

DerHasenHerbert schrieb:
> Die Welle dreht vorwärts und rückwärts leicht verschieden

Das ist doch mechanisch Unsinn. Aber abgesehen davon:

Bei einem korrekt ausgewerteten Drehgeber gibt es keinen sich 
steigernden Fehler, weil der auch bei Spiel und Hin- und Herwackeln 
genausoviele Schritte vorwärts wie zurück zählt.

Je nach Spiel zeigt der Zählerstand also nicht genau die tatsächliche 
Position an, aber der Fehler addiert sich nicht auf und wird bei 
wiederholten Positioniervorgängen nicht grösser. Kann man das Spiel 
nicht ausreichend verringern, so kann man in vielen Fällen das Problem 
lösen indem man die Position immer aus der gleichen Richtung anfährt.

Wird der Fehler immer grösser so muss es im System Schlupf geben, z.B. 
rutschende Riemen.

Georg
Gast #6034069
Lesenswert?

DerHasenHerbert schrieb:
> Die Welle dreht vorwärts und rückwärts leicht verschieden

Kaum.

Halt doch mal die Motorwelle vorne fest, und versuche hinten das 
schwarze Rad zu drehen.

Es wird fest sein.

Wenn der Motor nach dem abschalten weiterläuft, dann wegen der Trägheit 
(es wurde schon geschriebene: kurzschliessen bremst heftiuger, geht aber 
auch mehr alf's Getriebe), und das muss der Incrementalencoder trotzdem 
richtig zählen.
Gast #6034228
Lesenswert?

>Je nach Spiel zeigt der Zählerstand also nicht genau die tatsächliche
>Position an, aber der Fehler addiert sich nicht auf und wird bei
>wiederholten Positioniervorgängen nicht grösser. Kann man das Spiel
>nicht ausreichend verringern, so kann man in vielen Fällen das Problem
>lösen indem man die Position immer aus der gleichen Richtung anfährt.

Von der gleichen Richtung anfahren geht nicht, da ich eine Klappe hoch 
und runterfahren möchte, daher muss ich in beide Richtungen fahren. Und 
da er immer in eine Richtung weiter fährt, wie in die andere, addiert 
sich der Fehler in diesem Sinne schon.

> Halt doch mal die Motorwelle vorne fest, und versuche hinten das
> schwarze Rad zu drehen.
>
> Es wird fest sein.
>
> Wenn der Motor nach dem abschalten weiterläuft, dann wegen der Trägheit
> (es wurde schon geschriebene: kurzschliessen bremst heftiuger, geht aber
> auch mehr alf's Getriebe), und das muss der Incrementalencoder trotzdem
> richtig zählen.

Das schwarze Rad ist definitiv nicht fest ;) kann es auch so mit den 
Fingern drehen ohne das sich die Motorwelle dreht.

Kurzschließen halte ich für eine relativ unsaubere Lösung.
Ich werde eher noch einen etwas hochwertigeren Motor mit Drehgeber 
testen, ansonsten die selbst gebastelte Lösung...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren