趣味 電子工作

Arduino+家にあるリモコン(赤外線)でモーター制御してみました

エンジニア歴20年以上、フリーランスでソフトウェアエンジニア・ゲームクリエイター・シナリオライターをやっております『NaruTaku』と申します。

今回はArduino+家にあるDVDレコーダーのリモコンでモーターを制御してみましたので、その内容を紹介したいと思います。

Arduinoでモーター制御

最終的にリモコンを使用してモータを制御するのですが、まずはモーター制御単体から説明したいと思います。使用部材は以下になります。

1.Arduino(互換機) UNO R3

Arduinoは互換機を使ったのですが、なんの問題もありませんでした。

 

2.モータードライバー (L298N)

L298Nというモータードライバを使用しました。駆動電圧は5V~35Vまで対応できるようです。今回は6Vを入れて使いました。

3.DCモーター

入力電圧が3-6Vのモーターを使用しました。

4.単三用電池ボックス

6Vがほしかったので、単三用電池ボックス(6V用)を使用しました。

以上が使用部材となります。

配線

Arduinoと各部材は以下のように接続しました。

1.モータードライバとArduino
・モータードライバのENA⇒Arduinoの5ピン
・モータードライバのIN1⇒Arduinoの2ピン
・モータードライバのIN2⇒Arduinoの4ピン
ENAは出力の大きさを調整する部分になりますので、PWM出力に対応しているピンに接続する必要があります。今回5ピンに接続しましたが、PWM出力に対応しているピンは他にも,3,6,9,10,11とありますので、これらのいずれかでしたら大丈夫です。ちなみに、基板に表示されている「 ~ 」がPWM出力対応であることを示しています(ただし、使用するピンで周波数は異なる)。IN1とIN2は回転の方向を決めるために制御する信号になりますので、デジタルIOピンならどこでもよいです。

今回はモーター1つしか制御しませんが、このモータードライバはモーター2つまで制御できますので、もし2つ目のモーターを接続する場合はENB,IN3,IN4とArduinoを接続します。

2.モータードライバと単三用電池ボックス
・モータードライバのVSM(Vin)⇒単三用電池ボックスの+
・モータードライバのGND⇒単三用電池ボックスのー
モータードライバへ入力する電圧です。5V~35Vの範囲で入力できます(製品によって多少違うかもです)。注意点は5V端子は入力でなく出力端子になりますので、ここに電源電圧をつないではいけません。

3.モータードライバとDCモーター
・モータードライバのMOTORAのどちらか⇒DCモーターの端子のどちらか
・モータードライバのMOTORAのどちらか⇒DCモーターの端子のどちらか
僕が使ったモータードライバには二つの端子がまとめて「MOTORA」となっていました。「OUT1」、「OUT2」と記載されている製品もあるようです。ここにDCモータ-の端子をつなぐのですが、どちらをどちらにつないでも問題ありません。この二つの端子を制御することによって回転方向を決めるので、接続した端子に合わせて制御してやればよいことになります。(IN1とIN2がMOTORAの二つの端子(OUT1,OUT2)に対応しています)

ちなみに、2つ目のモーターを接続する場合は「MOTORB」の端子とDCモーターを同じように接続することになります。

ArduinoへはPCからUSB給電となります。ハードは以上です。

ソフトウェア作成

ソースコードは以下になります。


// Arduinoとモータードライバ(L298N)の接続
// モーターA
int ENA = 5;
int IN1 = 2;
int IN2 = 4;

void setup() {
  // put your setup code here, to run once: 
  // 制御に使用するArduinoピンをoutputにセット
  pinMode(ENA, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  // モーターA
  // 回転方向指定
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  // 出力(電圧)指定 0~255(8bit)
  analogWrite(ENA, 230);
}

では、簡単ですがソースコードの説明をします。

まず、宣言部でENA,IN1,IN2の制御に使用するピンを指定してます。わかりやすいように変数に割り当てているだけですね。

次に初期化部分です。pinMODEで使用するピンの入力、出力を設定するのですが、今回はすべて出力になりますのですべてOUTPUTで設定します。少し驚いたのですが、ArduinoはPWM出力する際、特に設定は必要ないみたいですね。通常マイコンなどだと、PWM出力するための設定が必要だったりするのですが何もしなくてよいみたいです。

また、PWM出力の分解能は変更できるみたいですがデフォルトで0~255(8bit)なので、今回はこのまま使います。周波数は使用するピンで変わるようで、今回使用する5ピンは980Hz出力でした。

次にLoop処理。digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW);で回転方向を指定します。どちらかをHIGH、どちらかをLOWにしてやると接続したDCモーターの端子に反映され、回転方向が決まります。止める場合はどちらもLOWにしてやります。(どちらもHIGHにしても止まります)

analogWrite(ENA, 230);にてPWM出力制御をしています。ここで指定した値に従ってモータードライバが電圧を出力してくれます。今回は0~255の間で値を指定しますので、255が最大になります。このとき、モータードライバへ入力している電圧が最大値になりますので、今回の例だと255指定で6V出力となります。当然ですが、モータードライバへ入力している電圧が高ければ、出力電圧も上がります。

気を付けないといけないのは、モーターは起動時に一番パワーを使うためPWM出力を低く設定しすぎるとモーターが回転しません。この辺りは入力電圧との兼ね合いもあるため、プログラムで出力を変えながら「どのくらいから回りだしてくれるだろう」と確認してみるのもよいと思います。

以上、簡単ですが上記のプログラムでモーターが回転します。しかし、このプログラムではプログラムを転送した瞬間にモーターが回転し止めることもできませんので、家にあるリモコンを使ってモーターを制御してみました。

リモコンを使用してモーター制御

では、家にあった東芝のDVDレコーダーリモコンを使用してモーター制御してみたいと思います。

まず配線ですが、上記で紹介したモーター制御の配線に赤外線モジュールを追加で接続することになります。赤外線モジュールとArduinoの接続、そして制御プログラムについては以下の記事で詳しく紹介しておりますので、参考にしていただければと思います。

こちらもCHECK

Arduinoで赤外線受信モジュールを使いリモコン信号受信してみました

エンジニア歴20年以上、フリーランスでソフトウェアエンジニア・ゲームクリエイター・シナリオライターをやっております『NaruTaku』と申します。 今回はArduinoで赤外線受信モジュールを使って遊 ...

続きを見る

赤外線の制御も追加したソースコードは以下になります。


#include <IRremote.h>
#define IR_RECEIVE_PIN  12  //受信ピン指定
IRrecv rcvdata(IR_RECEIVE_PIN); // 受信オブジェクトを作成 
decode_results dec_results;  // 受信データの格納先

// Arduinoとモータードライバ(L298N)の接続
// モーターA
int ENA = 5;
int IN1 = 2;
int IN2 = 4;

//未受信カウンター
int no_rcvcnt;

void setup() {
  // put your setup code here, to run once:
   rcvdata.enableIRIn();     // 赤外線受信開始

  // 制御に使用するArduinoピンをoutputにセット
  pinMode(ENA, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);

  no_rcvcnt = 0;
}

void loop() {
  // put your main code here, to run repeatedly:
   if (rcvdata.decode(&dec_results)) {      // 受信確認
      if (dec_results.value == 0xA23D807F){ // 1ボタンを押すと前進
            // モーターA
            // 回転方向指定
            digitalWrite(IN1, HIGH);
            digitalWrite(IN2, LOW);
            // 出力(電圧)指定 0~255(8bit)
            analogWrite(ENA, 240);
       }else if(dec_results.value == 0xA23D40BF){ // 2ボタンを押すと後進
            // モーターA
            // 回転方向指定
            digitalWrite(IN1, LOW);
            digitalWrite(IN2, HIGH);
            // 出力(電圧)指定 0~255(8bit)
            analogWrite(ENA, 240);
       }
       rcvdata.resume();                    //リセット
       no_rcvcnt = 0;
   }else{
      //受信していないときは停止(2回で確定にする)
      if(no_rcvcnt >0){
         // モーターA
         // 停止
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        // PWM出力 0に設定
        analogWrite(ENA, 0);
        }else{
          no_rcvcnt++;
        }
   }
   delay(100); //100ms待つ
}

上記、モーター制御で説明した部分と赤外線モジュールの記事で説明している部分以外のソースコードを説明します。

まず、受信確認判定がTRUEの場合の処理、 if (dec_results.value == 0xA23D807F)判定とelse if(dec_results.value == 0xA23D40BF)判定ですが、リモコンに割り当てられている値をチェックしています。持っているリモコンでは「1」がA23D807F(16進表記)、「2」がA23D40BF(16進表記)、となっていましたので、それぞれのボタンで処理を切り分けています。具体的には「1」と「2」で回転方向を逆転させています。これ以外の判定はしておりません(if分を作っていない)ので、「1」と「2」にしか反応しなくなっています。

次に受信確認判定がFALSEの場合の処理で回転を止めているのですが、これはボタンを押し続けている間だけモーターを回転させたかったのでこうしています。単純に考えると受信確認判定がFALSEの場合止めたらすむ話なのですが、if(no_rcvcnt >0)の処理を入れているのは、2回連続で未受信が続いた場合に未受信と確定させるためです。

動きを見ていると、リモコンのボタンを押し続けていてもたまに「未受信」と判定してしまうことがありました。おそらく、赤外線を受信するタイミングと判定するタイミングにずれが生じることがあるためではないかと思います。

delay(100);で判定間を100ms待たせているのですが、これをなくすと「未受信」と判定が増えました。これはLoop処理が早すぎてrcvdata.resume(); で受信信号をリセットした後、次の受信をする前に何度も受信判定をしてしまうためだと思います。

なので100ms待たせているのですが、それでも未受信判定があったので2回連続未受信判定で回避しました。100ms待たせておいて、ボタンを押し続けている状態で2回連続未受信と判定することはなかったのでそうしております。 no_rcvcntは未受信回数をカウントするために追加した変数になります。

こうしましたので、ボタンを離したあと最短でも100ms(0.1秒)後に停止する仕様になっておりちょっとカッコ悪いですが、よしとしておきます^^;

また、本来であればメインループに100msのウエイト処理を入れるのはよくなくて、100msの割り込みを作って処理させるべきなのですが、今回はモーターを制御するだけで他に影響がないので楽をしてdelay(100);で100ms待たせました。

ソースの説明は以上となります。

実行結果

実際に動かしてみました。ちゃんと「1」と「2」だけに反応し、ほかのボタンには反応せず、ボタンを押している間だけモーターが回転しています。

ボタンを離してから止まるまで最短でも100ms(0.1秒)かかってしまってますが、趣味なのでまあこのくらいならいいかと思うようにしました笑

以上、今回はArduino+家にあるリモコンでモーター制御した内容を紹介させていただきました。

まとめ

今回も前回に引き続き簡単な電子工作を紹介させていただきました。

次はこれを利用してリモコンで動くラジコンを作りたいなと思っていますので完成したら紹介させていただきます。→ラジコン作成しましたので、こちらで紹介させていただきました!

こちらもCHECK

Arduino+家にあるリモコン(赤外線)でラジコンを作ってみました

エンジニア歴20年以上、フリーランスでソフトウェアエンジニア・ゲームクリエイター・シナリオライターをやっております『NaruTaku』と申します。 今回はArduino+家にあるDVDレコーダーのリモ ...

続きを見る

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

  • この記事を書いた人
  • 最新記事

NaruTaku

40代のフリーランスエンジニア・シナリオライター。 20代前半から20年間エンジニアとしてキャリアを積みフリーランスへ転身。ソフトウェア開発とゲーム開発、シナリオ執筆をメインに、プログラミング講師・Webライターとしても活動。また、フリーランスになり見た目の重要性に今さら気づき、ヒゲ脱毛を実施中。

-趣味, 電子工作