Forum: Mikrocontroller und Digitale Elektronik STM32F4 Encoder


von Gabriel J. (nyquist)


Lesenswert?

Hallo,

bin gerade bei der Auswertung von Winkel und Winkelgeschwindigkeit eines 
Incremental Encoders. Nutze dafür beim STM32F4 Disc. den Encoder 
Interface Mode, der bis dato funktioniert.

main.c:
1
#include "ch.h"
2
#include "hal.h"
3
#include "test.h"
4
5
#define ARM_MATH_CM4
6
#include "arm_math.h"
7
8
/*
9
 * Application entry point.
10
 */
11
int main(void) {
12
13
  halInit();
14
  chSysInit();
15
16
  // ENCODER STUFF
17
  /* Enables Encoder Input on CH1 for Timer 3 on PB4 */
18
  palSetPadMode(GPIOB, GPIOB_PIN4, PAL_MODE_ALTERNATE(2));
19
  /* Enables Encoder Input for CH2 Timer 3 on PB5 */
20
  palSetPadMode(GPIOB, GPIOB_PIN5, PAL_MODE_ALTERNATE(2));
21
  /* Enables Zero Mark Indicator from Encoder Input for CH3 Timer 3 on PC8 */
22
  palSetPadMode(GPIOC, GPIOC_PIN8, PAL_MODE_ALTERNATE(2));
23
  GPIOC->PUPDR |= GPIO_PUPDR_PUPDR8_1;
24
  
25
  // Encoder Stuff
26
  encoder_tim3_init();
27
28
  while (true) {
29
  }
30
}

In "encoder_tim3_init" nehme ich die Einstellungen nach Reference Manual 
0090 vor. Habe ein Input capture 1,2,3 filter vorgesehen. Der 
Inkrementalencoder liefer mir 4096 Inkremente/Umdrehung und 6600 
Umdrehungen je Minute ergeben 450k Imkremente/Sekunde, 2.2µs je 
Inkrement, Timer 3 mit 42MHz -> 92 Takte je Inkrement.

Einstellung für IC1F und IC2F 0011: fSAMPLING=fCK_INT, N=8
Für IC3F reicht 0010: fSAMPLING=fCK_INT, N=4

Für die weiteren Berechnungen werde ich die Zählrichtung, Registerzeit 
und den Nullldruchgang brauchen. Werte stehen in folgenden Registern.
1
// Direction
2
(TIM3->CR1 & TIM_CR1_DIR)>>(TIM_CR1_DIR-1);
3
// RegisterTime
4
TIM3->CCR4;
5
// ZeroMark
6
TIM3->CCR3;

Wie soll ich die Auswertung von Winkel und Winkelgeschwindigkeit am 
besten bewerkstelligen? Mit einem Circular Buffer, oder über Interrupts? 
Für die Winkelgeschwindigkeit muss ich Differenzenbildung anwenden 
(vermutlich). Hat da jemand von euch Erfahrung drin, bzw. kann mir 
weiterhelfen? Bin über jegliche Hilfe dankbar.

Lg Gabriel

von Gabriel J. (nyquist)


Lesenswert?

Hallo,

anscheinend hat sich doch noch ein Fehler in der Encoderkonfiguration 
eingeschlichen.

Prinzipieller Aufbau:
TIM3 CH1 und CH2 werden für den "encoder interface mode" und TIM3 CH3 
als mechanical zero des Drehgebers verwendet. Input capture filter 
wurden entsprechend eingestellt.
1
void encoder_tim3_init(void){
2
3
  // Disable timer 2 counter
4
  TIM3->CR1 &= ~(TIM_CR1_CEN);
5
6
  // Enable timer 3 clock
7
  RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
8
  // TIM3 clock enable during Sleep mode
9
  RCC->APB1LPENR |= RCC_APB1LPENR_TIM3LPEN;
10
11
  // Disable timer 3 SMCR
12
  TIM3->SMCR &= ~(TIM_SMCR_SMS);
13
14
  // Encoder which is counting on both TI1 and TI2 edges (SMS = 011)
15
  TIM3->SMCR |= (TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0);
16
17
  // ENCTICKS_TIMES4 = 16384 = 2^14
18
  TIM3->ARR  = ENCTICKS_TIMES4;
19
20
  /*CC1S: Capture/Compare 1 selection
21
  01: CC1 channel is configured as input, IC1 is mapped on TI1.*/
22
  TIM3->CCMR1 &= ~(TIM_CCMR1_CC1S | TIM_CCMR1_CC2S);
23
  // TI1FP1 mapped on TI1 and TI2FP2 mapped on TI2
24
  TIM3->CCMR1 |= (TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0);
25
26
  /*  TI1FP1 noninverted,  TI1FP1=TI1*/
27
  TIM3->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
28
  /*  TI2FP2 noninverted,  TI2FP2=TI2*/
29
  TIM3->CCER &= ~(TIM_CCER_CC2P | TIM_CCER_CC2NP);
30
31
  /* Input capture 1 filter Einstellung 0011: fSAMPLING=fCK_INT, N=8*/
32
  TIM3->CCMR1 |= (TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1);
33
  /* Input capture 2 filter Einstellung 0011: fSAMPLING=fCK_INT, N=8*/
34
  TIM3->CCMR1 |= (TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_1);
35
36
  /* Force Update Event */
37
  TIM3->EGR |= TIM_EGR_UG;
38
39
  /* --- Input Capture for CH3 --- */
40
  /*01: CC3 channel is configured as input, IC3 is mapped on TI3 */
41
  TIM3->CCMR2 &= ~(TIM_CCMR2_CC3S);
42
  // TI3FP3 mapped on TI3
43
  TIM3->CCMR2 |= TIM_CCMR2_CC3S_0;
44
45
  /*0010: fSAMPLING=fCK_INT, N=4 */
46
  TIM3->CCMR2 |= TIM_CCMR2_IC3F_1;
47
48
  /*00: noninverted/rising edge
49
  Circuit is sensitive to TIxFP3 rising edge (capture, trigger in reset, external clock or trigger
50
  mode), TIxFP3 is not inverted (trigger in gated mode, encoder mode).*/
51
52
  // Disable Capture/Compare 3 output Polarity.
53
  TIM3->CCER &= ~(TIM_CCER_CC3P | TIM_CCER_CC3NP);
54
55
  // Capture/Compare 3 output enable.
56
  TIM3->CCER |= TIM_CCER_CC3E;
57
58
  /* --- Enable Counter --- */
59
  TIM3->CR1 |= TIM_CR1_CEN;
60
}

Zu den Problemen. Der Counter zählt die Inkremente wie im Reference 
Manual beschrieben mit, nur leider nicht ganz ordnungsgemäß. Bei 4096 
Inkrementen/Umdrehung und 4-fach Auswertung, müsste bei einer ganzen 
Umdrehung der Counter den Wert "16384" (mit Abweichung) enthalten. Der 
Counter zählt pro Umdrehung nur bis knapp 12500. Woran könnte das 
liegen?

Beim der Auswertung des mechanical zero's stimmt auch etwas nicht. 
Gewollt wäre es so, dass wenn der Puls kommt, der aktuelle Counterwert 
im Capture/Compare Register steht. Es steht zu jedem Zeitpunkt immer der 
aktuelle Counterwert im Register.

Vielleicht kann mir einer von Euch sagen, wo der Hund begraben liegt. 
Danke!

Hab noch eine Frage zur Ermittlung der Geschwindigkeit. Ist es da 
sinnvoller einen Timer Interrupt zu definierten Zeitpunkten auszulösen 
und Geschwindigkeit zu berechnen, oder die Periode zwischen zwei Encoder 
events (mechanical zero) zu bestimmen und dann auf die Geschwindigkeit 
zu schließen? Im Bezug auf die Umdrehungsgeschwindigkeit wird das Rolle 
spielen, oder? Bei hohen Umdrehungen wird die eine und bei niedrigen die 
andere Variante genauer sein.

Lg

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
Noch kein Account? Hier anmelden.