Forum: Mikrocontroller und Digitale Elektronik AVR32 auslesen des HCTL-2022


von Godi S. (godi22)


Angehängte Dateien:

Lesenswert?

Hallo,
ich möchte gerne die Position eines Motors mittels HCTL-2022 auf einen 
AVR32 auslesen.
Dazu habe ich eine Funktion geschrieben die den Wert aus dem HCTL-2022 
ausliest.
Diese wird in einem Task (freeRTOS) alle 5ms aufgerufen, und der Aufruf 
befindet sich in einer "critical section".
Jedoch habe ich beim auslesen höchstwahrscheinlich ein Timing Problem.
Der HCTL-2022 reseted sich manchmal von selbst.
Also die Funktion liefert mir manchmal Werte bis ca 30, dann beginnt es 
wieder bei 0, manchmal wird aber auch nur bis 3 gezählt.

Hat jemand eine Ahnung warum dies ist?


Handbuch Motor: 
http://www.faulhaber.com/uploadpk/DE_2619_SR_IE2-16_DFF.pdf
Handbuch HCTL-2022: http://www.avagotech.com/docs/AV02-0096EN
AVR32: AT32UC3A0512 mit 60MHz getaktet.


Code von Task:
1
void vMotorPosTask( void * pvParameters ) {
2
3
  // Initialize the xLastWakeTime variable with the current time.
4
  portTickType xLastWakeTime = xTaskGetTickCount();
5
  
6
  
7
      
8
  for( ;; ) {    
9
    taskENTER_CRITICAL();
10
    pos = HCTL2022_get_position();
11
        
12
    if (pos != motor[0].position) {
13
      
14
      // save the last element (pointer)
15
      struct Motor last = motor[MOTOR_BUFFER_LENGTH-1];
16
          
17
      for (int i = MOTOR_BUFFER_LENGTH-1; i>0; i--) {
18
        motor[i] = motor[i-1];        
19
      }
20
      
21
      // set the pointer of the last element to the first element => ring buffer
22
      motor[0] = last;
23
    
24
      motor[0].time = time;  
25
      timeDiff = time - motor[1].time;
26
      motor[0].position = pos;    
27
      motor[0].velocity = ((motor[0].position - motor[1].position) * 2*M_PI / DECODER_PULSE_PER_ROUND) * 1000 / timeDiff;
28
      motor[0].acceleration = (motor[0].velocity - motor[1].velocity) * 1000 / timeDiff;
29
    
30
    }
31
    taskEXIT_CRITICAL();
32
    
33
    time += MOTOR_POSITION_DELAY_TIME_MS;
34
    // Wait for the next cycle.
35
    
36
    vTaskDelayUntil( &xLastWakeTime, MOTOR_POSITION_DELAY_TICKS);    
37
  }
38
}

Code vom auslesen des HCTL-2022:
1
inline uint32_t HCTL2022_read_data_byte( void ) {
2
  return AVR32_GPIO.port[HCTL2022_DATA_PORT].pvr & HCTL2022_DATA_MASK;
3
}
4
5
6
// ************************************************
7
// Read-out current position
8
// Precaution: Init_ and Reset_ have been invoked
9
// Status: (Beginning and end) -RST = High; -OE = High; SEL1 = Low; SEL2 = High
10
// ************************************************
11
int32_t HCTL2022_get_position ( void ) {
12
  uint32_t temp;
13
  uint32_t pos;
14
15
  // -OE = High; SEL2 = High; SEL1 = Low
16
  // Set -OE = Low (Inhibit=1)
17
  gpio_set_pin_low(HCTL2022_OE_N);
18
  
19
  // Do nothing - Delay time, SEL1~SEL2 (tSDV) = 29 ns
20
  asm("nop");
21
  asm("nop");
22
    
23
  // Read byte 4
24
  pos = HCTL2022_read_data_byte();
25
  
26
  // -OE = Low; SEL2 = High; SEL1 = High
27
  gpio_set_pin_high(HCTL2022_SEL1);
28
  
29
        
30
  // Read byte 3
31
  temp = HCTL2022_read_data_byte();
32
    
33
  // -OE = Low; SEL2 = Low; SEL1 = Low
34
  gpio_set_pin_low(HCTL2022_SEL1);
35
  gpio_set_pin_low(HCTL2022_SEL2);
36
  
37
  // [ Byte 4 ] or ( Byte 3 >> 8 )
38
  pos |= ( temp >> 8 );
39
      
40
  // Read byte 2
41
  temp = HCTL2022_read_data_byte();  
42
  
43
  
44
  // -OE = Low; SEL2 = Low; SEL1 = High  
45
  gpio_set_pin_high(HCTL2022_SEL1);
46
  pos |= ( temp >> 16 );
47
  asm("nop");
48
              
49
  // Read byte 1
50
  temp =  HCTL2022_read_data_byte();
51
  // [ Byte 4 or ( Byte 3 >> 8 ) or ( Byte 2 >> 16 ) ] or ( Byte 1 >> 24 )
52
  pos |= ( temp >> 24 );
53
  
54
  
55
  // -OE = High; SEL2 = High (Inhibit=0)
56
  gpio_set_pin_high(HCTL2022_OE_N);
57
  gpio_set_pin_high(HCTL2022_SEL2);  
58
  // SEL1 = Low
59
  gpio_set_pin_low(HCTL2022_SEL1);
60
  return pos;  
61
}

godi

von amateur (Gast)


Lesenswert?

Habe das gleiche Problem, bin nicht dahinter gekommen.
Dachte zwischenzeitlich mal es läge an der Spannung - war's aber nicht.
Habe auch jede Menge NOP's eingebaut – typischer Fall von Denkste.

von Godi S. (godi22)


Lesenswert?

Wenigstens bin ich nicht der einzige mit dem Problem :)

Wenn ich jede Menge nop's einfüge dann kommen bei mir ganz falsche Werte 
heraus, aber laut Handbuch müsste es ja egal sein wie lange man wartet 
bis die Daten ausgelesen werden.
Es sollten ja nur die 29ns zwischen setzen der SEL bits und dem Auslesen 
nicht unterschritten werden.
Wenn ich das richtig verstanden habe... ;)

von amateur (Gast)


Lesenswert?

Davon bin ich bei meinen ersten Versuchen ebenfalls ausgegangen.
Ich glaube die 29ns waren die längste Verzögerung im Programmheft.
Was ich aber nie verstanden habe ist die ewig lange Verzögerung (wait 
25ms), vor dem ersten Zugriff, im Beispielprogramm.

von Godi S. (godi22)


Lesenswert?

Ja die 25ms sind mir auch schon aufgefallen,
habe ich aber nicht eingehalten weil die im Handbuch sonst nirgends 
verlangt werden.
Müssen die eingehalten werden?

von amateur (Gast)


Lesenswert?

Ich bezweifle dass die eingehalten werden müssen. Habe es aber probiert 
- ohne Erfolg. Bei mir zumindest, wurden zwischenzeitlich mehr als 25 
ms, an anderer Stelle vergrübelt, bevor es zu einem Folgezugriff kam.

von Godi S. (godi22)


Lesenswert?

Ich habe auch gerade herumprobiert und bei mir macht es auch keinen 
Unterschied.

von Godi S. (godi22)


Lesenswert?

Wenn nur jede Sekunde abgetastet wird dann sieht das ganze besser aus.
Aber ich will ja möglichst schnell erkennen ob sich die Position 
geändert hat. Es soll mit der Position /berechnete Geschwindigkeit dann 
mal ein Geschwindigkeitsregler / Positionsregler entworfen werden...

von amateur (Gast)


Lesenswert?

Ab wann das Teil einen Durchhänger hat habe ich nicht ausprobiert.
Im Sekundenraster abzufragen erscheint mir bestenfalls akademisch.
Ich habe mir auch, weil nicht ganz klar, eine Zwischenplatine 
angefertigt um nachträglich ein paar Level-shifter einzufügen – aber 
auch ohne Erfolg.

von Godi S. (godi22)


Lesenswert?

Würde es eigentlich funktionieren den Encoder direkt an Interrupt - 
Eingängen des Mikrocontrollers anzuschließen, oder ist das Rauschen zu 
groß?

Hat sonst noch jemand Ideen warum es nicht funktioniert, bzw wie es 
funktionieren könnte?
Kann ja nicht sein das der HCTL-2022 unbrauchbar ist.

von Godi S. (godi22)


Lesenswert?

Wie zählt der HCTL 2022 überhaupt?
Zählt der alle Flanken (positive + negative auf CHA und CHB)? Also wenn 
mein Encoder eine Auflösung von 16 Impulse pro Umdrehung hat dann zählt 
der 16*4 = 64?

Momentan bekomme ich pro ms ca eine Zähldifferenz von 6.
Auf die Minute hochgerechnet: 6*1000*60 = 360000
Durch die 4*16 Impulse pro Umdrehung ergibt: 5625 rpm

Also das würde für meinen Motor plausibel sein.
Leerlaufdrehzahl bei 24V = 7200rpm
Betreiben du ich den gerade mit 18V


Wenn da meine Annahmen soweit stimmen dann zählt er zumindest schon mal 
richtig.
Jetzt habe ich nur noch das Problem, dass das MSB und das nächst 
niderwertigere Byte nicht zählt.

Also in negative Richtung passiert dies:
Time: 5629 5628 5627 5626 5625
Position: -6 -65536 -32543 -32537 -32532

Das passiert aber nicht immer beim selben Wert (die Werte dazwischen 
habe ich leider nicht aufgezeichnet):
Time: 11895 11894 11893 11892 11891
Position: -36438 -36432 -36426 -36420 -36414
Time: 12020 12019 12018 12017 12016
Position: -529 -524 -518 -512 -506

Und hier auch noch mal:
Time: 18170 18169 18168 18167 18166
Position: -36290 -36284 -36278 -36272 -36266
Time: 18370 18369 18368 18367 18366
Position: -784 -778 -772 -767 -761

In die positive Richtung passiert dies viel öfters:
Time: 149939 149938 149937 149936 149935
Position: 0 627 622 616 610
oder
Time: 160699 160698 160697 160696 160695
Position: 0 116 110 104 99
oder
Time: 169858 169857 169856 169855 169854
Position: 0 470 464 458 453
oder
Time: 185379 185378 185377 185376 185375
Position: 6 0 989 983 978
oder
Time: 188324 188323 188322 188321 188320
Position: 12 6 0 1461 1455

usw...


Hat da jemand eine Idee warum dass so sein könnte?
Mir ist dies ein Rätsel...

von Godi S. (godi22)


Angehängte Dateien:

Lesenswert?

Im Anhang noch mal mein überarbeiteter Code.
Die Funktion HCTL2022_get_position() habe ich momentan im 1ms-Takt 
aufgerufen.
Initialisiert wird nur einmal am Anfang und die Funktion reset wird auch 
nur vor dem Start des Motors aufgerufen.

von Godi S. (godi22)


Lesenswert?

Push!
Vielleicht findet sich ja noch wer der dies schon funktionstüchtig 
realisiert hat. :)

von Godi S. (godi22)


Lesenswert?

So jetzt habe ich mal das Oszilloskope an den Reset-Pin des HCTL-2022 
angschlossen und versucht die Einzelschuss-Signale einzufangen.

Ich habe aber nur meine gewollten Signale aufzeichnen können. Also nehme 
ich mal an das der HTCL-2022 nicht durch einen Reset zurückgesetzt wird.

Was mir aber jetzt bei diesem Test aufgefallen ist, ist dass sich der 
Zählwert immer zwischen 29000 und 30000 zurückgesetzt hat.

Kann es sein dass es hier irgendwo zu einem Überlauf kommt?

von amateur (Gast)


Lesenswert?

Ich habe es nach dem Versuch der nachträglichen Pegelanpassung 
aufgegeben.

Den Reset habe ich zwar angeschlossen und am Anfang einmal aufgerufen, 
aber darüber hinaus nicht weiter beachtet. Da die Startposition im 
Grunde unbekannt ist, ist auch die "Startposition" als Zahl unwichtig.
Ich hatte vor, bei 32 Bit Zählbreite ja kein Problem, eine 
Softwarepositionskontrolle zu nutzen. Die sollte zyklisch den 
Zählerstand holen und, je nach dem, die interne Geschwindigkeit und 
Position aktualisieren. Einen zwischenzeitlichen Über- bzw. Unterlauf 
und somit Schrittverluste sind ja bei einer solchen Zählerbreite nicht 
zu erwarten.

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.