スマート壁面スイッチや検知スイッチの作成
最近独自のスマートスイッチを作って照明をスマート化していますが、昔の照明の様にヒモスイッチを下げる事で第三者も使える様にしています。コレだけでも「市販のスマートスイッチよりマシ」だと思っているのですが、階段で使われる三路スイッチを検討した際に単独の照明スイッチが必要だと感じました。ESP32C3を使ったスイッチも作る予定です。 ESP32とESP32C3ではDeepSleepの復帰設定に仕様変更が加わっている様です。 調べてみると各IOでHIGH→LOW / LOW→HIGHで復帰する設定が可能でした。 でもESP32C3って単価が少し高いンデスヨネ~~~ESP-01Sを使ったスイッチ ESP-01Sを使って3点と1点のスイッチを使う事を考えています。 どちらも押しボタン・リミットスイッチの使用で電源ONの最中にESP-NOW送信して DeepSleepに移行するだけの安直仕様です。電源の瞬間ON程度は送信できませんが、 電源ONから0.1秒程度のOnでESP-NOW送信を完了するので実用レベルだと思います。 ※動かなかったら複数回押せば良いんじゃね?とか安直に考えています。 これによって実現可能な機能です。 =>壁面スイッチ =>玄関チャイム ボタンを押すとGoogleHomeNotifier指示でGoogleHomeからMP3を鳴らす。2024年 気付けば似たような奴を売っていますスマートセンサー ドア 窓 開閉 スマホ リアルタイム通知 工事不要 wifi スマホ通知 電池式 セキュリティ 防犯 遠隔操作 泥棒 小型 +Style PS-SDW-W02価格:2,980円(税込、送料無料) (2024/1/30時点) マグネットの近寄る遠ざかるでスイッチON/OFFさせて検知するタイプです。 コッチの方がリミットスイッチを使うより、設置が楽ですね。2023年10月 壁スイッチを作り直す事にしました 今まで作った壁面スイッチは押しボタン式で、個人的にはインチキと思ってました。 今回ESP32のDeepSleep検討の際にアッサリ壁スイッチが出来そうだと判ったので こんな感じカナーとか思いながら実機検証してみました。 確認機のハード(右のLolin32Lite機です) pin 32/33をプルダウンとスイッチ2個でONすると3.3Vに繋がります。 スイッチを壁スイッチに変更すると2つのスイッチを管理できます。 電池駆動の検討は・・・ これじゃあ無理ですね・・・ ソフトは? 1点はesp_sleep_enable_ext0_wakeupを使用しました。 もう1点はesp_sleep_enable_ext1_wakeupを使用しました。 ※esp_sleep_enable_ext1_wakeupはLow切換え時の制約の回避方法が思いつかず多点を断念。 って・・・ それだけ? と言うとそれだけです。 後はESP-NOWの送信をしてやれば良いダロ?って気分でいます。2023年 スイッチができました。 部品配置を修正して18650リチウム充電池の幅に収まる様にしました。 これで3Dプリンタのケース作成時間及びフィラメント使用量の節約を図ります。タカチ電機工業 IT型電池端子 単3 (10個入) 【IT-3WM】価格:254円(税込、送料別) (2023/3/24時点) 折角3Dプリンタでケースを作るのですから18650充電池ホルダーも一緒に 作るツモリで受けの金属端子を買いました。AliExpressでの購入だと100ペアで 300円で買えるモノが日本だと10ペア254円になるんですね。 壁面スイッチはまだ用途が無いのですが検知スイッチを作りました。 電気配線は全く同じですが、18650電池での運用の方が良さそうなので使っています。 スイッチONの時に電源電圧を計測して電池不足警告が出る仕組みを用意しましたが、 長期のスイッチOFF時に電池の自然放電で死んだ場合は警告が出ません。2022/10 紆余曲折ありましたが、いいのが出来たと思います 何度か発想の転換をしましたが、押しボタンの電源ON中にメッセージ送信 する仕様にしました。自分の感覚的だと照明が点灯・消灯を確認し終わる までボタン押してるから良いよね。って感じです。 配線の方はダイオードがウザイですが、2種類のボタンを判別できる様に する事ができています。また待機中は電源が繋がっていないので、電池は 自然放電の消耗のみ済ませる事ができました。 ボタン押しっぱなしの対策はメッセージ送信完了後にDeepSleepに移行して 消費電力を抑える程度にとどめています。 ※1種類のメッセージ送信と割り切ると電源の配線だけで済む超簡単仕様です。(もったいないw ON/OFFの2点だけならTXの有無だけで成り立たせる事ができますが 検討も兼ねた設計なのでIO0/IO2を入力ポートとして使っています。 この作り方ならTXも使う様にすると3現象が可能かなと思います。 初期設定はボタンを押さないで電源ONするとモードに入る様にしました。 これでUSBシリアルユニット接続時は初期設定モードという事になります。 IO0/IO2は電源ON時にLowだと違うモードで起動がかかる仕様なので、電気的にはHigh又は Openで電源ONする様にしています。電源ON後にRXをLowに落としてやるとOpenの方は Lowに変化するのでそれでスイッチの入力状態を判定しています。 データの設定モードはESP-01SをUSB書き込み機で起動するとIO0とIO2がOpenで起動する を検知して移行する様にしています。回路に別途SW追加でも可能なのも考慮済みです♪ TXは電池交換警告のLED点灯に使うのが良さそうな気がしています。 ESPNOWメッセージの送信を終えたらDeepSleepで待機します。 ボードに部品配置をする検討中です。 追伸・・・・ 今回はESP-01Sにこだわって作ってみましたが、ESP-12Fを使うと GPIO12/13/14に簡素なSWを配線するだけで実現できる事に気付きました。2022年 超絶単純仕様を思いつきました。 検討用にESP-01S化と機能別ブロック化をしました。 これぐらいなら屋内の壁スイッチに埋め込む事も出来そうですね。 つくったのですが消費電力を測ると常時10mA消費で回路作成を誤っている様です。 予定ではDeepSleepの待機電力のみで動作させる予定だったのですが残念です。 じゃあ現状はどうすんの? 自分の能力の無さ故の惨敗を認めまして超絶単純仕様で落ち着く事にしました。 スイッチを使って通電した方のESP01Sがメッセージを投げてDeepSleepに移行で 待機機という形式にしました。 ユニットの小型化を図るのならコチラを使うのも良さそうです。パナソニック対応 CR-2/3AZ SH384552520 住宅火災警報機用リチウム電池 【けむり当番・ねつ当番】 住宅用火災報知器 交換用リチウム電池 専用リチウム電池 住宅火災警報器 住宅火災警報機 panasonic対応 ロワジャパン価格:950円(税込、送料別) (2022/10/6時点)楽天で購入2022年 ON-OFFスイッチ化できないかの検討 ESP-01SのリセットをしつつA又はBのIOを設定できないか考えています。 壁スイッチを無配線でESPNOW化してしまおうって魂胆です。 ※電源は乾電池3本で1年以上持つ仕組みなら検討の余地在りだと思いません? リセットボタンの2つのどちらを押したか判る様にすればOKかなーと思った ので片側に低消費電力の自己保持回路を組み込めるか検討してみました。 一応検討は上手くいき2つのリセットボタン押しを判別可能になりました。 ただ問題点が2つ・・・ 1・リセットボタンを押しっぱなしだと自己保持の電流を食い続ける これはまー仕様と思えば良いかと思っています。 2・リセットボタンを離さないとESP01Sの起動が始まらない 照明とか普通はボタンを押すと点灯するのですが、ボタンを離すと点灯に なっています。ボタンだと常識から外れてるので結構問題な気がします。 ※照明等で使われる紐を引っ張るタイプで使うなら問題無いんですけどね。 この問題は放置しといて今回の仕様で電池駆動可能かの検討に進む事にします。 写真の構成ではDeepSleep時の消費電力が多すぎて検討にならないと思っています。2022年 IO点数を稼げないか検討してみました。 直接GPIO0とGPIO1にセンサ入力を入れると状態次第では 電源ON時に書き込みモードに移行してしまう問題があります。 しかしながらリミットスイッチを複数個使ったセンサーの状態報告は 価値があるので検討しました。 とりあえずこんな形の回路図で3点得る事ができました。 電源ON時にRXがLOに落ちている場合は設定モードで起動します。 電源ON後にTXをLOに落とすと3点のIO入力が可能になります。 後は上手く状態変化でリセットをかけESPNOWで報告する仕組みを作れば 電池駆動で玄関や戸などで使う事ができるのですけどね~~ ※上手くリセットする仕組みを作るのは結構大変な様です(僕にゃ無理かもなー2022年9月 DeepSleepで待機してReset後にメッセージを投げる仕組みで考えてます。 プログラムの流れとしてはこんな感じです。 1・無制限Deepsleep 2・リセット 3・相手MACアドレスにESPNOWメッセージ送信 4・相手MACアドレスよりESPNOWメッセージ受信確認 5・無制限DeepSleep(1へ戻る 実際は相手の受信が判らないので再送機能が必要になりますが、 単純化するとこの程度の機能だよなぁ~~ なんて思います。 ※再送の時間を考慮しない場合だと1回のリセットでの動作時間は約100mSec程度に なるので相当長持ちする事が期待できます。 電気配線を検討してみました。(最小構成でESP-01Sを使用) ・VCCとGNDに繋ぐ電源は1.2Vのニッケル水素電池3本にします。 満充電時3.6Vチョイ超えですが動いてくれるんじゃね?と期待 ・RESETとGNDにプッシュスイッチを繋ぎます。 ってコレだけかい? って感じです。 ※WemosD1とモバイルバッテリーの間にスイッチを用意するだけで出来ちゃいます。 一応ソフトを検討してみました。 最初はメッセージを投げてDeepSleepするだけのソフトでしたが、 相手が受け付けない問題が発生したので相手の返答を待つ再送を数回 繰り返す様にしました。ESPNOWなので1回あたりの起動時間は1秒 ぐらいで抑えられそうです。#include <EEPROM.h>#include <ESP8266WiFi.h>#include <espnow.h>const int esp_now_channel = 0;uint8_t mac_address[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; // FF,FF,FF,FF,FF,FF はBroadcastです。(通常は相手先のMACアドレスを記述int sendDelay, sendCount=0;// データの受信#define ESP_NOW_RECEIVE_BUFFER 128uint8_t esp_now_receive_mac_address[6];char esp_now_send_data[ESP_NOW_RECEIVE_BUFFER];char esp_now_receive_data[ESP_NOW_RECEIVE_BUFFER];bool esp_now_receive = false;// データの受信イベントvoid on_esp_now_receive(uint8_t *mac_addr, uint8_t *data, uint8_t data_len) { memcpy( esp_now_receive_mac_address, mac_addr, 6 ); if( data_len>ESP_NOW_RECEIVE_BUFFER ) data_len = ESP_NOW_RECEIVE_BUFFER; memcpy( esp_now_receive_data, data, data_len ); esp_now_receive = true;}// データの送信イベントuint8_t esp_now_send_end = false;void on_esp_now_sent(uint8_t *mac_addr, uint8_t status) { esp_now_send_end = true;}void setup() { Serial.begin(115200); WiFi.disconnect(); EEPROM.begin(1); int value = EEPROM.read(0); EEPROM.write(0, (value+1)%5 ); sprintf( esp_now_send_data, "/TOGGLE%d", value ); //millis() ); WiFi.mode(WIFI_STA); int result = esp_now_init(); if ( result != 0 ) { Serial.printf( "\n\nESPNOW_initial error[%d]\n", result ); ESP.restart(); } esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);// esp_now_register_send_cb(on_esp_now_sent); esp_now_register_recv_cb(on_esp_now_receive);// result = esp_now_add_peer(mac_address, ESP_NOW_ROLE_SLAVE, esp_now_channel, NULL, 0); if (result != 0 ) { Serial.printf( "\n\nESPNOW_add peer error[%d]\n", result ); ESP.restart(); } esp_now_send( mac_address, (uint8_t *)esp_now_send_data, strlen(esp_now_send_data)+1 ); EEPROM.commit(); Serial.printf( "send:[%d][%s]\n", sendCount, esp_now_send_data ); sendCount++; sendDelay = (millis()/100);}void loop() { if( sendCount<10 ){ if( sendDelay!=(millis()/100) ){ esp_now_send( mac_address, (uint8_t *)esp_now_send_data, strlen(esp_now_send_data)+1 ); Serial.printf( "send:[%d][%s]\n", sendCount, esp_now_send_data ); sendCount++; sendDelay = (millis()/100); } delay(1); if( esp_now_receive != true ) return; Serial.printf( "\nReceive:[%s] : [%s]\n", esp_now_send_data, esp_now_receive_data ); if( memcmp( esp_now_send_data, esp_now_receive_data, strlen(esp_now_send_data) )!=0 ){ esp_now_receive = false; return; } } long times = millis(); Serial.printf( "\n\nESPNOW_send end %dmSec\n", times ); ESP.deepSleep( 0 );}