Forum: Mikrocontroller und Digitale Elektronik Resolverauswertung


von TNTBC (Gast)


Lesenswert?

Hallo liebes Team,

ich habe ein Problem. Ich habe einen Servomotor und dafür eine 
Steuerelektronik entworfen. In dem Servomotor ist ein Resolver verbaut. 
Jetzt habe ich meine Steuerelektronik für eine Resolverperiode so 
Programmiert das bei einer Periode des Resolvers einmal das Drehfeld 
herum läuft. Jetzt kommt das Problem. Meine Maschine ist eine 6pol 
Maschine aber der Resolver hat nur 2pole. Also habe ich für jede 
Resolverperiode 3 Maschinenperioden! Jetzt stehe ich vor einer Mauer und 
weiß nicht wie ich aus einer Resolverperiode so eben mal 3 mache!!! Hat 
jemand eine Idee oder so etwas schon einmal gemacht?

Danke
Gruß TNTBC

von Ralf (Gast)


Lesenswert?

Eine konkrete Lösung für Dich habe ich nicht, aber ich würde mal nach 
dem Stichwort PLL suchen.

http://www.elektronik-kompendium.de/public/schaerer/pll4046.htm


Benötigst Du so etwas nicht sowieso für eine Drehzahlregelung?..oder wie 
synchronisierst Du die beiden Drehfelder?

von Volker Z. (vza)


Lesenswert?

TNTBC schrieb:
> Jetzt stehe ich vor einer Mauer und
> weiß nicht wie ich aus einer Resolverperiode so eben mal 3 mache!!!

Winkel_elektrich = (Winkel_resolver * 3) % 360

Dein Resolver ist für deinen Motor ungünstig.

Volker

von TNTBC (Gast)


Lesenswert?

Hallo Ralf,

Ralf schrieb:
> Benötigst Du so etwas nicht sowieso für eine Drehzahlregelung?..oder wie
> synchronisierst Du die beiden Drehfelder?

Die Synchronisation erfolgt über das Resolversignal, da ich weiß in 
welchen Sektor des 6 Quadrantenstellers ich mich befinde! und die 
Berechnung der Tastverhältnisse gehen über ualpha und ubeta. Eine PLL 
gibt mir ja nur die Frequenz des Jeweiligen Trägersignals aus. Das hilft 
mir aber nicht weiter da ich dabei nicht weiß wie ich die Maschine jetzt 
anzusteuern habe! Das weitere Problem der PLL ist, dass die Maschine 
einmal gedreht haben muss um eine gültige Frequenz zu haben.

Ich habe eine Idee wie man es machen könnte wenn ich Sie rechnerische 
bewiesen haben werde ich sie mal Posten aber dennoch sammelt weitere 
Ideen

Danke dir Ralf

Gruß TNTBC

von TNTBC (Gast)


Lesenswert?

Hallo Volker

Volker Zabe schrieb:
> Winkel_elektrich = (Winkel_resolver * 3) % 360

Die Variante kenne ich, allerdings müsste ich mir dann den Sinus und 
Cosinus des Winkels neu errechnen und der Sinus und Cosinus des 
Resolvers wären unbrauchbar! Oder?

Volker Zabe schrieb:
> Dein Resolver ist für deinen Motor ungünstig.

Japp, nur ist er fest verbaut von Werksseite aus!!!


Gruß TNTBC

von Volker Z. (vza)


Lesenswert?

TNTBC schrieb:
> Die Variante kenne ich, allerdings müsste ich mir dann den Sinus und
> Cosinus des Winkels neu errechnen und der Sinus und Cosinus des
> Resolvers wären unbrauchbar! Oder?

Ja!
Aber wie willst Du aus einem Sin/Cos-Signal 18(=3*6) Umschaltpunkte 
generieren, ohne über den Winkel zu gehen?

Volker

von TNTBC (Gast)


Lesenswert?

Volker Zabe schrieb:
> Aber wie willst Du aus einem Sin/Cos-Signal 18(=3*6) Umschaltpunkte
> generieren, ohne über den Winkel zu gehen?

Genau vor dem Problem stehe ich gerade. Ich will aber kein Arctan 
berechnen. Die Entscheidung der 6 Sektoren ging bis jetzt ganz gut ohne!
Wenn es jedoch eine schnelle Möglichkeit gibt den Arctan zu berechnen 
dann werde ich darauf eingehen müssen!!
Gruß TNTBC

von Volker Z. (vza)


Angehängte Dateien:

Lesenswert?

TNTBC schrieb:
> Die Entscheidung der 6 Sektoren ging bis jetzt ganz gut ohne!

Das interessiert mich jetzt aber brennend. Wie hast du aus den 8 
Segmenten des Sin/Cos-Signal (die man durch einfaches Vergleichen 
erhält) die 6 Umschaltpunkte generiert?

> Wenn es jedoch eine schnelle Möglichkeit gibt den Arctan zu berechnen
> dann werde ich darauf eingehen müssen!

Ja gibt es. Alles in Integer. Du teilst das Sin/Cos-Signal in 8 
Segmenten (wie oben beschrieben) auf, der Quotient bildet dann ein Index 
in einer Tabelle. Interpolieren brauchst du noch nicht einmal.

Anbei ein Beispiel für ein 3-Phasiges System.
Ist auch noch eine Wurzelberechnung drinnen.

Volker

von TNTBC (Gast)


Lesenswert?

Volker Zabe schrieb:
> Das interessiert mich jetzt aber brennend. Wie hast du aus den 8
> Segmenten des Sin/Cos-Signal (die man durch einfaches Vergleichen
> erhält) die 6 Umschaltpunkte generiert?

Ich habe es aus einer Vorlesung von Prof. Hambrecht der Beuthochschule 
Berlin. Ich habe ihn angefragt sobald er seine Zustimmung gibt werde ich 
die Methode posten.

Volker Zabe schrieb:
> Ja gibt es. Alles in Integer. Du teilst das Sin/Cos-Signal in 8
> Segmenten (wie oben beschrieben) auf, der Quotient bildet dann ein Index
> in einer Tabelle. Interpolieren brauchst du noch nicht einmal.

Die Frage ist, wenn ich jetzt zwei int16_t werte habe die um Null sind 
und ich gebe es in deine Funktion ein, funktioniert diese dann auch? Und 
was ist mit Werten über 30°. Ich bin ehrlich ich verstehe nicht was du 
in der arctan Funktion machst!!! Kannst du das mal beschreiben?


Danke Gruß
TNTbc

von Volker Z. (vza)


Lesenswert?

TNTBC schrieb:
> Kannst du das mal beschreiben?

Die Funktionen kannst du so nicht verwenden. Sie sind für ein 
Drei-Phasen-System (120°- Versatz) gedacht.

- Du musst die Tabelle neu berechnen.
- Kannst die Interpolation vernachlässigen [ atan30() ].
    (Du brauchst eine Auflösung von ca 10°, ich brauchte 0,01°)
    Bei dir könnte es wahrscheinlich reichen, wenn du den Sinus im 
ersten
    Segment als linear ansiehst.
- Die Aufteilung der Segmente neu schreiben (360° -> 90°)[ Cal_Winkel() 
].

Es ging ums Prinzip, wie man Winkelfunktionen mit Integer-Werten 
berechnen kann. Dies sollte keine Vorgefertigte / Null-Denke Lösung 
sein!

Drei-Phasen kann man (durch einfaches Vergleichen(siehe Cal_Winkel()) 
auf 12 Segmente aufteilen -> 30°.  Das geht bei dir nicht.

Volker

von TNTBC (Gast)


Lesenswert?

Ok ich gebe es zu ich bin zu tum für den Code!!!!
Ich verstehe die Tabelle und den Ansatz nicht. Kannst du mir eine Seite 
oder irgendetwas geben um es besser zu verstehen??

Gruß TNTBC

von TNTBC (Gast)


Lesenswert?

Hallo,

damit ich die Sache hier richtig beende!
hier meine Lösung für den atan2. Danke an die Seite 
http://www.dsprelated.com/showmessage/10922/1.php

Die Einheit benötigt laut Simulator:2388clk
Im definitionbereich 0 <= alpha < 180;
1
int16_t i_atan2(int16_t y, int16_t x)
2
  {
3
    int16_t result = 0;
4
    int16_t y2;
5
6
    if ((x | y) == 0)
7
      return 0;  /* give up */
8
9
    if (y < 0)  /* if we point downward */
10
    {
11
      result += -180;
12
      y = -y;
13
      x = -x;
14
    }
15
    if (x < 0)  /* if we point left */
16
    {
17
      result += 90;
18
      y2 = y;
19
      y = -x;
20
      x = y2;
21
    }
22
    if (y > x)  /* 45 degrees or beyond */
23
    {
24
      result += 45;
25
      y2 = y;
26
      y -= x;
27
      x += y2;
28
    }
29
    if (2 * y > x)  /* 26.565 degrees */
30
    {
31
      result += 26.565;
32
      y2 = y;
33
      y = 2 * y - x;
34
      x = 2 * x + y2;
35
    }
36
    if (4 * y > x)  /* 14.036 degrees */
37
    {
38
      result += 14.036;
39
      y2 = y;
40
      y = 4 * y - x;
41
      x = 4 * x + y2;
42
    }
43
    if (8 * y > x)  /* 7.125 degrees */
44
    {
45
      result += 7.125;
46
      y2 = y;
47
      y = 8 * y - x;
48
      x = 8 * x + y2;
49
    }
50
51
    /* linear interpolation of the remaining 64-ant */
52
    result += (57) * y / x;
53
    if(result != 0){
54
      if(result > 0)
55
      
56
      result++;
57
    }      
58
    return result;
59
  }

von Volker Z. (vza)


Lesenswert?

TNTBC schrieb:
> Kannst du mir eine Seite
> oder irgendetwas geben um es besser zu verstehen?

Im Prinzip macht mein Code das Gleiche wie deiner. Aber viel feiner 
(mehr Nachkommastellen), die du aber nicht brauchst und auf 3-Phasen 
ausgelegt.

Durch die implizite Skalierung (Stichwort: Festpunkt-Arithmetik) ist der 
Code schlechter Nachtvollzierbar. Aber ich Versuchs mal:
1
# define MOVE1  0x10000
2
#define ANZAHL 13
3
#define INTERVALL 5041
4
const static t_stuetsstellen atan_table[ANZAHL] ={
5
                0,        2386
6
  ,        944754,        2198
7
  ,       2757006,        2019
8
  ,       5313604,        1850
9
  ,       8473691,        1693
10
  ,      12097609,        1549
11
  ,      16057864,        1418
12
  ,      20244280,        1300
13
  ,      24565367,        1192
14
  ,      28947482,        1096
15
  ,      33332900,        1009
16
  ,      37677470,         931
17
  ,      41948268,         860
18
};
19
20
unsigned short atan30(int U1,int U2)
21
{
22
   int index,flag;
23
   unsigned long teiler,res;
24
25
   teiler = (unsigned long)U1 * MOVE1 + (MOVE1/2);
26
   teiler /= U2;
27
28
   index = (int)(teiler/INTERVALL);
29
 
30
   res= atan_table[index].offset  + atan_table[index].faktor  * teiler;
31
   res /= MOVE1;
32
33
   return (unsigned short) (res);
34
}
Würde man den COS-Wert durch den SIN-Wert im Bereich 0-45° teilen ergäbe 
das ein Wertebereich von 0-1. Dies ist in Integer nicht darstellbar. 
Deshalb verschiebe ich den Bereich um 16 Bit (*0x10000).
Jetzt habe ich den Wertebereich von 0 bis 65535.

Jetzt muss ich den Wertebereich auf meine Stützstellen in der Tabelle 
aufteilen. Ich dividiere durch  5041 (65536/13), so erhalte ich ein 
Index von 0 bis 12. Eine höhere Anzahl an Stützstellen ergaben keine 
höhere Genauigkeit.

Damit hole ich mir den Stützstellenwert aus der Tabelle. Die 
Interpolation zwischen den Stützstellen ist etwas ungewöhnlich, Der 
Faktor ist nicht die Steigung zwischen den Stützstellen, sondern die 
Steigung von Null durch die Stützstelle. Erspart einige Rechnungen zur 
Laufzeit.

Die Werte in der Tabelle sind so berechnet, das sie mir meinen Winkel in 
0.01° mal 0x10000 ergeben. Das ergibt eine große Anzahl von 
Nachkommastellen bei den Rechnungen und damit einen kleinen 
Rundungsfehler. Des halb teile ich zum Schluss noch durch 0x10000.

Ich hoffe es ist damit etwas klarer.   Volker

von Volker Z. (vza)


Lesenswert?

Nachtrag:

Hallo TNTBC,
deine gepostete Funktion rechnet im Bereich 22,2 bis 26.5° bis zu -9,5° 
Falsch. Auch liefert sie nie das Ergebnis 1°.

TNTBC schrieb:
> result += 26.565;
Du addierst eine double zu einem int16_t.
Welchen Sinn macht das denn? Schaltest du immer die Compiler-Warnung ab?

Annsonsten (wenn der Fehler gefunden wurde) eine nette kleine 
arctan-Funktion mit einem Fehler von +/- 1°.


Volker

von Volker Z. (vza)


Angehängte Dateien:

Lesenswert?

Hat mir ja keine Ruhe gelassen. Habe den Fehler gefunden und noch paar 
Kleinigkeiten geändert.

Der Vergleich mit 8*y>x hat mehr Fehler produziert, als Genauigkeit 
gebracht.
Eine Fixpoint Nachkommastelle und eine richtige Rundung brachten den 
Rest.

Der maximale Fehler liegt jetzt bei - 0,6° / +0,7°.

Im Anhang meine Testfunktion.
1
#define FP 2
2
3
short i_atan2(short sinw, short cosw)
4
{
5
   short result = 0;
6
   short temp;
7
8
   if ((cosw | sinw) == 0)
9
   {
10
      return 0;  /* give up */
11
   }
12
13
   if (sinw < 0)  /* 180 - 360 */
14
   {
15
      result = 180*FP;
16
      sinw = -sinw;
17
      cosw = -cosw;
18
   }
19
   if (cosw < 0)  /* 90 - 180 */
20
   {
21
      result += 90*FP;
22
      temp =  sinw;
23
      sinw = -cosw;
24
      cosw =  temp;
25
   }
26
   if (sinw > cosw)  /* 45 - 90 */
27
   {
28
      result += 45*FP;
29
      temp  = sinw;
30
      sinw -= cosw;
31
      cosw += temp;
32
   }
33
   if (2 * sinw > cosw)  /* 26.565 degrees - 45 */
34
   {
35
      result += (short)(26.565*FP);
36
      temp = sinw;
37
      sinw = 2 * sinw - cosw;
38
      cosw = 2 * cosw + temp;
39
   }
40
   if (4 * sinw > cosw)  /* 14.036 degrees - 26.565 */
41
   {
42
      result += (short)(14.036*FP);
43
      temp = sinw;
44
      sinw = 4 * sinw - cosw;
45
      cosw = 4 * cosw + temp;
46
   }
47
48
    /* linear interpolation of the remaining 64-ant */
49
    result += 57*FP * sinw / cosw;
50
    return (result+FP/2)/FP;
51
}

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.