【Arduino】ESP32をWebサーバにしてiPhoneからESP32に接続された6Vモーターを動かす

スポンサーリンク




趣味のプログラム

いきなりだが、農業用ビニールハウスの温度調整は、ハウスサイドのレバー操作でビニールを巻き上げたりしている。

ビニールハウスの数が増えると、その分レバー操作の時間やハウス間の移動にかかる時間が増えていく。

もちろん自動開閉する既製品はあるが、高すぎる!

なので自作してみる事にした。

これは試作品作成までの記録です。

スポンサーリンク

完成した試作品

スマホからWiFiでESP32に接続されたモーターを動かす

YouTubeやブログで情報収集

ネットで検索するとさまざまなやり方が出てきました。

ざっくりまとめるとこんな感じです。

ハウスにあるボタンを手動で操作してモーターを動かす

ハウスにある制御盤により自動でモーターを動かす

スマホからリモート操作でモーターを動かす

結果として同じ動きだとしても、配線や機器の構成など人それぞれだったのでかなり参考になりました。

今回はスマホから複数のモーターを操作させるようにしたいと思います。

スポンサーリンク

イメージを図にする

何となくのイメージを紙に書いて描いて形にしていきます。

こんな感じにしたい!

少し書くとどんどんイメージが膨らんでくる。

カキカキカキカキ_φ(・_・

イメージも膨らみ3段階で完全システム化?の構想です。

書き出す事で、まだ自分でも気づいていない事や分からない事がどんどん出てきます。

モータードライバーってどうやって動かすの?

ESP32ってどんなプログラムで動くの?

スマホからPC経由でモーターを動かせる?

もちろんここでの疑問もネットで調べて潰していきます。

モータードライバーなどの論理回路には正直困りました。

全然わからない・・

少し調べましたが、

全然わからない・・

完全に理解するのは諦めて必要最低限の動きだけ確認しました。

 

イメージを図にできて疑問がほとんど無くなったので、これを設計図として作り始めようと思いました。

いざプログラムを考えていると、どんどんイメージが湧いてくるので先にメモる_φ(・_・

プログラムも書きはじめてからぐちゃぐちゃにならない様に頭のイメージを書き出しておきます。

文字に出すと、これを見ながらここは関数でまとめようとか思いつくので良かったのかなと思います。

arduinoは始めてなのでこのメモの構文はかなり違います。

試作用機器を選ぶ

イメージの段階でほとんど目星はつけていました。

また、前提としてはんだごてを持ってないのではんだ付けをしなくても良い物を選びました。

ESP32-WROOM-32E開発ボード1個

ブレッドボード BB-801 2個

ジャンパーワイヤ(オス-メス)6本

みの虫クリップ&ジャンパーワイヤ2本

電池ボックス 単3×4本

DCギヤードモーター 6V 1個

BTS7960モータードライバー 1個

単三電池4本

Windows OS のパソコン1台

USBケーブルmini B 1本

USBバッテリー1個

スマホ1台

Wi-Fiルーター ASUS RT-AC59U 1台

スポンサーリンク

プログラミング

ESP32WEB画面

基本的に直接ESP32を操作する事は想定しないので超適当です。

ESP32のプログラム

#include <WiFi.h>
#include <WebServer.h>

WebServer server(80);

// WiFi情報
const char* ssid = "ASUS_C8";
const char* pass = "xxxx";

// 最大移動時間
const long max_move_msec = 6000;

// 高さ
long height;

// 出力PIN
const long up_pin = 18;
const long down_pin = 19;

// 初期画面
void slash_root(void){
String _html;
_html = "<!DOCTYPE html>";
_html += "<html>";
_html += "<head>";
_html += "<meta charset=\"utf-8\">";
_html += "<title>Motor</title>";
_html += "</head>";
_html += "<body>";
_html += "<h2>開放率を選択してください。</h2>";
_html += "<ul>";
_html += "<li><a href=\"/move?absolute=100\">開放率100%</a></li>";
_html += "<li><a href=\"/move?absolute=50\">開放率50%</a></li>";
_html += "<li><a href=\"/move?absolute=0\">開放率0%</a></li>";
_html += "</ul>";
_html += "</body>";
_html += "</html>";
server.send(200, "text/html", _html);
}

//絶対値指定のPIN番号を取得
long pin_check(long _height){
if (_height > 0){
return up_pin;
}else if (_height < 0){
return down_pin;
}else{
return 0;
}
}

//絶対値指定の移動時間を取得
long msec_calc(long _height){
if (_height > 0){
return max_move_msec / 100 * _height;
}else if (_height < 0){
return max_move_msec / 100 * _height * -1;
}else{
return 0;
}
}

void slash_move(void){
String _msg;
long _height_diff;
long _move_pin;
long _move_msec;
//絶対値信号の処理
if (server.hasArg("absolute")){
_height_diff = server.arg("absolute").toInt() - height;
}
//相対値信号の処理
if (server.hasArg("relativity")){
_height_diff = server.arg("relativity").toInt();
}
//移動距離0の場合はモータ動作処理へ進まない
if (_height_diff == 0){
server.send(200, "text/plain; charset=utf-8", "モータ動作無し。処理終了します。");
return;
}else{
height = height + _height_diff;
_msg = "ハウス開放率を";
_msg.concat(String(height));
_msg.concat("%に設定します。");
server.send(200, "text/plain; charset=utf-8", _msg);
}

//移動方向と移動時間を求める
_move_pin = pin_check(_height_diff);
_move_msec = msec_calc(_height_diff);

//モータ動作&停止
digitalWrite(_move_pin,HIGH);
delay(_move_msec);
digitalWrite(_move_pin,LOW);
}

void slash_stop(void){
String _msg;
digitalWrite(up_pin,LOW);
digitalWrite(down_pin,LOW);
_msg = "モータ停止。";
server.send(200, "text/plain; charset=utf-8", _msg);
}

// 存在しないアドレスが指定された時の処理
void NotFound(void){
server.send(404, "text/plain", "Not Found.");
}

// 初期化
void setup(){
// シリアルポートの初期化
Serial.begin(115200);

// WiFiのアクセスポイントに接続
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
// ESP32のIPアドレスを出力
Serial.println("WiFi Connected.");
Serial.print("IP = ");
Serial.println(WiFi.localIP());

// PIN初期化
pinMode(up_pin, OUTPUT);
pinMode(down_pin, OUTPUT);

//初期の高さ
height = 0;

// 処理するアドレスを定義
server.on("/", slash_root);
server.on("/stop", slash_stop);
server.on("/move", slash_move);
server.onNotFound(NotFound);
// Webサーバーを起動
server.begin();

height = 0;
digitalWrite(up_pin,HIGH);
delay(1000);
digitalWrite(up_pin,LOW);
delay(1000);
digitalWrite(down_pin,HIGH);
delay(1000);
digitalWrite(down_pin,LOW);
}

// 処理ループ
void loop()
{
server.handleClient();
}

wifiの接続とwebサーバーはライブラリを使い、モーター動作だけ自作しています。

信号の処理としては全開を100とした絶対値でモーターを動かすパターンと、今の開閉率から何%開け閉めするのかを指定する相対値の2種類を使えるようにしました。

手動の場合は絶対値が分かりやすいですが、将来的な温度センサーによる自動制御を考えると、気温が1度上がると10%開けるなどの動作をさせたいのでこうしています。

WEBサーバーの画面

WEBサーバーのHTML


<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" charset="UTF-8">
<meta name="viewport" content="width=360,initial-scale=1">
<title>test</title>
<!--■■■style■■■-->
<style>
input[type=range]
{
writing-mode: bt-lr; /* IE */
-webkit-appearance: slider-vertical; /* WebKit */
width: 8px;
height: 175px;
padding: 0 5px;
}
.f-container{
display:flex;
justify-content: space-around;
flex-wrap: wrap;
}
.f-container .f-item{
width: 50%;
}
</style>

</head>
<body>
<h1>ハウス開閉操作画面</h1>

<div class="f-container">
<div class="f-item">
<h2>ハウス①東</h2>
<form action="http://192.168.50.230/move" method="GET">
<p>Open</p>
<input type="range" name="absolute" step="10">
<p>Close</p>
<input type="submit" class="btn-send" value="動かす">
</form>
<a herf="http://192.168.50.230/stop">止める</a>
</div>

<div class="f-item">

<h2>ハウス①西</h2>
<form action="http://192.168.50.230/move" method="POST" onsubmit="doSomething();return false;">
<p>Open</p>
<input type="range" name="absolute" step="10">
<p>Close</p>
<input type="submit" value="動かす">
</form>
</div>

<div class="f-item">
<h2>ハウス②東</h2>
<form action="http://house2-east/move" method="POST" onsubmit="doSomething();return false;">
<p>Open</p>
<input type="range" name="absolute" step="10">
<p>Close</p>
<input type="submit" value="動かす">
</form>
</div>

<div class="f-item">
<h2>ハウス②西</h2>
<form action="http://house2-west/move" method="POST" onsubmit="doSomething();return false;">
<p>Open</p>
<input type="range" name="absolute" step="10">
<p>Close</p>
<input type="submit" value="動かす">
</form>
</div>

</div>

</body>
</html>

試作品のモーターは1台ですがモーター4台を想定して作っています。

今はHTMLベタ書きですがモーター分繰り返しでHTMLを構成するようJavaScriptなどで描き直したいです。

組み立て

ここもイメージ図を見ながら接続していきます。

ESP32をブレッドボードに付ける所で苦戦しました。

ピンが多いので堅い。

少し調べるとESP32のピンはブレッドボードと若干ズレがあるようなのでブレッドボードの端を外しました。

裏のシール部分はカッターで軽く切れ目を入れてボード部分は手で外せます。

 

あと、押し込む時に上側のピンが親指に食い込んで痛い。

ポストイットを挟む事で力をかけてブレッドボードにしっかり接続する事ができました。

スポンサーリンク

完成(動かしてみた動画)

スマホからWiFiでESP32に接続されたモーターを動かす

ESP32起動直後に合図として正回転1秒、逆回転1秒を行います。

操作内容

①50%まで開ける操作→下回転

②100%まで開ける操作→下回転

③100%まで開ける操作→既に100%なので動作無し

④0%まで閉める操作→上回転

最大開放は6秒に設定しているので0%から50%は3秒回転します。

HTMLが雑なので毎回戻るを押さないといけませんが、まぁ想定通り動くので良いだろう。

この後

実際に農業用ビニールハウスのモーターを動かす場合は24Vのモーターを想定しているので、電池の部分を家庭用コンセントの100Vに変えます。

その際に100Vから24Vに変化させるコンバータを挟もうと考えています。

ACアダプタってやつですね。

実際の環境で試運転させたいですが、まだHTMLもプログラムも甘いのでもう少しブラッシュアップさせてからになりそうです。

最後に

安く済ませたい為の自作なので調べる事も多く、勉強しないといけない事もあるかもしれません。

初めてだと難しいと思うかもしれませんが、できる限り書いたつもりなので少しでも参考になれば幸いです。

あなたの作る装置がうまく動くことを祈ります。

自作に関するひとりQA集

Qモータードライバーは何故必要なのか?

A ESP32などのマイコンの信号ではハウスのモーターを動かすほどの電気を出せない。

だからと言ってマイコンにコンセントの電気を使うとマイコンが壊れてしまう。

そこでマイコンの信号を受けとる部分と、その信号によってコンセントの電気をモーターに流す部分の両方を行なってくれるのが今回言っているモータードライバーです。

Qマイコンはどうやって選べばいい?

A今回は無線通信をしたかったのでwifi付きモデルにしました。

後、マイコンによって使えるプログラム言語が違うので、自分の扱いたいプログラム言語を認識する物を選べば良いです。

マイコンとして人気のあるRaspberry Piでも良かったのですが、wifiが標準で付いていない点と、ESP32より値段も高く高性能なのでオーバースペックかなと思いました。

Q実際のボタン操作でも動かせる?

A試作品の状態では動かせません。

ですが、ボタンのパーツを買ってブレッドボードに取り付ければボタン操作で開閉させる事ができます。

arduinoプログラムの書き換えが必要です。

Q温度センサーは付けれる?

A付けれます。

温度センサーのパーツを買ってブレッドボードに取り付ければ温度を感知できます。

arduinoプログラムの書き換えが必要です。

Q温度によって自動開閉できる?

Aできません。

やる場合は、温度センサーを付けてその情報をESP32で処理するようにarduinoプログラムの書き換えが必要です。

Q外出先からも操作できる。

Aできません。

やる場合は、WEBサーバーとして動かしているPCをインターネットに公開すれば外出先からも操作可能になります。

Q WEBサーバーのPCって必要なの?

Aいいえ。

PCが無くても直接ESP32を指定して接続すればモーターは動かせますが、毎回選ぶのは面倒です。

Q何故WEBサーバーからESP32の通信をHTTPにしているの?

A WEBサーバー故障時でもスマホから操作出来るようにしたかったからです。

HTTPを使わずIPアドレスの指定で信号を出す場合、専用のプログラムをpythoneなどで新たに書く必要があります。

Q同時に複数のモーターを動作動かせる?

A試作品の方式であれば指示は一つずつ出す必要があります。

全く同じタイミングで動作させるにはWEBサーバーのHTMLを書き換える必要があります。

Q回路のGNDとかPWMとかが分かりません。

A説明出来るほどわかっていません(涙)

タイトルとURLをコピーしました