ロータリーエンコーダーでステッピングモーターを回す

ロータリーエンコーダーの回転をステッピングモーター回転用にLED表示をして試したので、それをSTPモーターにつないでみます。

ロータリーエンコーダーの回転をステッピングモーターへ

ロータリーエンコーダーの回転をステッピングモーターへ

 

Rエンコーダーの回転をステッピングモーター回転用にLED表示をして試したので、それをつないでみます。
単にLEDに出力するところをステッピングモーターにつなぎ変えるだけです。

1-1相励磁、2-2相励磁で回してみましょう。

 

1-1相励磁 駆動 です。

Pモーター相 x_ y_
LED P17 P16 P15 P14
SPcnt=0
回転

回転
SPcnt=1
SPcnt=2
SPcnt=3

 

STPモーターを回す場合には IOの出力をLEDから STPモーターに変えればよいだけです。

 

回路図

 

 

すでに回路があるので前回のLED点灯のものとIOピンが違いますが、もちろんLED点灯のピンをドライバ入力へつなぎ代えてもOKです。

 

プログラム

Rエンコーダー SPモーター用1相駆動

 

FQ_adv_Enc_SPmtr1_1


 
/* ロータリーエンコーダーの回転判別 
  STPモーター回転 & Rエンコーダー値 
*/

#include<3664.h>
#include"myfunc.h"

#define H8_3664

unsigned char ft;       //記憶値
unsigned char cnt=0;    //カウンタ
int SPcnt=0;


void SPmtr(){

  if(SPcnt>3) SPcnt=0;
  else if(SPcnt<0) SPcnt=3;
      
      //1-1相
 switch(SPcnt){

       case 0:   IO.PDR8.BIT.B4=1;  /* 0001 0010  */ 
                 IO.PDR8.BIT.B3=0;
                 IO.PDR8.BIT.B2=0;
                 IO.PDR8.BIT.B1=0;
                  break; 
        case 1:  IO.PDR8.BIT.B4=0;  /* 0001 0010  */ 
                 IO.PDR8.BIT.B3=0;
                 IO.PDR8.BIT.B2=1;
                 IO.PDR8.BIT.B1=0;
                  break;
        case 2:  IO.PDR8.BIT.B4=0;  /* 0001 0010  */ 
                 IO.PDR8.BIT.B3=1;
                 IO.PDR8.BIT.B2=0;
                 IO.PDR8.BIT.B1=0;
                  break;
        case 3:  IO.PDR8.BIT.B4=0;  /* 0001 0010  */ 
                 IO.PDR8.BIT.B3=0;
                 IO.PDR8.BIT.B2=0;
                 IO.PDR8.BIT.B1=1;
                  break;
    }
}



unsigned char fD(unsigned char ft0,unsigned char ft1){
    /* 回転方向 判別式関数    引数 ft0: 1つ前の状態値 */
    /*                ft1: 現在地     */
    /*                         返値 (01=)1 or (10=)2 */


   unsigned char D;
       
   ft = ft1;                /* ftに保存し 現在値とする */
                            /* ft と ft0 は 別変数 */                
  
   ft0 = ft0 << 1  ;     /* 1つ前の状態値 をビットシフト */
   ft0 = ft0 &  3  ;      // 0000 0011 でマスク(AND)し、下位2ビットだけ取り出す
   

   ft1 = ft1 &  3  ;      // 0000 0011 でマスク(AND)、下位2ビットだけ取り出す
   
   D =  (ft0 + ft1) &  3 ; //2つを+し判別式の結果、マスク

   return(D);   
}


void int_timerv(void){
                                
  unsigned char pb;     //回転判別式 値 
  unsigned char PD;     //Renc現在値
    

    PD=IO.PDR8.BYTE >> 6;       //Renc現在値 読み取り

            /* 記憶値(ft) と 現在値(PD)=Rencのビット状態(IO.PDR8.BYTE) が違う*/
    if(ft !=  PD){              //   → 回転した  

        pb = fD(ft,PD);            //回転判別式

        //回転方向によって、LEDでお知らせ#0,#1&カウンタ累積
        if(pb>=2){      //左回転のとき
 
            cnt++;
            SPcnt++;
            SPmtr();
 
             
        }else{          //右回転のとき

            cnt--;
            SPcnt--;
            SPmtr();            

            
        }   
    }                                             

  TV.TCSRV.BIT.CMFB = 0;
}


void main(void){


     DI;

    IO.PCR8=0x3F;       /* Bit0,1だけは0:入力 他は全て1にセットし出力に設定 0011 1111 */
    IO.PCR1=0xFF;

//                              /*タイマーV 約2msごとに割り込み */

TV.TCRV1.BYTE=0x01; // (0000  0001)
TV.TCRV0.BYTE=0x93; //(1001 0011) 1/128 125kHz)
TV.TCORB=250; //500kHz(2ms)


    ft= IO.PDR8.BYTE >> 6;     /* 初期化 :  現在値をグローバル変数に保存 */
    
    LCD_init( 16 );  
    

     EI;
     

  while(1) {
            //LCD表示
    LCD_disp("cnt=",1);
      LCD_dataout(cnt);

    LCD_disp("SPcnt=",2);      
      LCD_dataout(SPcnt);
  
  }
  

}

       

 

LEDへの出力部分をSTPモーターに代えただけです。

IOをP81~P84へ
   IO.PDR8.BIT.B4
   IO.PDR8.BIT.B3
   IO.PDR8.BIT.B2
   IO.PDR8.BIT.B1

同時に LCDに変数を表示させています。

 

2相駆動にする

続いて 2-2相駆動に変更します。少しだけ変更するだけです。

 

各IOのところの一つを 0→1 に変えるだけです。同時に毎回どれか2ピンに通電します。

 

Rエンコーダー SPモーター用2相駆動 R2:SP1

FQ_adv_Enc_SPmtr2_2



/* ロータリーエンコーダーの回転判別 
  Rエンコーダー値 & SP回転   2-2相
       1  : 2
   
*/

#include<3664.h>
#include"myfunc.h"

#define H8_3664

unsigned char ft;       //記憶値
unsigned char cnt=0;    //カウンタ
int SPcnt=0;


void SPmtr(){

  if(SPcnt>6) SPcnt=0;
  else if(SPcnt<0) SPcnt=6;
  
            //R:2:SP:1 2-2相
 switch(SPcnt){

        case 0:  IO.PDR8.BIT.B4=1;  /*  */ 
                 IO.PDR8.BIT.B3=0;
                 IO.PDR8.BIT.B2=0;
                 IO.PDR8.BIT.B1=1;
                  break; 
        case 2:  IO.PDR8.BIT.B4=1;  /*   */ 
                 IO.PDR8.BIT.B3=0;
                 IO.PDR8.BIT.B2=1;
                 IO.PDR8.BIT.B1=0;
                  break;
        case 4:  IO.PDR8.BIT.B4=0;  /* */ 
                 IO.PDR8.BIT.B3=1;
                 IO.PDR8.BIT.B2=1;
                 IO.PDR8.BIT.B1=0;
                  break;
        case 6:  IO.PDR8.BIT.B4=0;  /*  */ 
                 IO.PDR8.BIT.B3=1;
                 IO.PDR8.BIT.B2=0;
                 IO.PDR8.BIT.B1=1;
                  break;
    }
}



unsigned char fD(unsigned char ft0,unsigned char ft1){
    /* 回転方向 判別式関数    引数 ft0: 1つ前の状態値 */
    /*                ft1: 現在地     */
    /*                         返値 (01=)1 or (10=)2 */


   unsigned char D;
       
   ft = ft1;                /* ftに保存し 現在値とする */
                            /* ft と ft0 は 別変数 */                
  
   ft0 = ft0 << 1  ;     /* 1つ前の状態値 をビットシフト */
   ft0 = ft0 &  3  ;      // 0000 0011 でマスク(AND)し、下位2ビットだけ取り出す
   

   ft1 = ft1 &  3  ;      // 0000 0011 でマスク(AND)、下位2ビットだけ取り出す
   
   D =  (ft0 + ft1) &  3 ; //2つを+し判別式の結果、マスク

   return(D);   
}


void int_timerv(void){
                                
  unsigned char pb;     //回転判別式 値 
  unsigned char PD;     //Renc現在値
    

    PD=IO.PDR8.BYTE >> 6;       //Renc現在値 読み取り

            /* 記憶値(ft) と 現在値(PD)=Rencのビット状態(IO.PDR8.BYTE) が違う*/
    if(ft !=  PD){              //   → 回転した  

        pb = fD(ft,PD);            //回転判別式

        //回転方向によって、LEDでお知らせ#0,#1&カウンタ累積
        if(pb>=2){      //左回転のとき
 
            cnt++;
            SPcnt++;
            SPmtr();
 
             
        }else{          //右回転のとき

            cnt--;
            SPcnt--;
            SPmtr();            

            
        }   
    }                                             

  TV.TCSRV.BIT.CMFB = 0;
}


void main(void){


     DI;

    IO.PCR8=0x3F;       /* Bit0,1だけは0:入力 他は全て1にセットし出力に設定 0011 1111 */
    IO.PCR1=0xFF;

//                              /*タイマーV 約2msごとに割り込み */

TV.TCRV1.BYTE=0x01; // (0000  0001)
TV.TCRV0.BYTE=0x93; //(1001 0011) 1/128 125kHz)
TV.TCORB=250; //500kHz(2ms)


    ft= IO.PDR8.BYTE >> 6;     /* 初期化 :  現在値をグローバル変数に保存 */
    
    LCD_init( 16 );  
    

     EI;
     

  while(1) {
            //LCD表示
    LCD_disp("cnt=",1);
      LCD_dataout(cnt);

    LCD_disp("SPcnt=",2);
      LCD_dataout(SPcnt);

  }


}

       

 

2相励磁
STPモーター相 x_ y_ - -
SPモーター P84 P83 P82 P81 - -
SPcnt=0
回転

回転
SPcnt=1
SPcnt=2
SPcnt=3

 

case 0:
   IO.PDR8.BIT.B4=1;
   IO.PDR8.BIT.B3=0;
   IO.PDR8.BIT.B2=0;
   IO.PDR8.BIT.B1=1 
      ・
      ・
IO出力部分を少しだけ変えるだけです。

 

このようにIO部分を変更して2相駆動にしています。
また、今度は回転数をよりあわせるために、Rエンコーダー2ステップ回転で STPモーター1ステップ回転にしています。

 

そこは、

 if(SPcnt>6)  SPcnt=0;
 else if(SPcnt<0)  SPcnt=6;

caseを2 とびにしています。

 

実行

Rエンコーダーの回転にあわせて回るので、速く回すほどSTPモーターも速く回転します。

 

1相駆動では Rエンコーダー 1ステップ回転で STPモーターも1ステップ回ります。
1周のステップ数が違うので、Rエンコーダー半回転でSPモーターが1回転ぐらいになります。
あまり速く回すとSTPモーターが脱調してついていけません。

 

2相駆動にすると、力強くまわります。ついでに、Rエンコーダー2ステップでSPモーターが1ステップにしています。

 

Rエンコーダの回転にあわせてSTPモーターを回すという方法でした。

この方法ではパルスのON,OFF時間が手で回した速度によるため、SPモーターの回り方、トルクが操作によって変わることになります。


SPモーター駆動関数void SPmtr() で 各ピン出力のあと ホールド時間を設けるなどしての工夫、変更が必要になるでしょう。

 

 

 

スポンサーリンク
  • facebook
  • twtter
  • google+
  • hatena