diff --git a/code/espurna/config/arduino.h b/code/espurna/config/arduino.h index e173fe1f..b9587157 100644 --- a/code/espurna/config/arduino.h +++ b/code/espurna/config/arduino.h @@ -110,6 +110,7 @@ //#define HLW8012_SUPPORT 1 //#define MHZ19_SUPPORT 1 //#define PMSX003_SUPPORT 1 +//#define PZEM004T_SUPPORT 1 //#define SHT3X_I2C_SUPPORT 1 //#define SI7021_SUPPORT 1 //#define V9261F_SUPPORT 1 diff --git a/code/espurna/config/sensors.h b/code/espurna/config/sensors.h index 4fd0c2e6..2fb124d6 100644 --- a/code/espurna/config/sensors.h +++ b/code/espurna/config/sensors.h @@ -82,6 +82,7 @@ #define SENSOR_SI7021_ID 0x15 #define SENSOR_SHT3X_I2C_ID 0x16 #define SENSOR_BH1750_ID 0x17 +#define SENSOR_PZEM004T_ID 0x18 //-------------------------------------------------------------------------------- // Magnitudes @@ -400,6 +401,32 @@ #define PMS_RX_PIN 13 #define PMS_TX_PIN 15 +//------------------------------------------------------------------------------ +// PZEM004T based power monitor +// Enable support by passing PZEM004T_SUPPORT=1 build flag +//------------------------------------------------------------------------------ + +#ifndef PZEM004T_SUPPORT +#define PZEM004T_SUPPORT 1 +#endif + +#ifndef PZEM004T_USE_SOFT +#define PZEM004T_USE_SOFT 1 // Use software serial +#endif + +#ifndef PZEM004T_RX_PIN +#define PZEM004T_RX_PIN 13 // Software serial RX GPIO (if PZEM004T_USE_SOFT == 1) +#endif + +#ifndef PZEM004T_TX_PIN +#define PZEM004T_TX_PIN 15 // Software serial TX GPIO (if PZEM004T_USE_SOFT == 1) +#endif + +#ifndef PZEM004T_HW_PORT +#define PZEM004T_HW_PORT Serial1 // Hardware serial port (if PZEM004T_USE_SOFT == 0) +#endif + + //------------------------------------------------------------------------------ // SHT3X I2C (Wemos) temperature & humidity sensor // Enable support by passing SHT3X_SUPPORT=1 build flag diff --git a/code/espurna/sensor.ino b/code/espurna/sensor.ino index 128610ce..38d17995 100644 --- a/code/espurna/sensor.ino +++ b/code/espurna/sensor.ino @@ -147,6 +147,12 @@ void _sensorWebSocketStart(JsonObject& root) { } #endif + #if PZEM004T_SUPPORT + if (sensor->getID() == SENSOR_PZEM004T_ID) { + root["pwrVisible"] = 1; + } + #endif + } if (_magnitudes.size() > 0) { @@ -414,6 +420,19 @@ void _sensorInit() { } #endif + #if PZEM004T_SUPPORT + { + PZEM004TSensor * sensor = new PZEM004TSensor(); + #if PZEM004T_USE_SOFT + sensor->setRX(PZEM004T_RX_PIN); + sensor->setTX(PZEM004T_TX_PIN); + #else + sensor->setSerial(& PZEM004T_HW_PORT); + #endif + _sensors.push_back(sensor); + } + #endif + #if SHT3X_I2C_SUPPORT { SHT3XI2CSensor * sensor = new SHT3XI2CSensor(); diff --git a/code/espurna/sensors/PZEM004TSensor.h b/code/espurna/sensors/PZEM004TSensor.h new file mode 100644 index 00000000..9e2cea38 --- /dev/null +++ b/code/espurna/sensors/PZEM004TSensor.h @@ -0,0 +1,134 @@ +// ----------------------------------------------------------------------------- +// PZEM004T based power monitor +// Copyright (C) 2018 by Xose PĂ©rez +// ----------------------------------------------------------------------------- + +#if SENSOR_SUPPORT && PZEM004T_SUPPORT + +#pragma once + +#include "Arduino.h" +#include "BaseSensor.h" + +#include + +class PZEM004TSensor : public BaseSensor { + + public: + + // --------------------------------------------------------------------- + // Public + // --------------------------------------------------------------------- + + PZEM004TSensor(): BaseSensor(), _data() { + _count = 4; + _sensor_id = SENSOR_PZEM004T_ID; + } + + ~PZEM004TSensor() { + if (_pzem) delete _pzem; + } + + // --------------------------------------------------------------------- + + void setRX(unsigned char pin_rx) { + if (_pin_rx == pin_rx) return; + _pin_rx = pin_rx; + _dirty = true; + } + + void setTX(unsigned char pin_tx) { + if (_pin_tx == pin_tx) return; + _pin_tx = pin_tx; + _dirty = true; + } + + void setSerial(Stream & serial) { + _serial = serial; + _dirty = true; + } + + // --------------------------------------------------------------------- + + unsigned char getRX() { + return _pin_rx; + } + + unsigned char getTX() { + return _pin_tx; + } + + Stream & getSerial() { + return _serial; + } + + // --------------------------------------------------------------------- + // Sensor API + // --------------------------------------------------------------------- + + // Initialization method, must be idempotent + void begin() { + + if (!_dirty) return; + _dirty = false; + + if (_pzem) delete _pzem; + if (_serial == NULL) { + _pzem = PZEM004T(_pin_rx, _pin_tx); + } else { + _pzem = PZEM004T(_serial); + } + _pzem->setAddress(_ip); + + } + + // Descriptive name of the sensor + String description() { + char buffer[28]; + snprintf(buffer, sizeof(buffer), "PZEM004T @ SwSerial(%u,%u)", _pin_rx, _pin_tx); + return String(buffer); + } + + // Descriptive name of the slot # index + String slot(unsigned char index) { + return description(); + }; + + // Address of the sensor (it could be the GPIO or I2C address) + String address(unsigned char index) { + return _ip.toString(); + } + + // Type for slot # index + unsigned char type(unsigned char index) { + if (index == 0) return MAGNITUDE_CURRENT; + if (index == 1) return MAGNITUDE_VOLTAGE; + if (index == 2) return MAGNITUDE_POWER_ACTIVE; + if (index == 3) return MAGNITUDE_ENERGY; + return MAGNITUDE_NONE; + } + + // Current value for slot # index + double value(unsigned char index) { + if (index == 0) return _pzem->current(_ip); + if (index == 1) return _pzem->voltage(_ip); + if (index == 2) return _pzem->power(_ip); + if (index == 3) return _pzem->energy(_ip); + return 0; + } + + protected: + + // --------------------------------------------------------------------- + // Protected + // --------------------------------------------------------------------- + + unsigned int _pin_rx = PZEM004T_RX_PIN; + unsigned int _pin_tx = PZEM004T_TX_PIN; + Stream & _serial = NULL; + IPAddress _ip(192,168,1,1); + PZEM004T * _pzem = NULL; + +}; + +#endif // SENSOR_SUPPORT && PZEM004T_SUPPORT diff --git a/code/espurna/utils.ino b/code/espurna/utils.ino index 3d86c767..e4035c65 100644 --- a/code/espurna/utils.ino +++ b/code/espurna/utils.ino @@ -377,6 +377,9 @@ void info() { #if PMSX003_SUPPORT DEBUG_MSG_P(PSTR(" PMSX003")); #endif + #if PZEM004T_SUPPORT + DEBUG_MSG_P(PSTR(" PZEM004T")); + #endif #if SHT3X_I2C_SUPPORT DEBUG_MSG_P(PSTR(" SHT3X_I2C")); #endif diff --git a/code/platformio.ini b/code/platformio.ini index 89ba3ca7..13b6f99f 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -29,6 +29,7 @@ lib_deps = https://github.com/xoseperez/NtpClient.git#b35e249 OneWire PMS Library + PZEM004T PubSubClient https://github.com/xoseperez/RemoteSwitch-arduino-library.git https://github.com/xoseperez/Time