NUCLEOのキットを使ったルーレット
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) }