DCモーターの回転を制御してみる(Arduino)

電池で駆動するおもちゃなど、
モーターを使った製品は多くあります。
正転、逆転などは、電池の向きを変えてあげればできそう?
ですが、回転数や、ブレーキなどの制御ができれば、
いろいろできそうな気がします。

今回は、
プラモデルやおもちゃによく使われている、
DCモータ(1.5V~3.0V程度で動作)を使ってみます。
・・・乾電池1~2本で使っているものです。

今回使用するものは、
・DCモーター
・モータードライバ
・DCモーター用電源(3V)
・可変抵抗(10KΩ)
です。

DCモーター、ドライバ、可変抵抗
DCモーター、ドライバ、可変抵抗他

DCモーターですが、
何か目的がある場合には、その目的に合わせて選択します。
・電圧範囲、無負荷時電流、無負荷時回転数、
 定格負荷時電流、定格負荷時回転数、負荷出力、
 効率、静止電流、静止トルク、などでしょうか?

モータードライバは、
DCモーターを制御するために使用します。
ただ回ってくれれば良いのであれば、電池を繋ぐ、放す
を行うリレーユニットなどを入れれば良いですが、
回転数を変化させたり、ブレーキを掛けるなどを行いたい
場合には、このドライブを利用すると簡単に行えます。

今回私が利用する、TB6612FNG搭載 デュアルモータードライバは、
詳しい解説や使用例が、メーカー(SPARKFUN)ページ に紹介されています。
私が解説するするより確かです。
https://learn.sparkfun.com/tutorials/tb6612fng-hookup-guide?_ga=2.68766999.766402060.1591960917-1588015560.1591960917

各ピンとその機能について1
各ピンとその機能について1
各ピンとその機能について2
各ピンとその機能について2
配線例
配線例
BIN1BIN2PWMB説明
LLH停止(制御なし)
HLHCW(時計回り):正転
LHHCCW(反計回り):反転
HLLショートブレーキ
LHLショートブレーキ
※STBYがHIGHであることが動作条件
ピンラベルの制御組み合わせ

モータードライバは、使用するモータに合わせたものを選択します。
今回使用するドライバは、2台のモーターを制御できるもので、
車のおもちゃなどの両輪にモーターを設置して制御したい
場合などによく利用されるものです。
・2つモーターを同時に制御できるため、左右輪のモーターの
 同時回転・同時停止のタイムラグを少なくできます。

電池ボックスは、
今回使用するモーターの電圧範囲は、1.5~3.0V (標準1.5V)
ということで、Arduino 本体のからの 3.3V 供給 は、
製品によっても異なるようですが、(50mA程度)が利用可能です。
モーター類は、大量の電流を必要とするため、別途専用電源を
用意するが一般的で、可能範囲であっても Arduino 本体からの
電源供給は避けるのが無難でしょう。
今回は、単三電池を2本セットできる電池ボックスを使用して、
モーターへ電源供給します。

入手できる通販サイトを掲載しておきます。
TB6612FNG搭載 デュアルモータードライバ
  ¥629- [SFE-ROB-14451]
  スイッチサイエンス
  https://www.switch-science.com/catalog/3587/
TB6612使用 Dual DCモータードライブキット
  ¥350- [AE-TB6612]
  秋月電子通商
  http://akizukidenshi.com/catalog/g/gK-11219/
DCモーター FA-130RA-2270L
  ¥120- [FA-130RA-2270L]
  秋月電子通商
  http://akizukidenshi.com/catalog/g/gP-09169/
電池ボックス 単3×2本 リード線・間仕切りあり
  ¥50- [BH-321-2A150]
  秋月電子通商
  http://akizukidenshi.com/catalog/g/gP-00327/

スケッチですが、
このメーカーが、Webページで提供しているライブラリを使用して制御するものと、
ライブラリを使用せずに制御するものを書いてみます。

回路は図の通りです。
   この回路図の作図には fritzing を利用させて頂いております。
   https://fritzing.org/home/

回路図1
回路図1
実際の配線1
実際の配線1

まず、ライブラリを使用するものですが、
これは、メーカーのページでサンプルが紹介されていますので、
このサンプルを使用させて頂きます。

ライブラリのインストールです。

1.メーカー(sparkfun)ページ
 https://learn.sparkfun.com/tutorials/tb6612fng-hookup-guide?_ga=2.68766999.766402060.1591960917-1588015560.1591960917
 ”TB6612FNG ARDUINO ライブラリ” を選択します。
 ”SparkFun_TB6612FNG_Arduino_Library-master.zip”
 というファイルがダウンロードされます。

sparkfunのホームページ
sparkfunのホームページ
TB6612FNG ARDUINO ライブラリのページ
TB6612FNG ARDUINO ライブラリのページ

2.メニュー「スケッチ」→「ライブラリのインクルード」
  →「.ZIP形式のライブラリをインストール」を選択しインストールします。
 1.でダウンロードしたファイル
 (私の場合SparkFun_TB6612FNG_Arduino_Library-masterというファイル名)を
 指定して、[開く]ボタンを押します。

ライブラリのインクルード1
ライブラリのインクルード1
ライブラリのインクルード2
ライブラリのインクルード2

3.インストールができているか確認します。
 メニュー「ファイル」→「スケッチ例」→「SparkFun_TB6612FNG・・・」
  →「Motor TestRun」が表示されれば、インストールは完了です。

スケッチ例の選択
スケッチ例の選択

では、このサンプルを利用して動作確認してみます。
 メニュー「ファイル」→「スケッチ例」→「SparkFun_TB6612FNG・・・」
  →「Motor TestRun」 を選択します。

このスケッチの先頭で、
define定義を使って Arduino の使用デジタルピンを設定しています。
この定義に合わせて、配線をするか、
私の配線図に合わせる場合は、
// 使用デジタルピン設定(今回はBのみ設定)
define AIN1 2 // 未設定
define AIN2 3 // 未設定
define PWMA 5 // 未設定
define BIN1 11
define BIN2 10
define PWMB 9
define STBY 7
と変更します。

使用デジタルピン設定変更
使用デジタルピン設定変更

必要ないとは思いますが、
このサンプルにコメント付けたものを貼り付けておきます。

// This is the library for the TB6612 that contains the class Motor and all the
// functions
// インクルード宣言 SparkFun_TB6612ライブラリ利用宣言
#include <SparkFun_TB6612.h>
// Pins for all inputs, keep in mind the PWM defines must be on PWM pins
// the default pins listed are the ones used on the Redbot (ROB-12097) with
// the exception of STBY which the Redbot controls with a physical switch
// 使用デジタルピン設定(今回はBのみ設定)
define AIN1 2    // 未設定
define AIN2 3    // 未設定
define PWMA 5    // 未設定
define BIN1 11
define BIN2 10
define PWMB 9
define STBY 7
// these constants are used to allow you to make your motor configuration 
// line up with function names like forward.  Value can be 1 or -1
// モータの構成を設定
const int offsetA = 1;
const int offsetB = 1;
// Initializing motors.  The library will allow you to initialize as many
// motors as you have memory for.  If you are using functions like forward
// that take 2 motors as arguements you can either write new functions or
// call the function more than once.
// オブジェクト生成
Motor motor1 = Motor(AIN1, AIN2, PWMA, offsetA, STBY);
Motor motor2 = Motor(BIN1, BIN2, PWMB, offsetB, STBY);
void setup() {
   // put your setup code here, to run once:
}
void loop() {
   //Use of the drive function which takes as arguements the speed
   //and optional duration.  A negative speed will cause it to go
   //backwards.  Speed can be from -255 to 255.  Also use of the 
   //brake function which takes no arguements.
   // motor1を255の(正転)速度で、1秒回転(次の指示があっても1秒は実行する)
   motor1.drive(255,1000);
   // motor1を-255の(逆転)速度で、1秒回転(次の指示があっても1秒は実行する)
   motor1.drive(-255,1000);
   // motor1を停止
   motor1.brake();
   delay(1000);
   //Use of the drive function which takes as arguements the speed
   //and optional duration.  A negative speed will cause it to go
   //backwards.  Speed can be from -255 to 255.  Also use of the 
   //brake function which takes no arguements.
   // motor2を255の(正転)速度で、1秒回転(次の指示があっても1秒は実行する)
   motor2.drive(255,1000);
   // motor2を-255の(逆転)速度で、1秒回転(次の指示があっても1秒は実行する)
   motor2.drive(-255,1000);
   // motor2を停止
   delay(1000);
   //Use of the forward function, which takes as arguements two motors
   //and optionally a speed.  If a negative number is used for speed
   //it will go backwards
   // motor1,motor2を150の(正転)速度で、前進(同時に回転)させる
   forward(motor1, motor2, 150);
   delay(1000);
   //Use of the back function, which takes as arguments two motors 
   //and optionally a speed.  Either a positive number or a negative
   //number for speed will cause it to go backwards
   // motor1,motor2を-150の(逆転)速度で、後退(同時に回転)させる
   back(motor1, motor2, -150);
   delay(1000);
   //Use of the brake function which takes as arguments two motors.
   //Note that functions do not stop motors on their own.
   // motor1,motor2を同時に停止する
   brake(motor1, motor2);
   delay(1000);
   //Use of the left and right functions which take as arguements two
   //motors and a speed.  This function turns both motors to move in 
   //the appropriate direction.  For turning a single motor use drive.
   // motor1,motor2を使って100の速度で左へ(効率よく?)旋回する
   left(motor1, motor2, 100);
   delay(1000);
   // motor1,motor2を使って100の速度で右へ(効率よく?)旋回する
   right(motor1, motor2, 100);
   delay(1000);
   //Use of brake again.
   // motor1,motor2を同時に停止する
   brake(motor1, motor2);
   delay(1000);
}

Arduino に書き込んで実行してみます。
回転方向や回転速度などが変わって実行されると思います。

続いて、ライブラリを使用せず、制御してみます。

この、TB6612FNGドライバのモーター制御は、
各ピンの設定を以下のように設定することで実現できます。

回路図は同じです。
スケッチしてみます。

// 使用デジタルピン設定
define BIN1 11
define BIN2 10
define PWMB 9
define STBY 7
void setup() {
  // put your setup code here, to run once:
  // ピンモード設定
  pinMode( BIN1, OUTPUT ); 
  pinMode( BIN2, OUTPUT );
  pinMode( STBY, OUTPUT );
  // 停止状態に設定(初期化)
  digitalWrite( BIN1, LOW );
  digitalWrite( BIN2, LOW );
  analogWrite( PWMB, 255);
  // 駆動可能状態に設定
  digitalWrite( STBY, HIGH );
}
void loop() {
  // put your main code here, to run repeatedly:
  // 正転(時計回り)CW
  digitalWrite( BIN1, HIGH );
  digitalWrite( BIN2, LOW );
  analogWrite( PWMB, 255);
  delay(200);
  // ショートブレーキ
  digitalWrite( BIN1, HIGH );
  digitalWrite( BIN2, LOW );
  analogWrite( PWMB, 0);
  delay(2000);
  // 反転(反時計回り)CCW
  digitalWrite( BIN1, LOW );
  digitalWrite( BIN2, HIGH );
  analogWrite( PWMB, 255);
  delay(200);
  // 停止
  digitalWrite( BIN1, LOW );
  digitalWrite( BIN2, LOW );
  analogWrite( PWMB, 0);
  delay(2000);
}
Arduino IDEの画面
Arduino IDEの画面

Arduino に書き込んで実行してみます。
こちらも回転速度が変わって実行されると思います。
速度については、
analogWrite( PWMB, 255 )
で、最高回転数で定義しています。

ライブラリを使うか使わないかは、どちらでもよいと思いますが、
車のおもちゃのようなもので、
左右のタイヤにそれぞれモーターを設置した場合、
この2つのモータを同時正転させる方法に難易度があります。
例えば、
 右:ON
  digitalWrite( AIN1, HIGH );
  digitalWrite( AIN2, LOW );
  analogWrite( PWMA, 255);
 左:ON
  digitalWrite( BIN1, HIGH );
  digitalWrite( BIN2, LOW );
  analogWrite( PWMB, 255);
とスケッチすれば、右がONになった後に左がONとなり、
同時ではありません。停止させる場合も同じです。
こんな時、このライブラリには、
2つのモータに対して同時に指示する関数が用意されています。
 右左:ON
 forward(motor1, motor2, 150);
これらを考えると、使うものによっては、ライブラリの方が
簡単に作成できるかもしれませんね。

次は、回路上に可変抵抗(10KΩ)を入れて、
この抵抗の値により、モーターの回転を変化させてみます。

回路は図の通りです。

回路図2
回路図2
実際の配線2
実際の配線2

スケッチしてみます。
このスケッチは、SparkFun_TB6612ライブラリを使用しました。

// インクルード宣言 SparkFun_TB6612ライブラリ利用宣言
#include <SparkFun_TB6612.h>
// 使用デジタルピン設定
define BIN1 11
define BIN2 10
define PWMB 9
define STBY 7
// モータの構成を設定
const int offsetB = 1;
// オブジェクト生成
Motor motor2 = Motor(BIN1, BIN2, PWMB, offsetB, STBY);
void setup() {
  // put your setup code here, to run once:
}
void loop() {
  // put your main code here, to run repeatedly:
  // A0ピンより可変抵抗値の電圧を取得
  int val = analogRead( A0 );
  // A0ピンの取得値を map()関数で、0 から 255 に数値置換
  val = map( val, 0, 1023, 0, 255 );
  // 変換したvalの値で、モータを回転させる
  motor2.drive( val );
  delay(20);
}
Arduino IDEの画面
Arduino IDEの画面

Arduino に書き込んで実行してみます。
可変抵抗のつまみを廻すと、モーターの回転が変化します。

可変抵抗を通過した電圧を取得します。
 analogRead( A0 );
このとき、0~1023の整数値で表現されます。
これを、モーターのPWMに受け渡すのですが、
PWMは0~255の範囲で指定でした。
そのため、変化が必要になります。
そこで map( ) 関数をを利用します。
この関数は、
ある範囲の値を、別の範囲の値に変換してくれます。
 map( 変数名, 現在の範囲下, 現在の範囲上, 変換する範囲下, 変換する範囲上 );
という使い方で、
A0から、analogRead( )で取得した、0~1023範囲内の値を、
PWMの指定範囲 0~255 に変換します。
 map( val, 0, 1023, 0, 255 );
となり、変換された値を、変数へ代入します。
 val = map( val, 0, 1023, 0, 255 );
別に、valに入れなくても、別途変数を用意しても良いです。
この変換済みの値を、ライブラリ関数を使用して、
 motor2.drive( val )
モータードライバへ送ります。