2019年11月16日土曜日

ROHM BP35A1 ローム製Wi-SUN通信モジュールを使ってスマートメーターにBルート接続する

TwitterでM5StickC用にRohmのBP35A1を取り付けるアダプターを
作っておられる方がいて、BOOTHで購入できたので買ってみました。


サンプルコードも配布されていますが、開いてみるとMicroPythonだったので、Arduinoのスケッチを書いてArduinoで使ってみました


そもそもBルートとはなにか?
電力会社の設置している、各家庭にある電力量計は、アラゴの円板を使っていたアナログのものからデジタル化されています。
デジタル化されたメーターは、サブギガ(920MHzあたり)を使う無線で通信ができるようになっています。

なんのために無線通信できるのか?
毎月の検針を、検針員がメーターを直接読み取らなくても手元のプリンターで積算電力量を受信して印刷できます。
植栽や建物の密集度の関係上検針しにくい住宅や、集合住宅などでは集合ポスト前で一括受信・印刷することができるのだと思います。検針員はとても省力化できると思います。実際のところ、電波の到達距離も大したことがないため、どのような運用をしているのかはわかりません。
また、遠隔で電力供給の休止を行えるとされています。

これらはすべて電力会社が電力の使用を監視・制御するための通信で、Aルートと呼ばれています。
今回の話題であるBルートは、需要家(ユーザー)ごとにスマートハウスのようなHEMS機器とスマートメーターを直接無線接続して、使用電力のマネジメントなどを行うための仕組みです。

現在の使用電力量や各電力機器の動作状況をHEMS機器同士で共有することで、効率的に電力の使用ができるとされています。

今回使ったモジュールはこのようなHEMS対応機器を開発するための通信モジュールです。

スマートメーターと通信モジュールをBルート接続して使うためには電力会社にBルート接続用ID、パスワードを発行してもらう必要があります。
東京電力の場合、スマートメーター化されていない電力量計であっても、ID発行の申請を行うことでスマートメーターへの切り替えも行えるようです。(要工事)

BP35A1はUARTでシリアル通信コマンドを使って制御します。
公式のコマンドリファレンスは日本語ですが、この手のモジュールを使ったことがないと、読んでも心が折れそうだと思います。

ざっくりとした流れとしては

Bルート接続用ID/パスワードを設定
スマートメーターの電波をスキャン
スキャン結果からスマートメーターの接続情報を調べる
スキャン結果の接続情報を接続先として設定
接続開始・完了
電力取得コマンド送信
結果受信

と、初期化シーケンスがいろいろあってめんどくさいです。
とりあえずシリアルターミナルで手打ちして接続までいけるようにこれら一連の流れをメモしておきます。
上記のWi-SUN HATの場合、ピンを下にして裏面を向けて、
左側のピンから
GND/NC/NC/TX/RX/NC/3.3V/NC
というピン配置になっているため、電源とUARTを接続すればUSBシリアル変換などを使って使うこともできます。
115200bps 3.3VのUART 改行コード\r\nです。

以下コマンドでスマートメーターの接続までを行います。

Bルートのパスワードを設定
SKSETPWD C passwordhere

BルートのIDを設定
SKSETBID idhere

アクティブスキャンを実行
SKSCAN 2 FFFFFFFF 6

結果が返ってくる
EVENT 20 FE80:0000:0000:0000:xxxx:xxxx:xxxx:xxxx
EPANDESC
   Channel:31
   Channel Page:09
   Pan ID:ABCD
   Addr:xxxxxxxxxxxxxx
   LQI:93
   PairID:00E79995
 EVENT 22 FE80:0000:0000:0000:xxxx:xxxx:xxxx:xxxx


取得したスマートメーターのアドレスをIPv6アドレスに変換
 SKLL64 xxxxxxxxxxxxxx  //Addrの値
 FE80:0000:0000:0000:xxxx:xxxx:xxxx:xxxx

チャンネルを設定
SKSREG S2 31  //Channelの値

Pan IDを設定
SKSREG S3 ABCD  //Pan IDの値

接続開始
SKJOIN FE80:0000:0000:0000:xxxx:xxxx:xxxx:xxxx  //IPv6アドレスに変換後の値

EVENT 25が来ると接続成功です。
私は当初、EVENT 24で接続失敗しかしなかったのですが、
東電のフォームでパスワードを変更依頼したところ、以降つながるようになりました。
以前のパスワードではスマートメーターの設定がうまくできていなかったのかもしれません。

接続完了後、電力取得のコマンドを送信します。

SKSENDTO 1  FE80:0000:0000:0000:xxxx:xxxx:xxxx:xxxx 0E1A 1 000E
000Eのあとに半角スペースを入れて、続いてバイナリで
{0x10, 0x81, 0x00, 0x01, 0x05, 0xFF, 0x01, 0x02, 0x88, 0x01, 0x62, 0x01, 0xE7, 0x00} + \r\n
を送信すると瞬時電力が取得できます。

成功すると
ERXUDP FE80:0000:0000:0000:xxxx:xxxx:xxxx:xxxx
FE80:0000:0000:0000:xxxx:xxxx:xxxx:xxxx 0E1A 0E1A xxxxxxxxxxxxxxx 1 0012 xxxxxxxxxxxxxxxxxxxxxxxxxxxx000000BA
のようなレスポンスが返ってきます。
ここで見るのは最後の8桁、000000BAです。
これをそのまま10進に変換して、0xBA=瞬時電力186W
というような感じで読むようです。
上記サンプルコードでは、M5StickCで本体の液晶画面にこの数字を取得表示するようにしています。
Arduinoのスケッチなので、これを改良して、Wi-Fi経由でデータ送信して、
遠隔地から電力量を確認するような使い方も可能です。

それほど死ぬほど難しいわけではないですが、まだまだ情報量が少なく、
活用例も乏しいためもっと使う人が増えると楽しいのかなと思います。


2019年4月28日日曜日

ESP32をWi-Fi AP/イーサネットコンバーターにする(LAN8720使用)

最近になって、昨年公式githubに”eth2wifi”というサンプルが上がっているのに気づきました。
どうやらこれを使うと、有線LANをつないでWi-Fiアクセスポイントを立ち上げる
あるいはESP32がWi-Fiアクセスポイントに接続して、ESP32を介して有線LANの機器をLANに接続する
ということができるようです。1000円そこらでAPが作れるのは画期的です。

ESP32は、Wi-Fiの他に、物理層の部分以外Ethernetにも対応しています。
実際にEthernetを使うためにはEthernet PHY(フィジカル=物理層)
の回路が必要です。
よく知りませんが、通信用のクロックを作ったり、
信号レベルなどを有線LANの規格にあわせたりしてくれる回路なのだと思います。
これらの回路をESP32内部に入れるのはあまり使う人いないのに不毛ということで
物理層がはじめからは載っていないのだと思います。僕もそれでいいと思います。

調べるとEthernet PHYのICというものがいろいろ出ていて、簡単にブレークアウトボードに乗っているものが手に入るICとして、LAN8720がESP32ではよく使われているようです。

というわけで、LAN8720の載った基板をAliexpressで注文しました。
200円くらいで売っています。
https://www.aliexpress.com/item/1pcs-Smart-Electronics-LAN8720-module-network-module-Ethernet-transceiver-RMII-interface-development-board-for-arduino/32947407343.html?spm=2114.search0204.3.41.18a547acrOaaW9&ws_ab_test=searchweb0_0,searchweb201602_4_10065_10068_319_10059_10884_317_10887_10696_321_322_10084_453_10083_454_10103_10618_10307_537_536,searchweb201603_16,ppcSwitch_0&algo_expid=a53a62b5-87f4-46c8-8fea-e77569fc6b6b-6&algo_pvid=a53a62b5-87f4-46c8-8fea-e77569fc6b6b&transAbTest=ae803_5

届いたので、
冒頭のリンクのURLに書いてあるとおり配線しました。


 まあたくさん配線しないといけなくて、めんどくさいですがジャンパ線で直接接続のバラックです。
リンク先に注意書きが書いてあるのですが、
LAN8720ボードからのクロック出力をGPIO0に入力していますが、
ESP32の起動時にGPIO0がローに落ちていると、ファーム書き込みモードに入ってしまいます。
そこで、調べたら出てきた対策をします。
発振子の足をNCのピンに引き出して、GPIO17につなぎます。
GPIO17はコードの中でクロック出力の有効化・無効化をしてくれています。
こんなやり方でいいのか?という感じがしますがこれでうまくいきました。
基板を立ち上げるなら、トランジスタで電源ごと切ったりするほうが健全な気もします。



eth2wifiサンプルのディレクトリで、make menuconfigで動作の設定ができます。


僕が買ったボードのPHY Addressは1でした。
USE PHY Power pinにチェックが入っていると、PHY Power GPIOで制御ができます。
WiFi station modeにチェックが入っていると、イーサネットコンバーター
チェックを外すとAPになります。

実際通信してみましたが、CATV12Mではほぼ上限の値が出ていたので、実際にはもっと早いスピードで通信できると思います。
ツイッターを見ながらプライムビデオを流すくらいの使い方は余裕でできました。
本当に1000円そこらでAPを自作できるのはすごいですね。
2つ数珠つなぎにしてAP-イーサネットコンバーターとやれば中継機とかも組めそうです。
(それはもっとうまいやり方がありそうですが)

どうやってこれを実現しているのか?コードを見るととてもシンプルで驚きます。

static esp_err_t tcpip_adapter_sta_input_eth_output(void* buffer, uint16_t len, void* eb)
{
    if (ethernet_is_connected) {
        esp_eth_tx(buffer, len);
    }

    esp_wifi_internal_free_rx_buffer(eb);
    return ESP_OK;
}

Wi-Fiに受信バッファがあったらEthernetに送る
Ethernetに受信バッファがあったらWi-Fiに送るというような関数があります
シリアル通信のようなノリでこんなことができているのですね。
パケットをそのまま処理しているので、ESP32自身に宛てられたパケットを判別して処理するようなコードを書かないとESP32自身は通信ができないような気がします。
市販のAPのようにWebUIを実装したりするのは結構たいへんそうです。
ボタンを押しながら起動で別モードとして設定モードが立ち上がるような実装だと特に問題なく作れそうです。

2019年2月24日日曜日

M5CameraでGoogle Driveにアップロードする

結論というか、基本的にはこちらのブログがとてもためになるので読んでください

ESP32にWROVERというSPI RAM付きモデルが出て、大容量のRAMを使えるようになりました。
そこで、200万画素のCMOSセンサーが作る画像をバッファすることも容易になり、M5Stackシリーズを作っているメーカーから出ているM5Cameraをはじめとして、Omnivision OV2640が載ったESP32ボードが続々登場しています。

購入してすぐ、本体がSoftAPモードで立ち上がり、本体のWebサーバーにブラウザでつなぐとカメラの映像がストリーミングできるなどアツい展開になっています。
ただまあ、映像オタク的にはそれをやるなら別にネットワークカメラやWi-Fi付きデジカメのほうが画質もいいしいいじゃんということで、
マイコンにやらせるなら、実際にはなにかのトリガーで写真を撮ってどこかにアップロードさせたいみたいな用途のほうが強みが発揮できそうです。

そこで、M5CameraでGoogle Driveに写真をアップロードしてみました。

Google Driveは、Drive APIというものが用意されており、これを使うとRESTでファイル操作が可能になります。が、
一番冒頭にリンクさせていただいた、cURLでGoogle Driveにアップロードする方法をご覧いただくとわかるように、認証がやや面倒です。

簡単にまとめると
・APIを登録
・クライアントIDとシークレットキーを取得
・ブラウザでクライアントID付きの登録URLを開いて認証コードを取得(OAuth認証)
・認証コードとクライアントIDとシークレットキーをPOSTしてリフレッシュトークンを取得※
ここまでが初期設定です。

次からがファイルをPOSTするたびに行う操作です。
・リフレッシュトークンとクライアントIDとシークレットキーをPOSTしてアクセストークンを取得
・アクセストークンとファイル、ファイル情報をPOSTしてファイルをアップロード

※アクセストークンには有効期限があり、アクセストークンを取得するためのトークンがリフレッシュトークンです。
そのため、毎回リフレッシュトークンから有効なアクセストークンを取得する必要があります。

これらの操作をすべて行い、実際にM5Cameraで画像をアップロードするサンプルをArduinoで作ってみました。この例をちょっといじれば、カメラ画像以外にも、
ローカルのSPIフラッシュやSDカードに貯めたセンサーデータをまとめてCSVでアップロードするなど、ArduinoでGoogle Driveにファイルをアップロードできます。


さて、このサンプルを使う前にはGoogle DriveのAPIキーを取得する必要があります。
この操作がしょっちゅう画面構成が変わって、探してもやり方が見つからない場合があるので自分用にもメモしておきます。

Google Developers Consoleを開く


プロジェクトの選択をクリック


新しいプロジェクトを適当に作成


認証情報→OAuthクライアントID



同意画面を設定


名前を適当につけて保存


アプリケーションの種類:その他
名前適当で作成



クライアントIDとクライアントシークレットが取得できた。

あとはファームを入れ替えたM5Cameraを起動し、シリアルモニターを開くと、これらを聞いてきて、OAuth認証用コード取得URLが表示されるので、
要求されるコードを入力していくと、SPIフラッシュにそれらが保存されて次からは電源を入れるだけでGoogle Driveに写真を撮ってアップロードしてくれます。