UVW 3 phases Brushless DC motor control

Dependencies:   QEI mbed-rtos mbed

Fork of BLDCmotor by manabu kosaka

main.cpp

Committer:
kosakaLab
Date:
2013-09-07
Revision:
17:1ac855d69c78
Parent:
15:427f5ae8e957

File content as of revision 17:1ac855d69c78:

//  UVW three phases Blushless DC motor control program using 3 H-bridge driver (ex. TA7291P) and incremental rotary encoder with A, B phase.
//      ver. 130903 by Kosaka lab.
#include "mbed.h"
#include "rtos.h"

#include "fast_math.h"
#include "controller.h"
#include "UVWpwm.h"


Serial pc2(USBTX, USBRX);        // Display on tera term in PC 
LocalFileSystem local("mbedUSBdrive"); // save data to mbed USB disk drive in PC
//Semaphore semaphore1(1);      // wait and release to protect memories and so on
//Mutex stdio_mutex;            // wait and release to protect memories and so on
Ticker TickerTimerTS0;          // Timer interrupt using TIMER3, TS<0.001 is OK. Priority is higher than rtosTimer.
unsigned char   fTimerTS2ON=0, fTimerTS3ON=0, fTimerTS4ON=0;  // ON/OFF flag for timerTS2, 3, 4.

extern "C" void mbed_reset();

void CallTimerTS2(void const *argument) {   // make sampling time TS3 timer (priority 3: precision 4ms)
    int ms;
    unsigned long c;
    while (true) {
        c = _count;
        if( fTimerTS2ON ){
            timerTS2();  // timerTS2() is called every TS2[s].
        }
        if( (ms=(int)(TS2*1000-(_count-c)*TS0*1000))<=0 ){    ms=1;}
        Thread::wait(ms);
    }
}
void CallTimerTS3(void const *argument) {   // make sampling time TS3 timer (priority 3: precision 4ms)
    int ms;
    unsigned long c;
    while (true) {
        c = _count;
        if( fTimerTS3ON ){
            timerTS3();  // timerTS3() is called every TS3[s].
        }
        if( (ms=(int)(TS3*1000-(_count-c)*TS0*1000))<=0 ){    ms=1;}
        Thread::wait(ms);
    }
}

void CallTimerTS4(void const *argument) {   // make sampling time TS4 timer (priority 4: precision 4ms)
    int ms;
    unsigned long c;
    while (true) {
        c = _count;
        if( fTimerTS4ON ){
            timerTS4();  // timerTS4() is called every TS4[s].
        }
        if( (ms=(int)(TS4*1000-(_count-c)*TS0*1000))<=0 ){    ms=1;}
        Thread::wait(ms);
    }
}

//void stop_fprintf(){ // emergencyStop if fprintf keep busy for 3 secons
//    fclose(fp);
//    pc2.printf("error: fprintf was in hung-up!");
//}

//#define OLD
int main(){
    unsigned short  i, i2=0;
    FILE *fp = fopen("/mbedUSBdrive/data.csv", "w");    // save data to PC
//    char chr[100];
    RtosTimer RtosTimerTS1(timerTS1);  // RtosTimer priority is osPriorityAboveNormal, just one above main()
    Thread ThreadTimerTS3(CallTimerTS3,NULL,osPriorityBelowNormal);
    Thread ThreadTimerTS4(CallTimerTS4,NULL,osPriorityLow);
// Priority of Thread (RtosTimer is osPriorityAboveNormal)
//  osPriorityIdle          = -3,          ///< priority: idle (lowest)--> then, mbed ERROR!!
//  osPriorityLow           = -2,          ///< priority: low
//  osPriorityBelowNormal   = -1,          ///< priority: below normal
//  osPriorityNormal        =  0,          ///< priority: normal (default)
//  osPriorityAboveNormal   = +1,          ///< priority: above normal
//  osPriorityHigh          = +2,          ///< priority: high 
//  osPriorityRealtime      = +3,          ///< priority: realtime (highest)
//  osPriorityError         =  0x84        ///< system cannot determine priority or thread has illegal priority

    // 指令速度
//    float  w_ref_req[2] = {20* 2*PI, 40* 2*PI};        // [rad/s](第2要素は指令速度急変後の指令速度)
    float  w_ref_req[2] = {5* 2*PI, 10* 2*PI};        // [rad/s](第2要素は指令速度急変後の指令速度)
    // 指令dq電流位相
//    float  beta_ref = 30*PI/180;   // [rad], 電流位相指令βを30度に
    float  beta_ref = 35*PI/180;   // [rad], 電流位相指令βを30度に
    float  tan_beta_ref1;
    float  tan_beta_ref2,tan_beta_ref;
    float  t;   // current time
    extern void    velocity_loop();

//    start_timers(1); // start multi-timers, sampling times are TS0, TS1, TS2, TS3, TS4.

    // IPMSMの機器定数等の設定, 制御器の初期化
    init_parameters();
    p.th[0] = 2*PI/3;   //θの初期値

//  p.Lq0 = p.Ld;   // SPMSMの場合
//  p.phi = 0;      // SynRMの場合

//    w_ref=p.w;          // 速度指令[rad/s]
    tan_beta_ref1 = tan(beta_ref);           // tan30°を計算
    tan_beta_ref2 = tan(beta_ref-30*PI/180); // tan0°を計算
    tan_beta_ref = tan_beta_ref1;            // βの指令値をtan30°に
    // シミュレーション開始
    pc2.printf("Simulation start!!\r\n");
#ifndef OLD
    // start control (ON)
    start_pwm();
    TickerTimerTS0.attach(&timerTS0, TS0 ); // Sampling period[s] of i_controller
    RtosTimerTS1.start((unsigned int)(TS1*1000.));   // Sampling period[ms] of th controller
    fTimerTS3ON = 1;    // timerTS3 start
    fTimerTS4ON = 1;    // timerTS3 start
#endif
    
    // set th by moving rotor to th=zero.
    f_find_origin=1;    // 回転角原点復帰フラグをセット
    while( (t = _count*TS0) < TMAX_FIND_ORIGIN ){  // TMAX秒経過するまで制御実行
        if     (t<1)    p.th_const =  0*2*PI*t*1;       // Set theta with constant angular velosity
        else if(t<3)    p.th_const =  9*2*PI*t*1;       // Set theta with constant angular velosity
        else if(t<5)    p.th_const = 15*2*PI*t*1;       // Set theta with constant angular velosity
        else if(t<TMAX_FIND_ORIGIN-2)
                        p.th_const =  9*2*PI*t*1;       // Set theta with constant angular velosity
        else            p.th_const =  0*2*PI*t*1;       // Set theta with constant angular velosity
#ifdef OLD
        timerTS0();
#endif
        Thread::wait(1);
    }
    // IPMSMの機器定数等の設定, 制御器の初期化
    init_parameters();
    f_find_origin=0;

#ifndef OLD
    TickerTimerTS0.detach(); // timer interrupt stop
    // start control (ON)
    TickerTimerTS0.attach(&timerTS0, TS0 ); // Sampling period[s] of i_controller
    RtosTimerTS1.start((unsigned int)(TS1*1000.));   // Sampling period[ms] of th controller
#endif

    while( (t = _count*TS0-TMAX_FIND_ORIGIN) < TMAX ){
//        debug_p24 = 1;

        // 電流位相(dq軸電流)を変化させるベクトル制御
        if( t>=0.15 && t<0.19 ){  // 0.15~0.19秒の間に
            if( tan_beta_ref>tan_beta_ref2 ){ // βの指令値が0度以上のとき
                tan_beta_ref=tan_beta_ref-0.002;  // 指令値を小さくする
            }
        }else{                   // 0.15~0.19秒の間でないときに
            if( tan_beta_ref<tan_beta_ref1){ // βの指令値が30度以下のとき
                tan_beta_ref=tan_beta_ref+0.002;  // 指令値を大きくする
            }
        }
        // 目標電流位相をメインルーチンから速度制御メインループへ渡す。
        vl.tan_beta_ref = tan_beta_ref;

#if 0
        // 速度急変
        if( 0.26<=t && t<0.3 ){
            vl.w_ref=w_ref_req[1];   // 目標速度をメインルーチンから速度制御メインループへ渡す。
        }else{
            vl.w_ref=w_ref_req[0];
        }
#else
        vl.w_ref=0.999*vl.w_ref + (1-0.999)*w_ref_req[0];
#endif
#ifdef SIMULATION
        // 負荷トルク急変
        if( t<0.4 ){
            p.TL = 1;
        }else{
            p.TL = 2;
        }
#endif

#ifdef OLD
        if( (++i2)>=(int)(TS1/TS0) ){  i2=0;
            timerTS1(&j);   //velocity_loop();    // 速度制御メインループ(w_ref&beta_ref to idq_ref)
        }
#endif

#ifdef OLD
        timerTS0();
        //current_loop(); // 電流制御マイナーループ(idq_ref to vuvw)
        //vuvw2pwm();     // vuvw to pwm
        //sim_motor();    // IPM, dq座標
#endif

//        if( (ms=(int)(TS1*1000-(_count-c)*TS0*1000))<=0 ){    ms=1;}// ms=TS0
//        debug_p24 = 0;
        Thread::wait(1);         // 1ms待つ
    }
//pc2.printf("\r\n^0^ 2\r\n");
    // stop timers (OFF)
    stop_pwm();
    TickerTimerTS0.detach(); // timer interrupt stop
    RtosTimerTS1.stop();    // rtos timer stop
//    Thread::wait(1000); // wait till timerTS3 completed
    fTimerTS3ON=0;//ThreadTimerTS3.terminate();   // 
    fTimerTS4ON=0;//ThreadTimerTS4.terminate();   // 
//pc2.printf("\r\n^0^ 0\r\n\r\n");

    // save data to mbed USB drive
//    if ( NULL == (fp = fopen( "/mbedUSBdrive/data.csv", "w" )) ){   error( "" );} // save data to PC
//pc2.printf("\r\n^0^ %d\r\n\r\n",_count_data);
//    emergencyStop.attach(&stop_fprintf, 0.001); // emergencyStop if fprintf keep busy for 3 secons
    for(i=0;i<_count_data;i++){
//pc2.printf("%d: ",i);
//pc2.printf("%f, %f, %f, %f, %f\r\n", 
//        data[i][0],data[i][1],data[i][2],data[i][3],data[i][4]);  // save data to PC (para, y, time, u)
//        sprintf(&chr[0],"Temperature: f ºC\r\n");//,data[i][0]);
//        sprintf(&chr[0],"%d, ", data[i][1]);
//        fprintf(fp,&chr[0]); 
//               fprintf( fp, ", ");
//       fprintf( fp, "%d, ", data[i][1]*10000);
//       fprintf( fp, "\r\n");
//
//        pc2.printf("%f, %f, %f, %f, %f\r\n", 
//        fprintf( fp, "%f, %f, %f, %f, %f\r\n", 
//        data[i][0],data[i][1],data[i][2],data[i][3],data[i][4]);  // save data to PC (para, y, time, u)
//
//        wait(0.1);
//        Thread::wait(100);
    }
//pc2.printf("\r\n^0^ 2\r\n\r\n");
    fclose( fp );               // release mbed USB drive
    
    Thread::wait(100);
    pc2.printf("Control completed!!\r\n\r\n");
}