Kosaka Lab / Mbed 2 deprecated BLDCmotor

Dependencies:   QEI mbed-rtos mbed

Fork of BLDCmotor by manabu kosaka

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers UVWpwm.cpp Source File

UVWpwm.cpp

00001 #include "mbed.h"
00002 #include "controller.h"
00003 #include "UVWpwm.h"  // PWM発生用UVWpwm.cppの変数や定数の定義
00004 
00005 #define DEADTIME_US (unsigned long)(DEADTIME*1000000)  // [us], デッドタイム
00006 
00007 Timeout pwm[3];    // タイムアウト関数の宣言(ある時間経過後に関数コールする)
00008 
00009 // デジタル信号を出力するポートupperとlowerをU, V, W相について設定
00010 DigitalOut pwm_upper[] = {(U_UPPER_PORT), (V_UPPER_PORT),(W_UPPER_PORT)};
00011 DigitalOut pwm_lower[] = {(U_LOWER_PORT), (V_LOWER_PORT),(W_LOWER_PORT)};
00012 
00013 pwm_parameters     uvw[3]; // UVW相pwm用の定数、変数宣言
00014 
00015 // U, V相シャント抵抗の両端の電圧のアナログ入力名の設定, *3.3[V]
00016 AnalogIn VshuntR_Uplus( R_SHUNT_UP_PORT); // *3.3[V], U相+側アナログ入力
00017 AnalogIn VshuntR_Uminus(R_SHUNT_UM_PORT); // *3.3[V], U相-側アナログ入力
00018 AnalogIn VshuntR_Vplus( R_SHUNT_VP_PORT); // *3.3[V], V相+側アナログ入力
00019 AnalogIn VshuntR_Vminus(R_SHUNT_VM_PORT); // *3.3[V], V相-側アナログ入力
00020 
00021 // 関数配列: NG
00022 //void (*pwmUVWout[])(int) = {pwmout,pwmout,pwmout};
00023 //  pwmUVWout[i](i);
00024 void pwmVout(), pwmWout();
00025 
00026 #if PWM_WAVEFORM==0   // 0: saw tooth wave comparison
00027 void pwmUout() {    // タイムアウト関数でU相PWMを発生する関数
00028     unsigned char   i=0;  // i=0のときU相
00029     uvw[i].mode += 1;   // チョッピングのオンオフを決定するモードを1増やす
00030     if( uvw[i].mode==1 ){       // モードが1のとき、Tonの状態をつくる
00031         pwm_upper[i] = 1;         // 上アームUuをオン
00032         pwm_lower[i] = 0;         // 下アームUdをオフ
00033         // モード1の時間幅 T1 = Ton-Tdt を計算
00034         uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US;
00035         // 時間幅が小さいときはTMINにする
00036         if( uvw[i].upper_us < TMIN ){  uvw[i].upper_us=TMIN;}
00037         // T1[μs]経過してからタイムアウトでこの関数自身をコール
00038         pwm[i].attach_us(&pwmUout, uvw[i].upper_us);
00039         // モード3の時間幅 T3=Toff-Tdt=Tpwm-(T1+Tdt)-Tdtを計算
00040         uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US;
00041         // 時間幅が小さいときはTMINにする
00042         if( uvw[i].lower_us < TMIN ){  uvw[i].lower_us=TMIN;}
00043         pwmVout();  pwmWout();
00044     }else if( uvw[i].mode==2 ){ // モードが2のとき、デッドタイムをつくる
00045         // Tdt[μs]経過してからタイムアウトでこの関数自身をコール
00046         pwm[i].attach_us(&pwmUout, DEADTIME_US);
00047 #ifndef SIMULATION
00048         // シャント抵抗の両端の電圧を見てモータ電流を検出
00049         p.iuvw[0] = (VshuntR_Uplus - VshuntR_Uminus)*3.3 /R_SHUNT; // iu [A]
00050 #endif
00051         pwm_upper[i] = 0;         // 上アームUuをオフ
00052         pwm_lower[i] = 0;         // 下アームUdをオフ
00053     }else if( uvw[i].mode==3 ){ // モードが3のとき、Toffの状態をつくる
00054         // T3[μs]経過してからタイムアウトでこの関数自身をコール
00055         pwm[i].attach_us(&pwmUout, uvw[i].lower_us);
00056         pwm_upper[i] = 0;         // 上アームUuをオフ
00057         pwm_lower[i] = 1;         // 下アームUdをオン
00058     }else{                     // モードが4のとき、デッドタイムをつくる
00059         // Tdt[μs]経過してからタイムアウトでこの関数自身をコール
00060         pwm[i].attach_us(&pwmUout, DEADTIME_US);
00061         pwm_upper[i] = 0;         // 上アームUuをオフ
00062         pwm_lower[i] = 0;         // 下アームUdをオフ
00063         uvw[i].mode = 0;          // チョッピングのオンオフを決定するモードを
00064     }                             // 0にする
00065 }
00066 
00067 void pwmVout() {    // pwm out using timer
00068     unsigned char   i=1;
00069     uvw[i].mode += 1;
00070     if( uvw[i].mode==1 ){
00071         pwm_upper[i] = 1;
00072         pwm_lower[i] = 0;
00073         uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US;   // ON time of Uupper
00074         if( uvw[i].upper_us < TMIN ){  uvw[i].upper_us=TMIN;}
00075         pwm[i].attach_us(&pwmVout, uvw[i].upper_us); // setup pwmU to call pwmUout after t [us]
00076         uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // ON time of Ulower
00077         if( uvw[i].lower_us < TMIN ){  uvw[i].lower_us=TMIN;}
00078     }else if( uvw[i].mode==2 ){
00079         pwm[i].attach_us(&pwmVout, DEADTIME_US); // setup pwmU to call pwmUout after t [us]
00080 #ifndef SIMULATION
00081         // シャント抵抗の両端の電圧を見てモータ電流を検出
00082         p.iuvw[1] = (VshuntR_Vplus - VshuntR_Vminus)*3.3 /R_SHUNT; // iv [A]
00083 #endif
00084         pwm_upper[i] = 0;
00085         pwm_lower[i] = 0;
00086     }else if( uvw[i].mode==3 ){
00087         pwm[i].attach_us(&pwmVout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us]
00088         pwm_upper[i] = 0;
00089         pwm_lower[i] = 1;
00090     }else{// if( u.mode==4 ){
00091 //        pwm[i].attach_us(&pwmVout, DEADTIME_US); // setup pwmU to call pwmUout after t [us]
00092         pwm_upper[i] = 0;
00093         pwm_lower[i] = 0;
00094         uvw[i].mode = 0;
00095     }
00096 }
00097 
00098 void pwmWout() {    // pwm out using timer
00099     unsigned char   i=2;
00100     uvw[i].mode += 1;
00101     if( uvw[i].mode==1 ){
00102         pwm_upper[i] = 1;
00103         pwm_lower[i] = 0;
00104         uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US;   // ON time of Uupper
00105         if( uvw[i].upper_us < TMIN ){  uvw[i].upper_us=TMIN;}
00106         pwm[i].attach_us(&pwmWout, uvw[i].upper_us); // setup pwmU to call pwmUout after t [us]
00107         uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // ON time of Ulower
00108         if( uvw[i].lower_us < TMIN ){  uvw[i].lower_us=TMIN;}
00109     }else if( uvw[i].mode==2 ){
00110         pwm[i].attach_us(&pwmWout, DEADTIME_US); // setup pwmU to call pwmUout after t [us]
00111         pwm_upper[i] = 0;
00112         pwm_lower[i] = 0;
00113     }else if( uvw[i].mode==3 ){
00114         pwm[i].attach_us(&pwmWout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us]
00115         pwm_upper[i] = 0;
00116         pwm_lower[i] = 1;
00117     }else{// if( u.mode==4 ){
00118 //        pwm[i].attach_us(&pwmWout, DEADTIME_US); // setup pwmU to call pwmUout after t [us]
00119         pwm_upper[i] = 0;
00120         pwm_lower[i] = 0;
00121         uvw[i].mode = 0;
00122     }
00123 }
00124 #elif PWM_WAVEFORM==1   // 1: triangler wave comparison
00125 void pwmUout() {    // タイムアウト関数でU相PWMを発生する関数
00126     unsigned char   i=0;  // i=0のときU相
00127     uvw[i].mode += 1;   // チョッピングのオンオフを決定するモードを1増やす
00128     if( uvw[i].mode==1 ){       // モードが1のとき、Toffの状態をつくる
00129         pwm_upper[i] = 0;         // 上アームUuをオフ
00130         pwm_lower[i] = 1;         // 下アームUdをオン
00131         // モード3の時間幅 T3 = Ton-Tdt を計算
00132         uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US;
00133         // モード1,5の時間幅 T1=(Toff-Tdt)/2=(Tpwm-T3-2Tdt)/2を計算
00134         uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US;
00135         uvw[i].lower_us /= 2;
00136         // 時間幅が小さいときはTMINにする
00137         if( uvw[i].lower_us < TMIN ){  uvw[i].lower_us=TMIN;}
00138         // T1[μs]経過してからタイムアウトでこの関数自身をコール
00139         pwm[i].attach_us(&pwmUout, uvw[i].lower_us);
00140         // 時間幅が小さいときはTMINにする
00141         if( uvw[i].upper_us < TMIN ){  uvw[i].upper_us=TMIN;}
00142     }else if( uvw[i].mode==2 ){ // モードが2のとき、デッドタイムをつくる
00143         // Tdt[μs]経過してからタイムアウトでこの関数自身をコール
00144         pwm[i].attach_us(&pwmUout, DEADTIME_US);
00145         pwm_upper[i] = 0;         // 上アームUuをオフ
00146         pwm_lower[i] = 0;         // 下アームUdをオフ
00147     }else if( uvw[i].mode==3 ){ // モードが3のとき、Tonの状態をつくる
00148         // T3[μs]経過してからタイムアウトでこの関数自身をコール
00149         pwm[i].attach_us(&pwmUout, uvw[i].upper_us);
00150         pwm_upper[i] = 1;         // 上アームUuをオン
00151         pwm_lower[i] = 0;         // 下アームUdをオフ
00152     }else if( uvw[i].mode==4 ){ // モードが4のとき、デッドタイムをつくる
00153         // Tdt[μs]経過してからタイムアウトでこの関数自身をコール
00154         pwm[i].attach_us(&pwmUout, DEADTIME_US);
00155 #ifndef SIMULATION
00156         // シャント抵抗の両端の電圧を見てモータ電流を検出
00157         p.iuvw[0] = (VshuntR_Uplus - VshuntR_Uminus)*3.3 /R_SHUNT; // iu [A]
00158 #endif
00159         pwm_upper[i] = 0;         // 上アームUuをオフ
00160         pwm_lower[i] = 0;         // 下アームUdをオフ
00161     }else{                     // モードが5のとき、Toffの状態をつくる
00162         // T5(=T1)[μs]経過してからタイムアウトでこの関数自身をコール
00163         pwm[i].attach_us(&pwmUout, uvw[i].lower_us);
00164         pwm_upper[i] = 0;         // 上アームUuをオフ
00165         pwm_lower[i] = 1;         // 下アームUdをオン
00166         uvw[i].mode = 0;          // チョッピングのオンオフを決定するモードを
00167     }                             // 0にする
00168 }
00169 void pwmVout() {    // pwm out using timer
00170     unsigned char   i=1;
00171     uvw[i].mode += 1;
00172     if( uvw[i].mode==1 ){
00173         uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US;   // ON time of Uupper
00174         uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // ON time of Ulower
00175         pwm_upper[i] = 0;
00176         pwm_lower[i] = 1;
00177         uvw[i].lower_us /= 2;
00178         if( uvw[i].lower_us < TMIN ){  uvw[i].lower_us=TMIN;}
00179         pwm[i].attach_us(&pwmVout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us]
00180         if( uvw[i].upper_us < TMIN ){  uvw[i].upper_us=TMIN;}
00181     }else if( uvw[i].mode==2 ){
00182         pwm[i].attach_us(&pwmVout, DEADTIME_US); // setup pwmU to call pwmUout after t [us]
00183         pwm_upper[i] = 0;
00184         pwm_lower[i] = 0;
00185     }else if( uvw[i].mode==3 ){
00186         pwm[i].attach_us(&pwmVout, uvw[i].upper_us); // setup pwmU to call pwmUout after t [us]
00187         pwm_upper[i] = 1;
00188         pwm_lower[i] = 0;
00189     }else if( uvw[i].mode==4 ){
00190         pwm[i].attach_us(&pwmVout, DEADTIME_US); // setup pwmU to call pwmUout after t [us]
00191 #ifndef SIMULATION
00192         // シャント抵抗の両端の電圧を見てモータ電流を検出
00193         p.iuvw[1] = (VshuntR_Vplus - VshuntR_Vminus)*3.3 /R_SHUNT; // iv [A]
00194 #endif
00195         pwm_upper[i] = 0;
00196         pwm_lower[i] = 0;
00197     }else{// if( uvw[i].mode==5 ){
00198         pwm[i].attach_us(&pwmVout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us]
00199         pwm_upper[i] = 0;
00200         pwm_lower[i] = 1;
00201         uvw[i].mode = 0;
00202     }
00203 }
00204 
00205 void pwmWout() {    // pwm out using timer
00206     unsigned char   i=2;
00207     uvw[i].mode += 1;
00208     if( uvw[i].mode==1 ){
00209         uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US;   // ON time of Uupper
00210         uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // ON time of Ulower
00211         pwm_upper[i] = 0;
00212         pwm_lower[i] = 1;
00213         uvw[i].lower_us /= 2;
00214         if( uvw[i].lower_us < TMIN ){  uvw[i].lower_us=TMIN;}
00215         pwm[i].attach_us(&pwmWout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us]
00216         if( uvw[i].upper_us < TMIN ){  uvw[i].upper_us=TMIN;}
00217     }else if( uvw[i].mode==2 ){
00218         pwm[i].attach_us(&pwmWout, DEADTIME_US); // setup pwmU to call pwmUout after t [us]
00219         pwm_upper[i] = 0;
00220         pwm_lower[i] = 0;
00221     }else if( uvw[i].mode==3 ){
00222         pwm[i].attach_us(&pwmWout, uvw[i].upper_us); // setup pwmU to call pwmUout after t [us]
00223         pwm_upper[i] = 1;
00224         pwm_lower[i] = 0;
00225     }else if( uvw[i].mode==4 ){
00226         pwm[i].attach_us(&pwmWout, DEADTIME_US); // setup pwmU to call pwmUout after t [us]
00227         pwm_upper[i] = 0;
00228         pwm_lower[i] = 0;
00229     }else{// if( uvw[i].mode==5 ){
00230         pwm[i].attach_us(&pwmWout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us]
00231         pwm_upper[i] = 0;
00232         pwm_lower[i] = 1;
00233         uvw[i].mode = 0;
00234     }
00235 }
00236 #endif
00237 
00238 
00239 void start_pwm(){
00240     unsigned char i; 
00241     for( i=0;i<3;i++ ){
00242         uvw[i].duty = 0.5;  // 0.5のときにVu=0[V]
00243         pwm_upper[i] = pwm_lower[i] = 0;
00244         uvw[i].mode = 0;
00245     }
00246     pwmUout();
00247 #if PWM_WAVEFORM == 1
00248     pwmVout();
00249     pwmWout();
00250 #endif
00251 }
00252 
00253 void stop_pwm(){
00254     unsigned char i; 
00255     for( i=0;i<3;i++ ){
00256         pwm_upper[i] = pwm_lower[i] = 0;
00257         uvw[i].mode = 0;
00258         pwm[i].detach();
00259     }
00260 }