NUCLEOのキットを使ったルーレット

Dependencies:   mbed-src

main.cpp

Committer:
motomiya
Date:
2016-03-22
Revision:
0:b8098a4ce012

File content as of revision 0:b8098a4ce012:

/*************************************************
"Nucleo_motor_control2"
Nucleo Pack
 マイコンボード NUCLEO-F302R8
 拡張ボード X-NUCLEO-IHM07M1
 モーター BR2804-1700KV-1
を使ったモーター制御の実験

アナログPWM版 ルーレット仕様
 Copyright(C) 2016 Columbus-seiki
 
 2016-02-22 Rev0

**************************************************/
#include "mbed.h"
#include "main.h"

#define POLE_PAIR 7//モーターの磁極対数
#define PERIOD_TIMER 0.005 //タイマー周期(S)
#define SINTBL_LENGTH 512 //sinTbl[]要素数
#define PERIOD_PWM 0.0002 //PWM周期(S) これ以下では ヒゲ がでる 
#define HALF_PWM  (PERIOD_PWM / 2) //PWM周期の真ん中 PERIOD_PWM÷2
#define DEG360 1024 //360°相当
#define DEG120 341 //120°
#define DEG240 682 //240°


//入出力ピンを定義
DigitalIn mybutton(USER_BUTTON);
Serial pc(PA_2, PA_3); //USB/COM パソコンの仮想シリアルポートへ。ここでは使いません
DigitalOut ld2(PB_13); //LD2 グリーンLED
DigitalOut d11(PB_2); //D11 パワボード赤LED

//pwm出力の定義
PwmOut pwmU(PA_8), pwmV(PA_9), pwmW(PA_10);//それぞれUH_PWM, VH_PWM, WH_PWM

//IOの定義
DigitalOut enableU(PC_10), enableV(PC_11), enableW(PC_12);//それぞれEnable_CH1-L6230, _CH2-, _CH3-

//アナログ入力の定義
AnalogIn ain(PB_1);//R42 POTENTIOPOTENTIOMETER
AnalogIn ainThrm(PC_2);// Temperature feedback

//タイマーの定義
Ticker myTimer;//繰返しタイマー

//変数
int preMybutton; //記憶
int enablePWM=0;//PWM開始と停止フラグ
//int scope[100];//モニター用バッファ
int count, loopCount=0; //カウンター
double outDuty=0 ,outU, outV, outW; //PWM出力デューティー
float theta, omega; //角度と角速度
int timePerRound=60; //1回転時間(S)

int sumThrm; //積算値
bool runRoulette=false;
int thetaMech=0; //機械(物理的な)モータ角度

/**********************************
    sin関数
    引数:最大1024=360°
    出力:最大512=1.0
***********************************/
int mySin(int angleNum)
{

    angleNum &= 0x3ff; //0x3ff=1023 でマスク
    if(angleNum >= 512)  //180~360°
        return -sinTbl[angleNum - 512];
    else                //0~180°
        return sinTbl[angleNum];
}


/**********************************
    タイマー割込み関数 5mS
***********************************/
void myTimerCallBack() //全相をONにする
{
    outDuty = 0.2; //最大1.0 出力電圧を調整します

    theta += omega; //増加分
    if(theta >= 1024) //360°オーバーフローを防止
        theta -= 1024;
    else if(theta <= -1024)
        theta += 1024;

    pwmU.pulsewidth(HALF_PWM + outDuty * mySin((int)theta & 0x3ff) / 512.0  * HALF_PWM);
    pwmV.pulsewidth(HALF_PWM + outDuty * mySin(((int)theta - DEG120) & 0x3ff) / 512.0  * HALF_PWM);
    pwmW.pulsewidth(HALF_PWM + outDuty * mySin(((int)theta - DEG240) & 0x3ff) / 512.0  * HALF_PWM);

    thetaMech += omega;  //増加分

    //サイクルカウンター処理(同期)
    count++;
    if( count == 100) {
        count = 0;
        loopCount = 1;  //loopの同期用 5mS X 100 = 0.5S
    }

}
/***********************************

************************************/
int main()
{

    //pwmデューティー 初期値
    outU = 0;
    outV = 0;
    outW = 0;

    //PWM設定
    enableU = 0;//PWM出力OFF. L6230PのENable端子です
    enableV = 0;
    enableW = 0;

    pwmU.period(PERIOD_PWM);//0.2mS 5KHz
    pwmV.period(PERIOD_PWM);
    pwmW.period(PERIOD_PWM);

    //タイマー設定
    myTimer.attach(&myTimerCallBack, PERIOD_TIMER);//5mS毎にmyTimerCallBack()がコールされます


    while(1) {
        //------ およそ一定周期の処理 -------
        if(loopCount != 0) {//5x100=0.5S
            loopCount = 0;

            ld2 = !ld2; //点滅
            d11 = !d11; //パワボード

            //ルーレット目標位置の作成用データ
            sumThrm += (float)ainThrm * 1000000; //積算

            //pc.printf("%f", ((float)(sumThrm & 0x1f) / 32.0  + 10) * 1024 * POLE_PAIR); 
        }

        //-------- 時間に関係しない処理 --------
        //PWM開始と停止
        if((int)mybutton != preMybutton) {//ボタンが押された。チャタリングを考慮していません
            preMybutton = (int)mybutton;//次に押されたときのために記憶

            if(mybutton == 0) {//押されたときだけ。 
                runRoulette = true; //enablePWM = ~enablePWM;//オルタネート
                thetaMech = 0;//機械角リセット
                //PWM開始
                enableU = 1;//PWM出力ON. L6230PのENable端子です
                enableV = 1;
                enableW = 1;
            }
        }

        //ルーレット停止位置
        if( thetaMech > ((float)(sumThrm & 0x1f) / 32.0F  + 5) * 1024 * POLE_PAIR)//
            runRoulette = false;
        //thetaMechが1024*POLE_PAIRで一回転. 5回転を追加. sumThrmの0~31を抽出


        //角速度に変換 ルーレットのスタートと停止
        if(runRoulette) { //回転
            timePerRound = 2;//速度指定(S/r)
            omega = PERIOD_TIMER * DEG360 * POLE_PAIR / timePerRound; 
        } else //停止
            omega = 0;

    }//END while(1)


}