Forum: Mikrocontroller und Digitale Elektronik SVPWM Variante für FOC PMSM


von Peter S. (powerpanse)


Angehängte Dateien:

Lesenswert?

Hallo

Ich habe einen Motorsteuerung für einen PMSM (BLDC) auf Basis eines AVR 
UC3C gebaut und verwende einen SVPWM Algorithmus den ich mir aus einer 
Application Note abgekupfert habe(siehe Anhang). Er funktioniert 
grundsätzlich und ich bekomme schöne Popokurven heraus. Der Algorithmus 
ist simpler als alle anderen die ich so im Netz gefunden habe und ich 
frage mich ob er auch einen Nachteil hat?! Er kommt ohne 
Sektorbestimmung aus! Vielleicht kann ihn ja jemand auch einfach gut 
gebrauchen...
1
static inline void Inverse_Clarke_Transformation(void)    //adopted invers clark from microchip AN1078 or TI
2
{
3
  Vr_a = U_alpha;                                
4
  Vr_b = -(U_alpha >> 1) + dsp32_op_mul(_1Q31_SQR3_DIV2, (U_beta));            
5
  Vr_c = -(U_alpha >> 1) - dsp32_op_mul(_1Q31_SQR3_DIV2, (U_beta));              
6
}
7
8
static inline void Calc_SVPWM(void)
9
{
10
  S32 Voff;
11
  S32 V_Min; 
12
  S32 V_Max;
13
  
14
  V_Min = min3(Vr_a, Vr_b, Vr_c);
15
  V_Max = max3(Vr_a, Vr_b, Vr_c);
16
  Voff = (V_Min + V_Max) >> 1;
17
  //Generate SVPWMs Vectors 
18
   Vr_a = (Vr_a - Voff);
19
   Vr_b = (Vr_b - Voff);
20
   Vr_c = (Vr_c - Voff);
21
}    //eof Calc_SVPWM
22
23
static inline void Generate_PWM_Duties(void)
24
{
25
  S64 DutyA, DutyB, DutyC;
26
  ////transform (-2048 .....0.....+2047)* ADC_SCALE  to (1600....800....0)
27
  //PWM A
28
  //PWM = -((i_out - 2048*ADC_SCALE) * 1600/2/2^25))
29
  DutyA = -(Vr_a - FULLSCALE_S25);    
30
  DutyA *= default_duty_var;
31
  Pwm_duty_a = (U32)(DutyA >> 25);
32
 
33
  //PWM B
34
  //PWM = -((i_out - 2048*ADC_SCALE) * 1600/2/2^25))
35
  DutyB =  -(Vr_b - FULLSCALE_S25);    
36
  DutyB *= default_duty_var;
37
  Pwm_duty_b = (U32)(DutyB >> 25);
38
39
  //PWM C
40
  //PWM = -((i_out - 2048*ADC_SCALE) * 1600/2/2^25))
41
  DutyC =  -(Vr_c - FULLSCALE_S25);      
42
  DutyC *= default_duty_var;
43
  Pwm_duty_c = (U32)(DutyC >> 25);
44
 
45
  //write in registers
46
  AVR32_PWM.channel[PWM_A_PWM_CHANNEL].cdtyupd = Pwm_duty_a;
47
  AVR32_PWM.channel[PWM_B_PWM_CHANNEL].cdtyupd = Pwm_duty_b;
48
  AVR32_PWM.channel[PWM_C_PWM_CHANNEL].cdtyupd = Pwm_duty_c;
49
  //unlock to trigger update next periode
50
  AVR32_PWM.SCUC.updulock = 1;
51
}  //eof static inline void Generate_PWM_Duties(void)

von temp (Gast)


Lesenswert?

Die Vergleiche die man sonst so hat in den Routinen sind hier hinter das 
Macro min3 bzw. max3 gepackt. so in der Art:

#define min3( A, B, C ) ((A) < (B) ? min(A, C) : min(B, C))
#define max3( A, B, C ) ((A) > (B) ? max(A, C) : max(B, C))


Am Ende sieht es nur besser aus, die Laufzeit wird sich kaum 
unterscheiden. Da der Sektor hier nicht ermittelt wird, steht er für 
nachfolgende Aufgaben auch nicht zur Verfügung.

von Peter S. (powerpanse)


Lesenswert?

Was kann man den nachfolgend noch mit der Sektorinformation anfangen?

von temp (Gast)


Lesenswert?

Peter Scheuermann schrieb:
> Was kann man den nachfolgend noch mit der Sektorinformation anfangen?

Das kann ich dir auch noch nicht sagen. Wenn du aber den Teil der die 
Sektovariable setzt raus nimmst, und siehst dir an was vom Code übrig 
bleibt ist es ungefähr das was die min3 und max3 daraus machen. Nichts 
gewonnen außer dass es schön aussieht. Hier käme es mal auf einen 
Vergleich Laufzeit/Codegröße nach Compileroptimierung an.

von anvilex (Gast)


Lesenswert?

Habe gestern in einem Projekt verwendet. Funktioniert perfekt, sehr 
geringere Laufzeit. Danke...

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.