🖱️

2015年:ESP-WROOM-02 で【モバイル物理スイッチ】を作る!!

2021/09/11に公開3

※注意)Qiitaからの移転で、2015年12月02日に投稿した記事なので、内容はかなり古いです

2015年12月19日 23時59分追記:申し訳ありません。pullupの仕方に、誤りがありました。
2015年12月20日 14時21分追記:そもそも pullup/pulldown が不要である事が分かりました。

ESP8266 Advent Calendar 2015 の2日目担当 ie4 と申します。

このエントリーでは、「ESP-WROOM-02を使うと、結局どんなものが作れるのか。」という疑問に答えるべく、その1例を挙げてみたいと思います。

携帯できるインターネット物理ボタンを作ろう

ESP_WROOM_02_NETBOTTUN 01

Web上のアプリケーションに、ON/OFFの信号を送る物理ボタンを作ります。
で、その物理ボタンにバッテリーを繋いで、持ち歩けるようにするのが目標です。

ぶっちゃけ、物理ボタンである事にこだわらなければ、スマホで実現可能な機能です。

ただ、物理ボタンには、こだわるだけの価値があります

  • 操作する人への案内が簡単:「このQRを読んで、このURLにアクセスして、それから…」と長々と説明しなくても、この物理ボタンを手渡せば終了
  • 操作が簡単で、誤操作がない: 余計なボタンや機能がないので、ホームボタンやメニューボタンなど、変なボタンを押してしまって、アタフタする事がない
  • ボタンをカチカチすることの楽しさ: 説明しづらいけど、ボタンカチカチは楽しい

この辺が、私の考える物理ボタンの良さです。

ESP_WROOM_02_NETBOTTUN 02

で、作るのは良いけど、その物理ボタンが結局何の役に立つの、という点ですが、ON/OFFを通知するだけの機能なので、Webアプリ側の作り方次第で何でも出来ます。

オフィスの隅にあるコーヒーメーカーにコーヒーを淹れさせる事も、ドローンにぶら下げたクス玉を割って門出を祝うことも、作り方次第では可能です。(本エントリーより難しい実装が別途必要ですが…)

ESP_WROOM_02_NETBOTTUN 03

とりあえず今回は、YesかNoかを回答するボタンを作成する事にします。
ユースケースは、エントリー後半に記載します。

完成品はこちら

ESP_WROOM_02_NETBOTTUN 04

かなり雑な作りですが、これでも立派にインターネットに繋がります・・・

白いボタンで1、赤いボタンで10をサーバーに送信します。
同時に押した場合は、11が送信され、何も押してない状態に戻ると0が送信されます。

ケースを開けると、中身は
ESP_WROOM_02_NETBOTTUN 05
このようになっており、
基板を裏返すと
ESP_WROOM_02_NETBOTTUN 06
このようになっております… (お見せするのが恥ずかしい有様です…)

次に、ただサーバーへ数値を送信するだけでも意味がないので、それをモニタリングします。
サーバー側はNode.jsで実装し、socket.ioを使って、Web画面を切り替えています。

ESP_WROOM_02_NETBOTTUN 07
ボタンを何も押していない時は、**?**が表示されます。

ESP_WROOM_02_NETBOTTUN 08
赤いボタンを押せばNoが表示され、

ESP_WROOM_02_NETBOTTU 09
白いボタンを押せばYesが表示されます。

以上が、最終的に作るモノになります。
以下、作り方となります。

用意したモノ

ESP-WROOM-02 ピッチ変換済みモジュール (フル版)

https://www.switch-science.com/catalog/2347/

  • これが無いと始まりません。
  • ピッチ変換済みのESP-WROOM-02モジュールは、各社から出ていますが、今回はスイッチサイエンスさんのフル版を利用しました。
  • ボタンの入力に使うのは2ピンだけなので、デジタル入力できるピンが2つ空いていれば、どのモジュールでも良いかと思います。ただ、ケースに収まるサイズを選ぶようにしましょう。
  • ピンヘッダを付けるために、はんだ付けする作業が必要です。

リチウムイオンポリマー電池 3.7V 400mAh

https://www.switch-science.com/catalog/821/

  • 今回の工作の要は、なんと言ってもこの電源(バッテリー)です。サイズ的にもジャストサイズで、電圧も容量もジャストです。電源の確保については、CR2032・CR2450・18650等など、色々と試行錯誤した結果、最終的にココに落ち着きました。
  • 先日まで品切れ状態でしたが、大量入荷したようです。
  • スイッチサイエンスさんのページにも記載がありますが、取扱いには十分にご注意ください。

リチウムイオン電池充電器 (マイクロUSBタイプ)

https://www.switch-science.com/catalog/506/

  • 上記バッテリーと一緒に購入しておきましょう。
  • PCでの充電用にマイクロUSBケーブルが別途必要ですが、マイクロUSBタイプの携帯充電器があれば、その携帯充電器から充電可能なので、マイクロUSBケーブルは不要です。

JST製2ピンPHコネクタ用ソケット

https://www.switch-science.com/catalog/2090/

  • 基板へバッテリーを接続する際に必要になります。

普通のピンヘッダ10本セット

https://www.switch-science.com/catalog/92/

  • ESP-WROOM-02を基板に取り付ける際に必要になります。
  • また、他の用途にも活躍するので、ぜひ持っておきたい消耗品です。

スライドスイッチ

http://www.marutsu.co.jp/pc/i/14846/

  • 基板に取り付け、電源のON/OFFに使用します。

ポータブル プラスチックケース

http://www.marutsu.co.jp/pc/i/101676/

  • もろもろ、このケースに収めます。手のひらに完全に収まるサイズです。

ユニバーサル基板 (44mm×69mm)

http://www.marutsu.co.jp/pc/i/14190/

  • 上記ケースにスッポリ収まる基板です。
  • ケースにカチッとはハマらないので、ケースの中身がカタカタするのが嫌な場合は、ケースにねじ止めするなりする必要があります。

タクトスイッチキャップ 2個 + タクトスイッチキャップ (赤、白 各1個)

http://www.aitendo.com/product/9609
http://www.aitendo.com/product/9530

  • 押しボタンはこちらを使います。

カーボン抵抗 10kΩ

http://akizukidenshi.com/catalog/g/gR-25103/

  • 追記:今回のケースでは、pullup/pulldown抵抗は不要でした。
  • プルアップ/プルダウン抵抗に使用します。
  • 実は、うっかりコレを実装するのを忘れてしまったのですが、それでも動くには動くようです。とはいえ、パーツを破損させない為にも、「なぜか動かない!><」という事態を回避する為にも、実装しておいた方が良いです。 追記:今回のケースでは、スイッチング等の開放状態が発生しない為、電流制限抵抗等の目的がない限り、プルアップ/プルダウンは不要でした
  • プルアップ/プルダウン抵抗に関しては、後述します。

その他

電子工作用はんだ

http://www.amazon.co.jp/dp/B0029LGANO/

  • 電子工作と言えば、はんだですね。
  • ブレッドボードのおかげで、「とりあえず動くもの」を作るのは簡単になりましたが、色んなパーツと組み合わせたり、ケースに入れて云々…とこだわりだすと、やはり避けては通れないのが、はんだ付けです。
  • ワイヤラッピング - Wikipediaという、はんだ付けを行わない電子配線もあるみたいです。⇒ ラッピングツール - 共立エレショップ

ダイヤル式温度制御はんだこて

http://www.amazon.co.jp/gp/product/B006MQD7M4/

ラッピングワイヤ 5色セット

http://www.amazon.co.jp/gp/product/B005FNVOWU/

  • 映画などで、ニッパーでちょきんと切ると、タイマーが止まったり、早まったりする奴ですね。
  • 剥き出しの銅線だと、基板の裏で交差したり出来ないので、被膜付きの銅線が必要です。
  • 太すぎると取り回しが不便ですが、細すぎると加工が難しいです。

スズメッキ線 φ0.6mm

http://www.amazon.co.jp/dp/B00FIXM89U/

  • ほとんど使ってないので、不要かもしれませんが、持っておくと役に立ちます。
  • 抵抗やコンデンサなどの、切り落とした余分な足を再利用するケースも多々あります。

FTDI USB・シリアル変換ケーブル (3.3V)

http://akizukidenshi.com/catalog/g/gM-05840/

  • ESP-WROOM-02 へのプログラミングは、コレ経由でやることにします。
  • 電圧をお間違えなく(5Vではないです)。
  • いささか高いので、この辺もある程度自作したい感じではあります。(まぁ、いくつも必要なモノではありませんが)

ホットナイフ

http://www.amazon.co.jp/gp/product/B0016V7JII/

  • ケースから押しボタンを出すため、矩形の穴を開けるのに使用しました。
  • ただ、プラスティックを溶かして穴を開ける為、バリも大きく、嫌な臭いも出るので、ドリルで小さな穴をたくさん開けて、矩形状にくり抜く方が良さそうです。

配線・回路図

本エントリーでは、ESP-WROOM-02へのスケッチの書き込み方や接続の方法については触れません。
後日、誰かがきっと、そのようなエントリーを投稿してくれるでしょうし、もうあるかもしれません。

というわけで早速、完成した携帯できる物理スイッチが、どのような構成になっているかを見てみます。

配線は、下記のようにしました。
※スケッチ書き込み済みの FLASH Boot Mode での配線です。

追記: pullupの配線に誤りがありました。正しくは、2つ目の図の配線となります。

▼誤りがある方の図
ESP_WROOM_02_NETBOTTUN 11 NG

▼正しい方の図
ESP_WROOM_02_NETBOTTUN 11 OK
※手書きで申し訳ありません…

  • pullup抵抗とpulldown抵抗が入っていますが、「pullup/pulldwonってなんぞ!」という方は、こちらの動画「【実況?】 零からの電子工作 第10回:タクトスイッチ 後編」で非常に分かり易く解説されているので、視聴をオススメします(9分20秒辺りからpullup抵抗を無くした場合の実際の挙動が見れます)。 追記:動画は、不安定になるのを防止する目的でpullup/pulldownを入れていますが、上図では開放状態(不安定になる状態)が発生しない為、実際は、電流制限抵抗としての役割しかありません。電流制限抵抗としての役割が不要であれば、pullup/pulldown抵抗も不要です。

書き込み済みのスケッチは、下記になります。

#include <ESP8266WiFi.h>

const char* ssid     = "お使いのWiFiのSSIDを入れてください";
const char* password = "お使いのWiFiのPasswordを入れてください";
const char* host = "IPアドレス or ホスト名"; // Webアプリを設置するサーバー
const int port = 20000; // 接続を受け付けるポート

const int btnYes = 12;
const int btnNo  = 13;
int curData ;
int tmpData ;

void setup() {
  pinMode(btnYes, INPUT_PULLUP);
  pinMode(btnNo, INPUT_PULLUP);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}

void loop() {
  int yesState = digitalRead(btnYes);
  int noState = digitalRead(btnNo);
  curData = 0 ;
  if(!yesState){
    curData = 1 ;
  }
  if(!noState){
    curData |= 1 << 1 ;
  }
  if ( tmpData != curData ) {
    sendMessage(curData);
    tmpData = curData;
  }
  delay(50);
}

void sendMessage(int data) {

  WiFiClient client;
  if (!client.connect(host, port)) {
    return;
  }

  client.print(data, BIN);

  while (client.available()) {
    String line = client.readStringUntil('\r');
  }

}

WiFiへの接続が成功すれば、これで該当サーバーのポート:20000番へデータを送信します。

サーバー側

サーバー側では、Node.js でデータを受け付けます。

Webアプリですが、通常の80番ポートは使用せず、下記の2つのポートを使用する事にしました。

8888番ポート: モニタリングWebアプリ用ポート
20000番ポート: 物理ボタンからのデータの受け取り

app.js
var net = require('net'),
    http = require("http"),
    socketio = require("socket.io"),
    fs = require("fs");

// モニタリング画面の用意
var server = http.createServer(function(req, res) {
	res.writeHead(200, {"Content-Type":"text/html"});
	var output = fs.readFileSync("./index.html", "utf-8");
	res.end(output);
}).listen(8888);
var io = socketio.listen(server);

// 物理ボタンからのデータ受け口
var server = net.createServer(function(conn){
  conn.on('data', function(data){
    console.log(data.toString('ascii'));
    // モニタリング画面へデータ送信
    io.sockets.emit("message", {value:data.toString('ascii')});
  });
}).listen(20000);
index.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Yes/No Bottun</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
var socket = io.connect();
socket.on("connect", function(){});
socket.on("disconnect", function(client){});
socket.on("message", function(data){ addMessage(data.value); });
function addMessage(val) {
	if(val==1){
		color = "#fff";
		fontc = "#000";
		text = "Yes";
	}else if(val==10){
		color = "#f00";
		fontc = "#fff";
		text = "No";
	}else{
		color = "#333";
		fontc = "#fff";
		text = "?";
	}
	$("#answer").css("background-color",color);
	$("#answer").css("color",fontc);
	$("#answer").text(text);
}
</script>
<style>
body{
  background-color: #000;
}
#answer{
  height: 300px;
  width:  300px;
  font-size: 150px;
  font-weight: bold;
  color: #fff;
  display: table-cell;
  vertical-align: middle;
  text-align: center;
  background-color: #333;
}
</style>
</head>
<body>

<div id="answer">?</div>

</body>
</html>

必要に応じて、requireされているモジュールをnpmなりでインストールしておいてください。

動作確認

ユニバーサル基板へ各パーツをはんだ付けし、配線を済ませ、バッテリーを繋いで、node appすれば、準備はすべて完了です。

http://WebアプリのIPアドレス:8888/へアクセスすると、以下のような?マークの画面が表示され
ESP_WROOM_02_NETBOTTUN 12
白と赤の物理ボタンで、YesNoの表示に切り替わります。
※離すとまた**?**に戻ります

また、ターミナル上にも

$ ls
app.js  index.html
$ 
$ node app
1
0
10
0

のように、物理ボタンから送信された数値が、ほぼリアルタイムで表示されます。

以上で、インターネット接続可能な持ち歩ける物理ボタンの完成です。

おまけ

ユースケース

Webアプリ側は作り変える必要がありますが、例えばこんな使い方。

  • 100個作って、その場で人気投票大会
  • 10個作って、審査員10名によるオーディション (8イイネ以上が合格)
  • 5個作って、審査員5名による、紅白戦 (3イイネ以上が勝利)
  • 1個作って、誰かが隠し持ち、みんなの質問にYes/Noで答えて(Yes/Noの回答は画面で確認)、誰がもってるか当てる

ちょうど忘年会シーズンですので、何かのゲームに使ってみてはいかがでしょうか。

書き終えてみて

  • Advent Calendar 初投稿でした。作法とかよく分かっていないので、至らぬ点もあったかも。
  • スイッチという表記と、ボタンという表記が混在し、統一できていない…スイッチは機能として、ボタンはUIとして、書き分けているとお考えください。
  • イメージが湧きやすいようにと、イラスト付きで臨みましたが、逆効果だった可能性も。
  • 作っても作っても、作りたいモノが無くならないのが、ESP-WROOM-02の面白さかもしれません。

Discussion

ie4ie4

本エントリーについては、過去に色々と誤りを指摘頂いているので、その内容も残しておきます。

▼ご指摘

これプルアップ/ダウン要ります?

..snip..

基本的にICの入力がH/Lレベル固定なら直結でいいと思います。
今回はGPIOらしいので、
うっかり操作で出力に設定した時のための電流制限抵抗を心配なら入れますが、
だったらIO12/13にも入れるべきなので、結局じゃあいいやってなりますね。

..snip..

H/L切替えではなく、I/O切り替えです。
ENピンはGPIOらしいので、やろうと思えば出力にも設定できます。
そうしてしまうと、出力ピンに3.3Vを繋ぐことになります。
このときENピンからLレベルを出力すると
(Hレベルでも微妙に電位差がある場合は)ショートするので、保護のため抵抗を入れるということです。

▼わたし

確かに、pullupもpulldownもしていない状態で、動作は確認できてますね。

ただ、短時間(10分程度)での使用でしか確認していないのと
pullup、pulldownを追加した状態でも、問題なく動作が確認できており、
ICへH/Lを入力する際は、pullup、pulldownする方が安定するという現状の理解と、
「pullupとpulldownは不要である」という確固たる情報が現状得られていない為、
現状「pullup/pulldown すべし」としました。
※エントリー内の動画リンク「pullup」の説明でも、
 ロジックICへpullupせずにH(5V)を入力すると、動作が不安定になっていた為
 H(5V)直結は、あまり良い方法ではないと考えた感じです

ESP-WROOM-02側(EN,IO00,IO02,IO15等の内部)で、
特に指定せずとも、pullup/pulldown処理をしてくれているのですかね。
直結では、電圧(H/L)は安定しない、というのが現状の理解でして・・・

▼ご指摘

エントリー内の動画とは全然状況が違いますよ。

ロジックICへpullupせずにH(5V)を入力すると

していません。入力したのはHi-Z(開放状態)です。

ロジックICのピンとESP-WROOM-02のGPIOでは、その性質が異なる

いやそうではなく、ロジックICでもH(L)レベルに固定するなら、
プルアップ(ダウン)目的の抵抗は0です。(他に心配がないなら)直結します。

ネット上によくある、ESP-WROOM-02のIO00,02,15等をpullup/pulldownしている例は、何を目的としたpullup/pullodownなのでしょうか。

電流制限抵抗かと
参考

▼わたし

なるほど。理解しました。

確かに、H(5V)は入力していませんね。
思いっきり勘違いでした。
不安定になったのは、H入力でもL入力でもない、Hi-Z(どこにも繋がってない状態)ですね。

pullup/pulldownは、開放状態を作らない為で、特に心配がなければ直結でもOKなんですね。
開放状態が発生しない今回のケースでは、開放状態を避ける為の pullup/pulldown は不要である、と。
で、GPIOから電流が流れ出てしまった場合に備える場合は、電流制限抵抗をいれる、と。
※その心配がなければ、そもそも抵抗は不要

勉強になりましたmm

ie4ie4

▼ご指摘

Lipoは充電完了時に4.2Vありますので、ESP8266がかわいそうです。
Lipoは過放電にも弱いので、普通は保護チップ推奨かも
このあたりのLipoと
http://tiisai.dip.jp/?p=2335
スマホなどに入っているLDOを使うと幸せになれるかも~

▼わたし

Lipoは充電完了時に4.2Vありますので、ESP8266がかわいそうです。

確かに、充電完了時に4.2V程度の電圧がありますね…

ESP8266をいたわるなら、LDO(低損失定電圧レギュレータ)は実装すべきでしょうね。
無理をさせてる感はありました・・・
※更に言うと、ブレッドボードでのプロトタイピング時は、5Vで動かしたりもしていました・・・
(ごめんなさい、、ESP8266…)

このあたりのLipoと
http://tiisai.dip.jp/?p=2335
スマホなどに入っているLDOを使うと幸せになれるかも~

情報ありがとうございます!

LDOは、今回は無くても動いてくれたため端折りましたが、
電源の保護周りは、もう少し丁寧にやった方が良いかもしれませんね。

Polymer Lithium Ion Battery - 400mAh - Spark Fun Electronics
https://www.sparkfun.com/products/10718

こちらのDatasheetを見ると、
チップ?が2種(8810/TSSOP-8、R5402N149KD/SOT23-6)入っているようなので、
それらがどういう動作をするモノなのか調べてみて、
いただいた情報と合わせて、追って記事を更新しておこうと思います。

さておき、ご指摘・助言ありがとうございます!

▼ご指摘

ああ、保護チップ付きなんですね♪
充電保護してるので、抵抗一本で充電できますよ~

ie4ie4

すごく優しくご指南頂きました。感謝しかないです。