PCケース操作パネルを改造してHomeKitからOn/Offする

DIYする

PCケースの電源操作パネル内部にESP32を組み込んで、HomeKitからOn/Offできるようにしました。電源スイッチを導通させてOn/Offし、通電表示用LEDの状態を取得します。

既存機器操作パネルの改造方法

PCケースの電源をHomeKitから投入したいと思いました。作業部屋に入る前にPC電源を入れておくと、PC前に座った時にはすでに起動しています。このほか、外出先から家のPCの電源を入れて、リモート接続で作業をすることもできます。

PCケース上部には、操作パネルがあり、ここに押しボタン電源スイッチが付いてます。また、電源が入ったことを表示するLEDも付いてます。電気スイッチと状態表示用LEDの組み合わせは、PCケースに限らず、従来の家電や家の設備の操作パネルで一般的な構成です。今回と全く同じ手法で、さまざまな機器の操作パネルを改造して、スマート化できると思います。例えば、テレビの電源、給湯器の電源や操作ボタン、インターフォンの操作ボタンなどにも応用できます。


(noritz.co.jpから引用)     (panasonic.biz から引用)

今回使用するのは、ESP32のデジタル入出力ピン2本だけです。1本を出力に設定して、電源スイッチをOn/Offします。もう1本を入力に設定して、LEDの点灯状態を取得します。

コンピュータのデジタル入出力ピンを、他の機器にインターフェースする方法はたくさんあります。それらの方法を、以下でいくつか列挙します。

FETでOn/Offする

ESP32の動作電圧は3Vなので、相手が3Vのデジタル機器なら直結も可能です。動作電圧が違っても、グラウンドが同じならばトランジスタやFETを使って電圧変換することも可能です。なので大抵の場合は、FETをオープンドレイン配線して、制御パネルのスイッチに接続すれば、On/Off可能になると思われます。

akizukidenshi.com から引用

リレーでOn/Offする

電圧とグラウンドの状況が確認できない場合は、機械式リレーを使うことも可能です。例えば、押しボタンスイッチに並列にリレーを接続すれば、人が押して導通させる操作を、リレーで実現できます。

akizukidenshi.com から引用

HomeKitからコントロールできるWiFiリレーユニットもあります。ESP32もHomebridgeも不要で、これだけでHomeKitから直接スイッチ操作が可能です。価格も1,600円くらいとお手頃です。

HomeKit対応リレーモジュール

この機械式リレーは、80V 10AまでOn/Offできます。5V 数mAくらいしか使わないデジタルな操作パネルスイッチに使うにはオーバースペックです。その場合、次に説明する電子的なスイッチを使うのが効率的です。機械式リレーよりも、高速で小型で操作音もしません。

フォトカプラーでOn/Offする

グラウンドを絶縁してOn/Off動作させるために、フォトカプラーとか、フォトアイソレーターと言われる部品が使用されます。これらは、LEDとフォトトランジスタの組み合わせで動作します。下は1回路製品の例です。この図で1-2番ピンに電流を流すと、内蔵LEDが発光して、3-4番ピンのフォトトランジスタが導通します。

(akizukidensi.comから引用)

フォトカプラーは、機械式リレーと同様に、入力・出力回路を電気的に絶縁状態にできます。なので相手の回路の素性がよくわからない場合でも安心です。エアコンのJEM-A端子をESP32に接続した以前の記事で使用しました。

家庭用エアコンに付いてたJEM-A HA端子をHomeKitから使う
廉価版の家庭用エアコンに、JEM-A HA端子が付いているのを発見しました。仕様を調べて、ESP32に接続し、MQTTとHomebridge経由でHomeKitから使えるようにしました。 参考記事のご紹介 Homebridgeについては以下...

内蔵フォトトランジスタに接続された3-4番ピンを制御パネルスイッチと並列に配線して、ESP32から内蔵LEDを点灯すれば、スイッチをonにできます。ESP32に適切なプログラムを書いておけば、スマートホーム側から制御パネルのスイッチをOn/Offできます。

フォトカプラーでスイッチを操作

表示LEDの状態を検出する

一方、操作パネル表示用LEDへ流れる電流を分けてもらってフォトカプラーの1-2番ピンに入れて、3-4番ピンをESP32に接続すれば、操作パネルの表示状態を取得することができます。これは機械式リレーだけでは実現できない機能です。下の接続図は、ESP32の入力ピンを内部でプルアップする設定にした場合の例です。

LED状態をフォトカプラで取得

操作パネルのボタンスイッチを押すごとに、On/Offがトグルする機器では、スイッチ操作でOnにもOffにもなるため、HomeKitから確実な操作ができません。しかし、表示LEDがOn/Offによって点灯・消灯した状態を取得できれば、HomeKitがOn/Off状態を正しく把握できます。また、人がスイッチを手動で操作した場合、その結果をHomeKit側に伝えることもできます。

フォトスイッチを使う

フォトカプラは、上記の回路図のように、内部にフォトトランジスタが1個だけ入っています。なので、電流が一方向にしか流れません。それに対して、フォトスイッチという部品もあります。フォトスイッチは、逆極性のフォトトランジスタを2個内蔵しているので、機械式リレーのように両方向に電流を流せます。

フォトスイッチのピン配置

デジタル操作パネルのスイッチは、導通した時に一方向にしか電流は流れないので、フォトカプラーでも良いです。ただ、既存の操作パネルのスイッチから線を取り出して接続することを考えると、極性を気にせず配線できるほうが楽かと思いました。価格差(2回路で40円と120円くらいの価格差)も大したことはありませんので、今回はフォトスイッチを使用しました。使用したフォトスイッチはTLP222G-2という製品で、2回路が一つのパッケージに入っています。

(akizukidensi.comから引用)

回路を設計する

今回作った回路は以下です。右側にある点線で囲んだ部分がPCケースの操作パネル部分です。操作パネルの電源スイッチと、表示用LEDにそれぞれ並列に接続します。基本的な動作は以下です。

  • ESP32のD13をHighにすると、PCの電源スイッチが導通します。
  • 操作パネルのLEDが点灯すると、ESP32のD12がLowになります。

ESP32に操作パネルのLED・スイッチを接続する

電源スイッチの回路

デジタル出力ピンD13の回路はシンプルです。TLP222のデータシートが秋月電子のページにあります。それを見ると、発光側の順電圧が1.15Vで、

推奨順電流は7.5mA程度とのことです。

上記の回路では470Ωの抵抗で接続しました。D13がHighの時に3V出力されると考えると、(3 – 1.15) / 470 = 4mAです。最小推奨電流の5mAを目指すなら、370Ωくらいが良かったかもしれません。省電力ですし、動いているのでこれで良しとします。

状態表示LEDの回路

一方、状態表示LEDに接続している部分の回路は少しトリッキーです。LEDの電流制限抵抗の部分にアクセスできるならば、そちらから線を引っ張り出してフォトスイッチに接続したほうが良いと思います。パソコンのマザーボード内にアクセスするのが困難でしたので、今回は操作パネルのLED両端に接続しました。

回路図では、操作パネルのLEDと並列に線を引き出して、フォトスイッチ内部のLEDに220Ωの抵抗を介して接続しています。

LED並列接続の注意

この抵抗を無しにして、直結するとどうなるでしょう?実は、最初に回路を作った時は直結してしまいました。するとフォトスイッチは動作するのですが、操作パネルのLEDが点灯しなくなりました。理由は以下です。

フォトスイッチ内蔵LEDの順方向電圧が1.15Vなのに対して、表示パネルのLEDは、測定したところ2.58Vでした。抵抗無しで直結してしまうと、どちらのLEDの両端とも1.15Vになってしまい、表示パネルLEDが点灯しなくなるのでした。220Ωの抵抗で接続したことにより、それぞれのLEDの両端に、1.15V, 2.58Vが発生することになり、どちらのLEDも動作するようになりました。フォトスイッチのLEDには、( 2.58 – 1.15 ) / 220 = 6.5 mAの電流が流れます。これはデータシートの推奨動作範囲内です。

今回は、フォトスイッチLED順方向電圧の方が、表示用LED電圧よりも低かったので、後付け抵抗を入れる場所が楽でした。電圧の高低が逆の場合は、表示LED側に抵抗を入れる必要があります。操作パネルのプリント基板の中で配線されている場合は、基板パターンを切って配線する必要があります。でもその心配は、実は無用です。フォトスイッチ内のLEDは赤外線LEDなので、順方向電圧が1.1V程度と低いです。一方で、表示用LEDは当然のことながら可視光LEDなので、順方向電圧が高めで、通常は1.9Vから2.6Vくらいです。波長が短くなると、光を出すためにより高いポテンシャルエネルギーが必要で、高電圧になるという量子力学的な理由だと思います。

ただ、表示用LEDに流れる電流の一部を分けてもらって、フォトスイッチを駆動することになるので、表示が多少暗くなります。光量低下を最小にするためには、フォトスイッチが動作する範囲でできるだけ大きな抵抗を選ぶ必要があります。最小推奨電流の5mAを目指すなら300Ωくらいでも良かったかもしれません。今回の抵抗値でも、光量低下は気にならなかったのでこれで良いことにします。

全体の構成

ESP32での実装にはMQTTサーバ(ブローカ)を使います。HomeSpanMatterを使ったESP32プログラミングも試してきましたが、HomeSpanは応答無しになる頻度が高く、Matterは今のところSwitchデバイスがHomeKitで使えませんでした。MQTTならばシンプルで確実に動作します。Home Assistantからも使いやすいかと思います。

Raspberry PiでMQTTブローカのMosquittoを動かし、Homebridgeにmqttthingプラグインを入れて使います。詳しくはこちらをご覧ください。

MQTTブローカーMosquittoを設置する
今回はMQTTブローカーをインストールします。MQTTがあると、スイッチ、センサ、リレー、サーボモータなどを接続したArduinoのようなコンピュータを、ネットワーク越しにIP接続したい時にとても便利です。また、MQTTを使うスマートホーム...

mqttthingの設定

Homebridgeのmqttthingプラグインの設定を以下のようにしました。

{
    "type": "switch",
    "name": "Computer",
    "topics": {
        "getOn": "mqttthing/computer/get",
        "setOn": "mqttthing/computer/set"
    },
    "accessory": "mqttthing"
},

getとsetのためのトピック名を設定してあります。getとsetの違いについては以下をご覧ください。

set, get と target, current の違い
HomeKitの動作説明で、setState, setTargetState, getCurrentStateなどの用語が出てきます。字面から意味をなんとなく想像していたのですが、わりと混乱してました。調べて理解したことをメモしておきます。...

このトピックにtrueもしくはfalseという文字列が流れると、スイッチアクセサリがonまたはoffに設定されます。

ESP32のプログラム

Ardiomp IDEで作ったプログラムを以下に示します。EspMQTTClientライブラリを使ってます。Client IDをMACアドレスを含んだものに設定してますが、ここまで凝らなくても適当なユニークな文字列を設定しておけば良いです。

//MQTT switch for ESP32.

#include <EspMQTTClient.h>

EspMQTTClient *client;

//input & output pins
const int POWERSW=13; //photo relay to switch power button
const int POWERLED=12; //photo relay driven by power LED

//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.99.99"; //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/computer/set"; //mqtt topic to subscribe
const char PUBTOPIC[] = "mqttthing/computer/get"; //mqtt topic to publish
const char PUBDEBUG[] = "mqttthing/computer/debug"; //for debug message

void setup() {
    //Digital I/O
    pinMode(POWERSW, OUTPUT);
    pinMode(POWERLED, INPUT_PULLUP);//Pull up
    digitalWrite(POWERSW, LOW); //off the power switch
    //Serial
    Serial.begin(115200); // ESP standard speed 115200
    while (!Serial); // wait for serial port to connect.
    Serial.println("ESP32 Power Switch started.");
    String wifiMACString = WiFi.macAddress(); //WiFi MAC address
    wifiMACString.toCharArray(&CLIENTID[6], 18, 0); //"ESP32_xx:xx:xx:xx:xx:xx"
    Serial.print("SSID: ");Serial.println(SSID);
    Serial.print("MQTT broker address: ");Serial.println(MQTTADD);
    Serial.print("MQTT CLIENTID: ");Serial.println(CLIENTID);
    //MQTT
    client = new EspMQTTClient(SSID,PASS,MQTTADD,MQTTUSER,MQTTPASS,CLIENTID,MQTTPORT);
}

//current state of the POWERLED
int currentLEDstate;

void onMessageReceived(const String& msg) { // topic = mqttthing/computer/set
    Serial.println(msg);
    client->publish(PUBDEBUG, "Set topic received.");
    
    if(msg.compareTo("true")==0) { //set true, then turn on for 1 sec
        digitalWrite(POWERSW, HIGH); //on for 1 sec
        delay(1000);
        digitalWrite(POWERSW, LOW);
    }
    else if(msg.compareTo("false")==0) { //set false, then virtually do nothing
        digitalWrite(POWERSW, LOW);//keep sw on. no way to shutdown via MQTT
    }
    currentLEDstate = -999; //force to update LED state in the next main loop()
}

void onConnectionEstablished() {
    Serial.println("MQTT onnection established.");
    client->subscribe(SUBTOPIC, onMessageReceived); //set callback function
    client->publish(PUBDEBUG, "ESP32 Power Switch is ready.");
    currentLEDstate = -999; //force update at next loop()
}

void publishSwitchState(int sw){
    if(sw==LOW)
        client->publish(PUBTOPIC, "true");
    else
        client->publish(PUBTOPIC, "false");
}

int counter; //to count the loop
void loop() {
    client->loop();
    delay(10); //10ms delay
    
    int newLEDstate=digitalRead(POWERLED);
    if(currentLEDstate!=newLEDstate) { //power-led has changed
        counter=0;
        currentLEDstate=newLEDstate;
    }
    if(counter++ == 10) //at 10th loops, update.
        publishSwitchState(currentLEDstate);
    if(counter % 6000 == 0) //at every 6000 loops, update.
        publishSwitchState(currentLEDstate);
    
    delay(90); //90ms delay
} 

setトピックにメッセージが来たらonMessageReceived()関数が呼び出されます。メッセージがtrueならばフォトスイッチを1秒間onにしてます。

一方、loop()では表示用LEDの状態を調べて、必要ならばgetメッセージをパブリッシュしてます。表示用LED状態をパブリッシュするタイミングは、次の2つです。

  • 600秒(10分)ごと:表示に変化がなくても10分に1回は現在の状態をパブリッシュします
  • 表示に変化があった後、1秒間変化がない場合:表示状態を電源状態としてパブリッシュします。スリープ対策です

2項目めの、スリープ時電源判定について補足します。PCマザーボードがスリープ状態になると、電源LEDが下のように点滅します。

もしLEDの状態を即座に電源状態として反映すると、スリープ時にはOn/Offを繰り返していると認識されてしまいます。そこで、LED表示に1秒間変化がない場合、その状態を電源状態としてMQTTサーバにパブリッシュすることにしてます。

このように、機器の操作パネルLEDは、点滅状態で色々なメッセージを伝える場合もあります。点滅をプログラムで判断すれば、それを適切にMQTTにパブリッシュして、スマートホームで活用できると思います。

組み込み

PCケースの電源スイッチの裏側は、結構空間が空いてました。なのでここにESP32とフォトスイッチを組み込みます。PCケースは全体的にシールドされているんですが、スイッチ部分だけはプラスチック製でした。なのでWiFi接続も良好と期待できます。

写真がわかりにくいですが、左上の部分にESP32をテープで貼り付けてます。フォトカプラは、ESP32の裏側に貼り付けて、ピンから直接配線しました。USBケーブルで給電しています。ケーブルの先は、マザーボードの内部USBポートに接続してます。給電線だけでなくデータ線も接続しているので、PC上のArduino IDEからのデバッグも可能です。

PCケース操作パネル内部にESP32を組み込む

写真右下あたりが電源スイッチと表示用LEDです。それぞれ並列に線を引き出して、ESP32基板裏のフォトスイッチに接続してあります。

HomeKitから使う

この結果、iPhoneやMacのホーム.appにスイッチとしてPCケースの電源ボタンが現れます。これをクリックすると、電源投入できました。

このボタンアクセサリは、表示LEDの点灯・消灯に同期してOn/Offします。なのでHomeKitから確実にOn/Off操作できますし、人が手動でOn/Offした場合も状態が反映されます。

HomeKitからPCをoffにする操作は、今回は実装しませんでした。家の外部からonにした場合も、PCにリモート接続してOSからシャットダウンすれば良いかと考えてます。

まとめ

PCケースの電源操作パネル内部にESP32を組み込んで、HomeKitからOn/Offできるようにしました。電源スイッチを導通させてOn/Offし、通電表示用LEDの状態を取得します。手操作で電源を投入しても、通電状態がHomeKitに反映されます。PCケースに限らず、家電や家の設備の操作パネルにも応用できると思います。

コメント

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