リモートコントロール(RC)戦車をつくる【XBeeコントロール①】 [XBee]
これまで遠隔コントロールとして赤外線リモコンを使ってきましたが、一旦、前回までで終了して、次に”XBee"を使ってみたいと思います。
若干”今さら?”感も拭えないところですが、電子工作的には必ず通る基礎スキルのようなものですので、遠隔コントロールの第2弾として、やってみたいと思います。
で、こちら↓です。
わたしが持っているのは”s2"というシリーズですが、少々調べたところ2015年12月~2016年2月くらいに”s2c"という後継シリーズがリリースされています。そのため、今(2019年10月)時点で販売終了品となっています。
本来であれば、販売終了品を積極的に使う理由はなく、新しいタイプに買い直して。。。ということになるのですが、XBee本体の設定ができれば、その後の用途でs2とs2cの差分が問題にはならないため(まぁ、買い直すのももったいないかなーとも思って)、今回は"s2"を利活用することにしました。ちなみにs2とs2cの主な差分は以下のようです。
・従来のXBee ZB(S2)と同程度の消費電力で、従来のPROシリーズ(S2B)に近い通信距離
・最大5 MbpsのSPI通信ができる
・ZigBeeデバイスタイプ(コーディネータやルータなど)のモード設定変更時におけるファーム
ウェアの書き換えが不要
今さらXBee s2モジュールへの設定ですので、ググっても今の最新版XCTU(Ver.6.x)とs2の組み合わせはなかなか見当たりませんでした。実現までに多少手探りで苦労したところもあったので、一通り今回できた手順をTipsとして列記していきたいと思います。
【XCTUインストール】
Digi社のサイトからXTCUをダウンロードしインストールします。
2019年10月時点でバージョン6.4.4でした。
https://www.digi.com/products/embedded-systems/digi-xbee/digi-xbee-tools/xctu#productsupport-utilities
>XCTU v. 6.4.4 Windows x86/x64
【ハードウェアの準備】
XBee を PC に接続するためには USBアダプタが必要になります。もちろん、それ用のものを購入して使ってもよいのですが、手元にUSB-シリアル変換モジュールがあるので自作します。XBeeはピン間隔が2mmピッチで、そのままではブレッドボードやユニバーサル基板に差すことができないので、変換基板を使います。電源とGND、あとはシリアルデータ(TX, RX)2本を接続して簡単に作りました。
XBee用2.54mmピッチ変換基板
"http://akizukidenshi.com/catalog/g/gP-05060/"
【Xbee s2を接続した直後のXCTU画面】
XCTUとハードウェアの準備ができたら、XBeeをPCと接続します。
USB-シリアル変換モジュールのJ1ピンヘッダでシリアルI/Oの電圧を切り替えています。XBeeは3.3V動作なので1-2ピンをショートして使用します(ちなみに2-3ピンショートは5V)。
(2020.5.31)XBee用2.54mmピッチ変換基板には3.3V電圧レギュレータが実装されています。データシートを見ると概ね5V~12V印加で3.3V出力します。なので、この場合では5V印加が正しいです(2-3ピンをショートして5V印加)。一応、3.3V印加で3.3V出力はしてくれているので、使い方的には少し間違えたかもしれませんが、動作はするってことですね。
XBeeモジュールは認識したようですが”ファームウェアが見つからない”と言われています。
"ファームウェアのライブラリをアップデートするか?"と聞かれているのでYesを押します。
”探してもファームウェアが見つからない”と言われています。
次に手動でファームウェアを探そうと試みますが、これもうまくいきません。
既にs2cシリーズがリリースされてから約3年半くらい経過して、ネットショップでもs2シリーズは販売終了品として流通在庫も無い状況のようなので、”legacyとして扱われていてもおかしくはないのでは?“と考えて、古いバージョンのファームウェアをインストールしてみます。
これでうまくいったようです。
Functioinにファームウェアの表示が出てきました。ルータモードのようですね。
【ファームウェアの書き換え】
s2シリーズでは、コーディネータやルータなどのモード設定変更時にはファームウェアを書き換える必要があります。
XBeeネットワークでは1つのコーディネータが必須なので、1個をルータからコーディネータへ変更します。ついでに1個のルータモードのxBeeは、ファームウェアバージョンが最新版ではないのでバージョンアップします。
若干”今さら?”感も拭えないところですが、電子工作的には必ず通る基礎スキルのようなものですので、遠隔コントロールの第2弾として、やってみたいと思います。
で、こちら↓です。
わたしが持っているのは”s2"というシリーズですが、少々調べたところ2015年12月~2016年2月くらいに”s2c"という後継シリーズがリリースされています。そのため、今(2019年10月)時点で販売終了品となっています。
本来であれば、販売終了品を積極的に使う理由はなく、新しいタイプに買い直して。。。ということになるのですが、XBee本体の設定ができれば、その後の用途でs2とs2cの差分が問題にはならないため(まぁ、買い直すのももったいないかなーとも思って)、今回は"s2"を利活用することにしました。ちなみにs2とs2cの主な差分は以下のようです。
・従来のXBee ZB(S2)と同程度の消費電力で、従来のPROシリーズ(S2B)に近い通信距離
・最大5 MbpsのSPI通信ができる
・ZigBeeデバイスタイプ(コーディネータやルータなど)のモード設定変更時におけるファーム
ウェアの書き換えが不要
今さらXBee s2モジュールへの設定ですので、ググっても今の最新版XCTU(Ver.6.x)とs2の組み合わせはなかなか見当たりませんでした。実現までに多少手探りで苦労したところもあったので、一通り今回できた手順をTipsとして列記していきたいと思います。
【XCTUインストール】
Digi社のサイトからXTCUをダウンロードしインストールします。
2019年10月時点でバージョン6.4.4でした。
https://www.digi.com/products/embedded-systems/digi-xbee/digi-xbee-tools/xctu#productsupport-utilities
>XCTU v. 6.4.4 Windows x86/x64
【ハードウェアの準備】
XBee を PC に接続するためには USBアダプタが必要になります。もちろん、それ用のものを購入して使ってもよいのですが、手元にUSB-シリアル変換モジュールがあるので自作します。XBeeはピン間隔が2mmピッチで、そのままではブレッドボードやユニバーサル基板に差すことができないので、変換基板を使います。電源とGND、あとはシリアルデータ(TX, RX)2本を接続して簡単に作りました。
XBee用2.54mmピッチ変換基板
"http://akizukidenshi.com/catalog/g/gP-05060/"
【Xbee s2を接続した直後のXCTU画面】
XCTUとハードウェアの準備ができたら、XBeeをPCと接続します。
USB-シリアル変換モジュールのJ1ピンヘッダでシリアルI/Oの電圧を切り替えています。XBeeは3.3V動作なので1-2ピンをショートして使用します(ちなみに2-3ピンショートは5V)。
(2020.5.31)XBee用2.54mmピッチ変換基板には3.3V電圧レギュレータが実装されています。データシートを見ると概ね5V~12V印加で3.3V出力します。なので、この場合では5V印加が正しいです(2-3ピンをショートして5V印加)。一応、3.3V印加で3.3V出力はしてくれているので、使い方的には少し間違えたかもしれませんが、動作はするってことですね。
XBeeモジュールは認識したようですが”ファームウェアが見つからない”と言われています。
"ファームウェアのライブラリをアップデートするか?"と聞かれているのでYesを押します。
”探してもファームウェアが見つからない”と言われています。
次に手動でファームウェアを探そうと試みますが、これもうまくいきません。
既にs2cシリーズがリリースされてから約3年半くらい経過して、ネットショップでもs2シリーズは販売終了品として流通在庫も無い状況のようなので、”legacyとして扱われていてもおかしくはないのでは?“と考えて、古いバージョンのファームウェアをインストールしてみます。
これでうまくいったようです。
Functioinにファームウェアの表示が出てきました。ルータモードのようですね。
【ファームウェアの書き換え】
s2シリーズでは、コーディネータやルータなどのモード設定変更時にはファームウェアを書き換える必要があります。
XBeeネットワークでは1つのコーディネータが必須なので、1個をルータからコーディネータへ変更します。ついでに1個のルータモードのxBeeは、ファームウェアバージョンが最新版ではないのでバージョンアップします。
リモートコントロール(RC)戦車をつくる【スケッチ_モータ制御②】 [RC戦車]
前回の記事(リモートコントロール(RC)戦車をつくる【赤外線コントロール②】)で赤外線リモコンのコードが判ったのでスケッチを修正するのですが、もう一つ修正する箇所があります。
これまでは
>#define SPEED 128 //モータへの電圧(スピード)は一定
として、どの方向に対してもスピードを一定にしていましたが、緩旋回では左右のキャタピラのスピードに差分をつけるため、左右のモータへかける電圧(Vref)を変える必要があります。
ジョイスティックであればアナログ的に電圧を変化させる(スピードを変化させる)ことができるのですが、今回はリモコンボタンのため2種類の電圧を組み合わせての変化とします。
他にも全般的にスケッチを見直して修正しています。
【スケッチ】
※#include <IRremote.h>は表示の不具合で全角<>で記載しています。本当は半角<>ですのでご注意ください。
【動作確認】
早速、動かしてみます。
右/左と緩旋回もできています。動作の変化時のwaitも外したので、前回よりスムーズに動作してラジコンらしい動きになりました。直進でやや左に寄ってしまうのはおそらく車軸がずれているか?、それともVref電圧に少々の電圧差があるのかもしれません。真っ直ぐ走らせるためにはこのズレを補正する形でVref電圧を調整すればよいのですが、今回はやりません。(動けばOK!だったので。。。)
これまでは
>#define SPEED 128 //モータへの電圧(スピード)は一定
として、どの方向に対してもスピードを一定にしていましたが、緩旋回では左右のキャタピラのスピードに差分をつけるため、左右のモータへかける電圧(Vref)を変える必要があります。
ジョイスティックであればアナログ的に電圧を変化させる(スピードを変化させる)ことができるのですが、今回はリモコンボタンのため2種類の電圧を組み合わせての変化とします。
他にも全般的にスケッチを見直して修正しています。
【スケッチ】
/* SparkFun Electronics 2013 Playing with Infrared Remote Control IR Receiver Breakout (SEN-8554): Supply voltage of 2.5V to 5.5V Attach OUT: To pin 13 on Arduino GND: GND VCC: 5V This is based on Ken Shirriff's code found on GitHub: https://github.com/shirriff/Arduino-IRremote/ This code works with cheap remotes. If you want to look at the individual timing of the bits, use this code: http://www.arduino.cc/playground/Code/InfraredReceivers */ #include <IRremote.h> // 赤外線送受信用ヘッダファイル int RECV_PIN = 11; // 赤外線受信モジュール IRrecv irrecv(RECV_PIN); // 赤外線受信用オブジェクトの設定 decode_results results; // 赤外線受信結果を格納する #define POWER 0x8F71BE4 #define A 0x8F71FE0 #define B 0x8F71EE1 #define C 0x8F71AE5 #define UP 0x8F705FA #define DOWN 0x8F700FF #define LEFT 0x8F708F7 #define RIGHT 0x8F701FE #define SELECT 0x8F704FB #define UP_LEFT 0x8F78D72 #define DOWN_LEFT 0x8F78877 #define UP_RIGHT 0x8F7847B #define DOWN_RIGHT 0x8F7817E #define SPEED_0 0 //モータへの電圧(スピード)を3種類用意 #define SPEED_1 77 #define SPEED_2 153 //0~255(MAX):Vref電圧を3Vまでに制限 // set pin numbers: // 右キャタピラ用ピン const int R_Vref = 5; //D5(PWM) const int R_OUT1 = 3; //D3 const int R_OUT2 = 4; //D4 // 左キャタピラ用ピン const int L_Vref = 6; //D6(PWM) const int L_OUT1 = 7; //D7 const int L_OUT2 = 8; //D8 // 初期化(電源投入/リセット時1回のみ実行): void setup() { Serial.begin(9600); irrecv.enableIRIn(); // Start the receiver // initialize the motor driver pin as an output(Arduinoにモータドライバへのピンが出力であることを伝える) pinMode(R_Vref, OUTPUT); pinMode(R_OUT1, OUTPUT); pinMode(R_OUT2, OUTPUT); pinMode(L_Vref, OUTPUT); pinMode(L_OUT1, OUTPUT); pinMode(L_OUT2, OUTPUT); } // main loop: void loop() { if (irrecv.decode(&results)) //(★これが無いと動作しない) { switch(results.value) { case UP: //UPなら前進 analogWrite(R_Vref, SPEED_2); // モータドライバのスピードを指定 analogWrite(L_Vref, SPEED_2); digitalWrite(R_OUT1, LOW); //貫通電流防止(ストップ) digitalWrite(R_OUT2, LOW); digitalWrite(L_OUT1, LOW); digitalWrite(L_OUT2, LOW); digitalWrite(R_OUT1, HIGH); digitalWrite(R_OUT2, LOW); digitalWrite(L_OUT1, HIGH); digitalWrite(L_OUT2, LOW); break; case RIGHT: //RIGHTなら右超信地旋回 analogWrite(R_Vref, SPEED_2); // モータドライバのスピードを指定 analogWrite(L_Vref, SPEED_2); digitalWrite(R_OUT1, LOW); //貫通電流防止(ストップ) digitalWrite(R_OUT2, LOW); digitalWrite(L_OUT1, LOW); digitalWrite(L_OUT2, LOW); digitalWrite(R_OUT1, LOW); digitalWrite(R_OUT2, HIGH); digitalWrite(L_OUT1, HIGH); digitalWrite(L_OUT2, LOW); break; case LEFT: //LEFTなら左超信地旋回 analogWrite(R_Vref, SPEED_2); // モータドライバのスピードを指定 analogWrite(L_Vref, SPEED_2); digitalWrite(R_OUT1, LOW); //貫通電流防止(ストップ) digitalWrite(R_OUT2, LOW); digitalWrite(L_OUT1, LOW); digitalWrite(L_OUT2, LOW); digitalWrite(R_OUT1, HIGH); digitalWrite(R_OUT2, LOW); digitalWrite(L_OUT1, LOW); digitalWrite(L_OUT2, HIGH); break; case DOWN: //DOWNなら後進 analogWrite(R_Vref, SPEED_2); // モータドライバのスピードを指定 analogWrite(L_Vref, SPEED_2); digitalWrite(R_OUT1, LOW); //貫通電流防止(ストップ) digitalWrite(R_OUT2, LOW); digitalWrite(L_OUT1, LOW); digitalWrite(L_OUT2, LOW); digitalWrite(R_OUT1, LOW); digitalWrite(R_OUT2, HIGH); digitalWrite(L_OUT1, LOW); digitalWrite(L_OUT2, HIGH); break; case SELECT: //SELECTなら停止(ブレーキ→ストップ) analogWrite(R_Vref, SPEED_0); // モータドライバのスピードを指定 analogWrite(L_Vref, SPEED_0); digitalWrite(R_OUT1, LOW); //貫通電流防止(ストップ) digitalWrite(R_OUT2, LOW); digitalWrite(L_OUT1, LOW); digitalWrite(L_OUT2, LOW); digitalWrite(R_OUT1, HIGH); //ブレーキ digitalWrite(R_OUT2, HIGH); digitalWrite(L_OUT1, HIGH); digitalWrite(L_OUT2, HIGH); digitalWrite(R_OUT1, LOW); //ストップ digitalWrite(R_OUT2, LOW); digitalWrite(L_OUT1, LOW); digitalWrite(L_OUT2, LOW); break; case UP_RIGHT: //UP_RIGHTなら右前進緩旋回 analogWrite(R_Vref, SPEED_1); // 右キャタピラの速度を遅く analogWrite(L_Vref, SPEED_2); // 左キャタピラの速度を速く digitalWrite(R_OUT1, LOW); //貫通電流防止(ストップ) digitalWrite(R_OUT2, LOW); digitalWrite(L_OUT1, LOW); digitalWrite(L_OUT2, LOW); digitalWrite(R_OUT1, HIGH); digitalWrite(R_OUT2, LOW); digitalWrite(L_OUT1, HIGH); digitalWrite(L_OUT2, LOW); break; case DOWN_RIGHT: //DOWN_RIGHTなら右後進緩旋回 analogWrite(R_Vref, SPEED_1); // 右キャタピラの速度を遅く analogWrite(L_Vref, SPEED_2); // 左キャタピラの速度を速く digitalWrite(R_OUT1, LOW); //貫通電流防止(ストップ) digitalWrite(R_OUT2, LOW); digitalWrite(L_OUT1, LOW); digitalWrite(L_OUT2, LOW); digitalWrite(R_OUT1, LOW); digitalWrite(R_OUT2, HIGH); digitalWrite(L_OUT1, LOW); digitalWrite(L_OUT2, HIGH); break; case UP_LEFT: //UP-LEFTなら左前進緩旋回 analogWrite(R_Vref, SPEED_2); // 右キャタピラの速度を速く analogWrite(L_Vref, SPEED_1); // 左キャタピラの速度を遅く digitalWrite(R_OUT1, LOW); //貫通電流防止(ストップ) digitalWrite(R_OUT2, LOW); digitalWrite(L_OUT1, LOW); digitalWrite(L_OUT2, LOW); digitalWrite(R_OUT1, HIGH); digitalWrite(R_OUT2, LOW); digitalWrite(L_OUT1, HIGH); digitalWrite(L_OUT2, LOW); break; case DOWN_LEFT: //DOWN-LEFTなら左後進緩旋回 analogWrite(R_Vref, SPEED_2); // 右キャタピラの速度を速く analogWrite(L_Vref, SPEED_1); // 左キャタピラの速度を遅く digitalWrite(R_OUT1, LOW); //貫通電流防止(ストップ) digitalWrite(R_OUT2, LOW); digitalWrite(L_OUT1, LOW); digitalWrite(L_OUT2, LOW); digitalWrite(R_OUT1, LOW); digitalWrite(R_OUT2, HIGH); digitalWrite(L_OUT1, LOW); digitalWrite(L_OUT2, HIGH); break; default: break; } irrecv.resume(); // 受信機をリセットする(★これが無いと1回のみの制御となる) } }
※#include <IRremote.h>は表示の不具合で全角<>で記載しています。本当は半角<>ですのでご注意ください。
【動作確認】
早速、動かしてみます。
右/左と緩旋回もできています。動作の変化時のwaitも外したので、前回よりスムーズに動作してラジコンらしい動きになりました。直進でやや左に寄ってしまうのはおそらく車軸がずれているか?、それともVref電圧に少々の電圧差があるのかもしれません。真っ直ぐ走らせるためにはこのズレを補正する形でVref電圧を調整すればよいのですが、今回はやりません。(動けばOK!だったので。。。)
リモートコントロール(RC)戦車をつくる【赤外線コントロール②】 [RC戦車]
これまで使った赤外線リモコン(SparkFun 赤外線リモコン COM-11759)では4方向のボタンしかありませんので、前後進と左右の4方向の動きしかできません。特に左右に曲がる場合には超信地旋回(スピンターン)というものでしていますが、ふつうに曲がりたいわけです(緩旋回というらしいです)。
で、もうちょっと方向ボタンがあるリモコンがないかなー?と探していたらありました。
↓これです。秋月電子で300円(税抜)です。
オプトサプライ赤外線リモコン[OE13KIR]
"http://akizukidenshi.com/catalog/g/gM-07245/"
取扱説明書を読むとデータフォーマットは"NECフォーマット"で、受信したときのコードもこれまでのSparkFunの赤外線リモコンと同じなので、プログラムにはデータコードを追記するだけでそのまま流用できそうです。
が。。。、そうは簡単にはいかないもので、試しにやってみると全く動きません
追加したところ以外の前後進と左右も動きませんので、今回改造した部分が悪いわけではなさそうです。
そうなると赤外線リモコンが壊れているか? or 取扱説明書とは別のコードを発信しているか?ですが、オシロで見たところ何らかの信号は出ているので壊れてはいないようです。
となると、”別のコードを発信してる?”となるわけですが、それをどう確かめるかです。
ググると純粋に”赤外線リモコンを作ろー!”的なサイトがたくさんありますので、リーダーコードから順次読み込んでいくようなプログラムも掲載されているのですが、そこまで手を広げるとちょっと難易度も上がるので避けたいところです。
で、ありました。Arduinoのサンプルスケッチで受信したコードをシリアルモニタに表示してくれるのが。。。
”IRrecvDumpV2”というスケッチです。
早速、これをArduino unoにダウンロードして使ってみます。
Auduino unoの配線図とかはこちら↓を参照してください。
リモートコントロール(RC)戦車をつくる【赤外線コントロール】
うーん、違いますねー。。。
取扱説明書ではSparkFun COM-11759と同じですから、次のようになっています。
UP :0x10EFA05F
DOWN:0x10EF00FF
LEFT :0x10EF10EF
RIGHT:0x10EF807F
なぜ取扱説明書と違うかは今は気にせず(ごめんね、いい加減で)、判ったコードでスケッチを書き直してみます。
で、もうちょっと方向ボタンがあるリモコンがないかなー?と探していたらありました。
↓これです。秋月電子で300円(税抜)です。
オプトサプライ赤外線リモコン[OE13KIR]
"http://akizukidenshi.com/catalog/g/gM-07245/"
取扱説明書を読むとデータフォーマットは"NECフォーマット"で、受信したときのコードもこれまでのSparkFunの赤外線リモコンと同じなので、プログラムにはデータコードを追記するだけでそのまま流用できそうです。
が。。。、そうは簡単にはいかないもので、試しにやってみると全く動きません
追加したところ以外の前後進と左右も動きませんので、今回改造した部分が悪いわけではなさそうです。
そうなると赤外線リモコンが壊れているか? or 取扱説明書とは別のコードを発信しているか?ですが、オシロで見たところ何らかの信号は出ているので壊れてはいないようです。
となると、”別のコードを発信してる?”となるわけですが、それをどう確かめるかです。
ググると純粋に”赤外線リモコンを作ろー!”的なサイトがたくさんありますので、リーダーコードから順次読み込んでいくようなプログラムも掲載されているのですが、そこまで手を広げるとちょっと難易度も上がるので避けたいところです。
で、ありました。Arduinoのサンプルスケッチで受信したコードをシリアルモニタに表示してくれるのが。。。
”IRrecvDumpV2”というスケッチです。
早速、これをArduino unoにダウンロードして使ってみます。
Auduino unoの配線図とかはこちら↓を参照してください。
リモートコントロール(RC)戦車をつくる【赤外線コントロール】
うーん、違いますねー。。。
取扱説明書ではSparkFun COM-11759と同じですから、次のようになっています。
UP :0x10EFA05F
DOWN:0x10EF00FF
LEFT :0x10EF10EF
RIGHT:0x10EF807F
なぜ取扱説明書と違うかは今は気にせず(ごめんね、いい加減で)、判ったコードでスケッチを書き直してみます。
リモートコントロール(RC)戦車をつくる【組み上げ~動作確認】 [RC戦車]
制御回路部の作製ができたので、ベース車体を組み上げます。
制御回路部とモバイルバッテリーの高さは、なるべく上面をツラ一に合わせるようにして、フラットな感じにしました。
周辺部の赤外線受光部は、暫定的にブレッドボードに実装してモバイルバッテリーに仮置き、ジャンパワイヤで接続しています。
【組み上げ】
【車体①(上面)】
【車体②(側面)】
【動作確認】
いよいよシェイクダウンです。どんなものでも初物はドキドキです。
再生できない場合、ダウンロードは🎥こちら
動作ロジックは間違いなさそうです。
ただ、動作を変えるタイミングで停止(ストップ)と100μsのwaitを入れているので、少々かったるい感じはします。
制御回路部とモバイルバッテリーの高さは、なるべく上面をツラ一に合わせるようにして、フラットな感じにしました。
周辺部の赤外線受光部は、暫定的にブレッドボードに実装してモバイルバッテリーに仮置き、ジャンパワイヤで接続しています。
【組み上げ】
【車体①(上面)】
【車体②(側面)】
【動作確認】
いよいよシェイクダウンです。どんなものでも初物はドキドキです。
再生できない場合、ダウンロードは🎥こちら
動作ロジックは間違いなさそうです。
ただ、動作を変えるタイミングで停止(ストップ)と100μsのwaitを入れているので、少々かったるい感じはします。