以前の記事で、AliExpressで安価に販売されているESP-01リレーモジュールを買って、Arduino IDEでプログラムして、HomeKitから使いました。
ただこの時は、リレーを動作させただけで、実際に役立つ工作は行いませんでした。今回はこのリレーモジュールを使って、HomeKit対応セキュリティシステムを作ります。HomeKitのセキュリティシステムに関しては、以下の記事でESP32を使用して作成しました。
同等機能のものを、より安価なESP-01リレーモジュールを使って作り直します。
HomeKitセキュリティシステム
まずはHomeKitセキュリティシステムの復習です。HomeKitには、SecuritySystemというアクセサリが用意されています。これは、ドアセンサ、人感センサ、アラームベルなどが接続されるアクセサリで、センサ検出結果に従ってアラームを鳴らします。アクセサリには、夜間モード、留守モード、在宅モードが用意されていて、それぞれで使用するセンサを切り替えられます。
前回は、このセキュリティシステムをESP32を使って作成しました。以下で簡単に説明します。詳しくは過去の記事を見てください。
まずは、ESP32にパワーFETを取り付けて、警報ブザーを鳴らすハードウェアを作成しました。さらに、MQTTブローカーに接続して、MQTTメッセージに従って動作するプログラムを書き込みました。
今回、このハードウェア部分をESP-01リレーモジュール
に置き換えます。ESP32/ESP-01は、HomeKitにはSecuritySystemとして表示されます。
さらに、ダミーのアラームブザーアクセサリをMQTTプラグインで作成しました。これもESP32/ESP-01が管理します。
人感センサ、開閉センサなどは、検出時にダミーアラームブザーをonにするようオートメーション設定をしておきます。鳴動し続けるのが困るようならば、例えば3分て停止するように設定します。
他にも必要なセンサがあれば、すべてAlarm Buzzerをonにするように設定しておきます。それで、実際に物理的な警報ブザーを鳴らすかどうかは、Security Systemの設定によって、ESP32/ESP-01が判断します。
ESP-01でハードウェアを作る
前回ESP32で作成した部分を、今回はESP-01リレーモジュールで作り直します。
ESP-01とリレーが組み込まれてモジュール化されているので、あとは、これに電鈴と電源を取り付け、箱に収めれば完成です。順番に説明します。
電源を3.3Vにする
このリレーモジュールには、5V電源で動作します。ESP-01とリレーは3.3Vで動作するので、モジュールの中では、3端子レギュレータを使って5Vを3.3Vに変換しています。回路図で確認すると、5Vを使用する部品は一つもありませんでした。ならば、3端子レギュレータをスキップして、3.3V電源で動作させれば、電力ロスを回避できると考えました。コストをかけて5V電源対応している理由は、5V動作することが多い制御回路に組み込みやすいからかなと想像してます。
5VのACアダプタならUSB電源用として多数出回っています。でも3.3Vのアダプタはそれほどありません。それでも近所のハードオフで、税込330円のACアダプタが大量に入ったジャンク箱を漁ったところ、1個見つけました。今後も見つけたら確保しておきたいです。
次に、リレーモジュールの3端子レギュレータを回避するために、その入出力を接続することにしました。回路図では、以下の部分を接続します。
ESP-01のプリントパターンを見たところ、3端子レギュレータは表面実装で、ジャンパ線を取り付けるのが困難でした。その代わり、電源を接続するターミナルと、3.3V駆動のリレーコイルの場所が、大きなハンダ付ポイントになっていて、ジャンパ線を取り付け易そうでした。なのでここを接続しました。
下は、実際に配線したジャンパー線の写真です。
これでリレーモジュールは3.3Vで動作するようになりました。省エネになって、3端子レギュレータからの発熱も無くなったはずです。
警報ベルを探す
前回の試作では12V動作の電子ブザーを使用しました。そのため、ESP32用電源アダプタの他に、12V ACアダプタも用意してました。今回は、せっかくの100V対応リレーが用意されているので、100Vで動作する警報ベルを物色しました。AliExpressで、100V動作の電動ベル(電鈴)が見つかりました。送料込みで1,329円とお手頃価格ですし、レトロな音色も良さそうですので、これを使うことにしました。
AC 100Vを接続したところ元気な音がしました。消費電流は125mA程度でした。
箱に収める
AC 100Vの配線をするので、配線が剥き出しにならないよう、箱に収めたいと思いました。そこでSeriaでプラスチック箱を探してきました。100円で大きな箱だと、壁が薄いのですが、その代わり加工が容易です。またWiFi電波も良く透過しそうです。
箱の上に電鈴を取り付けると、怪しい装置という感じが醸し出されました。
箱の中には、テーブルタップ、念のための0.5Aヒューズ、3.3V ACアダプタ、ESP-01リレーモジュールを取り付けました。100Vコンセントへのケーブルは、箱の背面から取り出しています。
プログラミング
プログラムは、以前のESP32のものとほとんど同じです。詳しくはこちらの説明をご覧ください。多少変更したところがあります。
一つは、Arduino OTAに対応させたことです。これでシリアル接続しなくてもプログラムを更新できます。Arduino OTAを使う場合に、Arduino IDEから接続できないことが時々あります。ESP-01を再起動すれば接続できます。この時、ESP-01のブートボタンを押すのが面倒なので、MQTTから”reset”のメッセージを送ると再起動するようにしました。プログラムは以下です。
もう1点、セキュリティシステムの動作・非動作がわかるように工夫しました。そこで、セキュリティシステムを動かした場合に電鈴が短く1回、リンと鳴り、offにした場合に、電鈴が2回、リンリンと鳴ります。また、on/offに合わせて、ESP-01の青色LEDもon/offします。
プログラムは以下です。
//ESP-01 security system with EspMQTTClient library.
#include <arduinoota.h>
#include <espmqttclient.h>
EspMQTTClient *client; //instance of MQTT
//input & output pins and values
#define ALARMOUT 0 //GPIO for a relay to activate alarm buzzer.
#define ARMEDLED 1 //GPIO for armed-indicator LED.
//security level. Only AA (Away Arm) and D (Disarm) are used.
#define level_SA 0 //Stay Arm, not used in this version
#define level_AA 1 //Away Arm, this version uses this
#define level_NA 2 //Night Arm, not used in this version
#define level_D 3 //Disarm
int currentLevel=level_D; //current security level 0=SA, 1=AA, 2=NA, 3=D
//WiFi
const char SSID[] = "xxxxxxxx"; //WiFi SSID
const char PASS[] = "XXXXXXXX"; //WiFi password
//MQTT
char CLIENTID[] = "ESP32_xx:xx:xx:xx:xx:xx"; //MAC address is set in setup()
//for example, this will be set to "ESP32_84:CC:A8:7A:5F:44"
const char MQTTADD[] = "192.168.xxx.xxx"; //Broker IP address
const short MQTTPORT = 1883; //Broker port
const char MQTTUSER[] = "";//Can be omitted if not needed
const char MQTTPASS[] = "";//Can be omitted if not needed
const char SUBTOPIC[] = "mqttthing/security/setTargetState"; //mqtt topic to subscribe
const char PUBCURRENT[] = "mqttthing/security/getCurrentState"; //mqtt topic to publish
const char PUBDEBUG[] = "mqttthing/security/debug"; //for debug message
void setup() {
//Digital I/O
pinMode(ALARMOUT, OUTPUT);
pinMode(ARMEDLED, OUTPUT);
digitalWrite(ALARMOUT, HIGH); //set alarm off
digitalWrite(ARMEDLED, HIGH); //set LED off
currentLevel=level_D; //set disarm
//MQTT
String wifiMACString = WiFi.macAddress(); //WiFi MAC address
wifiMACString.toCharArray(&CLIENTID[6], 18, 0); //"ESP32_xx:xx:xx:xx:xx:xx"
client = new EspMQTTClient(SSID,PASS,MQTTADD,MQTTUSER,MQTTPASS,CLIENTID,MQTTPORT);
delay(500);
}
void onConnectionEstablished() {
ArduinoOTA.setHostname("ESP-01_security");
ArduinoOTA.setPasswordHash("xxxxxxxxxxxxxxxxxxxxxxxxxx");
ArduinoOTA.begin();
client->subscribe(SUBTOPIC, onMessageReceived);
client->publish(PUBDEBUG,"ESP-01 Security System is ready.");;
}
void onMessageReceived(const String& msg) {// topic: mqttthing/security/setTargetState
client->publish(PUBDEBUG, "Set TS received.");
if(msg.compareTo("alarmtest1")==0) { //test with 1sec. alarm for debug
client->publish(PUBDEBUG, "Alarm test started.");
digitalWrite(ALARMOUT, LOW); delay(1000); digitalWrite(ALARMOUT, HIGH);
client->publish(PUBDEBUG, "Alarm test stopped.");
}
else if(msg.compareTo("AA")==0) { //is set AA
currentLevel = level_AA;
//indicate with a short beep
digitalWrite(ALARMOUT, LOW); delay(20); digitalWrite(ALARMOUT, HIGH);
digitalWrite(ARMEDLED, LOW); //turn LED on
client->publish(PUBCURRENT,"false"); //turn off the button JIC it is on
client->publish(PUBCURRENT,"AA");
}
else if(msg.compareTo("D")==0){ //target state is D (Disarm)
currentLevel = level_D;
digitalWrite(ARMEDLED, HIGH); //turn the LED off
digitalWrite(ALARMOUT, HIGH); //turn the alarm off JIC it is on
//indicate with two short beeps
digitalWrite(ALARMOUT, LOW); delay(30); digitalWrite(ALARMOUT, HIGH);
delay(600);
digitalWrite(ALARMOUT, LOW); delay(30); digitalWrite(ALARMOUT, HIGH);
client->publish(PUBCURRENT,"false"); //turn the button off JIC it is on
client->publish(PUBCURRENT,"D");
}
else if(msg.compareTo("false")==0) { //a sensor or human turned off the switch
digitalWrite(ALARMOUT, HIGH); //turn the alarm off anyway
if(currentLevel == level_AA){ // if AA, alarm likely to have been triggered
client->publish(PUBCURRENT,"AA"); //return to AA from T
}
}
else if(msg.compareTo("true")==0) { //sensor turned on the switch
if(currentLevel == level_AA){ //if it is armed
client->publish(PUBCURRENT,"T"); //trigger the security system
digitalWrite(ALARMOUT, LOW); //turn on the alarm buzzer
}
else{ //if currentLevel is level_D
delay(500); //do nothing but just delay for 500 ms.
client->publish(PUBCURRENT,"false"); //turn off the button on the Home.app
}
}
else if(msg.compareTo("reset")==0) { //reset ESP01 for debug
client->publish(PUBDEBUG,"Restarting ESP01..."); delay(500);
//mainly used to retry mDNS and ArduinoOTA connection.
ESP.restart();
}
}
void loop() {
ArduinoOTA.handle();
client->loop();
}
Homebridgeを設定する
このプログラムはMQTTで通信するので、Mosquittoが必要です。またHomebridgeでは、MQTTThingプラグインを使います。以下の構成図で示すように、これらをRaspberry Pi 4で動かしています。
HomebridgeのコンフィグのMQTTThingの部分に、以下を追加します。まずは、セキュリティシステムのアクセサリ
の部分の記述です。不在用のAway Arm (1)と、Disarm (3)に対応させました。setTargetStateは、変更すべきセキュリティ動作設定を、HomeKit側からESP-01側に伝えるためのトピックスです。getCurrentStateは、現在のセキュリティシステムの状態を、ESP-01側からHomeKitに伝えるためのトピックスです。
{
"type": "securitySystem",
"name": "Security System",
"topics": {
"setTargetState": "mqttthing/security/setTargetState",
"getCurrentState": "mqttthing/securit/getCurrentState"
},
"restrictTargetState": [
1,
3
],
"accessory": "mqttthing"
},
次に、アラームブザー
の部分です。setTargetStateは、HomeKit側からESP-01に、設定すべきブザーの状態を伝えるためのトピックスです。getCurrentStateは、ESP-01側からHomeKitに、現在のブザーの状態を伝えるためのトピックスです。
{
"type": "switch",
"name": "Alarm Buzzer",
"topics": {
"getOn": "mqttthing/security/getCurrentState",
"setOn": "mqttthing/security/setTargetState"
},
"accessory": "mqttthing"
},
これでセキュリティシステムとアラームブザーが、HomeKit画面に現れます。
あとは、センサーの結果で、アラームブザーが動作するよう、HomeKitオートメーションを設定します。
そして、セキュリティシステムを動作させれば、センサの検出結果により、電鈴が鳴るようになります。
まとめ
ESP-01用のリレーモジュールを使い、セキュリティシステムを作り直しました。リレーを使って電鈴を鳴らすようにしたので、ESP32で作成した場合と比べて回路が簡単になりました。
コメント