Vektorregelung ohne Strommessung

OP #5139971
Lesenswert?

Hi,

Ich habe eine Vektorregelung (FOC) für einen brüstenlosen Motor 
implementiert und festgestellt, dass wenn ich die Phasenströme für den 
FOC Algorithmus einfach auf einen konstanten Wert setzte, es trotzdem 
hervorragend funktioniert, wenn nicht sogar noch besser (weniger torque 
ripple) als wenn ich die gemessenen Phasenströme in die Rechnung mit 
einbeziehe. Wenn ich ja das magnetische Feld kenne, dann kann ich ja 
mein Stator Feld immer 90° voraus haben, ohne dass ich die Amplitude 
wissen muss, solange ich nicht genau den Strom bestimmen will und somit 
genau das Drehmoment, oder? Hat eine FOC ohne Strommessung weitere 
Nachteile als nur die Unbestimmtheit des Drehmomentes und Strom?
OP #5140625
Lesenswert?

Ich hab hier mal den FOC Code welchen ich verwende. Das ganze habe ich 
mehr oder weniger von hier:

http://www.st.com/content/ccc/resource/technical/document/application_note/06/30/4a/f2/c8/e3/48/e5/CD00116774.pdf/files/CD00116774.pdf/jcr:content/translations/en.CD00116774.pdf

Das ganze funktioniert ziemlich gut, aber eben bei höheren Strömen wird 
der torque ripple gross, aber nur wenn ich 
v_d_ref=k_p_foc*(i_d+i_d_ref*B) + k_i_foc*sum_i_d; und nicht v_d_ref=0 
setze.
1
void startFOC(float ia, float ib, float ic, float pos, float out , float v) {
2
  v_dc=v_dc_val;
3

4
  i_a=ia;
5
  i_b=ib;
6
  i_c=ic;
7

8

9
  /*i_a=0;//ia;
10
  i_b=0;//ib;
11
  i_c=0;//ic;*/
12

13

14
  theta=(pos*(float)MY_PI)/180.0f;
15

16
  i_q_ref=-out;
17
  i_d_ref=0;
18
  clarkTransformation();
19
  parkTransformation();
20
  currentControl();
21
  inverseParkTransformation();
22
  inverseClarkTransformation();
23
  calcCommutationDuration();
24
  sectorDetermination();
25
  setPeriods();
26
}
27

28
void calcCommutationDuration() {
29
  //PU- System to scale v_beta, v_alpha
30
  v_alpha=v_alpha/440;
31
  v_beta=v_beta/440;
32

33
  x_dur=v_dc*v_beta*SQRT_3;
34
  y_dur=(v_dc*v_beta*SQRT_3 + 3*v_dc*v_alpha)/2;
35
  z_dur=(v_dc*v_beta*SQRT_3- 3*v_dc*v_alpha)/2;
36
}
37

38
void inverseClarkTransformation() {
39
  v_a=v_beta;
40
  v_b=(SQRT_3*v_alpha - v_beta)/2;
41
  v_c=-(v_beta + SQRT_3*v_alpha)/2;
42
}
43

44
void clarkTransformation() {
45
  i_alpha=i_a;
46
  i_beta=(i_a + 2*i_b)/SQRT_3;
47
}
48

49
void inverseParkTransformation() {
50
  v_alpha= v_d_ref*cosf(theta) - v_q_ref*sinf(theta);
51
  v_beta= v_q_ref*cosf(theta) + v_d_ref*sinf(theta);
52
}
53

54
void parkTransformation() {
55
  i_d = i_alpha*cosf(theta) + i_beta*sinf(theta);
56
  i_q = -i_alpha*sinf(theta) + i_beta*cosf(theta);
57
}
58

59
void currentControl() {
60
  v_d_ref=k_p_foc*(i_d+i_d_ref*B) + k_i_foc*sum_i_d;
61
  v_q_ref=k_p_foc*(i_q+i_q_ref*B) + k_i_foc*sum_i_q;
62

63
  sum_i_d+=(i_d+i_d_ref)/SUM_W;
64
  sum_i_q+=(i_q+i_q_ref)/SUM_W;
65

66
  if(sum_i_d>integral_windup) {
67
    sum_i_d=integral_windup;
68
  } else if(sum_i_d<-integral_windup) {
69
    sum_i_d=-integral_windup;
70
  }
71

72
  if(sum_i_q>integral_windup) {
73
    sum_i_q=integral_windup;
74
  } else if(sum_i_q<-integral_windup) {
75
    sum_i_q=-integral_windup;
76
  }
77

78
}
79

80
void sectorDetermination() {
81
  if(v_a>0) {
82
    sector[0]=1;
83
  } else {
84
    sector[0]=0;
85
  }
86

87
  if(v_b>0) {
88
    sector[1]=1;
89
  } else {
90
    sector[1]=0;
91
  }
92

93
  if(v_c>0) {
94
    sector[2]=1;
95
  } else {
96
    sector[2]=0;
97
  }
98

99
  sector_is= sector[0]+2*sector[1]+4*sector[2];
100

101
  switch(sector_is) {
102
    case 1:
103
      period_t1=z_dur;
104
      period_t2=y_dur;
105
      break;
106
    case 2:
107
      period_t1=y_dur;
108
      period_t2=-x_dur;
109
      break;
110
    case 3:
111
      period_t1=-z_dur;
112
      period_t2=x_dur;
113
      break;
114
    case 4:
115
      period_t1=-x_dur;
116
      period_t2=z_dur;
117
      break;
118
    case 5:
119
      period_t1=x_dur;
120
      period_t2=-y_dur;
121
      break;
122
    case 6:
123
      period_t1=-y_dur;
124
      period_t2=-z_dur;
125
      break;
126
    default:
127
      break;
128
  }
129

130
  if((period_t1+period_t2) > period_t) {
131
    period_t1_sat=period_t1*(period_t)/(period_t1+period_t2);
132
    period_t2_sat=period_t2*(period_t)/(period_t1+period_t2);
133
  }
134

135
  if(period_t1_sat>0 && period_t1>period_t1_sat)
136
    period_t1=period_t1_sat;
137
  if(period_t1_sat<0 && period_t1<period_t1_sat)
138
    period_t1=period_t1_sat;
139
  if(period_t2_sat>0 && period_t2>period_t2_sat)
140
    period_t2=period_t2_sat;
141
  if(period_t2_sat<0 && period_t2<period_t2_sat)
142
    period_t2=period_t2_sat;
143

144
    period_a=(period_t+1 - period_t1 - period_t2)/2;
145
    period_b=period_a + period_t1;
146
    period_c=period_b + period_t2;
147
}
148

149
void setPeriods(void) {
150
  switch(sector_is) {
151
    case 1:
152
      TIM2->CCR1 = period_b;
153
      TIM2->CCR2 = period_a;
154
      TIM2->CCR3 = period_c;
155
      break;
156
    case 2:
157
      TIM2->CCR1 = period_a;
158
      TIM2->CCR2 = period_c;
159
      TIM2->CCR3 = period_b;
160
      break;
161
    case 3:
162
      TIM2->CCR1 = period_a;
163
      TIM2->CCR2 = period_b;
164
      TIM2->CCR3 = period_c;
165
      break;
166
    case 4:
167
      TIM2->CCR1 = period_c;
168
      TIM2->CCR2 = period_b;
169
      TIM2->CCR3 = period_a;
170
      break;
171
    case 5:
172
      TIM2->CCR1 = period_c;
173
      TIM2->CCR2 = period_a;
174
      TIM2->CCR3 = period_b;
175
      break;
176
    case 6:
177
      TIM2->CCR1 = period_b;
178
      TIM2->CCR2 = period_c;
179
      TIM2->CCR3 = period_a;
180
      break;
181
    default:
182
      break;
183
  }
184
}

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