UVW 3 phases Brushless DC motor control
Dependencies: QEI mbed-rtos mbed
Fork of DCmotor by
Diff: UVWpwm.cpp
- Revision:
- 13:791e20f1af43
- Parent:
- 12:a4b17bb682eb
--- a/UVWpwm.cpp Fri Dec 21 22:06:56 2012 +0000 +++ b/UVWpwm.cpp Sun Mar 03 09:09:34 2013 +0000 @@ -1,44 +1,65 @@ #include "mbed.h" #include "controller.h" -#include "UVWpwm.h" +#include "UVWpwm.h" // PWM発生用UVWpwm.cppの変数や定数の定義 + +#define DEADTIME_US (unsigned long)(DEADTIME*1000000) // [us], デッドタイム -#define DEADTIME_US (unsigned long)(DEADTIME*1000000) // [us], deadtime to be set between plus volt. to/from minus +Timeout pwm[3]; // タイムアウト関数の宣言(ある時間経過後に関数コールする) -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 の定数、変数 +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); #if PWM_WAVEFORM==0 // 0: saw tooth wave comparison -void pwmUout() { // pwm out using timer - unsigned char i=0; - 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 - pwm[i].attach_us(&pwmUout, 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 - }else if( uvw[i].mode==2 ){ - pwm[i].attach_us(&pwmUout, 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(&pwmUout, 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(&pwmUout, DEADTIME_US); // setup pwmU to call pwmUout after t [us] - pwm_upper[i] = 0; - pwm_lower[i] = 0; - uvw[i].mode = 0; - } +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;} + }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 @@ -48,10 +69,16 @@ 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 ){ @@ -73,8 +100,10 @@ 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; @@ -91,34 +120,49 @@ } } #elif PWM_WAVEFORM==1 // 1: triangler wave comparison -void pwmUout() { // pwm out using timer - unsigned char i=0; - 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; +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; - pwm[i].attach_us(&pwmUout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] - }else if( uvw[i].mode==2 ){ - pwm[i].attach_us(&pwmUout, 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(&pwmUout, 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(&pwmUout, 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(&pwmUout, uvw[i].lower_us); // setup pwmU to call pwmUout after t [us] - pwm_upper[i] = 0; - pwm_lower[i] = 1; - uvw[i].mode = 0; - } + // 時間幅が小さいときは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; @@ -129,7 +173,9 @@ 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; @@ -140,6 +186,10 @@ 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 ){ @@ -159,7 +209,9 @@ 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; @@ -185,7 +237,7 @@ void start_pwm(){ unsigned char i; for( i=0;i<3;i++ ){ - uvw[i].duty = 0.5; + uvw[i].duty = 0.5; // 0.5のときにVu=0[V] pwm_upper[i] = pwm_lower[i] = 0; uvw[i].mode = 0; }