6/08/2008

Arduino 小型DCモータ/TA7291P

小型のDCモータ「FA-130」を制御する方法についてです。このモータは、車のプラモデルなどに使われるDCモータです。最大で500mAの電流が流れます。大抵DCモータを扱う場合、Arduino基盤にとっては過電流となるので別電源(乾電池など)が必要となります。
DCモータには二本の線がついており、一方をプラスに、もう一方をマイナスにつなげば回転し、プラスとマイナスを入れ替えれば逆回転します。スピードは、電圧が低いと遅く、高いと速く回転しますが、今回の場合はPWM(パルス)で調節します。パルスは、一定の電圧でONとOFFを高速に繰り返して出力する方法で、ONの継続時間が長いほど速く回転し、OFFの時間が長いほど遅く回転します。このONとOFFの時間の比率を「デューティ比」と言います(実際には、回転速度というよりトルクに反映されます)。



上図と下図を比較すると、「ONの継続時間」については、下図より上図のほうが長いので、上図の方がモータは速く回転します(トルクが高くなります)。



PWMでは、このONとOFFの時間の比率を変えることでスピード調節を行っています。以前行ったLEDの照度調整も同様の仕組みです。LEDの場合、実際は点滅しているのに過ぎないのですが、繰り返されるON/OFFがあまりにも速いので、明るさが変わったように見えています。

また下図のように、モータを正転/逆転させる場合は、電源へつないでいる二本の線の途中にスイッチを設けて入れ替え可能にします。切り離せば静止状態になります。このような切替を可能にする回路を「Hブリッジ回路」といいます。



そこで、いままで説明したことを容易にしてくれるのが、今回用いるモータドライバIC「TA7291P」です。「TA7291P」には、10本の端子があります。
東芝 TA7291P

東芝 TA7291P

価格:189円(税込、送料別)





 1:GND(Arduino/GND端子)と共有
 2:モータの端子へ接続
 3:非接続
 4:PWM端子(Arduino/アナログ出力端子)へ接続
 5:信号用端子(Arduino/デジタル出力端子)へ接続
 6:信号用端子(Arduino/デジタル出力端子)へ接続
 7:5V電源(Arduino/5V端子)と共有
 8:外部電源のプラス端子へ接続(乾電池など)
 9:非接続
10:モータの端子へ接続

今回は、可変抵抗器で正転/逆転/静止/スピード調節しようと思います。以下のようにそれぞれを接続することとします。複雑な配線に見えるかもしれませんが、間違わずにそれぞれを接続して下さい。


TA7291Pの5番ピンと6番ピンは、静止/正転/逆転を決めるための信号用の端子であり(それぞれArduinoのデジタル出力の1番ピン、2番ピンに接続)、
5番ピンが「LOW」、6番ピンが「LOW」の場合は静止
5番ピンが「HIGH」、6番ピンが「LOW」の場合は正転
5番ピンが「LOW」、6番ピンが「HIGH」の場合は逆転
となります。ArduinoのdigitalWrite()から出力されるLOW/HIGHの組合わせによって決められます。つまり、Arduinoのデジタル出力1番ピンと2番ピンのHIGH/LOWの出力の組合わせをプログラムによって操作することになります。
スピード調節については、TA7291Pの4番ピンがArduinoのアナログ出力の3番ピン(PWMピン)と接続され、ArduinoからPWM出力によって制御されます。

今回は、可変抵抗器を右に回すと正転、左に回すと逆転、中間だと静止するプログラムにします。可変抵抗器からanalogRead()によって読み取られる値は0〜1023なので、それを2で割って0〜511にスケールダウンし、
  0〜254:逆転(0で高速、254で低速)
255〜256:静止
257〜511:正転(257で低速、511で高速)
となるようにします。逆転時では数値が0に近いほど速く、254に近いほど遅くなり、正転時では数値が大きいほど速くなるので、調整した値をanalogWrite()の出力値に入れます。よって、以下のようなプログラムになります。

Arduinoのプログラム:

void setup(){
pinMode(1,OUTPUT); //信号用ピン
pinMode(2,OUTPUT); //信号用ピン
}

void loop(){
//アナログ入力:0番ピンの値を2で割る
int val=analogRead(0)/2; //0~511の値にする

//静止/正転/逆転の状態に分けてプログラムする
if(val>=255 && val<=256){ //静止:255~256
//LOW,LOWでデジタル出力
digitalWrite(1,LOW);
digitalWrite(2,LOW);
}else if(val>256){ //正転:257~511
//HIGH,LOWでデジタル出力
digitalWrite(1,HIGH);
digitalWrite(2,LOW);
//valが大きいほど出力値も大きくなる
analogWrite(3,val-256); //出力値:1~255
}else{ //逆転:0~254
//LOW,HIGHでデジタル出力
digitalWrite(1,LOW);
digitalWrite(2,HIGH);
//valが小さいほど出力値は大きくなる
analogWrite(3,255-val); //出力値:1~255
}
}

外部電源には、1.5Vの乾電池が4本入る電池ボックスなどを使うといいでしょう。
TA7291Pのデータシートには、外部電源のプラス端子をつなぐための8番ピンの電圧は、PWMに使うための4番ピンの電圧以上なければいけないと書いてあります。これに従えば、今回の場合の外部電源は、5V以上必要となります。

関連:「Arduino モータドライバ+モータ」(その他のモータドライバ等について)


MonotaRO (モノタロウ)

9 件のコメント:

  1. これで4つのモーターは制御できますか
    その方法とつなぎ方プログラムを教えてください

    返信削除
  2. いつも勉強させていただいております。
    確認ですが、接続図でTA7291Pの4番ピンがArduinoのデジタルの3番に接続されています。
    これはアナログの3番への接続ではないですか?
    教えていただけると助かります。

    返信削除
  3. 参考にさせて勉強させていただいています。
    質問ですがよろしくお願いします。
    モーターを回しながらシリアル通信でPCに文字を表示する事はできるでしょうか?
    右に回すとシリアル通信でPCにAと表示させ左に回すとBと表示させたいのです。色々挑戦したのですがPCにAと表示されるのですがモーターが止まってしまいます。
    よろしくお願いします。

    返信削除
  4. ポートの0番と1番はパソコンとのシリアル通信用にも使っています。

    パソコンとシリアル通信する場合はモーターとの配線にポート0と1は使わないでください。

    返信削除
  5. FA130は定格電圧?が1.5V~3Vとなっているのですが電池4本で6Vかけても大丈夫なんですか?

    返信削除
  6. 外部電源なしで配線する場合はどうしたらいいでしょうか?

    返信削除
  7. ドライバの8番につないでいる線をArduinoの5V端子につなげればいちおう回ると思いますが、Arduinoに過電流が流れて、シャットダウンするか燃えてしまうかもしれません。なのでDCモーターを使うときは、できるだけ外部電源にしたほうがいいです。

    返信削除
  8. このブログを参考に少し改造して、下記スケッチを書きました、ちゃんと動いているようで、シリアルモニターもきちんと表示されています、if else 文の使い方なのですが、続けて書けると色々な所で目にするのですが、はじめはif 2回目は else if 3回目は else だけなのですが、4回目は2回目の else if と、3回目に書けば良いのでしょうか?最後の delay(500); は無い方が良いのでしょうか? ご教授くださいませ。

    const int mot1 = 7; //モーター用信号ピン7に指定
    const int mot2 = 8; //モーター用信号ピン8に指定
    const int mot12_PWM = 9; //PWM制御
    void setup(){
    pinMode(mot1,OUTPUT); //モーター用信号7ピン出力に設定
    pinMode(mot2,OUTPUT); //モーター用信号8ピン出力に設定
    Serial.begin(9600); //シリアル通信速度設定
    }
    void loop(){
    int val=analogRead(0)/2; //アナログ入力:0番ピンの値1022を2で割り0~511の値にする
    //静止/正転/逆転の状態に分けてプログラムする
    if(val>=235 && val<=276){ //静止:235~276
    digitalWrite(mot1,LOW); //LOWでデジタル7に出力
    digitalWrite(mot2,LOW); //LOWでデジタル8に出力
    }
    else if(val>276){ //正転:277~511
    digitalWrite(mot1,HIGH); //HIGHでデジタル7に出力
    digitalWrite(mot2,LOW); //LOWでデジタル8に出力
    analogWrite(mot12_PWM,val-276); //出力値:1~275 valが大きいほど9の出力値も大きく
    }
    else{ //逆転:0~234
    digitalWrite(mot1,LOW); //LOWでデジタルに7出力
    digitalWrite(mot2,HIGH); //HIGHでデジタル8に出力
    analogWrite(mot12_PWM,235-val); //出力値:1~255 valが小さいほど9の出力値は大きく
    }
    Serial.println(analogRead(0)/2); //シリアル通信出力
    delay(500); //0.5秒遅らせる
    }

    返信削除
  9. elseは、上記条件以外という意味なので、大抵if文の最後の条件につけることが多いです。
    条件が5種類あるなら以下のような感じ。

    if (A){

    }else if (B){

    }else if (C){

    }else if (D){

    }else{ //条件AでもなくBでもなくCでもなくDでもない、それら以外という条件

    }

    優先順位は上から書いた順なので、もし間違ってAとBで条件が重複している部分がある場合は、条件Aが優先されます。

    delay(500)については、0.5秒間隔で内容を更新するので、もう少し早くしてもいいかもしれません。
    delay(10)でも大丈夫かもしれません。

    返信削除