PR

Arduinoでステッピングモーターを操作する

組み込みエンジニア
本記事はプロモーションが含まれています。

こんにちは、ENGかぴです。

ArduinoのDOを使用することでステッピングモーターを操作することができます。ステップごとにDOを切り替えて励磁パターンを生成することでステッピングモーターを時計/反時回りに回転させることができます。

本記事ではDO操作でステッピングモーターを回転させる方法とStepperライブラリを使用して回転させる方法で動作確認しています。

Arduinoスターターキットに付属していたステッピングモーター(28BYJ-48-W01)及びドライバー基板を接続して動作確認を行います。

Arduino UNO(以下Arduinoとします。)を対象とします。Arduinoのライブラリを使用して動作確認したことをまとめています。

Arduinoで学べるマイコンのソフト開発と標準ライブラリの使い方

ステッピングモーターを操作する

ステッピングモーターは回転数を制御するドライバーとセットで使用します。産業用でベルトコンベヤーや水量を調整する弁の開閉に使用されており用途は様々です。

ステッピングモーターの励磁方法は電流を増幅して励磁する電流型とドライバーに電圧値を与えてモーターの速度を調整する電圧型があります。

28BYJ-48-W01はユニポーラ方式で巻線に対して一方向の電流を流して起動する電流型です。モーターの巻線の電流により励磁しますが、電流をパターンを切り替えて回転磁界を発生させることで軸(ローター)を回転させる仕組みです。

PR: わからないを放置せず、あなたにあったスキルを身に着けるコツを教える テックジムPython入門講座の申込

モーターの起動方法

ユニポーラ方式での起動方法は、1相励磁、2相励磁、1-2相励磁による励磁によって起動します。これらの励磁方式の特徴について以下にまとめています。

励磁方式特徴
1相励磁(Full step)1相ずつ順に励磁していくため消費電流は少なくなります。ただし各相に切り替わる際に振動が発生しやすくなります。
2相励磁(Full step)2相ずつ切り替えるため出力トルクが大きくなりますが消費電流が増えます。1相励磁よりも振動が抑えられるため滑らかな動きとなる。
1-2相励磁(Half step)1励磁と2相励磁を交互に繰り返す方式。モーターのステップ角の分解能が基本ステップの1/2になりますが、2相励磁よりもさらに滑らかな動きとなる。
ステッピングモーターの励磁方式

本記事ではデータシートに記載されている励磁方式である1-2相励磁の方法でステッピングモーターを駆動します。

ステッピングモーターの特性
ステッピングモーターの特性

ステッピングモーターの1ステップの操作は1パルスの入力で行います。そのため周波数の単位でHzまたはppsで記載されています。

ステッピングモーターを起動する場合は特性曲線に従って起動することが推奨されます。モーターが停止している状態から急速な入力周波数で起動するとスルーイング特性から外れて軸が回転しない同期外れの問題が発生することがあります。

モーターを起動は効率よくトルクを取りながら高速回転に遷移させることが推奨されるためスルー領域内(赤線と青線内の領域)に特性が収まるようにステップ周波数を制御します。

スターティング特性はステップ数が入力パルスと1対1に対応して起動でき、最大のトルクが発生できる関係を示しています。

スルーイング特性はスターティング特性範囲以内で起動して同期回転しているモーターの入力パルスの周波数を徐々に増加した場合、スターティング特性以上の入力周波数に1対1に対応できる最大トルクと入力パルスの関係を示しています。

スルー領域は自起動領域から入力パルスの周波数を増加させるもしくは負荷トルクを増加させるとき、モーターが入力パルスと同期を保って応答できる領域です。

自起動領域は無負荷状態で、入力パルスに同期して自起動が可能な領域です。この領域から入力パルスの周波数をあげて起動することでトルクを高く得ながら高速回転に移ることができます。

28BYJ-48-W01のデータシートではMax starting frequencyが500Hz、Max response frequencyが1000ppsと記載されています。無負荷状態で500pps(2ms)で起動して周波数を上げる場合1000pps(1ms)程度までは安定に動作させることができます。負荷がある場合は高トルクで起動するために500pps以下の入力周波数で起動して徐々に入力周波数をあげて制御します。

PR:技術系の通信教育講座ならJTEX

励磁のパターンを生成する

引用:28BYJ48-W01のデータシート
引用:28BYJ48-W01のデータシート

28BYJ-48-W01のデータシートに記載されているステップ数による制御は1-2励磁方式です。ArduinoのDOを増幅した信号で励磁パターンを作ることで回転させることができます。データシートを引用して制御に必要な事項を中心に説明します。

5.4極の励磁で1相励磁と2相励磁を切り替えて励磁パターンを作ります。-記号はDOをLOW、記号がない場所についてはHIGHにします。1から8ステップのパターンをDOで制御することで回転磁界を生成しモーターを回転させます。ステップ数1~8をDOのパターンを切り替えて励磁する例は以下の通りとなります。

/* ステッピングモーターの励磁 */
bool StepMove(uint8_t no, bool posi){
  bool ret = false;

  switch(no){
    case 0: //0111
      digitalWrite(PIN_STP_IN4,LOW);
      digitalWrite(PIN_STP_IN3,HIGH);
      digitalWrite(PIN_STP_IN2,HIGH);
      digitalWrite(PIN_STP_IN1,HIGH);
      if(posi){
        ret = true;
      }
      break;
    case 1: //0011
      digitalWrite(PIN_STP_IN4,LOW);
      digitalWrite(PIN_STP_IN3,LOW);
      digitalWrite(PIN_STP_IN2,HIGH);
      digitalWrite(PIN_STP_IN1,HIGH); 
      break;    
    case 2: //1011
      digitalWrite(PIN_STP_IN4,HIGH);
      digitalWrite(PIN_STP_IN3,LOW);
      digitalWrite(PIN_STP_IN2,HIGH);
      digitalWrite(PIN_STP_IN1,HIGH);
      break;              
    case 3: //1001
      digitalWrite(PIN_STP_IN4,HIGH);
      digitalWrite(PIN_STP_IN3,LOW);
      digitalWrite(PIN_STP_IN2,LOW);
      digitalWrite(PIN_STP_IN1,HIGH);
      break;
    case 4: //1101
      digitalWrite(PIN_STP_IN4,HIGH);
      digitalWrite(PIN_STP_IN3,HIGH);
      digitalWrite(PIN_STP_IN2,LOW);
      digitalWrite(PIN_STP_IN1,HIGH);
      break;            
    case 5: //1100
      digitalWrite(PIN_STP_IN4,HIGH);
      digitalWrite(PIN_STP_IN3,HIGH);
      digitalWrite(PIN_STP_IN2,LOW);
      digitalWrite(PIN_STP_IN1,LOW);
      break;            
    case 6: //1110
      digitalWrite(PIN_STP_IN4,HIGH);
      digitalWrite(PIN_STP_IN3,HIGH);
      digitalWrite(PIN_STP_IN2,HIGH);
      digitalWrite(PIN_STP_IN1,LOW);
      break;
    case 7: //0110
      digitalWrite(PIN_STP_IN4,LOW);
      digitalWrite(PIN_STP_IN3,HIGH);
      digitalWrite(PIN_STP_IN2,HIGH);
      digitalWrite(PIN_STP_IN1,LOW);
      if(posi == false){
        ret = true;
      }
      break;                 
    }
    return ret;
}

以下の説明ではユーザーがステッピングモーターの軸側を見た時を基準にして回転方向を決めています。反時計回りの場合はステップ数1~8、時計回りの場合はステップ数8~1を1セットとします。

励磁パターンを切り替えるStepMove()関数を実装します。第1引数はステップの番号を指定します。反時計周りの場合は0から7の順で指定します。時計回りの場合は7から0の順で指定します。

第2引数は回転方向を指定します。true(1)を指定すると時計回りの励磁パターンでの最終ステップの判断します。

6.Frequency of light pull outはMax response frequencyに相当します。7.Max starting frequency(最大応答周波数)の間にスルー領域(モーターが入力信号に応答できる領域)があるためこの区間の範囲内でのパルス(周波数)を調整します。

stepfreq_p = 10000; //周波数の初期値  

if(posi){
    now_p = micros() - oldtime_p;
    if ( now_p >= stepfreq_p ){
      oldtime_p = micros();

      if( StepMove(7- mng_p.md++, true)){//励磁パターンの生成
        if(++mng_p.stepcnt >= 2 ){ //2セットを同一周波数で繰り返す
          posi = false;

          if(stepfreq_p <= 1000){
            stepfreq_p = 1000;
          }
          else{
            stepfreq_p -= 1000; //周波数の更新
          }
        }
        else{
          mng_p.md = 0;
        }
      }
    }
  }

初期値を10000us(100Hz)から励磁パターンを切り替えます。micros()関数で取得したus経過時間と前回の処理時間との差によって判定して処理を行います。差が比較値以上になった場合な励磁のパターンの切り替えを行います。差が10000の場合は10000us経過したことになるため100Hz毎の処理のタイミングになります。

メイン処理1周分の遅れが生じるため厳密に励磁のパターンを切り替える場合はdelayMicroseconds()関数でウェイトを置く方が良いこともあります。

セットが終了するごとに比較値を低くすることで、周波数を高くしていきます。例では2セット毎に比較値を変更しています。

モーター駆動時は自起動領域でトルクを多く得るため100ppsでスタートし最大で1000ppsまで周波数を高くしながら回転させています。

ステップ間隔を調整する比較値を低く設定(周波数が高い)すると脱調(同期外れ)を起こし軸が回転しなくなるため注意が必要です。

スポンサーリンク

ライブラリを使用する

Arduino環境では標準ライブラリでステッピングモーターを操作するStepperライブラリが実装されています。Stepperライブラリを使用するにあたって必要な事項について説明します。押さえておく必要がある項目は以下の3点です。

  1. 1分間の当たり回転数
  2. 励磁方式に対する1回転に必要なステップ数
  3. 回転に必要なステップ数(任意の値)

1.と2.は使用するモーターの仕様に合わせて指定します。28BYJ48-W01は励磁方式として1-2相励磁(Half step)が記載されておりステップ角が5.625/64(Step angle)になっています。これは1-2励磁方式の8ステップ(1セット)を8回(64÷8)繰り返すと5.625度回転します。

無負荷状態では最大で1ms(1000pps)でステップを切り替えることを考慮すると5.625度回転させるまでの経過時間は約64msになります。ギア比の1/64を考慮すると1周に必要な秒数は64ms×64=4096ms(約4秒)となり、1分当たりでは15回転となります。

1回転に必要なステップ数は、5.625度で64ステップ必要であることギア比が1/64であることから64×64=4096ステップになります。

Stepperライブラリは2相励磁対応なので4ステップが8回分で5.625/32となり、ギア比の1/64から32×64=2048ステップになります。

広告
PR:わからないを放置せず、あなたにあったスキルを身に着けるコツを教える テックジム 「書けるが先で、理解が後」を体験しよう!

ライブラリの初期化

#include <Stepper.h>

Stepper myStepper(2048, PIN_STP_IN1, PIN_STP_IN3, PIN_STP_IN2, PIN_STP_IN4);

void setup() {
  myStepper.setSpeed(15);
}

Stepperライブラリを使用するためにStepper.hをインクルードします。Stepperクラスの変数をmyStepper()でインスタンス化します。引数に使用するステッピングモーターの回転情報や励磁パターンを作るDOピンを指定します。

第1引数にステッピングモーターの1回転当たりのステップ数を指定します。28BYJ48-W01の1回転当たりのステップ数は2048になります。第2引数から第5引数までは励磁に使用するDOピンを指定します。

StepperライブラリではIN1からIN4の順でなく、IN1、IN3、IN2、IN4になるので注意が必要です。

StepperクラスのsetSpeed()関数で1分当たりの回転速度を指定します。28BYJ48-W01の1分当たりの回転数は無負荷状態で15回なので引数に15を指定しています。回転速度を遅くする場合は15以下の値を指定します。ステッピングモーターのスルー領域を超えるような速度を指定した場合、同期外れ(脱調)のため回転しなくなります。

広告

ステップ数を指定して回転させる

myStepper.step(512);  //時計回りの場合
myStepper.step(-512); //反時計回りの場合

Stepperクラスのstep()関数でステッピングモーターを操作するステップ数を指定します。引数にステップ数を指定します。28BYJ48-W01の場合2048を指定すると1回転します。正の値を指定すると時計回りに回転し、負の値を指定すると反時計回りに回転します。

例では90度回転させるため最大値の2048を4で割った512を指定しています。

Stepperライブラリでステッピングモーターを操作する場合、step()関数が処理を占有するためメイン処理1周の時間が長くなります。他の処理が遅延するので注意が必要です。

ライブラリの使用例

以下は、Stepperライブラリの使用例です。コンパイルして動作していますが、ライブラリの更新により動作しなくなることがあります。

#include <MsTimer2.h>
#include <Stepper.h>

#define PIN_STP_IN1 8
#define PIN_STP_IN2 9
#define PIN_STP_IN3 10
#define PIN_STP_IN4 11
#define PIN_DO1 4
#define PIN_DO2 5
#define PIN_DI1 6
#define PIN_DI2 7
#define TIME_OFF -1  //タイマーを使用しない場合
#define TIME_UP 0    //タイムアップ
#define LED_OFF 100
#define DI_MAX 2
#define DI_FILT_MAX 4  //DIフィルタのサンプリング数
#define TIME_FILTER_MAX 1  //ベースタイマカウント値
#define	CNT_INIT_MAX 10  //10ms×10 = 100ms

const int stepsPerRevolution = 2048; //1回転のステップ数

typedef struct{
  uint8_t wp;
  uint8_t buf[DI_MAX][DI_FILT_MAX];
  uint8_t di[DI_MAX];
}DIFILT_TYP;

Stepper myStepper(stepsPerRevolution, PIN_STP_IN1, PIN_STP_IN3, PIN_STP_IN2, PIN_STP_IN4);

bool posi;
bool neg;
DIFILT_TYP difilt;
int16_t timdifilt;   //DIフィルタ起動
uint8_t CntInit;	//初期化時のみ使用
int16_t timstepoff = TIME_OFF;

/*プロトタイプ宣言 */
void mainTimer(void);
void mainApp(void);
bool StepMove(uint8_t no, bool posi);
void DiFilter(void);

void setup() {

  Serial.begin(9600);

  myStepper.setSpeed(15); //速度の指定

  pinMode(PIN_DI1,INPUT_PULLUP);
  pinMode(PIN_DI2,INPUT_PULLUP);
  pinMode(PIN_DO1,OUTPUT);
  pinMode(PIN_DO2,OUTPUT);
  
  CntInit = CNT_INIT_MAX;
  while(CntInit > 0){  //0になるまでフィルタを実施
    DiFilter();         //DIフィルタ処理
    delay(10);     //10ms遅延させてDIフィルタ処理
    CntInit--;
    timdifilt = TIME_UP;
  }     

  MsTimer2::set(10, mainTimer); // 10ms period
  MsTimer2::start();
}

void loop() {

  mainApp();
}
/* タイマ管理 */
void mainTimer(void){

  if( timdifilt > TIME_UP ){
    --timdifilt;
  }
  
  if( timstepoff > TIME_UP ){
    --timstepoff;
  }

  //ステッピングモーターの操作中は
  //処理が占有されるため割り込み内でDIフィルタを処理する
   DiFilter();
}

/* メイン処理 */
void mainApp(void){

  if(difilt.di[0] == LOW ){
    if( neg == false){
      Serial.println("nown");
      neg = true;
    }
  }
  else{
    neg = false;
    digitalWrite(PIN_DO1,LOW);
  }

  if(difilt.di[1] == LOW ){
    if(posi == false){
      Serial.println("nowp");
      posi = true;
    }
  }
  else{
    posi = false;
    digitalWrite(PIN_DO2,LOW);
  }

  if(neg){
    neg = false;
    timstepoff = LED_OFF;
    digitalWrite(PIN_DO1,HIGH);
    myStepper.step(-512);
  }
  
  if(posi){
    posi = false;
    timstepoff = LED_OFF;
    digitalWrite(PIN_DO2,HIGH);
    myStepper.step(512);  
  }

  if( timstepoff == TIME_UP ){
    timstepoff = TIME_OFF;
    //コイルに電流が流れる続けるのを防ぐ
    digitalWrite(PIN_STP_IN1, LOW);    
    digitalWrite(PIN_STP_IN2, LOW);
    digitalWrite(PIN_STP_IN3, LOW);
    digitalWrite(PIN_STP_IN4, LOW);
  }
}

/* DiFilter function add */
void DiFilter(void){
  uint8_t i;

  if( timdifilt == TIME_UP ){
    timdifilt = TIME_FILTER_MAX;
    difilt.buf[0][difilt.wp] = digitalRead(PIN_DI1);
    difilt.buf[1][difilt.wp] = digitalRead(PIN_DI2);

    for(i=0; i < DI_MAX; i++){
      if( difilt.buf[i][0] == difilt.buf[i][1] &&
      difilt.buf[i][1] == difilt.buf[i][2] &&
      difilt.buf[i][2] == difilt.buf[i][3] ){ //4回一致を確認
      difilt.di[i] = difilt.buf[i][0];
      }
    }

    if( ++difilt.wp >= DI_FILT_MAX ){
      difilt.wp = 0;
    }
  }
}

動作確認で使用している回路図と同様のもので動作します。SW1を押すと時計回りに90度回転し、SW2を押すと反時計回りに90度に回転します。

ステッピングモーターを操作している間は処理を占有するためメイン処理が遅延するデメリットはありますが、手早く実装できることやステップ角を正確に制御できるメリットがあります。

PR:わからないを放置せず、あなたにあった最低限のスキルを身に着けるコツを教える テックジム 「書けるが先で、理解が後」を体験しよう!

動作確認

ステッピングモーターの動作確認回路
ステッピングモーターの動作確認回路

Arduinoでステッピングモーターを起動する場合、増幅基板を使用してDOの出力電流を増幅してステッピングモーターを励磁します。増幅基板はステッピングモーターとセットになっていることが多く、トランジスタアレイ(ULN2003APGなど)が実装されておりArduinoのDOをトランジスタアレイの入力して増幅します。

マイコンのDOをステッピングモーターに直接接続すると出力電流による負荷が大きくなりすぎて発熱しマイコン故障の原因になるので注意が必要です。

Arduinoの電源のみではステッピングモーター用の消費電流が供給できないため外部からDC5Vを接続しています。Arduinoの電源とステッピングモーターのGND(ー)を共通に接続を行います。当記事では電源アダプター(AD-D50P100:秋月電子)を使用しています。

電源をONし、SW1を長押しするとステッピングモーターは時計回り回転を始め、LED1が点灯/消灯します。SW2を長押しすると反時計回りに回転を始め、LED2が点灯/消灯します。ステッピングモーターの起動時は緩やかに回転し、長押しするにつれて回転速度が速くなり一定速度になることが確認できました。またモーターが1周するまでの時間を測定すると約4秒となっていることも確認できました。

PR: わからないを放置せず、あなたにあったスキルを身に着けるコツを教える テックジムPython入門講座の申込

ソースコード全体

以下のソースコードはコンパイルして動作確認をしております。コメントなど細かな部分で間違っていたりやライブラリの更新などにより動作しなくなったりする可能性があります。参考としてお使いいただければと思います。

#include <MsTimer2.h>

#define MICRO_SEC 2000
#define STEP_START_FREQ 10000
#define PIN_STP_IN1 8
#define PIN_STP_IN2 9
#define PIN_STP_IN3 10
#define PIN_STP_IN4 11
#define PIN_DO1 4
#define PIN_DO2 5
#define PIN_DI1 6
#define PIN_DI2 7
#define TIME_OFF -1         //タイマーを使用しない場合
#define TIME_UP 0           //タイムアップ
#define LED_WAIT 20
#define STEP_OFF 100
#define STEP_START_FREQ 10000
#define STEP_CUT 1000
#define STEP_MAX 2
#define DI_MAX 2
#define DI_FILT_MAX 4            //DIフィルタのサンプリング数
#define TIME_FILTER_MAX 1    //ベースタイマカウント値
#define	CNT_INIT_MAX 10     //10ms×10 = 100ms

typedef struct{
  uint8_t wp;
  uint8_t buf[DI_MAX][DI_FILT_MAX];
  uint8_t di[DI_MAX];
}DIFILT_TYP;

typedef struct{
  uint8_t md;
  uint8_t stepcnt;
}STEP_CNT;

uint32_t oldtime_n;
uint32_t oldtime_p;
bool posi;
bool neg;
STEP_CNT mng_p;
STEP_CNT mng_n;
uint16_t stepfreq_n;
uint16_t stepfreq_p;
DIFILT_TYP difilt;
int16_t timdifilt;   //DIフィルタ起動
uint8_t CntInit;	//初期化時のみ使用
int16_t timled1 = TIME_OFF;
int16_t timled2 = TIME_OFF;
int16_t timstepoff = TIME_OFF;

/*プロトタイプ宣言*/
void mainTimer(void);
void mainApp(void);
bool StepMove(uint8_t no, bool posi);
void DiFilter(void);

void setup() {

  Serial.begin(9600);

  pinMode(PIN_DI1,INPUT_PULLUP);
  pinMode(PIN_DI2,INPUT_PULLUP);
  pinMode(PIN_DO1,OUTPUT);
  pinMode(PIN_DO2,OUTPUT);
  
  pinMode(PIN_STP_IN1, OUTPUT);
  pinMode(PIN_STP_IN2, OUTPUT);
  pinMode(PIN_STP_IN3, OUTPUT);
  pinMode(PIN_STP_IN4, OUTPUT);

  CntInit = CNT_INIT_MAX;
  while(CntInit > 0){  //0になるまでフィルタを実施
    DiFilter();         //DIフィルタ処理
    delay(10);     //10ms遅延させてDIフィルタ処理
    CntInit--;
    timdifilt = TIME_UP;
  }     

  MsTimer2::set(10, mainTimer); // 10ms period
  MsTimer2::start();
}

void loop() {

  mainApp();
  DiFilter();
}
/* タイマ管理 */
void mainTimer(void){

  if( timled1 > TIME_UP ){
    --timled1;
  }
  
  if( timled2 > TIME_UP ){
    --timled2;
  }    

  if( timdifilt > TIME_UP ){
    --timdifilt;
  }
  
  if( timstepoff > TIME_UP ){
    --timstepoff;
  }
}

/* メイン処理 */
void mainApp(void){
  uint32_t now_n,now_p;

  if(difilt.di[0] == LOW ){
    if( neg == false){
      Serial.println("nown");
      neg = true;
      mng_n.md = 0;
      mng_n.stepcnt = 0;
      oldtime_n = micros();
    }
  }
  else{
    neg = false;
    timled1 = LED_WAIT;
    stepfreq_n = STEP_START_FREQ;
    digitalWrite(PIN_DO1,LOW);
  }

  if(difilt.di[1] == LOW ){
    if(posi == false){
      Serial.println("nowp");
      posi = true;
      mng_p.md = 0;
      mng_p.stepcnt = 0;
      oldtime_p = micros();
    }
  }
  else{
    posi = false;
    timled2 = LED_WAIT;
    stepfreq_p = STEP_START_FREQ;
    digitalWrite(PIN_DO2,LOW);
  }

  if(neg){ //反時計回り
    now_n = micros() - oldtime_n;
    if ( now_n >= stepfreq_n ){
      oldtime_n = micros();
      timstepoff = STEP_OFF;
      if( StepMove(mng_n.md++, false)){
        if(++mng_n.stepcnt >= STEP_MAX){
          neg = false;

          if(stepfreq_n <= STEP_CUT){
            stepfreq_n = STEP_CUT;
          }
          else{
            stepfreq_n -= STEP_CUT;
          }
        }
        else{
          mng_n.md = 0;
        }
      }
    }
  }

  if(posi){ //時計回り
    now_p = micros() - oldtime_p;
    if ( now_p >= stepfreq_p ){
      oldtime_p = micros();
      timstepoff = STEP_OFF;    
      if( StepMove(7- mng_p.md++, true)){
        if(++mng_p.stepcnt >= STEP_MAX){
          posi = false;

          if(stepfreq_p <= STEP_CUT){
            stepfreq_p = STEP_CUT;
          }
          else{
            stepfreq_p -= STEP_CUT;
          }
        }
        else{
          mng_p.md = 0;
        }
      }
    }
  }

  if( timled1 == TIME_UP ){
    timled1 = LED_WAIT;
    digitalWrite(PIN_DO1,!digitalRead(PIN_DO1));
  }
  
  if( timled2 == TIME_UP ){
    timled2 = LED_WAIT;
    digitalWrite(PIN_DO2,!digitalRead(PIN_DO2));
  }
    
  if( timstepoff == TIME_UP){
    timstepoff = TIME_OFF;
    digitalWrite(PIN_STP_IN1,LOW);
    digitalWrite(PIN_STP_IN2,LOW);
    digitalWrite(PIN_STP_IN3,LOW);
    digitalWrite(PIN_STP_IN4,LOW); 
  }
}
/* ステッピングモーターの励磁 */
bool StepMove(uint8_t no, bool posi){
  bool ret = false;

//Serial.println(no);
  switch(no){
    case 0: //0111
      digitalWrite(PIN_STP_IN4,LOW);
      digitalWrite(PIN_STP_IN3,HIGH);
      digitalWrite(PIN_STP_IN2,HIGH);
      digitalWrite(PIN_STP_IN1,HIGH);
      if(posi){
        ret = true;
      }
      break;
    case 1: //0011
      digitalWrite(PIN_STP_IN4,LOW);
      digitalWrite(PIN_STP_IN3,LOW);
      digitalWrite(PIN_STP_IN2,HIGH);
      digitalWrite(PIN_STP_IN1,HIGH); 
      break;    
    case 2: //1011
      digitalWrite(PIN_STP_IN4,HIGH);
      digitalWrite(PIN_STP_IN3,LOW);
      digitalWrite(PIN_STP_IN2,HIGH);
      digitalWrite(PIN_STP_IN1,HIGH);
      break;              
    case 3: //1001
      digitalWrite(PIN_STP_IN4,HIGH);
      digitalWrite(PIN_STP_IN3,LOW);
      digitalWrite(PIN_STP_IN2,LOW);
      digitalWrite(PIN_STP_IN1,HIGH);
      break;
    case 4: //1101
      digitalWrite(PIN_STP_IN4,HIGH);
      digitalWrite(PIN_STP_IN3,HIGH);
      digitalWrite(PIN_STP_IN2,LOW);
      digitalWrite(PIN_STP_IN1,HIGH);
      break;            
    case 5: //1100
      digitalWrite(PIN_STP_IN4,HIGH);
      digitalWrite(PIN_STP_IN3,HIGH);
      digitalWrite(PIN_STP_IN2,LOW);
      digitalWrite(PIN_STP_IN1,LOW);
      break;            
    case 6: //1110
      digitalWrite(PIN_STP_IN4,HIGH);
      digitalWrite(PIN_STP_IN3,HIGH);
      digitalWrite(PIN_STP_IN2,HIGH);
      digitalWrite(PIN_STP_IN1,LOW);
      break;
    case 7: //0110
      digitalWrite(PIN_STP_IN4,LOW);
      digitalWrite(PIN_STP_IN3,HIGH);
      digitalWrite(PIN_STP_IN2,HIGH);
      digitalWrite(PIN_STP_IN1,LOW);
      if(posi == false){
        ret = true;
      }
      break;                 
    }
    //delayMicroseconds(1000); //1000以上で回転速度を調整する
    return ret;
}
/* DiFilter function add */
void DiFilter(void){
  uint8_t i;

  if( timdifilt == TIME_UP ){
    timdifilt = TIME_FILTER_MAX;
    difilt.buf[0][difilt.wp] = digitalRead(PIN_DI1);
    difilt.buf[1][difilt.wp] = digitalRead(PIN_DI2);

    for(i=0; i < DI_MAX; i++){
      if( difilt.buf[i][0] == difilt.buf[i][1] &&
      difilt.buf[i][1] == difilt.buf[i][2] &&
      difilt.buf[i][2] == difilt.buf[i][3] ){ //4回一致を確認
      difilt.di[i] = difilt.buf[i][0];
      }
    }

    if( ++difilt.wp >= DI_FILT_MAX ){
      difilt.wp = 0;
    }
  }
}

関連リンク

PICマイコンを使ってマイコンのレジスタの設定やMPLAB X IDEのプラグインであるMCCを使用して動作確認したことについてまとめています。

PICマイコン(PIC12F675)で実現できる機能と解説リンクまとめ

PICマイコン(PIC16F1827)で実現できる機能と解説リンクまとめ

PR:RUNTEQ(ランテック )- マイベスト3年連続1位を獲得した実績を持つWebエンジニア養成プログラミングスクール

最後まで、読んでいただきありがとうございました。

タイトルとURLをコピーしました