気の向くままに辿るIT/ICT/IoT
IoT・電子工作

ESP8266を2つ使ったWiFi玄関チャイム・呼び出しベル

ホーム前へ次へ
ESP8266って?

ESP8266を2つ使ったWiFi玄関チャイム・呼び出しベル

ESP8266を2つ使ったWiFi玄関チャイム・呼び出しベル

2018/07/29

 Wi-Fi(wifi)モジュールESP8266の内、ESP-01とESP-12F+ピッチ変換基板(ブレイクアウトボード)の2つを使ったドアベルを自作してみるページ。

 ただし、当然、WiFiが切断されると機能しないし、降圧前の電池電圧が7V切ったあたりで動作しなくなったりと、そもそもWiFi機能は、瞬間的にではあっても往々にして消費電力が高くなる、その際に著しい電圧降下を起こすことがあり、安定したレギュレータを要す他、一般に電池駆動には不向きとされ、双方共にコンセントから電源をとることができる場合は別としても、少なくとも電池駆動にするなら、他の方法(BLE)を選ぶのが賢明と思われます。

 一方、ドアフォン(音声通話や静止画、リアルタイム映像含む)となると主目的が超低消費電力であるBLEにおいては想定の範囲外なのでWiFiも選択肢としてはありかも。

 尚、ここでは、ESP-01とESP-12Fを使っていますが、このドアベルはGPIOを1本ずつしか必要としない為、ESP-01同士でも、上位機種のESP-02...、ESP-07...、ESP-12...、ESP-WROOM-02、ESP32などESP-xxでも、これら開発ボードでもできるということで。

 ただ、ESPシリーズの内、日本の技適を通っていて、モヤモヤすることなく、堂々と使えるものは、いまのところ、ESP-WROOM-02/ESP-WROOM-32(とこれらを搭載した開発ボード)のみ。

 何れにしても最も手軽で手間がなく、限りなく悩みどころが少ないのは、開発ボードです。

前提

 Arduino IDEが利用できることは、もちろん、ESP8266やESP32をArduino IDEで使えるようにしておくこと。

 ESP-01やESP-02〜ESP14などのESP8266チップなら、Arduino IDEの[ツール] => [ボード]から[Generic ESP8266 Module]を選択、ESPモジュールにスケッチをアップロードできる状態であること。

 ESP32なら、[espressif/arduino-esp32]の要領でESPモジュールにスケッチをアップロードできる状態であること。

 ちなみにこれらArduino IDEの環境設定で追加する方法の場合、カンマ区切りで複数指定可能。

 参考までに自身の使用しているOSは、Debian(Linux)、Arduino IDEのバージョンは、1.8.5。

開発ボードの場合[2019/05/14追記]

 尚、ESP8266やESP32の開発ボードである場合、先のようにArduino IDEで利用可能にするとボード情報に様々な関連ボードが追加されるので、使うボードに適したものを選択することになるわけですが、例えば、次のようになります。

 ESP8266 NodeMCUボードなら、Arduino IDEの[ツール] => [ボード]から[NodeMCU 0.9 (ESP-12 Module)]や[NodeMCU 1.0 (ESP-12E Module)]などを選びます。

 ちなみにESP8266 NodeMCUボードについては、ボード上のピン番号(D0-D8)と実際のGPIOが異なるのでプログラム・スケッチを書く場合、標準でインクルードされる模様のpins_arduino.hの定義に沿って指定します。

 また、ESP32 DevKitCやDevKitボードなら、[ESP Dev Module]を選びます。

 開発ボードについては、あとは基本的にArduinoボードと同様にスケッチをアップロード、電源としてUSBケーブルをつなぐか、VIN(5V)/G(ND)に5Vを供給して組んだ回路を実行するだけです。

必要なモノ

 前述の通り、今回のケースでは、WiFiモジュールはどれでもよいですが、サーバ側にESP-12F、クライアント側にESP-01を使いました。

サーバ側
クライアント側

 Amazonマーケットプレイス相場で一部電子部品などは単価割したとしてクライアント・サーバ込みで約2000円程度かと。

ESP-01/ESP-12Fへのスケッチのアップロード準備

 ESP-01や開発ボード以外のESP-12Fにプログラムをアップロードするには、USBポートを備えたCP2102やFTDI系のシリアルUSB変換モジュールを併用する必要があります。

 尚、USBポートを備えた開発ボードではないESP-01〜ESP-14単体及びブレイクアウトボード(≒ピッチ変換基板)との組み合わせは、全て同様にシリアルUSB変換モジュールを要します。

 ESP-01の定格電圧は3.3VなのでシリアルUSB変換モジュールも3.3V専用か3.3V/5V兼用なら3.3Vに切り替えて接続します。

 尚、ESP-01や開発ボード以外のESP-12Fは、プログラム書き込み時と実行時、ESP-01では、RSTとGPIO0のHIGH/LOWを巧みに切り替える、ESP-12では、GPIO00/GPIO15をLOWにする一方、実行時には、GPIO00はHIGHにしておく必要がありますが、RTS/DTRピン(ホール)のあるFTDIモジュールなら、これらにESP-01のRST/GPIO0をそれぞれ、ESP-12ではRESETを接続することで自動でアップロードできる為、これを使うことをおすすめします。

 ただ、これらRTS/DTR、ブレッドボード上でピンホールにジャンパワイヤを挿す場合、ピンヘッダや3.3V/5V切り替え用ジャンパピンのハンダ部が隆起しているのですが、ピンホールが、この付近にある為、USBシリアル変換モジュール並びに挿したジャンパワイヤを手でうまく押さえる必要はあるでしょう。

 なんなら、手で持った方が、安定するでしょう。

 ちなみにESP-01については、SPIFFSを使おうにもフラッシュメモリ容量の関係でArduinoOTAは難しい模様。

ESP-12FTDI別電源
RXTX-
TXRX-
RESETRTS-
GPIO00-マイナス
GPIO02-プラス
GPIO15-マイナス
CH_PC-3.3V
VCC-3.3V
GNDマイナス
ESP-01FTDI別電源
RXTX-
TXRX-
RSTRTS-
GPIO0DTR-
CH_PD-3.3V
VCC-3.3V
GNDマイナス

 また、パソコンのUSBは最大500mAと大丈夫そうに思えるし、実際、たいていの場合、書き込みできますが、往々にしてWiFiモジュールは多くの電流を必要とすることがあり、ESP8266も300mAを超えることもあるとのことなのでそれらが要する電流量不足やパソコンのUSBポートの損傷回避などを考慮し、実行時はもちろんのこと、書き込み時も念の為、別電源をとった方がよさ気。

 尚、検証・運用時には、元電源が3.3Vだと過電流により2V程度まで電圧降下し、ESP8266にリセットがかかり、WiFi接続が途切れるなどの状況になる可能性があるので5Vから降圧、更に電圧降下に耐え得るよう、より短時間で通常電圧に戻る負荷過渡応答特性に優れた電圧レギュレータを使う必要がありそう。

 全ての回路で同じとは限りませんが、とある回路を作って9V電池で動かしてみたところ、7V切ったあたりで動作が不安定になり、電池を交換したら正常になりました。

 ただし、これは、ESP-01やESP-xx+ピッチ変換基板での話であって、開発ボードについては、何らかの対策が講じられているようで、この必要はなさそうです。

回路

ESP-12FTDIブザー別電源
RXDTX--
TXDRX--
GPIO00--プラス
GPIO02--プラス
GPIO15--マイナス
GPIO05-プラス-
CH_PC--3.3V
VCC--3.3V
GNDマイナス
ESP-01FTDIタクトスイッチ別電源
RXTX--
TXRX--
GPIO2-プラス-
CH_PD--3.3V
VCC--3.3V
GNDマイナス

 ESP-12(サーバ側)では、GPIO00をプログラム書き込み時とは異なり、プラスにしておきます。

 サーバ側(ESP-12)のブザー用GPIOには、GPIO05を使い、クライアント側(ESP-01)のタクタイルスイッチ用には、GPIO2を使いました。

 運用・実行時、USBシリアル変換モジュールは、シリアルモニタで確認する場合には配線が必要ですが、そうでなければ外しても構いません。

スケッチ(Webサーバー側)

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
 
/* Set these to your desired credentials. */
const char *ssid = "ESPap";
const char *password = "thereisnospoon";
 
//ESP8266WebServer server(80);
WiFiServer server(80);
 
#define BEAT 500  // 音の長さを指定
#define BUZZER 5  // 圧電スピーカを接続したピン番号
 
void melody()
{
Serial.println("Link Requested from one of the device");
tone(BUZZER,131,BEAT); // ド
tone(BUZZER,165,BEAT); // ミ
tone(BUZZER,175,BEAT); // ファ
tone(BUZZER,196,BEAT); // ソ
delay(BEAT);
 
tone(BUZZER,131,BEAT); // ド
tone(BUZZER,165,BEAT); // ミ
tone(BUZZER,175,BEAT); // ファ
tone(BUZZER,196,BEAT); // ソ
delay(BEAT);
 
tone(BUZZER,131,BEAT); // ド
tone(BUZZER,165,BEAT); // ミ
tone(BUZZER,175,BEAT); // ファ
tone(BUZZER,196,BEAT); // ソ
delay(BEAT);
tone(BUZZER,165,BEAT); // ミ
delay(BEAT);
tone(BUZZER,131,BEAT); // ド
delay(BEAT);
tone(BUZZER,165,BEAT); // ミ
delay(BEAT);
tone(BUZZER,147,BEAT); // レ
delay(BEAT);
 
tone(BUZZER,165,BEAT); // ミ
tone(BUZZER,165,BEAT); // ミ
tone(BUZZER,147,BEAT); // レ
tone(BUZZER,131,BEAT); // ド
delay(BEAT);
tone(BUZZER,131,BEAT); // ド
tone(BUZZER,165,BEAT); // ミ
delay(BEAT);
tone(BUZZER,196,BEAT); // ソ
delay(BEAT);
tone(BUZZER,196,BEAT); // ソ
tone(BUZZER,175,BEAT); // ファ
delay(BEAT);
 
tone(BUZZER,165,BEAT); // ミ
tone(BUZZER,175,BEAT); // ファ
tone(BUZZER,196,BEAT); // ソ
delay(BEAT);
tone(BUZZER,165,BEAT); // ミ
delay(BEAT);
tone(BUZZER,131,BEAT); // ド
delay(BEAT);
tone(BUZZER,147,BEAT); // レ
delay(BEAT);
tone(BUZZER,131,BEAT); // ド
delay(BEAT);
}
void setup() {
 delay(1000);
 Serial.begin(115200);
 
 Serial.println();
 Serial.print("Configuring access point...");
 
 WiFi.softAPConfig(IPAddress(192, 168, 4, 2), IPAddress(192, 168, 4, 1), IPAddress(255, 255, 255, 0));
 WiFi.softAP(ssid, password);
 
 pinMode(BUZZER, OUTPUT);
 digitalWrite(BUZZER, LOW);
 
 IPAddress myIP = WiFi.softAPIP();
 Serial.print("AP IP address: ");
 Serial.println(myIP);
 
 server.begin();
 Serial.println("Server started");
 
 Serial.println(WiFi.localIP());
}
 
void loop() {
 WiFiClient client = server.available(); 
 if (!client) {
  return;
 }
 
 Serial.println("new client");
 while(!client.available()){
  delay(1);
 }
 Serial.printf("Client conenct Access Point: %dn", WiFi.softAPgetStationNum());
 
 String line = client.readStringUntil('r');
 Serial.println(line);
 client.flush();
 
 if (line.indexOf('/MELODY') != -1) {
//  digitalWrite(BUZZER, HIGH);
  melody();
/* 
  line ="";
  digitalWrite(BUZZER, LOW);
*/ 
 
  client.println("HTTP/1.1 200 OK");
  client.println("");                 
  client.println("<!DOCTYPE HTML>");
  client.println("<meta charset='UTF-8'>");
  client.println("<html>");
 
  client.print("<h1>Good Job!</h1>");        
 
  
  
  client.println("</html>");
  delay(1);
  Serial.println("line finish.");
 /*
  Serial.println("Waiting for the link");
  server.handleClient();
 */
 }
}
 

 今回、Webサーバー側は、SOFT_APモードとしました。

 STAモードでもWebサーバーを立てることはできるようですが、未確認。

 尚、サーバ側のIPアドレスは、WiFi.softAPConfig()関数を使って固定としましたが、ESP8266とArduinoでは引数が一部異なるという情報を見かけたのでArduinoで使う場合には要注意。

 あれ、メロディは、『聖者の行進』にしたつもりだったのですが...、まぁ気にしないことにしておこう。

スケッチ(クライアント側)

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
 
#define PUSHbtn 2 //GPIO 2
const char* ssid = "ESPap";
const char* password = "thereisnospoon";
 
void setup() {
 Serial.begin(115200);
 // Serial.setDebugOutput(true);
 Serial.println();
 Serial.println();
 Serial.println();
 
 for (uint8_t t = 4; t > 0; t--) {
  Serial.printf("[SETUP] WAIT %d...\n", t);
  Serial.flush();
  delay(1000);
 }
 
 WiFi.mode(WIFI_STA);
 WiFi.disconnect(true);
 WiFi.begin(ssid, password);
 while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
 
  delay(15000);
  Serial.println("Connected");
 }
 
 pinMode(PUSHbtn, INPUT_PULLUP);
}
 
void loop() {
 if ((WiFi.status() == WL_CONNECTED)) {
 
  HTTPClient http;
 
  if (digitalRead(PUSHbtn) == LOW) {
   Serial.print("[HTTP] begin...\n");
   // requesting required link
   http.begin("http://192.168.4.2/MELODY"); //HTTP
 
   Serial.print("[HTTP] GET...\n");
   // start connection and send HTTP header
   int httpCode = http.GET();
 
   http.end();
  }
 }
}
 

 今回、クライアント側は、STAモードとしました。

[2019/03/16]

 setup()内末尾のとてつもなく意味のない無駄なループをコメントアウトしました。

ネットワークアドレス

 インターネットにつなぐ必要がなく、ESP8266間だけで通信できればよいのであれば、社内や宅内のWiFiルーターやアクセスポイントにつなぐ必要はなく、2つのESP8266間でSSID/パスフレーズとアクセスするIPアドレスさえわかっていれば、SSID/パスフレーズやネットワークアドレスは任意で構いません。

[2019/02/12]

 ん?我ながら、ホントにそうだったっけ?と思わなくもありませんが...仮にそうだとしても無線LANを使う際に同時使用したらIPがバッティングする可能性があるし、ESP8266のスケッチにmDNSを追加する必要はあるにしても無線LANルータ/APに接続して、PCやラズパイがあれば、そこからmDNS.localでアクセス・操作するようにすることもできるし、LANに参加させる前提の方がよいかと。

[2019/03/16]

 あ、確かに無線ルータやアクセスポイントがなくても動作することを再確認しました、って近所の公衆無線LAN前提で繋がったわけじゃ...ないですよね...近所の無線LANアクセスポイント見るとここでSSID設定したESPapがあるから大丈夫ですね。

 これなら、特段の理由でもない限り、ドアベル単独で使うに際しては、LANに参加させる必要はなく、むしろ、参加させない方が、スマートでしょう。

 が...、ESP-01やESP-xx+ピッチ変換基板ではなく、NodeMCU開発ボードで試したところ、応答したはよいものの、クライアントの電源をOFFにしないと延々とメロディが流れ続ける...ついでに言うとメロディが意図したものと違う...現在、再検証中...。

 原因が判明しました。(メロディが音痴なのはさておきます...。)

ESP8266 NodeMCUボードでドアベル

 今回は、クライアント・サーバ共に敢えてNodeMCU開発ボードを使ったのですが、原因は、うっかり、D0(16)をクライアント側ボタンピンに割り当てたからで、これをD1(5)に変更したところ解決しました...。

 NodeMCU開発ボード購入時の動作確認検証でD0は、届いたまま、初期状態で何もしなくても出力があり、サンプルスケッチBlinkをアップするとLOWになるなど謎があったことを忘れていました。(初期状態不定を回避すべく、スケッチ上で全ての未使用ピンの出力設定をLOWにしておくなどすれば回避できるかもしれません。)

 また、関係があるのかは不明も少なくともArduino IDE ver1.8.8では、標準でインクルードされる模様のpins_arduino.hの定義からNodeMCU開発ボードのD0ピンには、Arduinoの(Megaなどにある)D16が割り当てられる一方、NodeMCUボードとしては、その直前でLED_BUILTINに割り当てられています。

 ESP-xx+ピッチ変換基板の場合、GPIO00/GPIO02/GPIO15は、プログラム書き込み時や初回実行時のフラグとしても使われているため、スケッチや回路上で他の用途を割り当てない方が何かと手がかかりません。

 このページのスケッチでは、ボタンピンにそのGPIO02を割り当てており、プログラム書き込み時や初回起動時やWiFi接続時実行時には、該当するジャンパワイヤを抜いておいて明示的にリセットをかけたりする必要がありましたが、たぶん、これらのピンを回避すれば、そのような手間は要らないかと思われます。

 そんな違いを確認するつもりで敢えて購入し、使った開発ボードでしたが、かえって混乱してしまいました...。

 ただ、結果、今回、NodeMCUボードのサーバ側では、変数BUZZERに14(D5)、クライアント側では、変数PUSHbtnに5(D1)をセットし、確認しましたが、何れも配線を抜いておく必要もリセットボタンを押す必要もなく、双方の電源投入だけで即機能しました。

 配線は、ブザーにSignal/VCC/GNDピンのあるモジュールを使ったため、クライアント側は、これをD5/3.3V/GND、サーバ側は、ブレッドボードを介してD1/GND間にタクトスイッチを入れただけ、開発ボードは何らかの対策が講じられているようで別電源も必要なくシンプルに構成できます。(想定していたことではありますが、これも今回、実際に確認したい事項の1つでした。)

ホーム前へ次へ