知的好奇心 for IoT

IoT関連の知的好奇心を探求するブログです

ESP8266とモータードライバを使ってBlynkで操作するカメラ付きキャタピラ車を作ってみた

2020年4月2日更新

ラズパイを使ってパン・チルトもできるラズパイタンクを作りました! 

今までESP8266をセンサーとしか組み合わせたことがなかったので、アクチュエーターとして一般的なモーターを使ってリモコンカーを作ってみることにしました。

f:id:IntellectualCuriosity:20171014231623j:plain
カメラ付きキャタピラ車

ただ、リモコンカーだけだとちょっと寂しいので、少し工夫してスマホのカメラ映像を見ながら遠隔操作できるものにしてみました。

f:id:IntellectualCuriosity:20171014233905p:plain
カメラ映像を見ながら操作できるBlynkリモコン
f:id:IntellectualCuriosity:20171017165006p:plain
テストコース


スマホ画面をキャプチャした試走映像

 

使ったもの

買ったもの

持ってたもの

WeMos D1 Miniは亀の子のようにシールドを重ねることができるので、Motor Shieldを上に重ねてブレッドボード要らずの回路にしました。Motor Shieldにはモーター2個とモーターの電源として電池ボックスを繋いでいます。

f:id:IntellectualCuriosity:20171016195158j:plain
亀の子状態のWeMos D1 MiniとMotor Shield

スマホの固定用にプチブロック、モバイルバッテリーの固定用に粘着タックを使用しました。モバイルバッテリーはWeMos D1 Miniの電源として使用しています。

f:id:IntellectualCuriosity:20171016174838j:plain
キャタピラ車の裏

モーターとギアボックス、電池ホルダーはキャタピラ車の裏に取り付けました。モーターにはケーブルが付いていなかったので、ジャンパーワイヤ(オスーメス)のオス側を切ってモーターに半田付けしています。また、モーターのノイズ防止用にセラミックコンデンサをモーターに半田付けしています。

ソフトウェア

 

Blynk設定

BlynkリモコンにはJoystick WidgetとVideo Streaming Widgetの2つのWidgetを配置しています。

f:id:IntellectualCuriosity:20171017181211p:plain

Joystick

JoystickはX軸とY軸のデータを繋げた機器に送ります。MERGEにするとX軸とY軸を一つのバーチャルピンにまとめることができます。

X軸とY軸のデフォルト値は0~1023になっていますが、その状態ではJoystickを放している時の値がX:512,Y:512になってしまうので、-100~100に変更してJoystickを放している時の値がX:0,Y:0になるように変更しました。

書き込み頻度は100msから設定できますが、データはBlynkのクラウドサーバーを経由して機器に届くため必ず少しのラグが出ます。

Video Streaming

URL ADDRESSにはストリーミングサーバーのURLを指定します。このWidgetクラウドサーバーを使わないので、指定したURLに直にアクセスします。今回使用したIP Webcamではhttp://IP_ADDRESS:8080/videoと指定します。

 

スケッチ

スケッチはかなりシンプルです。使用ライブラリもBlynkとMotor Shieldの2つだけです。Motor Shieldのライブラリは商品説明ページの一番下にあるArduino Libraryリンクの先のGitHubからダウンロードできます。

少し苦労したのが、Joystickのデータを2つのモーターの制御にうまく使えるようにする方法でした。Jostick Widgetの設定でデータの範囲を-100~100にすることで、かなり単純に全方向動作を可能にすることができました。

WeMosのMotor SheildはI2CインターフェースでESP8266と繋がっているので、ESP2866のGPIOを直接制御する必要もなくM1.setmotor(正転・逆転, 速度)で簡単にモーターを制御することができます。

Motor Shieldライブラリの修正 ※2017/10/21  追加 

Joystick操作の反応が悪いのはクラウドサーバーを使っているからだと思っていたのですが、Motor Shieldライブラリに原因がありました。

libraries > WEMOS_Motor_Shield_Arduino_Library-master > src > WEMOS_Motor.cpp

スケッチフォルダにあるlibrariesフォルダからたどっていって、WEMOS_Motor.cppファイルの114行目をdelay(100);からdelay(10);に変更するとJoystick操作の反応が良くなります。

Motor Shieldのファームウェア更新 ※2017/12/18 追加

※2017/2/15 Motor Shieldのファームウェア更新方法の記事を書きました!

たまたま購入したMotor Shieldがハズレだったのかと思っていたのですが、出荷時のファームウェアは少し残念なもののようです。

Motor Shield Reprogrammingという記事にファームウェアの更新方法が書かれていたので、ファームウェアを書き込むのに必要なstm32flashユーティリティのソース(stm32flash-0.5.tar.gz)をここからダウンロードして、Raspberry Piでビルドしインストールしました。

新しいファームウェアはサイトに載っていた「motor_shield.bin」を使いました。あと、USB2TTLの代わりに秋月電子超小型USBシリアル変換モジュールを使いました。

スケッチに合わせた配線 ※2017/10/21 写真修正

f:id:IntellectualCuriosity:20171021155630j:plain

スケッチ ※2017/12/18 スケッチ修正

/*
 * BlynkTank.ino
 * December 18, 2017
 * By Hiroyuki ITO
 * http://intellectualcuriosity.hatenablog.com/  
 * MIT Licensed.
*/
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h> #include <BlynkSimpleEsp8266.h> #include <WEMOS_Motor.h> char auth[] = "Replace here at Your Blynk Auth Token"; char ssid[] = "Replace here at WiFi SSID"; char pass[] = "Replace here at WiFi Password"; //Motor shiled I2C Address: 0x30 //PWM frequency: 1000Hz(1kHz) Motor MR(0x30,_MOTOR_A, 1000); //Motor A (Right) Motor ML(0x30,_MOTOR_B, 1000); //Motor B (Left) int mr_pwn = 0; // MR speed int ml_pwn = 0; // ML speed int mr_dir = 0; // MR direction int ml_dir = 0; // ML direction BLYNK_WRITE(V1) { int x = param[0].asInt(); int y = param[1].asInt(); // Forward or Backward ? if (y > -1) { mr_pwn = y + x; ml_pwn = y - x; } else { mr_pwn = y - x; ml_pwn = y + x; } // Right Motor if (mr_pwn > -1) { mr_dir = _CW; } else { mr_dir = _CCW; } mr_pwn = abs(mr_pwn); if (mr_pwn > 100) { mr_pwn = 100; } MR.setmotor(mr_dir, mr_pwn); // Left Motor if (ml_pwn > -1) { ml_dir = _CW; } else { ml_dir = _CCW; } ml_pwn = abs(ml_pwn); if (ml_pwn > 100) { ml_pwn = 100; } ML.setmotor(ml_dir, ml_pwn); } void setup() { delay(10); Serial.begin(74880); Blynk.begin(auth, ssid, pass); } void loop() { Blynk.run(); // Order to motor MR.setmotor(mr_dir, mr_pwn); ML.setmotor(ml_dir, ml_pwn); // Standby ? if (mr_pwn == 0 && ml_pwn == 0) { MR.setmotor(_STANDBY); // Standby is not related to the left or right. } }

 

おしまい