2018年11月5日月曜日

STM32duino Nodemcu BP35A1 のSmartmeter ロガー

心臓部は Neocatさんの
http://neocat.hatenablog.com/entry/20160110/1452407542
そのままです。
Nodemcu-Wroom2はDC50V配電のロガーと同じ形式。

/*
  smartmeter logger for STM32duino
  With NodeMCU and BP35A1 for use InfluxDB and Grafana

  created  by  http://d.hatena.ne.jp/NeoCat/20160110/1452407542
           for Alduino and 7seg.LED
  modified 04 Nov. 2018
       by knet-ore.no-ip.biz
           for SMT32duino and Nodemcu-firm.(WROOM-02 ESP01 etc.)
*/
//-----------------------------------------------------------
// Configurations
//-----------------------------------------------------------
#include "SPI.h"
#include "Wire.h"
const int chipSelect = 4;
const int pinCount = 2;
// B-route ID and Password (PANA authentication)
#define ID "000000##########################"
#define PASSWORD "############"

//Serial1 pins to BP35A1
// define txPin PA9   // -> BP35A1's RXD
// define rxPin PA10  // <- bp35a1="" br="" s="" txd="">
//Serial1 pins to Nodemcu
// define txPin PB10  // -> Nodemcu's RXD
// define rxPin PB11  // <- br="" nodemcu="" s="" txd="">
//Serial1 pins to monitor
// define txPin PA2   // -> Serialmonitor's RXD
// define rxPin PA3   // <- br="" s="" serialmonitor="" txd="">
//-----------------------------------------------------------
// data trasnfer buffer
//-----------------------------------------------------------
const int bufsize = 122;
char buf[bufsize];
const int size = bufsize - 1;

//-----------------------------------------------------------
// debug message utilities
//-----------------------------------------------------------
//#define DEBUG

char errbuf[80];  // error message buffer

#define error0(fmt) Serial3.println(F(fmt));
#define error1(fmt, str) Serial3.print(F(fmt)), Serial3.println(str)
#define error(fmt, ...) sprintf(errbuf, fmt "\r\n", __VA_ARGS__), Serial3.print(errbuf)
#define log0(fmt) Serial3.println(F(fmt))
#define log1(fmt, str) Serial3.print(F(fmt)), Serial3.println(str)
#define log(fmt, ...) sprintf(errbuf, fmt "\r\n", __VA_ARGS__), Serial3.print(errbuf)
#ifdef DEBUG
#define debug0(fmt, ...) Serial3.println(F(fmt))
#define debug1(fmt, str) Serial3.print(F(fmt)), Serial3.println(str)
#define debug(fmt, ...) sprintf(errbuf, fmt "\r\n", __VA_ARGS__), Serial3.print(errbuf)
#else
#define debug0(fmt)
#define debug1(fmt, str)
#define debug(fmt, ...)
#endif

//-----------------------------------------------------------
// BP35A1 communication class
//-----------------------------------------------------------
// Note: Before using this class, BP35A1 UART must be set to
//       9600 bps / 400us pause by "WUART 43" command to
//       ensure software Serial12 to work properly.
//-----------------------------------------------------------
 
このあと心臓部〜略
シリアルはSerial1

//-----------------------------------------------------------
// Main routine
//-----------------------------------------------------------
BP35A1 wisun;  // BP35A1 instance
String Date;
String Wptime;
String Wntime;
int Wpwh;
int Wnwh;
void setup()  {

  Serial1.begin(9600);
  Serial2.begin(9600);
  Serial3.begin(9600);

  Serial3.println("Start");

  buf[size] = 0;

  if (!wisun.setup(ID, PASSWORD, buf, size)) {
    error0("setup failed");
    Serial3.print("eeee");
    for (;;);  // stop forever on error
  }

  Serial3.print("cccc");
  while (!wisun.connect(buf, size))
    delay(5000);  // reconnect on error after 5 sec

  // check if the smart meter is in running state (EPC 0x80 = 0x30)
  byte val = 0;
  if (wisun.epc_get(0x80, buf, size))
    val = (wisun.hex(buf[28]) << 4) | wisun.hex(buf[29]);
  if (val != 0x30)
    error0("SmartMeter is not working!");

  // check if the smart meter is not in error state (EPC 0x88 = 0x42)
  val = 0;
  if (wisun.epc_get(0x88, buf, size))
    val = (wisun.hex(buf[28]) << 4) | wisun.hex(buf[29]);
  if (val != 0x42)
    error0("SmartMeter is in error state!");

}

void read_date() {
  String Year;
  String Month;
  String Day;
  String Hour;
  String Min;
  String Sec;

  long val = 0;
  for (int i = 28; i < 32; i++) {
    val <<= 4;
    val |= wisun.hex(buf[i]);
  }
  Year = String(val);
  val = 0;
  for (int i = 32; i < 34; i++) {
    val <<= 4;
    val |= wisun.hex(buf[i]);
  }
  Month = String(val);
  val = 0;
  for (int i = 34; i < 36; i++) {
    val <<= 4;
    val |= wisun.hex(buf[i]);
  }
  Day = String(val);
  val = 0;
  for (int i = 36; i < 38; i++) {
    val <<= 4;
    val |= wisun.hex(buf[i]);
  }
  Hour = String(val);
  val = 0;
  for (int i = 38; i < 40; i++) {
    val <<= 4;
    val |= wisun.hex(buf[i]);
  }
  Min = String(val);
  val = 0;
  for (int i = 40; i < 42; i++) {
    val <<= 4;
    val |= wisun.hex(buf[i]);
  }
  Sec = String(val);
  Date = (Year + "/" + Month + "/" + Day + " " + Hour + ":" + Min + ":" + Sec);
}

void loop() {
  static int err_cnt = 0;

  log0("getting EPC 0xe7 ...");
  bool ret = wisun.epc_get(0xe7, buf, size);
  if (ret) {
    // convert hex string into long not unsigned-long
    long val = 0;
    for (int i = 28; buf[i]; i++) {
      val <<= 4;
      val |= wisun.hex(buf[i]);
    }
    // print immediate power value to Nodemcu and Serialmonitor
    Serial3.print(F("Power = "));
    Serial3.print(val);
    Serial3.println(F(" Watt"));
    Serial3.print("\r\n");

    Serial2.print("\r\n");
    Serial2.print("a1=");
    Serial2.print(val);
    Serial2.print("\r\n");

    log0("getting EPC 0xea ...");
    bool ret = wisun.epc_get(0xea, buf, size);
    if (ret) {

      read_date();
      Serial3.print(Date);
      Serial3.print("\r\n");

      val = 0;
      for (int i = 42; buf[i]; i++) {
        val <<= 4;
        val |= wisun.hex(buf[i]);
      }
      Serial3.print(F("+Power = "));
      Serial3.print(-Wpwh+val);
      Serial3.println(F(" kWh"));
      Serial3.print("\r\n");
      if (Wptime != Date) {
        Serial2.print("\r\n");
        Serial2.print("a2=");
        Serial2.print(val);
        Serial2.print("\r\n");
        Wptime = Date;
        Wpwh=val;
      }
      log0("getting EPC 0xeb ...");
      bool ret = wisun.epc_get(0xeb, buf, size);
      if (ret) {
        long val = 0;
        for (int i = 28; i < 42; i++) {
          val <<= 4;
          val |= wisun.hex(buf[i]);
        }

        read_date();
        Serial3.print(Date);
        Serial3.print("\r\n");

        val = 0;
        for (int i = 42; buf[i]; i++) {
          val <<= 4;
          val |= wisun.hex(buf[i]);
        }
        Serial3.print(F("-Power = "));
        Serial3.print(Wnwh-val);
        Serial3.println(F(" kWh"));
        Serial3.print("\r\n");
        Serial3.println(Date);
        Serial3.print("\r\n");
        if (Wntime != Date) {
          Serial2.print("\r\n");
          Serial2.print("a3=");
          Serial2.print(-val);
          Serial2.print("\r\n");
          Wntime = Date;
          Wnwh=val;
        }
        err_cnt = 0;
      } else {
        err_cnt++;
        error0("EPC get failed");
        if (err_cnt >= 5) {
          err_cnt = 0;
          Serial3.print("cccc");
          Serial3.print("\r\n");
          log0("reconnecting ...");
          wisun.disconnect(buf, size);
          wisun.connect(buf, size);
        }
      }
      bool ok;
      unsigned long end = millis() + 10000; // wait 10 sec
      while (long(millis() - end) < 0) {
        //    wisun.wait_udp(buf, size, 3, ok);
      }
    }
  }
}

積算の棒グラフが細すぎて見えんぞ。時刻もいまいち・・・。
記録時刻もNodemcuに受け渡すようにしようかな〜  と思案中

0 件のコメント:

コメントを投稿