Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed QEI mbed-rtos
controller.cpp@12:459af534d1ee, 2013-01-04 (annotated)
- Committer:
- kosaka
- Date:
- Fri Jan 04 12:00:48 2013 +0000
- Revision:
- 12:459af534d1ee
- Child:
- 13:ba71733c11d7
DC motor control program using TA7291P type H bridge driver and rotary encoder with A, B phase.;
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| kosaka | 12:459af534d1ee | 1 | // BLDCmotor.cpp: 各種3相同期モータに対するセンサあり運転のシミュレーション |
| kosaka | 12:459af534d1ee | 2 | // Kosaka Lab. 121215 |
| kosaka | 12:459af534d1ee | 3 | #include "mbed.h" |
| kosaka | 12:459af534d1ee | 4 | #include "QEI.h" |
| kosaka | 12:459af534d1ee | 5 | |
| kosaka | 12:459af534d1ee | 6 | #include "controller.h" |
| kosaka | 12:459af534d1ee | 7 | #include "Hbridge.h" |
| kosaka | 12:459af534d1ee | 8 | Serial pc(USBTX, USBRX); // Display on tera term in PC |
| kosaka | 12:459af534d1ee | 9 | |
| kosaka | 12:459af534d1ee | 10 | motor_parameters p; // モータの定数、信号など |
| kosaka | 12:459af534d1ee | 11 | current_loop_parameters il; // 電流制御マイナーループの定数、変数 |
| kosaka | 12:459af534d1ee | 12 | velocity_loop_parameters vl; // 速度制御メインループの定数、変数 |
| kosaka | 12:459af534d1ee | 13 | |
| kosaka | 12:459af534d1ee | 14 | QEI encoder (CH_A, CH_B, NC, N_ENC, QEI::X4_ENCODING); |
| kosaka | 12:459af534d1ee | 15 | // QEI(PinName channelA, mbed pin for channel A input. |
| kosaka | 12:459af534d1ee | 16 | // PinName channelB, mbed pin for channel B input. |
| kosaka | 12:459af534d1ee | 17 | // PinName index, mbed pin for channel Z input. (index channel input Z phase th=0), (pass NC if not needed). |
| kosaka | 12:459af534d1ee | 18 | // int pulsesPerRev, Number of pulses in one revolution(=360 deg). |
| kosaka | 12:459af534d1ee | 19 | // Encoding encoding = X2_ENCODING, X2 is default. X2 uses interrupts on the rising and falling edges of only channel A where as |
| kosaka | 12:459af534d1ee | 20 | // X4 uses them on both channels. |
| kosaka | 12:459af534d1ee | 21 | // ) |
| kosaka | 12:459af534d1ee | 22 | // void reset (void) |
| kosaka | 12:459af534d1ee | 23 | // Reset the encoder. |
| kosaka | 12:459af534d1ee | 24 | // int getCurrentState (void) |
| kosaka | 12:459af534d1ee | 25 | // Read the state of the encoder. |
| kosaka | 12:459af534d1ee | 26 | // int getPulses (void) |
| kosaka | 12:459af534d1ee | 27 | // Read the number of pulses recorded by the encoder. |
| kosaka | 12:459af534d1ee | 28 | // int getRevolutions (void) |
| kosaka | 12:459af534d1ee | 29 | // Read the number of revolutions recorded by the encoder on the index channel. |
| kosaka | 12:459af534d1ee | 30 | /*********** User setting for control parameters (end) ***************/ |
| kosaka | 12:459af534d1ee | 31 | |
| kosaka | 12:459af534d1ee | 32 | AnalogOut analog_out(DA_PORT); |
| kosaka | 12:459af534d1ee | 33 | AnalogIn VshuntR_Uplus(p19); // *3.3 [V], Volt of shunt R_SHUNT[Ohm]. The motor current i = v_shunt_r/R_SHUNT [A] |
| kosaka | 12:459af534d1ee | 34 | AnalogIn VshuntR_Uminus(p20); // *3.3 [V], Volt of shunt R_SHUNT[Ohm]. The motor current i = v_shunt_r/R_SHUNT [A] |
| kosaka | 12:459af534d1ee | 35 | AnalogIn VshuntR_Vplus(p16); // *3.3 [V], Volt of shunt R_SHUNT[Ohm]. The motor current i = v_shunt_r/R_SHUNT [A] |
| kosaka | 12:459af534d1ee | 36 | AnalogIn VshuntR_Vminus(p17); // *3.3 [V], Volt of shunt R_SHUNT[Ohm]. The motor current i = v_shunt_r/R_SHUNT [A] |
| kosaka | 12:459af534d1ee | 37 | |
| kosaka | 12:459af534d1ee | 38 | unsigned long _count; // sampling number |
| kosaka | 12:459af534d1ee | 39 | float _time; // time[s] |
| kosaka | 12:459af534d1ee | 40 | float debug[20]; // for debug |
| kosaka | 12:459af534d1ee | 41 | float disp[10]; // for printf to avoid interrupted by quicker process |
| kosaka | 12:459af534d1ee | 42 | DigitalOut led1(LED1); |
| kosaka | 12:459af534d1ee | 43 | DigitalOut led2(LED2); |
| kosaka | 12:459af534d1ee | 44 | DigitalOut led3(LED3); |
| kosaka | 12:459af534d1ee | 45 | DigitalOut led4(LED4); |
| kosaka | 12:459af534d1ee | 46 | |
| kosaka | 12:459af534d1ee | 47 | #ifdef GOOD_DATA |
| kosaka | 12:459af534d1ee | 48 | float data[1000][5]; // memory to save data offline instead of "online fprintf". |
| kosaka | 12:459af534d1ee | 49 | unsigned int count3; // |
| kosaka | 12:459af534d1ee | 50 | unsigned int count2=(int)(TS2/TS0); // |
| kosaka | 12:459af534d1ee | 51 | unsigned short _count_data=0; |
| kosaka | 12:459af534d1ee | 52 | #endif |
| kosaka | 12:459af534d1ee | 53 | DigitalOut debug_p26(p26); // p17 for debug |
| kosaka | 12:459af534d1ee | 54 | DigitalOut debug_p25(p25); // p17 for debug |
| kosaka | 12:459af534d1ee | 55 | //DigitalOut debug_p24(p24); // p17 for debug |
| kosaka | 12:459af534d1ee | 56 | //AnalogIn VCC(p19); // *3.3 [V], Volt of VCC for motor |
| kosaka | 12:459af534d1ee | 57 | //AnalogIn VCC2(p20); // *3.3 [V], Volt of (VCC-R i), R=2.5[Ohm]. R is for preventing too much i when deadtime is failed. |
| kosaka | 12:459af534d1ee | 58 | |
| kosaka | 12:459af534d1ee | 59 | unsigned short f_find_origin; // flag to find the origin of the rotor angle theta |
| kosaka | 12:459af534d1ee | 60 | |
| kosaka | 12:459af534d1ee | 61 | #if 1 //BUG!! if move sqrt2 to fast_math.h, sim starts and completed without working!? |
| kosaka | 12:459af534d1ee | 62 | float sqrt2(float x){ // √xのx=1まわりのテイラー展開 √x = 1 + 1/2*(x-1) -1/4*(x-1)^2 + ... |
| kosaka | 12:459af534d1ee | 63 | // return((1+x)*0.5); // 一次近似 |
| kosaka | 12:459af534d1ee | 64 | return(x+(1-x*x)*0.25); // 二次近似 |
| kosaka | 12:459af534d1ee | 65 | } |
| kosaka | 12:459af534d1ee | 66 | #endif |
| kosaka | 12:459af534d1ee | 67 | |
| kosaka | 12:459af534d1ee | 68 | void init_parameters(){ // IPMSMの機器定数等の設定, 制御器の初期化 |
| kosaka | 12:459af534d1ee | 69 | #ifdef SIMULATION |
| kosaka | 12:459af534d1ee | 70 | p.L = 0.0063; // H |
| kosaka | 12:459af534d1ee | 71 | p.R = 0.143; // Ω |
| kosaka | 12:459af534d1ee | 72 | p.phi = 0.176; // V s |
| kosaka | 12:459af534d1ee | 73 | p.Jm = 0.00018; // Nms^2 |
| kosaka | 12:459af534d1ee | 74 | p.p = 2; // 極対数 |
| kosaka | 12:459af534d1ee | 75 | #endif |
| kosaka | 12:459af534d1ee | 76 | p.th[0] = p.th[1] = 0; |
| kosaka | 12:459af534d1ee | 77 | p.w = 0; |
| kosaka | 12:459af534d1ee | 78 | p.i = 0; |
| kosaka | 12:459af534d1ee | 79 | p.v =0; |
| kosaka | 12:459af534d1ee | 80 | |
| kosaka | 12:459af534d1ee | 81 | p.w = 0; |
| kosaka | 12:459af534d1ee | 82 | |
| kosaka | 12:459af534d1ee | 83 | // 制御器の初期化 |
| kosaka | 12:459af534d1ee | 84 | vl.i_ref=0; // 電流指令[A] |
| kosaka | 12:459af534d1ee | 85 | vl.w_lpf = 0; // 検出した速度[rad/s] |
| kosaka | 12:459af534d1ee | 86 | vl.eI_w = 0; // 速度制御用偏差の積分値(積分項) |
| kosaka | 12:459af534d1ee | 87 | il.eI_i = 0; // 電流制御用偏差の積分値(積分項) |
| kosaka | 12:459af534d1ee | 88 | #ifndef SIMULATION |
| kosaka | 12:459af534d1ee | 89 | encoder.reset(); // set encoder counter zero |
| kosaka | 12:459af534d1ee | 90 | p.th[0] = p.th[1] = (float)encoder.getPulses()/(float)N_ENC*2.0*PI; // get angle [rad] from encoder |
| kosaka | 12:459af534d1ee | 91 | #endif |
| kosaka | 12:459af534d1ee | 92 | } |
| kosaka | 12:459af534d1ee | 93 | |
| kosaka | 12:459af534d1ee | 94 | void idq_control(){ |
| kosaka | 12:459af534d1ee | 95 | // dq座標電流PID制御器(電流マイナーループのフィードバック制御) |
| kosaka | 12:459af534d1ee | 96 | // 入力:指令電流 i_ref [A], 実電流 p.i [A], PI制御積分項 eI, サンプル時間 TS0 [s] |
| kosaka | 12:459af534d1ee | 97 | // 出力:電圧指令 v_ref [A] |
| kosaka | 12:459af534d1ee | 98 | float e; |
| kosaka | 12:459af534d1ee | 99 | |
| kosaka | 12:459af534d1ee | 100 | //debug[0]=il.i_ref; |
| kosaka | 12:459af534d1ee | 101 | // dq電流偏差の計算 |
| kosaka | 12:459af534d1ee | 102 | e = il.i_ref - p.i; |
| kosaka | 12:459af534d1ee | 103 | |
| kosaka | 12:459af534d1ee | 104 | // dq電流偏差の積分項の計算 |
| kosaka | 12:459af534d1ee | 105 | il.eI_i = il.eI_i + TS0*e; |
| kosaka | 12:459af534d1ee | 106 | |
| kosaka | 12:459af534d1ee | 107 | // PI制御 |
| kosaka | 12:459af534d1ee | 108 | il.v_ref = iKP*e + iKI*il.eI_i; |
| kosaka | 12:459af534d1ee | 109 | |
| kosaka | 12:459af534d1ee | 110 | } |
| kosaka | 12:459af534d1ee | 111 | |
| kosaka | 12:459af534d1ee | 112 | void current_loop(){ // 電流制御マイナーループ |
| kosaka | 12:459af534d1ee | 113 | // 電流センサによってiu, iv を検出 |
| kosaka | 12:459af534d1ee | 114 | #ifndef SIMULATION |
| kosaka | 12:459af534d1ee | 115 | p.i = (VshuntR_Uplus - VshuntR_Uminus) /R_SHUNT; // get i [A] from shunt resistance; |
| kosaka | 12:459af534d1ee | 116 | #endif |
| kosaka | 12:459af534d1ee | 117 | //debug[0]=p.i; |
| kosaka | 12:459af534d1ee | 118 | // dq電流制御(電流フィードバック制御) |
| kosaka | 12:459af534d1ee | 119 | debug[0]=il.i_ref; |
| kosaka | 12:459af534d1ee | 120 | #ifdef USE_CURRENT_CONTROL |
| kosaka | 12:459af534d1ee | 121 | idq_control(); |
| kosaka | 12:459af534d1ee | 122 | #else |
| kosaka | 12:459af534d1ee | 123 | il.v_ref = il.i_ref/iMAX*vMAX; |
| kosaka | 12:459af534d1ee | 124 | #endif |
| kosaka | 12:459af534d1ee | 125 | // 電圧指令の大きさをMAX制限 |
| kosaka | 12:459af534d1ee | 126 | // anti-windup: if u=v_ref is saturated, then reduce eI. |
| kosaka | 12:459af534d1ee | 127 | if( il.v_ref > vMAX ){ |
| kosaka | 12:459af534d1ee | 128 | il.eI_i -= (il.v_ref - vMAX)/iKI; if( il.eI_i<0 ){ il.eI_i=0;} |
| kosaka | 12:459af534d1ee | 129 | il.v_ref = vMAX; |
| kosaka | 12:459af534d1ee | 130 | }else if( il.v_ref < -vMAX ){ |
| kosaka | 12:459af534d1ee | 131 | il.eI_i -= (il.v_ref + vMAX)/iKI; if( il.eI_i>0 ){ il.eI_i=0;} |
| kosaka | 12:459af534d1ee | 132 | il.v_ref = -vMAX; |
| kosaka | 12:459af534d1ee | 133 | } |
| kosaka | 12:459af534d1ee | 134 | p.v = il.v_ref; |
| kosaka | 12:459af534d1ee | 135 | |
| kosaka | 12:459af534d1ee | 136 | p.th[1] = p.th[0]; // thを更新 |
| kosaka | 12:459af534d1ee | 137 | } |
| kosaka | 12:459af534d1ee | 138 | |
| kosaka | 12:459af534d1ee | 139 | |
| kosaka | 12:459af534d1ee | 140 | void vel_control(){ |
| kosaka | 12:459af534d1ee | 141 | // 速度制御器:速度偏差が入力され、q軸電流指令を出力。 |
| kosaka | 12:459af534d1ee | 142 | // 入力:指令速度 w_ref [rad/s], 実速度 w_lpf [rad/s], PI制御積分項 eI, サンプル時間 TS1 [s] |
| kosaka | 12:459af534d1ee | 143 | // 出力:電流指令 i_ref [A] |
| kosaka | 12:459af534d1ee | 144 | float e; |
| kosaka | 12:459af534d1ee | 145 | |
| kosaka | 12:459af534d1ee | 146 | // 速度偏差の計算 |
| kosaka | 12:459af534d1ee | 147 | e = vl.w_ref - vl.w_lpf; |
| kosaka | 12:459af534d1ee | 148 | |
| kosaka | 12:459af534d1ee | 149 | // 速度偏差の積分値の計算 |
| kosaka | 12:459af534d1ee | 150 | vl.eI_w = vl.eI_w + TS1*e; |
| kosaka | 12:459af534d1ee | 151 | |
| kosaka | 12:459af534d1ee | 152 | // PI制御 |
| kosaka | 12:459af534d1ee | 153 | vl.i_ref = wKp*e + wKi*vl.eI_w; |
| kosaka | 12:459af534d1ee | 154 | } |
| kosaka | 12:459af534d1ee | 155 | |
| kosaka | 12:459af534d1ee | 156 | void velocity_loop(){ // 速度制御メインループ(w_ref&beta_ref to idq_ref) |
| kosaka | 12:459af534d1ee | 157 | float tmp; |
| kosaka | 12:459af534d1ee | 158 | |
| kosaka | 12:459af534d1ee | 159 | // 速度ωを求めるために、位置θをオイラー微分して、一次ローパスフィルタに通す。 |
| kosaka | 12:459af534d1ee | 160 | #if 1 |
| kosaka | 12:459af534d1ee | 161 | tmp = p.th[0]-p.th[1]; |
| kosaka | 12:459af534d1ee | 162 | while( tmp> PI ){ tmp -= 2*PI;} |
| kosaka | 12:459af534d1ee | 163 | while( tmp<-PI ){ tmp += 2*PI;} |
| kosaka | 12:459af534d1ee | 164 | vl.w_lpf = iLPF*vl.w_lpf + tmp/TS0 *(1-iLPF); |
| kosaka | 12:459af534d1ee | 165 | #else |
| kosaka | 12:459af534d1ee | 166 | vl.w_lpf = p.th[0]; |
| kosaka | 12:459af534d1ee | 167 | #endif |
| kosaka | 12:459af534d1ee | 168 | // 速度制御:速度偏差が入力され、電流指令を出力。 |
| kosaka | 12:459af534d1ee | 169 | vel_control(); |
| kosaka | 12:459af534d1ee | 170 | |
| kosaka | 12:459af534d1ee | 171 | // 電流指令のMAX制限(異常に大きい指令値を制限する) |
| kosaka | 12:459af534d1ee | 172 | // anti-windup: if u=i_ref is saturated, then reduce eI. |
| kosaka | 12:459af534d1ee | 173 | if( vl.i_ref > iMAX ){ |
| kosaka | 12:459af534d1ee | 174 | vl.eI_w -= (vl.i_ref - iMAX)/wKi; if( vl.eI_w<0 ){ vl.eI_w=0;} |
| kosaka | 12:459af534d1ee | 175 | vl.i_ref = iMAX; |
| kosaka | 12:459af534d1ee | 176 | }else if( vl.i_ref < -iMAX ){ |
| kosaka | 12:459af534d1ee | 177 | vl.eI_w -= (vl.i_ref + iMAX)/wKi; if( vl.eI_w>0 ){ vl.eI_w=0;} |
| kosaka | 12:459af534d1ee | 178 | vl.i_ref = -iMAX; |
| kosaka | 12:459af534d1ee | 179 | } |
| kosaka | 12:459af534d1ee | 180 | //debug[0]=vl.eI_w; |
| kosaka | 12:459af534d1ee | 181 | |
| kosaka | 12:459af534d1ee | 182 | // 電流の目標値を速度制御メインループから電流制御マイナーループへ渡す。 |
| kosaka | 12:459af534d1ee | 183 | il.i_ref = vl.i_ref; |
| kosaka | 12:459af534d1ee | 184 | //debug[0]=il.i_ref; |
| kosaka | 12:459af534d1ee | 185 | } |
| kosaka | 12:459af534d1ee | 186 | |
| kosaka | 12:459af534d1ee | 187 | void v2Hbridge(){ // vより、PWMを発生 |
| kosaka | 12:459af534d1ee | 188 | float duty; |
| kosaka | 12:459af534d1ee | 189 | |
| kosaka | 12:459af534d1ee | 190 | // duty = (p.v/vMAX+1)*0.5; |
| kosaka | 12:459af534d1ee | 191 | // IN.duty = duty; |
| kosaka | 12:459af534d1ee | 192 | duty = p.v/vMAX; |
| kosaka | 12:459af534d1ee | 193 | if( duty>=0 ){ |
| kosaka | 12:459af534d1ee | 194 | IN.duty = duty; |
| kosaka | 12:459af534d1ee | 195 | if( IN.fReverse[0]==1 ){ |
| kosaka | 12:459af534d1ee | 196 | IN.fDeadtime = 1; |
| kosaka | 12:459af534d1ee | 197 | } |
| kosaka | 12:459af534d1ee | 198 | IN.fReverse[0] = 0; |
| kosaka | 12:459af534d1ee | 199 | }else{ |
| kosaka | 12:459af534d1ee | 200 | IN.duty = -duty; |
| kosaka | 12:459af534d1ee | 201 | if( IN.fReverse[0]==0 ){ |
| kosaka | 12:459af534d1ee | 202 | IN.fDeadtime = 1; |
| kosaka | 12:459af534d1ee | 203 | } |
| kosaka | 12:459af534d1ee | 204 | IN.fReverse[0] = 1; |
| kosaka | 12:459af534d1ee | 205 | } |
| kosaka | 12:459af534d1ee | 206 | } |
| kosaka | 12:459af534d1ee | 207 | |
| kosaka | 12:459af534d1ee | 208 | #ifdef SIMULATION |
| kosaka | 12:459af534d1ee | 209 | void sim_motor(){ |
| kosaka | 12:459af534d1ee | 210 | // モータシミュレータ |
| kosaka | 12:459af534d1ee | 211 | // 入力信号:電圧p.v [V]、負荷トルクp.TL [Nm] |
| kosaka | 12:459af534d1ee | 212 | // 出力信号:モータ角度p.th[0] [rad], モータ速度p.w [rad/s], モータ電流p.i [A] |
| kosaka | 12:459af534d1ee | 213 | float i_dot, Tall, TL; |
| kosaka | 12:459af534d1ee | 214 | analog_out=p.v/100.+0.5;//debug |
| kosaka | 12:459af534d1ee | 215 | //debug[0]=p.v; |
| kosaka | 12:459af534d1ee | 216 | // get i |
| kosaka | 12:459af534d1ee | 217 | i_dot = (1.0/p.L) * ( p.v - (p.R*p.i + p.w*p.phi) ); |
| kosaka | 12:459af534d1ee | 218 | p.i = p.i + TS0*i_dot; |
| kosaka | 12:459af534d1ee | 219 | |
| kosaka | 12:459af534d1ee | 220 | // モータトルクの計算 |
| kosaka | 12:459af534d1ee | 221 | p.Tm = p.p * p.phi * p.i; |
| kosaka | 12:459af534d1ee | 222 | |
| kosaka | 12:459af534d1ee | 223 | // モータ速度ωの計算 |
| kosaka | 12:459af534d1ee | 224 | if( abs(p.w) > 5*2*PI ) |
| kosaka | 12:459af534d1ee | 225 | if( p.w>=0 ) TL= p.TL; |
| kosaka | 12:459af534d1ee | 226 | else TL=-p.TL; |
| kosaka | 12:459af534d1ee | 227 | else |
| kosaka | 12:459af534d1ee | 228 | TL = p.w/(5*2*PI)*p.TL; |
| kosaka | 12:459af534d1ee | 229 | |
| kosaka | 12:459af534d1ee | 230 | Tall = p.Tm - TL; |
| kosaka | 12:459af534d1ee | 231 | p.w = p.w + TS0 * (1.0 / p.Jm) * Tall; |
| kosaka | 12:459af534d1ee | 232 | |
| kosaka | 12:459af534d1ee | 233 | // モータ角度θの計算 |
| kosaka | 12:459af534d1ee | 234 | p.th[0] = p.th[0] + TS0 * p.w; |
| kosaka | 12:459af534d1ee | 235 | if( p.th[0]>2*PI) |
| kosaka | 12:459af534d1ee | 236 | p.th[0] = p.th[0] - 2*PI; |
| kosaka | 12:459af534d1ee | 237 | |
| kosaka | 12:459af534d1ee | 238 | if( p.th[0]<0 ) |
| kosaka | 12:459af534d1ee | 239 | p.th[0] = p.th[0] + 2*PI; |
| kosaka | 12:459af534d1ee | 240 | //debug[0]=p.v; |
| kosaka | 12:459af534d1ee | 241 | } |
| kosaka | 12:459af534d1ee | 242 | #endif |
| kosaka | 12:459af534d1ee | 243 | |
| kosaka | 12:459af534d1ee | 244 | void data2mbedUSB(){ // save data to mbed USB drive |
| kosaka | 12:459af534d1ee | 245 | if( _count_data<1000 ){ |
| kosaka | 12:459af534d1ee | 246 | data[_count_data][0]=p.th[0]/*vl.w_ref*/; data[_count_data][1]=debug[0]; |
| kosaka | 12:459af534d1ee | 247 | data[_count_data][2]=vl.w_lpf; data[_count_data][3]=_count*TS0; data[_count_data][4]=il.v_ref; |
| kosaka | 12:459af534d1ee | 248 | _count_data++; |
| kosaka | 12:459af534d1ee | 249 | } |
| kosaka | 12:459af534d1ee | 250 | #if 0 |
| kosaka | 12:459af534d1ee | 251 | if( _count_data<500 ){ |
| kosaka | 12:459af534d1ee | 252 | debug[0]=p.vab[0]; debug[1]=p.vab[1]; debug[2]=il.vdq_ref[0]; debug[3]=il.vdq_ref[1]; debug[4]=p.iab[0]; |
| kosaka | 12:459af534d1ee | 253 | debug[5]=p.iab[1]; debug[6]=p.vuvw[0]; debug[7]=p.vuvw[1]; debug[8]=p.vuvw[2]; debug[9]=p.iuvw[0]; |
| kosaka | 12:459af534d1ee | 254 | debug[10]=p.iuvw[1]; debug[11]=p.iuvw[2]; debug[12]=p.idq[0]; debug[13]=p.idq[1]; debug[14]=p.TL; |
| kosaka | 12:459af534d1ee | 255 | debug[15]=p.Tm; debug[16]=p.w; debug[17]=vl.w_lpf; debug[18]=p.th[0]; debug[19]=_count*TS0;//_time; |
| kosaka | 12:459af534d1ee | 256 | //BUG for(j=0;j<19;j++){ fprintf( fp, "%f, ",debug[j]);} fprintf( fp, "%f\n",debug[19]); |
| kosaka | 12:459af534d1ee | 257 | for(j=0;j<19;j++){ printf("%f, ",debug[j]);} printf("%f\n",debug[19]); |
| kosaka | 12:459af534d1ee | 258 | // for(j=0;j<19;j++){ pc.printf("%f, ",debug[j]);} pc.printf("%f\n",debug[19]); |
| kosaka | 12:459af534d1ee | 259 | } |
| kosaka | 12:459af534d1ee | 260 | #endif |
| kosaka | 12:459af534d1ee | 261 | } |
| kosaka | 12:459af534d1ee | 262 | void timerTS0(){ // timer called every TS0[s]. |
| kosaka | 12:459af534d1ee | 263 | debug_p26 = 1; |
| kosaka | 12:459af534d1ee | 264 | _count++; |
| kosaka | 12:459af534d1ee | 265 | _time += TS0; |
| kosaka | 12:459af534d1ee | 266 | |
| kosaka | 12:459af534d1ee | 267 | current_loop(); // 電流制御マイナーループ(i_ref to volt) |
| kosaka | 12:459af534d1ee | 268 | v2Hbridge(); // volt. to Hbridge |
| kosaka | 12:459af534d1ee | 269 | #ifdef SIMULATION |
| kosaka | 12:459af534d1ee | 270 | //debug[0]=p.v; |
| kosaka | 12:459af534d1ee | 271 | // モータシミュレータ |
| kosaka | 12:459af534d1ee | 272 | sim_motor(); // IPM, dq座標 |
| kosaka | 12:459af534d1ee | 273 | #else |
| kosaka | 12:459af534d1ee | 274 | p.th[1] = p.th[0]; |
| kosaka | 12:459af534d1ee | 275 | p.th[0] = (float)encoder.getPulses()/(float)N_ENC*2.0*PI; // get angle [rad] from encoder |
| kosaka | 12:459af534d1ee | 276 | #endif |
| kosaka | 12:459af534d1ee | 277 | debug_p26 = 0; |
| kosaka | 12:459af534d1ee | 278 | } |
| kosaka | 12:459af534d1ee | 279 | void timerTS1(void const *argument){ |
| kosaka | 12:459af534d1ee | 280 | debug_p25 = 1; |
| kosaka | 12:459af534d1ee | 281 | velocity_loop(); // 速度制御メインループ(w_ref&beta_ref to idq_ref) |
| kosaka | 12:459af534d1ee | 282 | debug_p25 = 0; |
| kosaka | 12:459af534d1ee | 283 | } |
| kosaka | 12:459af534d1ee | 284 | |
| kosaka | 12:459af534d1ee | 285 | void display2PC(){ // display to tera term on PC |
| kosaka | 12:459af534d1ee | 286 | pc.printf("%8.1f[s]\t%8.2f[V]\t%8.2f [Hz]\t%8.2f\t%8.2f\r\n", _time, il.v_ref, vl.w_lpf/(2*PI), vl.w_ref/(2*PI), debug[0]); // print to tera term |
| kosaka | 12:459af534d1ee | 287 | // pc.printf("%8.1f[s]\t%8.5f[V]\t%4d [deg]\t%8.2f\r\n", _time, _u, (int)(_th/(2*PI)*360.0), _r);//debug[0]*3.3/R_SHUNT); // print to tera term |
| kosaka | 12:459af534d1ee | 288 | } |
| kosaka | 12:459af534d1ee | 289 | void timerTS2(){ |
| kosaka | 12:459af534d1ee | 290 | } |
| kosaka | 12:459af534d1ee | 291 | void timerTS3(){ |
| kosaka | 12:459af534d1ee | 292 | data2mbedUSB(); // data2mbedUSB() is called every TS3[s]. |
| kosaka | 12:459af534d1ee | 293 | } |
| kosaka | 12:459af534d1ee | 294 | void timerTS4(){ |
| kosaka | 12:459af534d1ee | 295 | display2PC(); // display to tera term on PC. display2PC() is called every TS4[s]. |
| kosaka | 12:459af534d1ee | 296 | } |