UVW 3 phases Brushless DC motor control
Dependencies: QEI mbed-rtos mbed
Fork of BLDCmotor by
UVWpwm.cpp
- Committer:
- kosakaLab
- Date:
- 2013-09-03
- Revision:
- 15:427f5ae8e957
- Parent:
- 13:791e20f1af43
File content as of revision 15:427f5ae8e957:
#include "mbed.h" #include "controller.h" #include "UVWpwm.h" // PWM発生用UVWpwm.cppの変数や定数の定義 #define DEADTIME_US (unsigned long)(DEADTIME*1000000) // [us], デッドタイム Timeout pwm[3]; // タイムアウト関数の宣言(ある時間経過後に関数コールする) // デジタル信号を出力するポートupperとlowerをU, V, W相について設定 DigitalOut pwm_upper[] = {(U_UPPER_PORT), (V_UPPER_PORT),(W_UPPER_PORT)}; DigitalOut pwm_lower[] = {(U_LOWER_PORT), (V_LOWER_PORT),(W_LOWER_PORT)}; pwm_parameters uvw[3]; // UVW相pwm用の定数、変数宣言 // U, V相シャント抵抗の両端の電圧のアナログ入力名の設定, *3.3[V] AnalogIn VshuntR_Uplus( R_SHUNT_UP_PORT); // *3.3[V], U相+側アナログ入力 AnalogIn VshuntR_Uminus(R_SHUNT_UM_PORT); // *3.3[V], U相-側アナログ入力 AnalogIn VshuntR_Vplus( R_SHUNT_VP_PORT); // *3.3[V], V相+側アナログ入力 AnalogIn VshuntR_Vminus(R_SHUNT_VM_PORT); // *3.3[V], V相-側アナログ入力 // 関数配列: NG //void (*pwmUVWout[])(int) = {pwmout,pwmout,pwmout}; // pwmUVWout[i](i); void pwmVout(), pwmWout(); #if PWM_WAVEFORM==0 // 0: saw tooth wave comparison void pwmUout() { // タイムアウト関数でU相PWMを発生する関数 unsigned char i=0; // i=0のときU相 uvw[i].mode += 1; // チョッピングのオンオフを決定するモードを1増やす if( uvw[i].mode==1 ){ // モードが1のとき、Tonの状態をつくる pwm_upper[i] = 1; // 上アームUuをオン pwm_lower[i] = 0; // 下アームUdをオフ // モード1の時間幅 T1 = Ton-Tdt を計算 uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US; // 時間幅が小さいときはTMINにする if( uvw[i].upper_us < TMIN ){ uvw[i].upper_us=TMIN;} // T1[μs]経過してからタイムアウトでこの関数自身をコール pwm[i].attach_us(&pwmUout, uvw[i].upper_us); // モード3の時間幅 T3=Toff-Tdt=Tpwm-(T1+Tdt)-Tdtを計算 uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // 時間幅が小さいときはTMINにする if( uvw[i].lower_us < TMIN ){ uvw[i].lower_us=TMIN;} pwmVout(); pwmWout(); }else if( uvw[i].mode==2 ){ // モードが2のとき、デッドタイムをつくる // Tdt[μs]経過してからタイムアウトでこの関数自身をコール pwm[i].attach_us(&pwmUout, DEADTIME_US); #ifndef SIMULATION // シャント抵抗の両端の電圧を見てモータ電流を検出 p.iuvw[0] = (VshuntR_Uplus - VshuntR_Uminus)*3.3 /R_SHUNT; // iu [A] #endif pwm_upper[i] = 0; // 上アームUuをオフ pwm_lower[i] = 0; // 下アームUdをオフ }else if( uvw[i].mode==3 ){ // モードが3のとき、Toffの状態をつくる // T3[μs]経過してからタイムアウトでこの関数自身をコール pwm[i].attach_us(&pwmUout, uvw[i].lower_us); pwm_upper[i] = 0; // 上アームUuをオフ pwm_lower[i] = 1; // 下アームUdをオン }else{ // モードが4のとき、デッドタイムをつくる // Tdt[μs]経過してからタイムアウトでこの関数自身をコール pwm[i].attach_us(&pwmUout, DEADTIME_US); pwm_upper[i] = 0; // 上アームUuをオフ pwm_lower[i] = 0; // 下アームUdをオフ uvw[i].mode = 0; // チョッピングのオンオフを決定するモードを } // 0にする } void pwmVout() { // pwm out using timer unsigned char i=1; uvw[i].mode += 1; if( uvw[i].mode==1 ){ pwm_upper[i] = 1; pwm_lower[i] = 0; uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US; // ON time of Uupper if( uvw[i].upper_us < TMIN ){ uvw[i].upper_us=TMIN;} pwm[i].attach_us(&pwmVout, uvw[i].upper_us); // setup pwmU to call pwmUout after t [us] uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // ON time of Ulower if( uvw[i].lower_us < TMIN ){ uvw[i].lower_us=TMIN;} }else if( uvw[i].mode==2 ){ pwm[i].attach_us(&pwmVout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] #ifndef SIMULATION // シャント抵抗の両端の電圧を見てモータ電流を検出 p.iuvw[1] = (VshuntR_Vplus - VshuntR_Vminus)*3.3 /R_SHUNT; // iv [A] #endif pwm_upper[i] = 0; pwm_lower[i] = 0; }else if( uvw[i].mode==3 ){ pwm[i].attach_us(&pwmVout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] pwm_upper[i] = 0; pwm_lower[i] = 1; }else{// if( u.mode==4 ){ // pwm[i].attach_us(&pwmVout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] pwm_upper[i] = 0; pwm_lower[i] = 0; uvw[i].mode = 0; } } void pwmWout() { // pwm out using timer unsigned char i=2; uvw[i].mode += 1; if( uvw[i].mode==1 ){ pwm_upper[i] = 1; pwm_lower[i] = 0; uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US; // ON time of Uupper if( uvw[i].upper_us < TMIN ){ uvw[i].upper_us=TMIN;} pwm[i].attach_us(&pwmWout, uvw[i].upper_us); // setup pwmU to call pwmUout after t [us] uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // ON time of Ulower if( uvw[i].lower_us < TMIN ){ uvw[i].lower_us=TMIN;} }else if( uvw[i].mode==2 ){ pwm[i].attach_us(&pwmWout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] pwm_upper[i] = 0; pwm_lower[i] = 0; }else if( uvw[i].mode==3 ){ pwm[i].attach_us(&pwmWout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] pwm_upper[i] = 0; pwm_lower[i] = 1; }else{// if( u.mode==4 ){ // pwm[i].attach_us(&pwmWout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] pwm_upper[i] = 0; pwm_lower[i] = 0; uvw[i].mode = 0; } } #elif PWM_WAVEFORM==1 // 1: triangler wave comparison void pwmUout() { // タイムアウト関数でU相PWMを発生する関数 unsigned char i=0; // i=0のときU相 uvw[i].mode += 1; // チョッピングのオンオフを決定するモードを1増やす if( uvw[i].mode==1 ){ // モードが1のとき、Toffの状態をつくる pwm_upper[i] = 0; // 上アームUuをオフ pwm_lower[i] = 1; // 下アームUdをオン // モード3の時間幅 T3 = Ton-Tdt を計算 uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US; // モード1,5の時間幅 T1=(Toff-Tdt)/2=(Tpwm-T3-2Tdt)/2を計算 uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; uvw[i].lower_us /= 2; // 時間幅が小さいときはTMINにする if( uvw[i].lower_us < TMIN ){ uvw[i].lower_us=TMIN;} // T1[μs]経過してからタイムアウトでこの関数自身をコール pwm[i].attach_us(&pwmUout, uvw[i].lower_us); // 時間幅が小さいときはTMINにする if( uvw[i].upper_us < TMIN ){ uvw[i].upper_us=TMIN;} }else if( uvw[i].mode==2 ){ // モードが2のとき、デッドタイムをつくる // Tdt[μs]経過してからタイムアウトでこの関数自身をコール pwm[i].attach_us(&pwmUout, DEADTIME_US); pwm_upper[i] = 0; // 上アームUuをオフ pwm_lower[i] = 0; // 下アームUdをオフ }else if( uvw[i].mode==3 ){ // モードが3のとき、Tonの状態をつくる // T3[μs]経過してからタイムアウトでこの関数自身をコール pwm[i].attach_us(&pwmUout, uvw[i].upper_us); pwm_upper[i] = 1; // 上アームUuをオン pwm_lower[i] = 0; // 下アームUdをオフ }else if( uvw[i].mode==4 ){ // モードが4のとき、デッドタイムをつくる // Tdt[μs]経過してからタイムアウトでこの関数自身をコール pwm[i].attach_us(&pwmUout, DEADTIME_US); #ifndef SIMULATION // シャント抵抗の両端の電圧を見てモータ電流を検出 p.iuvw[0] = (VshuntR_Uplus - VshuntR_Uminus)*3.3 /R_SHUNT; // iu [A] #endif pwm_upper[i] = 0; // 上アームUuをオフ pwm_lower[i] = 0; // 下アームUdをオフ }else{ // モードが5のとき、Toffの状態をつくる // T5(=T1)[μs]経過してからタイムアウトでこの関数自身をコール pwm[i].attach_us(&pwmUout, uvw[i].lower_us); pwm_upper[i] = 0; // 上アームUuをオフ pwm_lower[i] = 1; // 下アームUdをオン uvw[i].mode = 0; // チョッピングのオンオフを決定するモードを } // 0にする } void pwmVout() { // pwm out using timer unsigned char i=1; uvw[i].mode += 1; if( uvw[i].mode==1 ){ uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US; // ON time of Uupper uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // ON time of Ulower pwm_upper[i] = 0; pwm_lower[i] = 1; uvw[i].lower_us /= 2; if( uvw[i].lower_us < TMIN ){ uvw[i].lower_us=TMIN;} pwm[i].attach_us(&pwmVout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] if( uvw[i].upper_us < TMIN ){ uvw[i].upper_us=TMIN;} }else if( uvw[i].mode==2 ){ pwm[i].attach_us(&pwmVout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] pwm_upper[i] = 0; pwm_lower[i] = 0; }else if( uvw[i].mode==3 ){ pwm[i].attach_us(&pwmVout, uvw[i].upper_us); // setup pwmU to call pwmUout after t [us] pwm_upper[i] = 1; pwm_lower[i] = 0; }else if( uvw[i].mode==4 ){ pwm[i].attach_us(&pwmVout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] #ifndef SIMULATION // シャント抵抗の両端の電圧を見てモータ電流を検出 p.iuvw[1] = (VshuntR_Vplus - VshuntR_Vminus)*3.3 /R_SHUNT; // iv [A] #endif pwm_upper[i] = 0; pwm_lower[i] = 0; }else{// if( uvw[i].mode==5 ){ pwm[i].attach_us(&pwmVout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] pwm_upper[i] = 0; pwm_lower[i] = 1; uvw[i].mode = 0; } } void pwmWout() { // pwm out using timer unsigned char i=2; uvw[i].mode += 1; if( uvw[i].mode==1 ){ uvw[i].upper_us = uvw[i].duty*1000000/PWM_FREQ - DEADTIME_US; // ON time of Uupper uvw[i].lower_us = 1000000/PWM_FREQ -uvw[i].upper_us - 2*DEADTIME_US; // ON time of Ulower pwm_upper[i] = 0; pwm_lower[i] = 1; uvw[i].lower_us /= 2; if( uvw[i].lower_us < TMIN ){ uvw[i].lower_us=TMIN;} pwm[i].attach_us(&pwmWout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] if( uvw[i].upper_us < TMIN ){ uvw[i].upper_us=TMIN;} }else if( uvw[i].mode==2 ){ pwm[i].attach_us(&pwmWout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] pwm_upper[i] = 0; pwm_lower[i] = 0; }else if( uvw[i].mode==3 ){ pwm[i].attach_us(&pwmWout, uvw[i].upper_us); // setup pwmU to call pwmUout after t [us] pwm_upper[i] = 1; pwm_lower[i] = 0; }else if( uvw[i].mode==4 ){ pwm[i].attach_us(&pwmWout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] pwm_upper[i] = 0; pwm_lower[i] = 0; }else{// if( uvw[i].mode==5 ){ pwm[i].attach_us(&pwmWout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] pwm_upper[i] = 0; pwm_lower[i] = 1; uvw[i].mode = 0; } } #endif void start_pwm(){ unsigned char i; for( i=0;i<3;i++ ){ uvw[i].duty = 0.5; // 0.5のときにVu=0[V] pwm_upper[i] = pwm_lower[i] = 0; uvw[i].mode = 0; } pwmUout(); #if PWM_WAVEFORM == 1 pwmVout(); pwmWout(); #endif } void stop_pwm(){ unsigned char i; for( i=0;i<3;i++ ){ pwm_upper[i] = pwm_lower[i] = 0; uvw[i].mode = 0; pwm[i].detach(); } }