前回は家全体の消費電流が測定できるようになりました。今回は測定結果を別の場所でも確認できるようにしたいと思います。
UDPマルチキャストを使う
マルチキャストはネットワークに参加している複数の端末へ、同じデータを送信する方法です。送信者はマルチキャスト用のIPアドレス(正確にはIPアドレスのうち特定の番号をマルチキャスト用に利用している)へデータを送信すると、同じIPアドレス宛のデータが欲しい受信者へ、ルーターがデータを転送してくれます。
このため、送信者は複数の端末へそれぞれデータを送信する必要がなくなり、1回送信するだけで済みます。また受信したい端末のIPアドレスを保持する必要もありません。
送信者は受信者がいるいないに関わらず勝手に送信し、受信者は勝手にデータがやってくるという、とてもシンプルな仕組みです。
プログラム
送信側
define... //UDP #include <AsyncUDP.h>AsyncUDP udp; const IPAddress MulticastIP = IPAddress(239, 29, 01, 41); const uint16_t MulticastPort = 0141; #define PacketLength 6 const uint8_t PacketHeader = 0x55; void setup() { setup... } void loop() { getData... sendUDP(gridI * 10, solarI * 10); } //UDP Multicast void sendUDP(float i1, float i2) { uint8_t message[PacketLength]; message[0] = PacketHeader; int16_t temp = (int16_t)(i1); message[1] = (uint8_t)(temp >> 8); message[2] = (uint8_t)(temp & 0x00FF); temp = (int16_t)(i2); message[3] = (uint8_t)(temp >> 8); message[4] = (uint8_t)(temp & 0x00FF); uint8_t checksum = 0; for (int i = 1; i < PacketLength - 1 ; i++) { checksum += message[i]; } message[PacketLength - 1] = checksum; udp.writeTo(message, PacketLength, MulticastIP, MulticastPort, TCPIP_ADAPTER_IF_STA); }
マルチキャスト用のIPアドレスは、224.0.0.0〜239.255.255.255の範囲となっています。
5行目でIPアドレスを指定しています。239.29(ニク).01(オイ).41(シイ)を、測定した電流をマルチキャストするIPにします。
IPの他にポート番号も指定します。0141(オイシイ)をポート番号にしました。
これらのIPとポートに対してUDPを送信すれば、それでマルチキャストができてしまいます。
40行目の
パケットデータは
またUDPは正しいデータが届く保証がないため、パケットの先頭に0x55を、パケットの最後にチェックサムを追加して、受信側でデータが正しいのかチェックできるようにしています。
受信側
define... //UDP #include <AsyncUDP.h>AsyncUDP udp; const IPAddress MulticastIP = IPAddress(239, 29, 01, 41); const uint16_t AmmeterMulticastPort = 0141; #define AmmeterPacketLength 6 void setup() { setup... //UDP recieve if (udp.listenMulticast(MulticastIP, AmmeterMulticastPort)) { udp.onPacket(recvCB); } } void loop() { show recieved data... } //UDP recieve process void recvCB(AsyncUDPPacket& packet) { //Err check if ( packet.length() != AmmeterPacketLength ) { Serial.printf("Packet length %d is wrong.", packet.length()); return; } uint8_t packetData[AmmeterPacketLength]; memcpy(packetData, packet.data(), AmmeterPacketLength); if ( packetData[0] != PacketHeader ) { Serial.printf("Packet header %x is wrong.", packetData[0]); return; } uint8_t checkSum = 0; for ( int i = 1 ; i < AmmeterPacketLength - 1 ; i++) { checkSum += packetData[i]; } if ( packetData[AmmeterPacketLength - 1] != checkSum) { Serial.printf("checksum %d is wrong. calculated%d", packetData[AmmeterPacketLength - 1], checkSum); return; } //decode uint16_t temp; temp = ((uint16_t)packetData[1]) << 8 | (uint16_t)packetData[2]; int16_t temp2; temp2 = (int16_t)temp; gridI = (float)temp2; gridI *= 0.1; Serial.printf("%.1f ", gridI); temp = ((uint16_t)packetData[3]) << 8 | (uint16_t)packetData[4]; temp2 = (int16_t)temp; solarI = (float)temp2; solarI *= 0.1; Serial.printf("%.1f ", solarI); Serial.printf("\n"); }
13行目で、マルチキャストIP:239.29(ニク).01(オイ).41(シイ)のポート番号0141(オイシイ)を受信したいと要求します。
要求が通ると、14行目で、受信した場合に呼び出す関数(コールバック関数)を設定します。今回は
パケットのデータは
実行
マルチキャスト送信のプログラムを電流計のプログラムに追加しました。また別のM5StickCを用意して、マルチキャストデータを受信するプログラムを書き込みます。
送信受信ともに、液晶画面にデータを表示するプログラムは同じにしてあります。そのため、右側の送信側のM5StickCの画面のクローンが、左側の手に持っている受信用のM5StickCの画面に表示されます。
UDPのマルチキャストで、電流計のデータが他の端末に送信できるようになりました。
電子レンジに設置
電子レンジを使った途端、ブレーカーが落ちるということはよくあることです。そのため、電子レンジに受信用M5StickCを貼り付けました。
受信側のM5StickCは、無線LANに接続されている限り、ブレーカーを流れている電流を表示してくれます。現在の値は25Aです。
電子レンジを使うと42Aまで上昇しました!うちのブレーカーは40Aなので、限界を超えてしまいました。
現在の消費電流が分かっていれば、電子レンジを使う前にどこかのエアコンを切ったりして、ブレーカーが落ちることを回避することが可能になります。
ちなみに40Aのブレーカーは「40Aになったら切れる」のではなく、「40Aは必ず通す」と設計されています。そのため、40Aでも切れません。40A以上の場合は、ある時間継続すると切れます。そのため、少し超えたくらいではブレーカーは切れません。
どこでも消費電流がわかるよ
現在の消費電流が家のどこでも確認できるようになりました。これで、家庭内の電力の逼迫状況をリアルタイムに知ることができるようになりました。
さて次回は、この家で一番電力を逼迫させてブレーカーが落ちる原因を作っている、ある機器にこの装置を導入して問題を解決したいと思います。
この記事で使っている測定回路は、このキットを改造して使っています。
コメント