ESPr Developerを使って、スマホからWiFi経由で操作できるロボットを作ろうと思います。
子供部屋にころがっていた「タミヤ 楽しい工作シリーズ組み立てキット リモコンロボット(クローラータイプ)」を使います。
これを ESPr Developer と接続し、WiFi経由で動かせるようにしたいと思います。
ハードウェアの作成(電子回路)
まずは、ハードウェアのうち、電子回路の部分を作成しました。
モータは消費電力が大きいため、ESPr Developerの出力端子を直接繋ぐことはできません。ESPr Developerでモータを制御するためには、モータドライバを使う必要があります。
今回は、秋月電子で購入した「DRV8835使用 ステッピング&DCモータドライバモジュール」を使います。
これひとつで、2個のモータを駆動できます。
IN/INモードの時、以下のとおり動作します(「x」のところに「A」または「B」が入ります)。
MODE | xIN1 | xIN2 | xOUT1 | xOUT2 | FUNC |
---|---|---|---|---|---|
0 | 0 | 0 | Z | Z | 空転 |
0 | 0 | 1 | L | H | 逆転 |
0 | 1 | 0 | H | L | 正転 |
0 | 1 | 1 | L | L | ブレーキ |
今回は、このモータドライバをふたつ使って、モータを4つまで制御できるようにしたいと思います。
回路図は以下のようにしました。下のモータドライバのBIN2はGNDに繋いでいますので、このモータのみ、回転方向を変えることはできず、モータの回転/停止だけを制御できます。
できあがりです。部品はブレッドボードに組み付けました。
動作確認のため、以下のようなスケッチを準備しました。1秒ごとに、各端子のHIGH/LOWを切り替えるだけのものです。
#define A_AIN1 15
#define A_AIN2 13
#define A_BIN1 12
#define A_BIN2 14
#define B_AIN1 4
#define B_AIN2 5
#define B_BIN1 2
void setup() {
pinMode(A_AIN1, OUTPUT);
pinMode(A_AIN2, OUTPUT);
pinMode(A_BIN1, OUTPUT);
pinMode(A_BIN2, OUTPUT);
pinMode(B_AIN1, OUTPUT);
pinMode(B_AIN2, OUTPUT);
pinMode(B_BIN1, OUTPUT);
}
void loop() {
digitalWrite(A_AIN1, HIGH);
digitalWrite(A_AIN2, LOW);
digitalWrite(A_BIN1, HIGH);
digitalWrite(A_BIN2, LOW);
digitalWrite(B_AIN1, HIGH);
digitalWrite(B_AIN2, LOW);
digitalWrite(B_BIN1, HIGH);
delay(1000);
digitalWrite(A_AIN1, LOW);
digitalWrite(A_AIN2, HIGH);
digitalWrite(A_BIN1, LOW);
digitalWrite(A_BIN2, HIGH);
digitalWrite(B_AIN1, LOW);
digitalWrite(B_AIN2, HIGH);
digitalWrite(B_BIN1, LOW);
delay(1000);
}
モータを繋ぐ代わりにLEDを接続して、動作確認しました。所望のとおりに動作しています。
これで、スケッチの内容に従って、モータを動作させることができるはずです。
ソフトウェアの作成(HTMLファイル)
次にソフトウェアを作ります。
今回は、ESPr Developerを、Webサーバとして動作させます。ESPr Developerは、クライアント(スマホ)から受け取った要求に従って、各モータを動かすための処理を行います。
まずは、ソフトウェアのうち、クライアント(スマホ)で表示や操作を行うためのHTMLファイルを作成します。
ここで作ったHTMLファイルは、後ほど、ESPr Developerのフラッシュメモリに保存します。
HTMLファイルでは、formタグでPOST送信を行うことで、Webサーバに要求を送ることにします。
まずは、最も基本的なHTMLファイルを作りました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>WiFi Controller</title>
</head>
<body>
<form action="" method="post"><input type="hidden" name="FLAG" value="FF"><input type="submit" value="↑"></form>
</body>
</html>
スマホでの表示結果は以下のようになります。
ボタンを押すことで、ESPr Developerに要求を送ることができます。
同様のボタンを、モータの動作内容に基づいて追加しました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>WiFi Controller</title>
</head>
<body>
<form action="" method="post"><input type="hidden" name="FLAG" value="FL"><input type="submit" value="←"></form>
<form action="" method="post"><input type="hidden" name="FLAG" value="FF"><input type="submit" value="↑"></form>
<form action="" method="post"><input type="hidden" name="FLAG" value="FR"><input type="submit" value="→"></form>
<form action="" method="post"><input type="hidden" name="FLAG" value="SS"><input type="submit" value="ー"></form>
<form action="" method="post"><input type="hidden" name="FLAG" value="BL"><input type="submit" value="←"></form>
<form action="" method="post"><input type="hidden" name="FLAG" value="BB"><input type="submit" value="↓"></form>
<form action="" method="post"><input type="hidden" name="FLAG" value="BR"><input type="submit" value="→"></form>
</body>
</html>
tableタグを使って、ボタンを分かりやすく並べました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>WiFi Controller</title>
</head>
<body>
<table>
<tr>
<td colspan="3">WiFi Controller</td>
</tr>
<tr>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FL"><input type="submit" value="←"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FF"><input type="submit" value="↑"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FR"><input type="submit" value="→"></form></td>
</tr>
<tr>
<td></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="SS"><input type="submit" value="ー"></form></td>
<td></td>
</tr>
<tr>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BL"><input type="submit" value="←"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BB"><input type="submit" value="↓"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BR"><input type="submit" value="→"></form></td>
</tr>
</table>
</body>
</html>
スマホで適当なサイズで表示されるよう、記述を追加しました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>WiFi Controller</title>
</head>
<body>
<table>
<tr>
<td colspan="3">WiFi Controller</td>
</tr>
<tr>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FL"><input type="submit" value="←"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FF"><input type="submit" value="↑"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FR"><input type="submit" value="→"></form></td>
</tr>
<tr>
<td></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="SS"><input type="submit" value="ー"></form></td>
<td></td>
</tr>
<tr>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BL"><input type="submit" value="←"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BB"><input type="submit" value="↓"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BR"><input type="submit" value="→"></form></td>
</tr>
</table>
</body>
</html>
tableの体裁を整えるための記述を追加しました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>WiFi Controller</title>
<style type="text/css">
<!--
body {
font-family: sans-serif;
}
.tbl {
width: 320px;
font-size: 20px;
font-weight: bold;
text-align: center;
}
-->
</style>
</head>
<body>
<table class="tbl">
<tr>
<td colspan="3">WiFi Controller</td>
</tr>
<tr>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FL"><input type="submit" value="←"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FF"><input type="submit" value="↑"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FR"><input type="submit" value="→"></form></td>
</tr>
<tr>
<td></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="SS"><input type="submit" value="ー"></form></td>
<td></td>
</tr>
<tr>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BL"><input type="submit" value="←"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BB"><input type="submit" value="↓"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BR"><input type="submit" value="→"></form></td>
</tr>
</table>
</body>
</html>
さらに、ボタンの体裁を整えるための記述を追加しました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>WiFi Controller</title>
<style type="text/css">
<!--
body {
font-family: sans-serif;
}
.tbl {
width: 320px;
font-size: 20px;
font-weight: bold;
text-align: center;
}
.btn {
border: none;
padding: 1rem 2rem;
background: limegreen;
color: white;
font-family: sans-serif;
font-size: 1rem;
font-weight: bold;
-webkit-appearance: none;
-moz-appearance: none;
}
-->
</style>
</head>
<body>
<table class="tbl">
<tr>
<td colspan="3">WiFi Controller</td>
</tr>
<tr>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FL"><input type="submit" class="btn" value="←"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FF"><input type="submit" class="btn" value="↑"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FR"><input type="submit" class="btn" value="→"></form></td>
</tr>
<tr>
<td></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="SS"><input type="submit" class="btn" value="ー"></form></td>
<td></td>
</tr>
<tr>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BL"><input type="submit" class="btn" value="←"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BB"><input type="submit" class="btn" value="↓"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BR"><input type="submit" class="btn" value="→"></form></td>
</tr>
</table>
</body>
</html>
最後に、ボタン類が画面の真ん中に表示されるよう、table全体をさらにtableで囲み、それをセンタリングしました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>WiFi Controller</title>
<style type="text/css">
<!--
body {
font-family: sans-serif;
}
.tbl {
width: 320px;
font-size: 20px;
font-weight: bold;
text-align: center;
}
.btn {
border: none;
padding: 1rem 2rem;
background: limegreen;
color: white;
font-family: sans-serif;
font-size: 1rem;
font-weight: bold;
-webkit-appearance: none;
-moz-appearance: none;
}
-->
</style>
</head>
<body>
<table border=0 cellpadding=0 cellspacing=0 width=100% height=100%>
<tr><td align=center valign=middle>
<table class="tbl">
<tr>
<td colspan="3">WiFi Controller</td>
</tr>
<tr>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FL"><input type="submit" class="btn" value="←"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FF"><input type="submit" class="btn" value="↑"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FR"><input type="submit" class="btn" value="→"></form></td>
</tr>
<tr>
<td></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="SS"><input type="submit" class="btn" value="ー"></form></td>
<td></td>
</tr>
<tr>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BL"><input type="submit" class="btn" value="←"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BB"><input type="submit" class="btn" value="↓"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="BR"><input type="submit" class="btn" value="→"></form></td>
</tr>
</table>
</td></tr>
</table>
</body>
</html>
これで、HTMLファイルはできあがりです。
ソフトウェアの作成(ESPr Developer用スケッチ)
次に、ESPr DeveloperをWebサーバとして動作させるためのスケッチを作成します。
クライアント(スマホ)からWebサーバ(ESPr Developer)にアクセスすると、サーバはクライアントに、前回の記事で作ったホームページ(HTMLファイル)を表示させます。
クライアント側で、ホームページ上のボタンをタップすると、その要求がサーバに送られ、サーバはそれに従って、各モータを動かすための処理を行います。
スケッチは以下のような感じです。Arduino IDEのサンプルスケッチ「Arduino」>「ファイル」>「スケッチ例」>「ESP8266WiFi」>「WiFiAccessPoint」を元にして作成しました。
// ライブラリの読み込み
#include <ESP8266WiFi.h> // ESP8266でWiFi接続するためのライブラリ
#include <ESP8266WebServer.h> // ESP8266をWebサーバにするためのライブラリ
#include <FS.h> // ESP8266のフラッシュメモリに読み書きするためのライブラリ
// 変数の定義
const char *ssid = "robot04"; // ESP8266に立ち上げるWebサーバのSSID(適当に決める)
const char *password = "testdata"; // ESP8266に立ち上げるWebサーバのパスワード(適当に決める)
const char *path_root = "/index.html"; // ESP8266のフラッシュメモリに格納しているHTMLファイル名を指定
uint8_t buf[16384]; // 読み出したHTMLファイルの内容を格納するバッファ
// ピンの割り当て(ピン番号を、分かりやすいピン名に置き換える)
#define A_AIN1 15
#define A_AIN2 13
#define A_BIN1 12
#define A_BIN2 14
#define B_AIN1 4 // B_XXXは未使用
#define B_AIN2 5
#define B_BIN1 2
ESP8266WebServer server(80); // Webサーバの設定
void handleRoot() { // クライアントから「/」リクエストを受信した時に実行する関数
if (server.method() == HTTP_POST) { // POSTで受信した場合、以下を実行
String s = server.arg("FLAG"); // FLAGの内容に応じて、各ピンのHIGH/LOWを切り替える
if (s == "FL") {
digitalWrite(A_AIN1, HIGH);
digitalWrite(A_AIN2, LOW);
digitalWrite(A_BIN1, HIGH);
digitalWrite(A_BIN2, HIGH);
} else if (s == "FF") {
digitalWrite(A_AIN1, HIGH);
digitalWrite(A_AIN2, LOW);
digitalWrite(A_BIN1, HIGH);
digitalWrite(A_BIN2, LOW);
} else if (s == "FR") {
digitalWrite(A_AIN1, HIGH);
digitalWrite(A_AIN2, HIGH);
digitalWrite(A_BIN1, HIGH);
digitalWrite(A_BIN2, LOW);
} else if (s == "SS") {
digitalWrite(A_AIN1, HIGH);
digitalWrite(A_AIN2, HIGH);
digitalWrite(A_BIN1, HIGH);
digitalWrite(A_BIN2, HIGH);
} else if (s == "BL") {
digitalWrite(A_AIN1, LOW);
digitalWrite(A_AIN2, HIGH);
digitalWrite(A_BIN1, HIGH);
digitalWrite(A_BIN2, HIGH);
} else if (s == "BB") {
digitalWrite(A_AIN1, LOW);
digitalWrite(A_AIN2, HIGH);
digitalWrite(A_BIN1, LOW);
digitalWrite(A_BIN2, HIGH);
} else if (s == "BR") {
digitalWrite(A_AIN1, HIGH);
digitalWrite(A_AIN2, HIGH);
digitalWrite(A_BIN1, LOW);
digitalWrite(A_BIN2, HIGH);
} else {
digitalWrite(A_AIN1, LOW);
digitalWrite(A_AIN2, LOW);
digitalWrite(A_BIN1, LOW);
digitalWrite(A_BIN2, LOW);
}
}
server.send(200, "text/html", (char *)buf); // クライアントにHTMLファイルを送信
}
void setup() {
pinMode(A_AIN1, OUTPUT);
pinMode(A_AIN2, OUTPUT);
pinMode(A_BIN1, OUTPUT);
pinMode(A_BIN2, OUTPUT);
pinMode(B_AIN1, OUTPUT); // B_XXXは未使用
pinMode(B_AIN2, OUTPUT);
pinMode(B_BIN1, OUTPUT);
digitalWrite(A_AIN1, LOW);
digitalWrite(A_AIN2, LOW);
digitalWrite(A_BIN1, LOW);
digitalWrite(A_BIN2, LOW);
digitalWrite(B_AIN1, LOW); // B_XXXは未使用
digitalWrite(B_AIN2, LOW);
digitalWrite(B_BIN1, LOW);
SPIFFS.begin(); // ファイルシステムを起動
File htmlFile = SPIFFS.open(path_root, "r"); // 読み込みモードでHTMLファイルを開く
size_t size = htmlFile.size(); // HTMLファイルのサイズを確認
htmlFile.read(buf, size); // HTMLファイルの内容をバッファに読み込む
htmlFile.close(); // HTMLファイルを閉じる
WiFi.softAP(ssid, password); // 設定したSSIDとパスワードでWiFiアクセスポイントを起動
IPAddress myIP = WiFi.softAPIP();
delay(500);
server.on("/", handleRoot); // クライアントからの要求に対して、実行する関数を指定
server.begin(); // Webサーバを起動
}
void loop() {
server.handleClient(); // クライアントから受け取ったリクエストを処理
}
ESPr DeveloperのFlashメモリへデータを書き込むためには、Arduino IDEに、SPIFFSファイルシステムアップローダーというものをインストールしておきます。
インストール後、スケッチと同じ場所に「data」フォルダを作り、この下に、前回の記事で作成したHTMLファイルを置きます。
この状態で「Arduino」>「ツール」>「ESP8266 Sketch Data Upload」を実行すると、HTMLファイルをFlashメモリにアップロードすることができます。なお、シリアルモニタを開いている状態ではアップロードできないようです。
この後、スケッチもESPr Developerに書き込みます。これで、ソフトウエアの準備は完了です。
ハードウェアの作成(ロボット)
電子回路ハードウェアをロボットに取り付け、実際にスマホから操作してみたいと思います。
先ほど作成した電子回路ハードウェアはこちらです。ESPr Developerをひとつ、2CHのモータドライバをふたつ搭載しており、4個までのモータの動作を制御できます。
電子回路ハードウエアを取り付けるロボットはこちらです。ふたつのモータで左右のキャタピラを動かすだけのものです。もともと上部に付いていたロボットハンドは、今回は取り除き、ただ走るだけの状態にしています。モータをブレッドボードに接続するために、モータの端子にコネクタピンを取り付けています。
まず最初に、ハードウェアに電池を取り付けます。
ESPr Developerとモータを同じ電池で駆動しようとすると、ESPr DeveloperのWiFi接続が不安定になってしまったため、両者の電池を分けることにしました。今回は、ESPr Developerには単三のニッケル水素電池を4本(1.2V*4=4.8V)、モータ用には同じ電池を2本(1.2V*2=2.4V)使うことにしました。
回路図は以下のとおりです。
ブレッドボードに電池を取り付けると、以下のようになります。
次に、これらをロボットに載せ、モータを接続します。輪ゴムで簡単に固定しているだけです。
いよいよ動かします。
電池をONにした後、スマホでWiFi設定メニューを開くと、WiFiネットワークの中に「robot04」というのが現れますので、それを選択し、パスワード入力欄で「testdata」と入力します。どちらもスケッチの中で定義しているものです。
次に、SafariなどのWebブラウザを開き、アドレス欄に「192.168.4.1」と入力します。これでESPr Developerに格納したHTMLファイルを表示できます。
あとは各ボタンを押すだけで、ロボットを操作できます。
応用編
ここまでで出来上がったものは、ロボットが前後左右に動くだけのもので、操作しているモータは2個だけです。
せっかく、モータを4個まで制御できるようにハードウエアを作ったので、モータをもうひとつ追加してみたいと思います。
なにか面白いネタがないか、いろいろ考えたのですが、あまりいいものが思い浮かばなかったので、全然面白くはありませんが、とりあえずアームを動かす機能を追加することにしました。
まずはHTMLファイルの更新です。テーブルの中に3つのボタンを追加しました。
:
<table class="tbl">
<tr>
<td colspan="3">WiFi Controller</td>
</tr>
<tr>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="PR"><input type="submit" class="btn" value="↓"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="PS"><input type="submit" class="btn" value="ー"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="PF"><input type="submit" class="btn" value="↑"></form></td>
</tr>
<tr><td colspan="3">====================</td></tr>
<tr>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FL"><input type="submit" class="btn" value="←"></form></td>
<td><form action="" method="post"><input type="hidden" name="FLAG" value="FF"><input type="submit" class="btn" value="↑"></form></td>
:
次はスケッチの更新です。handleRoot()関数の中に、追加した3つのボタンに対応する処理を追加しました。
:
} else if (s == "BR") {
digitalWrite(A_AIN1, HIGH);
digitalWrite(A_AIN2, HIGH);
digitalWrite(A_BIN1, LOW);
digitalWrite(A_BIN2, HIGH);
} else if(s == "PF") {
digitalWrite(B_AIN1, HIGH);
digitalWrite(B_AIN2, LOW);
} else if(s == "PS") {
digitalWrite(B_AIN1, HIGH);
digitalWrite(B_AIN2, HIGH);
} else if(s == "PR") {
digitalWrite(B_AIN1, LOW);
digitalWrite(B_AIN2, HIGH);
} else {
digitalWrite(A_AIN1, LOW);
digitalWrite(A_AIN2, LOW);
digitalWrite(A_BIN1, LOW);
digitalWrite(A_BIN2, LOW);
digitalWrite(B_AIN1, LOW);
digitalWrite(B_AIN2, LOW);
}
}
server.send(200, "text/html", (char *)buf); // クライアントにHTMLファイルを送信
}
:
ロボットには、追加のモータ、ギヤボックスとアームを取り付け、モータは、あまっている方のモータドライバのAOUT1、AOUT2に繋ぎました。
再度、スケッチとHTMLファイルをESPr Developerに書き込みます。
前回と同様、スマホのWiFi設定を行えば、以下のように操作できます。
アイデア次第で、いろいろ面白いものも作れそうです。