M5Stackでスマートメーターの瞬時電力をBP35A1から取得して表示してみた

# はじめに
以前から冬になると以上に電気代が高くなるので、どういった時間帯に使用電力量が多いのか把握したいと思っていました。

先人たちがすでにかなり同じことをやってくれているので、基本その流用ですが、M5StackでBP35A1で瞬時電力を取得して表示できたので、その内容を書きます。

# 参考情報
先にかなりまとまった情報があるのでそちらを参考にしてください。
この記事では差分点と、少しハマった点だけ書いておきます。

[スマートメーターの情報を最安ハードウェアで引っこ抜く](https://qiita.com/rukihena/items/82266ed3a43e4b652adb)
[Bルートで積算電力量計測値履歴１を取得する](https://ryuji-since2016.blog.so-net.ne.jp/2017-01-01)


# 開発環境
Arduino
ESP32:1.0.1

# 事前準備
下記のことは事前にやっておいてください。

- スマートメーターの申請
- BP35A1の購入
- M5Statckの購入

# 接続方法
HardwareSerial2で制御するため、M5Stackの16,17pinにBP35A1のTX,RXを接続します。
あとはVCC3.3VとGNDをつなぐだけです。

| M5Statck       |       BP35A1 |
|:-----------------|:------------------|
|16pin|TXD|
|17pin|RXD|

## 通信方法
公開しているソースコードのBP35A1クラスを使えば関数呼び出しだけで通信出来ます。
瞬時電力を30秒おきに表示するsimple-IPMVブランチをご使用ください。

https://github.com/Katsushun89/M5Stack_SmartMeter/tree/simple-IPMV

## 設定
config.hのB_ROOT_PASS, B_ROOT_AUTH_ID はスマートメーター申請して通知されたPass,IDを設定してください。

```cpp:config.h
const String B_ROOT_PASS = "XXXXXXXXXXXX";
const String B_ROOT_AUTH_ID = "00000000000000000000000000000000";
```

##お試し通信
ソースコードのtestComm()を呼べば、テスト通信出来ます。
https://github.com/Katsushun89/M5Stack_SmartMeter/blob/simple-IPMV/BP35A1.h#L78-L88


```cpp:BP35A1.h
    bool testComm(void){
        Serial2.println("SKVER");
        delay(100);
        bool is_received_res = waitExpectedRes(WAIT_TIME, "OK");
        if(!is_received_res){
            Serial.println("testcomm() nores err");
            return false;
        }
        Serial.println("testcomm() ok");
        return true;
    };
```

## 初期通信から瞬時電力取得
ソースコードのinitComm(), activeScan()を呼べば情報取得するための初期通信が実行されます。

```cpp:M5Stack_SmartMeter.ino
void setup()
{
  M5.begin();

  delay(1000);
  bp35a1 = new BP35A1();
  
  Serial.begin(115200);
  Serial2.begin(115200);
  delay(100);

  bp35a1->testComm();
  bp35a1->initComm();
  bp35a1->activeScan();
}
```

あとは、getInstantaneousPower()を呼ぶことで瞬時電力を取得します。

```cpp:M5Stack_SmartMeter.ino
void loop()
{
  uint32_t power;

  if(bp35a1->getInstantaneousPower(&power) == true){
    Serial.println("getInstantaneousPower success");
    M5.Lcd.println("IPMV:" + String(power, DEC) + "[W]");
  }
  delay(30 * 1000);
  M5.update();  
}
```



# 注意点
## 注意点1.M5Stackの書き込み時にBP35A1のVCC3.3Vは外す
M5StackでROM書き込みする際に、BP35A1のVCCをつないだままだと電源が不安定になるのか？書き込み出来ないです。
書き込みするときはVCC外しておきましょう。
回路組める人は、VCCをONするようなスイッチ機構を設けた方がいいです。
（もしくはBP35A1側のリセット端子で制御できるのかもしれない。未調査。）

## 注意点2.BP35A1からの応答情報をASCIIに設定する
これは一度だけ設定すればいいですが、設定しておかないと、データがバイナリで返ってくるため扱いにくいです。
ですので一度だけ下記のコマンドを実行してASCIIで返信してもらうように設定してください。
一度やればその後は不要です。
公開しているソースコードのsetWOPT()を呼んでもらえばいいです。

https://github.com/Katsushun89/M5Stack_SmartMeter/blob/simple-IPMV/BP35A1.h#L65-L75

```cpp:BP35A1.h
    bool setWOPT(void){
        Serial2.println("WOPT 01");
        delay(100);
        bool is_received_res = waitExpectedRes(WAIT_TIME, "OK");
        if(!is_received_res){
            Serial.println("setWOPT()) nores err");
            return false;
        }
        Serial.println("setWOPT() OK");
        return true;
    };
```

![DtNSv4xU0AEijIp.jpg](https://qiita-image-store.s3.amazonaws.com/0/302503/452057ac-60d2-d429-795d-f71a6685a45d.jpeg)
このような形で瞬時電力IPMVが表示されればOKです。

# 今後
まずは一番簡単な瞬時電力の取得だけ実行しました。
あとは、積算電力量をサーバーなどでロギングする、などやっていく予定です。

結構ツイッターではM5Stackで同じことやもっと高度なことをやっている人いるのに情報が余りなかったので、もしスマートメーターで電力取得したい人は、一番簡単なこの手順を参考にしてもらえたらと思います。