このレッスンでは赤外線通信により、サーボモーターを制御方法を学びます。今回は、Lesson8で使った赤外線送受信機を使い、信号の送受信とサーボモーターの制御に関する一般的な概念を取得することができます。
赤外線送信機を使い、信号を受信機に送信し、サーボモーターを制御します。必要な配線は下記図に従い組立てていってください。
IR アルドゥイーノライブラリからライブラリ情報をダウンロードします。
アルドゥイーノIDEからIRremoteデモ例を開き、アルドゥイーノボードにアップロードします。
次に、シリアルモニターを開き、赤外線送信機のボタンをクリックし、赤外線受信機に信号を送信します。下記動画のように、各ボタンを押すとボタンに割り振られたHEXコードが表示されます。
次に、サーボモーターの制御に使用されるボタンのHEXコードを検出します。2つのボタンを使用すると仮定し、1つは時計回りの回転用、もう1つは反時計回りの回転用です。
たとえば時計回りに(▲)を使用し、反時計回りに(▼)を使用するため、HEXコードを取得する必要があります。
上記の操作が完了したら、USBケーブルを使用してアルドゥイーノボードをコンピューターに接続します。緑の電源LED(PWRのラベル)が点灯します。アルドゥイーノIDEを開き、プロジェクトに対応するボードとポートタイプを選択し、アルドゥイーノに次のスケッチをロードします。
#include <IRremote.h> //IRremoteライブラリをアルドゥイーノライブラリにコピーする必要があります #include <Servo.h> #define plus 0xFF18E7 //時計回りのボタン #define minus 0xFF4AB5 //反時計回りのボタン int RECV_PIN = 3; //赤外線受信機のピン Servo servo; int val; //回転角度 bool cwRotation, ccwRotation; //回転の状態 IRrecv irrecv(RECV_PIN); decode_results results; void setup() { Serial.begin(9600); irrecv.enableIRIn(); // 受信機を起動する servo.attach(9); //サーボピン } void loop() { if (irrecv.decode(&results)) { Serial.println(results.value, HEX); irrecv.resume(); // Receive the next value if (results.value == plus) { cwRotation = !cwRotation; //回転角度の値を切り替えます ccwRotation = false; //これ以上回転しません } if (results.value == minus) { ccwRotation = !ccwRotation; //toggle the rotation value cwRotation = false; //回転角度の値を切り替えます } } if (cwRotation && (val != 175)) { val++; //連動ボタン用 } if (ccwRotation && (val != 0)) { val--; //カウンター連動ボタン用 } servo.write(val); delay(20); //回転速度 }
このプログラムは、送信機の(▲)(▼)ボタンを押すことで、モーターが前後進に回転・停止させることができます。また同じボタンを2回押すことで、モーターは停止します。
今回は、IRLibAllライブラリーを使用してサーボを制御します。サーボの回転速度と、角度を制御します。
上図に示したように、+ 3.3v、GND、およびピン3に接続された赤外線受信機とサーボが見て取れると思います。サーボの接続に関して赤い線は+5vに、GNDは暗褐色のワイヤはGND、残りのワイヤをピン9に接続しますが、デジタル出力ピンでもかまいません。
IRライブラリをインストールするには:
以下、「IRLib2 / examples」フォルダからservo.inoスケッチのバージョンとなっております。OSOYOO Smart Car V1 Remoteで使用できる内容に変更しています。別の操作方法を使用している場合は、dump.inoを使用してさまざまなボタンのコードに関する情報を収集し、適切なプロトコル名とコードでスケッチを変更する必要があります。
#include <IRLibAll.h> #include <Servo.h> // プロトコルに応じてこれらの値を設定する必要があります // ここで使用しているリモートコードはAdafruit用です // ミニリモコン #define MY_PROTOCOL NEC #define RIGHT_ARROW 0xFF5AA5 //時計回りに回転する #define LEFT_ARROW 0xFF10EF //反時計回りに回転する #define SELECT_BUTTON 0xFF38C7 //サーボの回転位置が中心 #define UP_ARROW 0xFF18E7 //サーボの速度を早くする #define DOWN_ARROW 0xFF4AB5 //サーボの速度を遅くする #define BUTTON_0 0xFF9867 //ボタン0〜9を押すと、決まった位置に移動します #define BUTTON_1 0xFFA25D // 20度ずつ回転 #define BUTTON_2 0xFF629D #define BUTTON_3 0xFFE21D #define BUTTON_4 0xFF22DD #define BUTTON_5 0xFF02FD #define BUTTON_6 0xFFC23D #define BUTTON_7 0xFFE01F #define BUTTON_8 0xFFA857 #define BUTTON_9 0xFF906F IRrecv myReceiver(2); //受信機のピン番号 IRdecode myDecoder; Servo myServo; // サーボを制御するサーボオブジェクトを作成する int16_t pos; // サーボ位置を保存する変数を設定する int16_t Speed; // 左/右ボタンが押されるたびに移動する度数 uint32_t Previous;//NEC繰り返しコードを処理します void setup() { myServo.attach(9); // ピン9のサーボをサーボオブジェクトに接続します pos = 90; // 中間点90度から開始 Speed = 3; // 左/右を押すたびにサーボが3度移動します myServo.write(pos); // 初期位置を設定 myReceiver.enableIRIn(); // 受信機を起動する } void loop() { if (myReceiver.getResults()) { myDecoder.decode(); if(myDecoder.protocolNum==MY_PROTOCOL) { if(myDecoder.value==0xFFFFFFFF) myDecoder.value=Previous; switch(myDecoder.value) { case LEFT_ARROW: pos=min(180,pos+Speed); break; case RIGHT_ARROW: pos=max(0,pos-Speed); break; case SELECT_BUTTON: pos=90; break; case UP_ARROW: Speed=min(10, Speed+1); break; case DOWN_ARROW: Speed=max(1, Speed-1); break; case BUTTON_0: pos=0*20; break; case BUTTON_1: pos=1*20; break; case BUTTON_2: pos=2*20; break; case BUTTON_3: pos=3*20; break; case BUTTON_4: pos=4*20; break; case BUTTON_5: pos=5*20; break; case BUTTON_6: pos=6*20; break; case BUTTON_7: pos=7*20; break; case BUTTON_8: pos=8*20; break; case BUTTON_9: pos=9*20; break; } myServo.write(pos); // 変数 'pos'の位置に移動するようサーボに指示する Previous=myDecoder.value; } myReceiver.enableIRIn(); } }
ここに示している例はアルドゥイーノUnoまたはMegaで問題なく動作しますが、アルドゥイーノLeonardo、アルドゥイーノMicro、アルドゥイーノYun、または他のATmega32u4ベースのシステムを使用している場合は、IRLibの内容を変更する必要があります。
IRLibは、アルドゥイーノに組み込まれたハードウェアタイマーを使用して50µsごとに割り込みを発生させ、入力ピンをポーリング(複数の機器やソフトウェアを円滑に連携させる制御方式の一つ)して変更があったかどうかを確認させます。標準ではTIMER2を使用します。アルドゥイーノサーボライブラリは、TIMER1を使用したハードウェア割り込みにも使用しています。ただし、ATmega32u4プロセッサにはTIMER2がないため、そのプロセッサを使用するシステムではIRLibのデフォルトはTIMER1になります。そこでデフォルトのタイマーを変更する必要があります。「IRLibProtocols / IRLibHardware.h」の56行目以下には、次のようなものがあります。
#elif defined(__AVR_ATmega32U4__) #ifdef CORE_TEENSY // it's Teensy 2.0 //#define IR_SEND_TIMER1 14 //#define IR_SEND_TIMER3 9 #define IR_SEND_TIMER4_HS 10 #else /* it's probably Leonardo */ #define IR_SEND_TIMER1 9 //#define IR_SEND_TIMER3 5 //#define IR_SEND_TIMER4_HS 13 #endif
上記のようにコメントアウトするには、#define IR_SEND_TIMER1の前に//を置く必要があります。次にTIMER3またはTIMER4_HSのいずれかの前にあるスラッシュを削除します。これらの定義は「IR_SEND_TIMERxx」ということに注意してください。ファイルの後半で、この値をコピーして、受信タイマーとして使用していきます。Leonardoを使用しており、IRLibの赤外線信号を送信する場合は、これらの定義後に数値をメモする必要があります。受信機の任意のデジタル入力ピンにフック(利用者が独自の処理を追加できるようにする仕組み)できますが、IRLibでは、使用しているタイマーに応じて特定の出力ピンを使用する必要があります。これについては、送信に関するセクションの後半で説明します。
スケッチをアップロードして、左右の矢印ボタンを押してみてください。サーボが左右に回転します。エンターボタンを押すと、サーボが中央にきます。上矢印ボタンまたは下矢印ボタンを押しても、目に見える効果はありませんが、左または右に押す動きの速度が変わります。0から9までの番号ボタンを押すことで、20°間隔でサーボを10の異なる位置に回転します。
サーボが動作が安定しない場合は電源に問題がある可能性が高いです。一部のUSBポートは、アルドゥイーノに接続しているサーボを動かすのに必要な電流が不足しているので、外部から5ボルト電源を追加する必要もあります。
DownLoad Url osoyoo.com