mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-27 19:57:38 +00:00
[Eastron] Add P078 plugin from the Playground (was P150)
Still problems using the Software Serial
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
## Library for reading SDM120 SDM220 SDM230 SDM630 Modbus Energy meters. ##
|
||||
|
||||
### SECTIONS: ###
|
||||
#### 1. [INTRODUCTION](#introduction) ####
|
||||
#### 2. [SCREENSHOTS](#screenshots) ####
|
||||
#### 3. [INITIALIZING](#initializing) ####
|
||||
#### 4. [READING](#reading) ####
|
||||
#### 5. [DEBUGING](#debuging) ####
|
||||
#### 6. [CREDITS](#credits) ####
|
||||
|
||||
---
|
||||
|
||||
### Introduction: ###
|
||||
This library allows you reading SDM module(s) using:
|
||||
- [x] Hardware Serial (<i>recommended option, smallest number of reads errors</i>) <b><i>or</i></b>
|
||||
- [x] Software Serial (<i>library for ESP8266</i> https://github.com/plerup/espsoftwareserial)
|
||||
|
||||
you also need rs232<->rs485 converter:
|
||||
- [x] with automatic flow direction control (<i>look at images below</i>) <b><i>or</i></b>
|
||||
- [x] with additional pins for flow control, like MAX485</br>
|
||||
(<i>in this case MAX485 DE and RE pins must be connected together to one of esp pin</br>
|
||||
and this pin must be passed when initializing the library</i>)
|
||||
|
||||
_Tested on Wemos D1 Mini with Arduino IDE 1.8.3-1.9.0b & ESP8266 core 2.3.0-2.4.1_
|
||||
|
||||
---
|
||||
|
||||
### Screenshots: ###
|
||||
<img src="https://github.com/reaper7/SDM_Energy_Meter/blob/master/img/hardware_sdm220_1.jpg" height="330"><img src="https://github.com/reaper7/SDM_Energy_Meter/blob/master/img/hardware_sdm220_2.jpg" height="330"></br>
|
||||
<p align="center">
|
||||
<img src="https://github.com/reaper7/SDM_Energy_Meter/blob/master/img/livepage.gif"></br>
|
||||
<i>live page example (extended) screenshot</i>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
### Initializing: ###
|
||||
```cpp
|
||||
//lib init when Software Serial is used:
|
||||
#include <SDM.h>
|
||||
// ______________________baudrate
|
||||
// | __________________rx pin
|
||||
// | | ______________tx pin
|
||||
// | | | __________dere pin(optional for max485)
|
||||
// | | | |
|
||||
SDM<4800, 13, 15, 12> sdm;
|
||||
|
||||
//lib init when Hardware Serial is used:
|
||||
#define USE_HARDWARESERIAL
|
||||
#include <SDM.h>
|
||||
// ______________________baudrate
|
||||
// | __________________dere pin(optional for max485)
|
||||
// | | ______________swap hw serial pins from 3/1 to 13/15(default false)
|
||||
// | | |
|
||||
SDM<4800, 12, false> sdm;
|
||||
```
|
||||
NOTE: <i>when GPIO15 is used (especially for swapped hardware serial):</br>
|
||||
some converters (like mine) have built-in pullup resistors on TX/RX lines from rs232 side,</br>
|
||||
connection this type of converters to ESP8266 pin GPIO15 block booting process.</br>
|
||||
In this case you can replace the pull-up resistor on converter with higher value (100k),</br>
|
||||
to ensure low level on GPIO15 by built-in in most ESP8266 modules pulldown resistor.</br></i>
|
||||
|
||||
---
|
||||
|
||||
### Reading: ###
|
||||
List of available registers for SDM120/220/230/630:</br>
|
||||
https://github.com/reaper7/SDM_Energy_Meter/blob/master/SDM.h#L36
|
||||
```cpp
|
||||
//reading voltage from SDM with slave address 0x01 (default)
|
||||
// __________register name
|
||||
// |
|
||||
float voltage = sdm.readVal(SDM220T_VOLTAGE);
|
||||
|
||||
//reading power from 1st SDM with slave address ID = 0x01
|
||||
//reading power from 2nd SDM with slave address ID = 0x02
|
||||
//useful with several meters on RS485 line
|
||||
// __________register name
|
||||
// | ____SDM device ID
|
||||
// | |
|
||||
float power1 = sdm.readVal(SDM220T_POWER, 0x01);
|
||||
float power2 = sdm.readVal(SDM220T_POWER, 0x02);
|
||||
```
|
||||
NOTE: <i>if you reading multiple SDM devices on the same RS485 line,</br>
|
||||
remember to set the same transmission parameters on each device,</br>
|
||||
only ID must be different for each SDM device.</i>
|
||||
|
||||
---
|
||||
|
||||
### Debuging: ###
|
||||
Sometimes <b>readVal</b> return <b>NaN</b> value (not a number),</br>
|
||||
this means that the requested value could not be read from the sdm module for various reasons.</br>
|
||||
|
||||
__Please check out open and close issues, maybe the cause of your error is explained or solved there.__
|
||||
|
||||
The most common problems are:
|
||||
- weak or poorly filtered power supply / LDO, causing NaN readings and ESP crashes</br>
|
||||
https://github.com/reaper7/SDM_Energy_Meter/issues/13#issuecomment-353532711</br>
|
||||
https://github.com/reaper7/SDM_Energy_Meter/issues/13#issuecomment-353572909</br>
|
||||
https://github.com/reaper7/SDM_Energy_Meter/issues/8#issuecomment-381402008</br>
|
||||
- faulty or incorrectly prepared converter</br>
|
||||
https://github.com/reaper7/SDM_Energy_Meter/issues/16#issue-311042308</br>
|
||||
- faulty esp module</br>
|
||||
https://github.com/reaper7/SDM_Energy_Meter/issues/8#issuecomment-381398551</br>
|
||||
- many users report that between each readings should be placed <i>delay(50);</i></br>
|
||||
https://github.com/reaper7/SDM_Energy_Meter/issues/7#issuecomment-272080139</br>
|
||||
(I did not observe such problems using the HardwareSerial connection)</br>
|
||||
- using GPIO15 without checking signal level (note above)</br>
|
||||
https://github.com/reaper7/SDM_Energy_Meter/issues/17#issue-313606825</br>
|
||||
https://github.com/reaper7/SDM_Energy_Meter/issues/13#issuecomment-353413146</br>
|
||||
https://github.com/reaper7/SDM_Energy_Meter/issues/13#issuecomment-353417658</br>
|
||||
|
||||
You can get last error code using function:
|
||||
```cpp
|
||||
//get last error code
|
||||
// __________optional parameter,
|
||||
// | true -> read and reset error code
|
||||
// | false or no parameter -> read error code
|
||||
// | but not reset stored code (for future checking)
|
||||
// | will be overwriten when next error occurs
|
||||
uint16_t lasterror = sdm.getErrCode(true);
|
||||
|
||||
//clear error code also available with:
|
||||
sdm.clearErrCode();
|
||||
```
|
||||
Errors list returned by <b>getErrCode</b>:</br>
|
||||
https://github.com/reaper7/SDM_Energy_Meter/blob/master/SDM.h#L128</br>
|
||||
|
||||
You can also check total number of errors using function:
|
||||
```cpp
|
||||
//get total errors counter
|
||||
// _________optional parameter,
|
||||
// | true -> read and reset errors counter
|
||||
// | false or no parameter -> read errors counter
|
||||
// | but not reset stored counter (for future checking)
|
||||
uint16_t cnterrors = sdm.getErrCount(true);
|
||||
|
||||
//clear errors counter also available with:
|
||||
sdm.clearErrCount();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Credits: ###
|
||||
|
||||
:+1: ESP SoftwareSerial library by Peter Lerup (https://github.com/plerup/espsoftwareserial)</br>
|
||||
:+1: crc calculation by Jaime García (https://github.com/peninquen/Modbus-Energy-Monitor-Arduino)</br>
|
||||
:+1: new registers for SDM120 and SDM630 by bart.e (https://github.com/beireken/SDM220t)</br>
|
||||
|
||||
---
|
||||
|
||||
**2016-2018 Reaper7**
|
||||
|
||||
[paypal.me/reaper7md](https://www.paypal.me/reaper7md)
|
||||
@@ -0,0 +1,292 @@
|
||||
/* Template library for reading SDM 120/220/630 Modbus Energy meters.
|
||||
* Reading via Software Serial library & rs232<->rs485 converter
|
||||
* 2016 Reaper7 (tested on wemos d1 mini->ESP8266 with Arduino 1.6.9 & 2.3.0 esp8266 core)
|
||||
* crc calculation by Jaime García (https://github.com/peninquen/Modbus-Energy-Monitor-Arduino/)
|
||||
*/
|
||||
|
||||
//#define USE_HARDWARESERIAL //option - use hardware serial
|
||||
|
||||
#ifndef SDM_h
|
||||
#define SDM_h
|
||||
//------------------------------------------------------------------------------
|
||||
#include <Arduino.h>
|
||||
#if !defined ( USE_HARDWARESERIAL )
|
||||
#include <SoftwareSerial.h>
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
#define SDM_BAUD 4800 //baudrate
|
||||
#define MAX_MILLIS_TO_WAIT 500 //max time to wait for response from SDM
|
||||
|
||||
#if !defined ( USE_HARDWARESERIAL )
|
||||
#define SDMSER_RX_PIN 13 //RX-D7(wemos)-13
|
||||
#define SDMSER_TX_PIN 15 //TX-D8(wemos)-15
|
||||
#else
|
||||
#define SWAPHWSERIAL 0 //when hwserial used, then swap uart pins from 3/1 to 13/15
|
||||
#endif
|
||||
|
||||
#define DERE_PIN NOT_A_PIN //digital pin for control MAX485 DE/RE lines (connect DE & /RE together to this pin)
|
||||
|
||||
#define FRAMESIZE 9 //size of out/in array
|
||||
//------------------------------------------------------------------------------
|
||||
#define SDM_REPLY_BYTE_COUNT 0x04 //number of bytes with data
|
||||
|
||||
#define SDM_B_01 0x01 //BYTE 1 -> slave address (default value 1 read from node 1)
|
||||
#define SDM_B_02 0x04 //BYTE 2 -> function code (default value 0x04 read from 3X input registers)
|
||||
//BYTES 3 & 4 (BELOW)
|
||||
//SDM 120 registers
|
||||
#define SDM120C_VOLTAGE 0x0000 //V
|
||||
#define SDM120C_CURRENT 0x0006 //A
|
||||
#define SDM120C_POWER 0x000C //W
|
||||
#define SDM120C_ACTIVE_APPARENT_POWER 0x0012 //VA
|
||||
#define SDM120C_REACTIVE_APPARENT_POWER 0x0018 //VAR
|
||||
#define SDM120C_POWER_FACTOR 0x001E //
|
||||
#define SDM120C_FREQUENCY 0x0046 //Hz
|
||||
#define SDM120C_IMPORT_ACTIVE_ENERGY 0x0048 //Wh
|
||||
#define SDM120C_EXPORT_ACTIVE_ENERGY 0x004A //Wh
|
||||
#define SDM120C_TOTAL_ACTIVE_ENERGY 0x0156 //Wh
|
||||
//SDM 220 registers
|
||||
#define SDM220T_VOLTAGE 0x0000 //V
|
||||
#define SDM220T_CURRENT 0x0006 //A
|
||||
#define SDM220T_POWER 0x000C //W
|
||||
#define SDM220T_ACTIVE_APPARENT_POWER 0x0012 //VA
|
||||
#define SDM220T_REACTIVE_APPARENT_POWER 0x0018 //VAR
|
||||
#define SDM220T_POWER_FACTOR 0x001E //
|
||||
#define SDM220T_PHASE_ANGLE 0x0024 //DEGREE
|
||||
#define SDM220T_FREQUENCY 0x0046 //Hz
|
||||
#define SDM220T_IMPORT_ACTIVE_ENERGY 0x0048 //Wh
|
||||
#define SDM220T_EXPORT_ACTIVE_ENERGY 0x004A //Wh
|
||||
#define SDM220T_IMPORT_REACTIVE_ENERGY 0x004C //VARh
|
||||
#define SDM220T_EXPORT_REACTIVE_ENERGY 0x004E //VARh
|
||||
#define SDM220T_TOTAL_ACTIVE_ENERGY 0x0156 //Wh
|
||||
#define SDM220T_TOTAL_REACTIVE_ENERGY 0x0158 //VARh
|
||||
//SDM 230 registers
|
||||
#define SDM230_VOLTAGE 0x0000 //V
|
||||
#define SDM230_CURRENT 0x0006 //A
|
||||
#define SDM230_POWER 0x000C //W
|
||||
#define SDM230_ACTIVE_APPARENT_POWER 0x0012 //VA
|
||||
#define SDM230_REACTIVE_APPARENT_POWER 0x0018 //VAR
|
||||
#define SDM230_POWER_FACTOR 0x001E //
|
||||
#define SDM230_PHASE_ANGLE 0x0024 //DEGREE
|
||||
#define SDM230_FREQUENCY 0x0046 //Hz
|
||||
#define SDM230_IMPORT_ACTIVE_ENERGY 0x0048 //Wh
|
||||
#define SDM230_EXPORT_ACTIVE_ENERGY 0x004A //Wh
|
||||
#define SDM230_IMPORT_REACTIVE_ENERGY 0x004C //VARh
|
||||
#define SDM230_EXPORT_REACTIVE_ENERGY 0x004E //VARh
|
||||
#define SDM230_TOTAL_SYSTEM_POWER_DEMAND 0x0054 //W
|
||||
#define SDM230_MAXIMUM_SYSTEM_POWER_DEMAND 0x0056 //W
|
||||
#define SDM230_CURRENT_POSITIVE_POWER_DEMAND 0x0058 //W
|
||||
#define SDM230_MAXIMUM_POSITIVE_POWER_DEMAND 0x005A //W
|
||||
#define SDM230_CURRENT_REVERSE_POWER_DEMAND 0x005C //W
|
||||
#define SDM230_MAXIMUM_REVERSE_POWER_DEMAND 0x005E //W
|
||||
#define SDM230_CURRENT_DEMAND 0x0102 //Amps
|
||||
#define SDM230_MAXIMUM_CURRENT_DEMAND 0x0108 //Amps
|
||||
#define SDM230_TOTAL_ACTIVE_ENERGY 0x0156 //kwh
|
||||
#define SDM230_TOTAL_REACTIVE_ENERGY 0x0158 //kvarh
|
||||
#define SDM230_CURRENT_RESETTABLE_TOTAL_ACTIVE_ENERGY 0x0180 //Wh
|
||||
#define SDM230_CURRENT_RESETTABLE_TOTAL_REACTIVE_ENERGY 0x0182 //VARh
|
||||
//SDM 630 registers
|
||||
#define SDM630_VOLTAGE1 0x0000 //V
|
||||
#define SDM630_VOLTAGE2 0x0002 //V
|
||||
#define SDM630_VOLTAGE3 0x0004 //V
|
||||
#define SDM630_CURRENT1 0x0006 //A
|
||||
#define SDM630_CURRENT2 0x0008 //A
|
||||
#define SDM630_CURRENT3 0x000A //A
|
||||
#define SDM630_CURRENTSUM 0x0030 //A
|
||||
#define SDM630_POWER1 0x000C //W
|
||||
#define SDM630_POWER2 0x000E //W
|
||||
#define SDM630_POWER3 0x0010 //W
|
||||
#define SDM630_POWERTOTAL 0x0034 //W
|
||||
#define SDM630_VOLT_AMPS1 0x0012 //VA
|
||||
#define SDM630_VOLT_AMPS2 0x0014 //VA
|
||||
#define SDM630_VOLT_AMPS3 0x0016 //VA
|
||||
#define SDM630_VOLT_AMPS_TOTAL 0x0038 //VA
|
||||
#define SDM630_VOLT_AMPS_REACTIVE1 0x0018 //VAr
|
||||
#define SDM630_VOLT_AMPS_REACTIVE2 0x001A //VAr
|
||||
#define SDM630_VOLT_AMPS_REACTIVE3 0x001C //VAr
|
||||
#define SDM630_VOLT_AMPS_REACTIVE_TOTAL 0x003C //VAr
|
||||
#define SDM630_POWER_FACTOR1 0x001E
|
||||
#define SDM630_POWER_FACTOR2 0x0020
|
||||
#define SDM630_POWER_FACTOR3 0x0022
|
||||
#define SDM630_POWER_FACTOR_TOTAL 0x003E
|
||||
#define SDM630_PHASE_ANGLE1 0x0024 //Degrees
|
||||
#define SDM630_PHASE_ANGLE2 0x0026 //Degrees
|
||||
#define SDM630_PHASE_ANGLE3 0x0028 //Degrees
|
||||
#define SDM630_PHASE_ANGLE_TOTAL 0x0042 //Degrees
|
||||
#define SDM630_VOLTAGE_AVERAGE 0x002A //V
|
||||
#define SDM630_CURRENT_AVERAGE 0x002E //A
|
||||
#define SDM630_FREQUENCY 0x0046 //HZ
|
||||
#define SDM630_IMPORT_ACTIVE_ENERGY 0x0048 //Wh
|
||||
#define SDM630_EXPORT_ACTIVE_ENERGY 0x004A //Wh
|
||||
#define SDM630_IMPORT_REACTIVE_ENERGY 0x004C //VARh
|
||||
#define SDM630_EXPORT_REACTIVE_ENERGY 0x004E //VARh
|
||||
#define SDM630_TOTAL_SYSTEM_POWER_DEMAND 0x0054 //W
|
||||
#define SDM630_MAXIMUM_TOTAL_SYSTEM_POWER 0x0056 //W
|
||||
|
||||
#define SDM_B_05 0x00 //BYTE 5
|
||||
#define SDM_B_06 0x02 //BYTE 6
|
||||
//------------------------------------------------------------------------------
|
||||
#define SDM_ERR_NO_ERROR 0 //no error
|
||||
#define SDM_ERR_CRC_ERROR 1 //crc error
|
||||
#define SDM_ERR_WRONG_BYTES 2 //bytes b0,b1 or b2 wrong
|
||||
#define SDM_ERR_NOT_ENOUGHT_BYTES 3 //not enough bytes from sdm
|
||||
#define SDM_ERR_TIMEOUT 4 //timeout
|
||||
//------------------------------------------------------------------------------
|
||||
#if !defined ( USE_HARDWARESERIAL )
|
||||
template <long _speed = SDM_BAUD, int _rx_pin = SDMSER_RX_PIN, int _tx_pin = SDMSER_TX_PIN, int _dere_pin = DERE_PIN>
|
||||
#else
|
||||
template <long _speed = SDM_BAUD, int _dere_pin = DERE_PIN, bool _swapuart = SWAPHWSERIAL>
|
||||
#endif
|
||||
struct SDM {
|
||||
|
||||
#if !defined ( USE_HARDWARESERIAL )
|
||||
#if defined ( ESP8266 )
|
||||
SoftwareSerial sdmSer = SoftwareSerial(_rx_pin, _tx_pin, false, 32); //for esp8266 SoftwareSerial (https://github.com/plerup/espsoftwareserial)
|
||||
#else
|
||||
SoftwareSerial sdmSer = SoftwareSerial(_rx_pin, _tx_pin); //for standard avr SoftwareSerial library
|
||||
#endif
|
||||
#else
|
||||
#if defined ( ESP8266 )
|
||||
HardwareSerial sdmSer = HardwareSerial(0);
|
||||
#else
|
||||
#error Hardware Serial option available only for ESP8266.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
uint16_t readingerrcode = SDM_ERR_NO_ERROR; //4 = timeout; 3 = not enough bytes; 2 = number of bytes OK but bytes b0,b1 or b2 wrong, 1 = crc error
|
||||
uint16_t readingerrcount = 0; //total errors couter
|
||||
|
||||
uint16_t calculateCRC(uint8_t *array, uint8_t num) {
|
||||
uint16_t temp, flag;
|
||||
temp = 0xFFFF;
|
||||
for (uint8_t i = 0; i < num; i++) {
|
||||
temp = temp ^ array[i];
|
||||
for (uint8_t j = 8; j; j--) {
|
||||
flag = temp & 0x0001;
|
||||
temp >>= 1;
|
||||
if (flag)
|
||||
temp ^= 0xA001;
|
||||
}
|
||||
}
|
||||
return temp;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
void clearErrCode() { //clear last errorcode
|
||||
readingerrcode = SDM_ERR_NO_ERROR;
|
||||
};
|
||||
|
||||
void clearErrCount() { //clear total errors count
|
||||
readingerrcount = 0;
|
||||
};
|
||||
|
||||
uint16_t getErrCode(bool _clear = false) { //return last errorcode (optional clear this value, default flase)
|
||||
uint16_t _tmp = readingerrcode;
|
||||
if (_clear == true)
|
||||
clearErrCode();
|
||||
return (_tmp);
|
||||
};
|
||||
|
||||
uint16_t getErrCount(bool _clear = false) { //return total errors count (optional clear this value, default flase)
|
||||
uint16_t _tmp = readingerrcount;
|
||||
if (_clear == true)
|
||||
clearErrCount();
|
||||
return (_tmp);
|
||||
};
|
||||
|
||||
void begin() {
|
||||
sdmSer.begin(_speed);
|
||||
#if defined ( USE_HARDWARESERIAL )
|
||||
if (_swapuart)
|
||||
sdmSer.swap();
|
||||
#endif
|
||||
if (_dere_pin != NOT_A_PIN) //set output pin mode for DE/RE pin when used (for control MAX485)
|
||||
pinMode(_dere_pin, OUTPUT);
|
||||
};
|
||||
|
||||
float readVal(uint16_t reg, uint8_t node = SDM_B_01) { //read value from register = reg and from deviceId = node
|
||||
uint16_t temp;
|
||||
unsigned long resptime;
|
||||
uint8_t sdmarr[FRAMESIZE] = {node, SDM_B_02, 0, 0, SDM_B_05, SDM_B_06, 0, 0, 0};
|
||||
float res = NAN;
|
||||
uint16_t readErr = SDM_ERR_NO_ERROR;
|
||||
|
||||
sdmarr[2] = highByte(reg);
|
||||
sdmarr[3] = lowByte(reg);
|
||||
|
||||
temp = calculateCRC(sdmarr, FRAMESIZE - 3); //calculate out crc only from first 6 bytes
|
||||
|
||||
sdmarr[6] = lowByte(temp);
|
||||
sdmarr[7] = highByte(temp);
|
||||
|
||||
#if !defined ( USE_HARDWARESERIAL )
|
||||
sdmSer.listen(); //enable softserial rx interrupt
|
||||
#endif
|
||||
|
||||
while (sdmSer.available() > 0) { //read serial if any old data is available
|
||||
sdmSer.read();
|
||||
}
|
||||
|
||||
if (_dere_pin != NOT_A_PIN) //transmit to SDM -> DE Enable, /RE Disable (for control MAX485)
|
||||
digitalWrite(_dere_pin, HIGH);
|
||||
|
||||
delay(2); //fix for issue (nan reading) by sjfaustino: https://github.com/reaper7/SDM_Energy_Meter/issues/7#issuecomment-272111524
|
||||
|
||||
sdmSer.write(sdmarr, FRAMESIZE - 1); //send 8 bytes
|
||||
|
||||
sdmSer.flush(); //clear out tx buffer
|
||||
|
||||
if (_dere_pin != NOT_A_PIN) //receive from SDM -> DE Disable, /RE Enable (for control MAX485)
|
||||
digitalWrite(_dere_pin, LOW);
|
||||
|
||||
resptime = millis() + MAX_MILLIS_TO_WAIT;
|
||||
|
||||
while (sdmSer.available() < FRAMESIZE) {
|
||||
if (resptime < millis()) {
|
||||
readErr = SDM_ERR_TIMEOUT; //err debug (4)
|
||||
break;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
if (readErr == SDM_ERR_NO_ERROR) { //if no timeout...
|
||||
|
||||
if(sdmSer.available() == FRAMESIZE) {
|
||||
for(int n=0; n<FRAMESIZE; n++) {
|
||||
sdmarr[n] = sdmSer.read();
|
||||
}
|
||||
|
||||
if (sdmarr[0] == node && sdmarr[1] == SDM_B_02 && sdmarr[2] == SDM_REPLY_BYTE_COUNT) {
|
||||
|
||||
if ((calculateCRC(sdmarr, FRAMESIZE - 2)) == ((sdmarr[8] << 8) | sdmarr[7])) { //calculate crc from first 7 bytes and compare with received crc (bytes 7 & 8)
|
||||
((uint8_t*)&res)[3]= sdmarr[3];
|
||||
((uint8_t*)&res)[2]= sdmarr[4];
|
||||
((uint8_t*)&res)[1]= sdmarr[5];
|
||||
((uint8_t*)&res)[0]= sdmarr[6];
|
||||
} else {
|
||||
readErr = SDM_ERR_CRC_ERROR; //err debug (1)
|
||||
}
|
||||
} else {
|
||||
readErr = SDM_ERR_WRONG_BYTES; //err debug (2)
|
||||
}
|
||||
} else {
|
||||
readErr = SDM_ERR_NOT_ENOUGHT_BYTES; //err debug (3)
|
||||
}
|
||||
}
|
||||
|
||||
if (readErr != SDM_ERR_NO_ERROR) { //if error then copy temp error value to global val and increment global error counter
|
||||
readingerrcode = readErr;
|
||||
readingerrcount++;
|
||||
}
|
||||
|
||||
#if !defined ( USE_HARDWARESERIAL )
|
||||
sdmSer.end(); //disable softserial rx interrupt
|
||||
#endif
|
||||
|
||||
return (res);
|
||||
};
|
||||
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
const char index_page[] PROGMEM = R"=====(
|
||||
<!DOCTYPE HTML>
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META name='viewport' content='width=device-width, initial-scale=1'>
|
||||
<TITLE>SDM live POWER table</TITLE>
|
||||
<SCRIPT>
|
||||
var xmlHttp=createXmlHttpObject();
|
||||
function createXmlHttpObject(){
|
||||
if(window.XMLHttpRequest){
|
||||
xmlHttp=new XMLHttpRequest();
|
||||
}else{
|
||||
xmlHttp=new ActiveXObject('Microsoft.XMLHTTP');
|
||||
}
|
||||
return xmlHttp;
|
||||
}
|
||||
function process(){
|
||||
if(xmlHttp.readyState==0 || xmlHttp.readyState==4){
|
||||
xmlHttp.open('PUT','xml',true);
|
||||
xmlHttp.onreadystatechange=handleServerResponse;
|
||||
xmlHttp.send(null);
|
||||
}
|
||||
setTimeout('process()',2000);
|
||||
}
|
||||
function handleServerResponse(){
|
||||
if(xmlHttp.readyState==4 && xmlHttp.status==200){
|
||||
xmlResponse=xmlHttp.responseXML;
|
||||
for(i=0;i<6;i++){
|
||||
xmldoc=xmlResponse.getElementsByTagName('response'+i)[0].firstChild.nodeValue;
|
||||
document.getElementById('resp'+i).innerHTML=xmldoc;
|
||||
}
|
||||
xmldoc=xmlResponse.getElementsByTagName('freeh')[0].firstChild.nodeValue;
|
||||
document.getElementById('freeheap').innerHTML=xmldoc;
|
||||
xmldoc=xmlResponse.getElementsByTagName('rst')[0].firstChild.nodeValue;
|
||||
document.getElementById('rstreason').innerHTML=xmldoc;
|
||||
}
|
||||
}
|
||||
</SCRIPT>
|
||||
<STYLE>
|
||||
h1 {
|
||||
font-size: 120%;
|
||||
color: blue;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
table{
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table, th, td {
|
||||
text-align: center;
|
||||
border: 1px solid blue;
|
||||
}
|
||||
tr:nth-child(even) {background-color: #f2f2f2}
|
||||
</STYLE>
|
||||
</HEAD>
|
||||
<BODY onload='process()'>
|
||||
<CENTER>
|
||||
<H1>SDM live POWER table</H1>
|
||||
<TABLE BORDER=1>
|
||||
<TR><TH title="VOLTAGE">VOLTAGE</TH><TD><A id='resp0'></A></TD><TD>V</TD></TR>
|
||||
<TR><TH title="CURRENT">CURRENT</TH><TD><A id='resp1'></A></TD><TD>A</TD></TR>
|
||||
<TR><TH title="POWER">POWER</TH><TD><A id='resp2'></A></TD><TD>W</TD></TR>
|
||||
<TR><TH title="POWER FACTOR">POWER FACTOR</TH><TD><A id='resp3'></A></TD><TD>PF</TD></TR>
|
||||
<TR><TH title="PHASE ANGLE">PHASE ANGLE</TH><TD><A id='resp4'></A></TD><TD>°</TD></TR>
|
||||
<TR><TH title="FREQUENCY">FREQUENCY</TH><TD><A id='resp5'></A></TD><TD>Hz</TD></TR>
|
||||
<TR><TH title="FREE HEAP">FREE HEAP</TH><TD><A id='freeheap'></A></TD><TD>bytes</TD></TR>
|
||||
<TR><TH title="LAST RESET REASON">LAST RESET REASON</TH><TD colspan="2"><A id='rstreason'></A></TD></TR>
|
||||
</TABLE>
|
||||
</CENTER>
|
||||
</BODY>
|
||||
</HTML>
|
||||
)=====";
|
||||
@@ -0,0 +1,187 @@
|
||||
//sdm live page example by reaper7
|
||||
|
||||
//#define USE_HARDWARESERIAL
|
||||
#define READSDMEVERY 2000 //read sdm every 2000ms
|
||||
#define NBREG 6 //number of sdm registers to read
|
||||
//#define USE_STATIC_IP
|
||||
|
||||
/* WEMOS D1 Mini
|
||||
______________________________
|
||||
| L T L T L T L T L T L T |
|
||||
| |
|
||||
RST| 1|TX HSer
|
||||
A0| 3|RX HSer
|
||||
D0|16 5|D1
|
||||
D5|14 4|D2
|
||||
D6|12 10kPUP_0|D3
|
||||
RX SSer/HSer swap D7|13 LED_10kPUP_2|D4
|
||||
TX SSer/HSer swap D8|15 |GND
|
||||
3V3|__ |5V
|
||||
| |
|
||||
|___________________________|
|
||||
*/
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <ArduinoOTA.h>
|
||||
|
||||
#include <ESPAsyncTCP.h> // https://github.com/me-no-dev/ESPAsyncTCP
|
||||
#include <ESPAsyncWebServer.h> // https://github.com/me-no-dev/ESPAsyncWebServer
|
||||
|
||||
#include <SDM.h> // https://github.com/reaper7/SDM_Energy_Meter
|
||||
|
||||
#include "index_page.h"
|
||||
//------------------------------------------------------------------------------
|
||||
AsyncWebServer server(80);
|
||||
|
||||
#if !defined ( USE_HARDWARESERIAL ) // SOFTWARE SERIAL
|
||||
SDM<4800, 13, 15, NOT_A_PIN> sdm; // baud, rx_pin, tx_pin, de/re_pin(not used in this example)
|
||||
#else // HARDWARE SERIAL
|
||||
SDM<4800, NOT_A_PIN, false> sdm; // baud, de/re_pin(not used in this example), uart0 pins 3/1(false) or 13/15(true)
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
String devicename = "PWRMETER";
|
||||
|
||||
#if defined ( USE_STATIC_IP )
|
||||
IPAddress ip(192, 168, 0, 130);
|
||||
IPAddress gateway(192, 168, 0, 1);
|
||||
IPAddress subnet(255, 255, 255, 0);
|
||||
#endif
|
||||
|
||||
const char* wifi_ssid = "YOUR_SSID";
|
||||
const char* wifi_password = "YOUR_PASSWORD";
|
||||
|
||||
String lastresetreason = "";
|
||||
|
||||
unsigned long readtime;
|
||||
//------------------------------------------------------------------------------
|
||||
typedef volatile struct {
|
||||
volatile float regvalarr;
|
||||
const uint16_t regarr;
|
||||
} sdm_struct;
|
||||
|
||||
volatile sdm_struct sdmarr[NBREG] = {
|
||||
{0.00, SDM220T_VOLTAGE}, //V
|
||||
{0.00, SDM220T_CURRENT}, //A
|
||||
{0.00, SDM220T_POWER}, //W
|
||||
{0.00, SDM220T_POWER_FACTOR}, //PF
|
||||
{0.00, SDM220T_PHASE_ANGLE}, //DEGREE
|
||||
{0.00, SDM220T_FREQUENCY}, //Hz
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
void xmlrequest(AsyncWebServerRequest *request) {
|
||||
String XML = F("<?xml version='1.0'?><xml>");
|
||||
for (int i = 0; i < NBREG; i++) {
|
||||
XML += "<response" + (String)i + ">";
|
||||
XML += String(sdmarr[i].regvalarr,2);
|
||||
XML += "</response" + (String)i + ">";
|
||||
}
|
||||
XML += F("<freeh>");
|
||||
XML += String(ESP.getFreeHeap());
|
||||
XML += F("</freeh>");
|
||||
XML += F("<rst>");
|
||||
XML += lastresetreason;
|
||||
XML += F("</rst>");
|
||||
XML += F("</xml>");
|
||||
request->send(200, "text/xml", XML);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void indexrequest(AsyncWebServerRequest *request) {
|
||||
request->send_P(200, "text/html", index_page);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ledOn() {
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ledOff() {
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ledSwap() {
|
||||
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void otaInit() {
|
||||
ArduinoOTA.setHostname(devicename.c_str());
|
||||
|
||||
ArduinoOTA.onStart([]() {
|
||||
ledOn();
|
||||
});
|
||||
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
|
||||
ledSwap();
|
||||
});
|
||||
ArduinoOTA.onEnd([]() {
|
||||
ledOff();
|
||||
});
|
||||
ArduinoOTA.onError([](ota_error_t error) {
|
||||
ledOff();
|
||||
});
|
||||
ArduinoOTA.begin();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void serverInit() {
|
||||
server.on("/", HTTP_GET, indexrequest);
|
||||
server.on("/xml", HTTP_PUT, xmlrequest);
|
||||
server.onNotFound([](AsyncWebServerRequest *request){
|
||||
request->send(404);
|
||||
});
|
||||
server.begin();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void wifiInit() {
|
||||
WiFi.persistent(false); // Do not write new connections to FLASH
|
||||
WiFi.mode(WIFI_STA);
|
||||
#if defined ( USE_STATIC_IP )
|
||||
WiFi.config(ip, gateway, subnet); // Set fixed IP Address
|
||||
#endif
|
||||
WiFi.begin(wifi_ssid, wifi_password);
|
||||
|
||||
while( WiFi.status() != WL_CONNECTED ) { // Wait for WiFi connection
|
||||
ledSwap();
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void sdmRead() {
|
||||
float tmpval = NAN;
|
||||
|
||||
for (uint8_t i = 0; i < NBREG; i++) {
|
||||
tmpval = sdm.readVal(sdmarr[i].regarr);
|
||||
|
||||
if (isnan(tmpval))
|
||||
sdmarr[i].regvalarr = 0.00;
|
||||
else
|
||||
sdmarr[i].regvalarr = tmpval;
|
||||
|
||||
yield();
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void setup() {
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
ledOn();
|
||||
|
||||
lastresetreason = ESP.getResetReason();
|
||||
|
||||
wifiInit();
|
||||
otaInit();
|
||||
serverInit();
|
||||
sdm.begin();
|
||||
|
||||
readtime = millis();
|
||||
|
||||
ledOff();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void loop() {
|
||||
ArduinoOTA.handle();
|
||||
|
||||
if (millis() - readtime >= READSDMEVERY) {
|
||||
sdmRead();
|
||||
readtime = millis();
|
||||
}
|
||||
|
||||
yield();
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/* WEMOS D1 Mini
|
||||
______________________________
|
||||
| L T L T L T L T L T L T |
|
||||
| |
|
||||
RST| 1|TX HSer
|
||||
A0| 3|RX HSer
|
||||
D0|16 5|D1
|
||||
D5|14 4|D2
|
||||
D6|12 10kPUP_0|D3
|
||||
RX SSer/HSer swap D7|13 LED_10kPUP_2|D4
|
||||
TX SSer/HSer swap D8|15 |GND
|
||||
3V3|__ |5V
|
||||
| |
|
||||
|___________________________|
|
||||
*/
|
||||
|
||||
#include <SDM.h> //import SDM template library
|
||||
|
||||
#define ASCII_ESC 27
|
||||
|
||||
char bufout[10];
|
||||
|
||||
//SDM<2400, 13, 15> sdm; //SDM120T baud, rx pin, tx pin, dere pin(optional for max485)
|
||||
//SDM<4800, 13, 15> sdm; //SDM220T baud, rx pin, tx pin, dere pin(optional for max485)
|
||||
//SDM<9600, 13, 15> sdm; //SDM630 baud, rx pin, tx pin, dere pin(optional for max485)
|
||||
//or without parameters (default from SDM.h will be used):
|
||||
SDM<> sdm;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200); //initialize serial
|
||||
sdm.begin(); //initialize SDM220 communication baudrate
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
sprintf(bufout,"%c[1;0H",ASCII_ESC);
|
||||
Serial.print(bufout);
|
||||
|
||||
Serial.print("Voltage: ");
|
||||
Serial.print(sdm.readVal(SDM220T_VOLTAGE), 2); //display voltage
|
||||
Serial.println("V");
|
||||
|
||||
delay(50);
|
||||
|
||||
Serial.print("Current: ");
|
||||
Serial.print(sdm.readVal(SDM220T_CURRENT), 2); //display current
|
||||
Serial.println("A");
|
||||
|
||||
delay(50);
|
||||
|
||||
Serial.print("Power: ");
|
||||
Serial.print(sdm.readVal(SDM220T_POWER), 2); //display power
|
||||
Serial.println("W");
|
||||
|
||||
delay(50);
|
||||
|
||||
Serial.print("Frequency: ");
|
||||
Serial.print(sdm.readVal(SDM220T_FREQUENCY), 2); //display frequency
|
||||
Serial.println("Hz");
|
||||
|
||||
delay(1000); //wait a while before next loop
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 157 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 136 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 37 KiB |
@@ -0,0 +1,8 @@
|
||||
SDM KEYWORD1
|
||||
|
||||
begin KEYWORD2
|
||||
readVal KEYWORD2
|
||||
getErrCode KEYWORD2
|
||||
getErrCount KEYWORD2
|
||||
clearErrCode KEYWORD2
|
||||
clearErrCount KEYWORD2
|
||||
@@ -0,0 +1,9 @@
|
||||
name=SDM
|
||||
version=1.0.4
|
||||
author=Reaper7
|
||||
maintainer=Reaper7
|
||||
sentence=SDM 120/220/630 modbus energy meter
|
||||
paragraph=template library for ESP8266
|
||||
category=Communication
|
||||
url=https://github.com/reaper7/SDM_Energy_Meter
|
||||
architectures=esp8266,avr
|
||||
@@ -0,0 +1,199 @@
|
||||
#ifdef USES_P078
|
||||
|
||||
//#######################################################################################################
|
||||
//############################# Plugin 078: SDM120C Eastron Energy Meter ################################
|
||||
//#######################################################################################################
|
||||
/*
|
||||
Plugin written by: Sergio Faustino sjfaustino__AT__gmail.com
|
||||
|
||||
This plugin reads available values of an Eastron SDM120C Energy Meter.
|
||||
It will also work with all the other superior model such as SDM220 AND SDM630 series.
|
||||
*/
|
||||
|
||||
#define PLUGIN_078
|
||||
#define PLUGIN_ID_078 78
|
||||
#define PLUGIN_NAME_078 "Energy (AC) - Eastron SDM120C"
|
||||
#define PLUGIN_VALUENAME1_078 "Voltage"
|
||||
|
||||
boolean Plugin_078_init = false;
|
||||
#include <SDM.h> // Requires SDM library from Reaper7 - https://github.com/reaper7/SDM_Energy_Meter/
|
||||
|
||||
SDM<2400, D6, D7> Plugin_078_SDM;
|
||||
|
||||
boolean Plugin_078(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_078;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_DUAL; // connected through 2 datapins
|
||||
Device[deviceCount].VType = SENSOR_TYPE_SINGLE;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = true;
|
||||
Device[deviceCount].ValueCount = 1;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_078);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_078));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
byte meter_model = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
byte meter_baudrate = Settings.TaskDevicePluginConfig[event->TaskIndex][2];
|
||||
byte query = Settings.TaskDevicePluginConfig[event->TaskIndex][3];
|
||||
|
||||
String options_model[3] = { F("SDM120C"), F("SDM220T"), F("SDM630") };
|
||||
addFormSelector(F("Model Type"), F("plugin_078_meter_model"), 3, options_model, NULL, meter_model );
|
||||
|
||||
String options_baudrate[6] = { F("1200"), F("2400"), F("4800"), F("9600"), F("19200"), F("38400") };
|
||||
addFormSelector(F("Baud Rate"), F("plugin_078_meter_baudrate"), 6, options_baudrate, NULL, meter_baudrate );
|
||||
|
||||
if (meter_model == 0 && meter_baudrate > 3)
|
||||
addFormNote(F("<span style=\"color:red\"> SDM120 only allows up to 9600 baud with default 2400!</span>"));
|
||||
|
||||
if (meter_model == 2 && meter_baudrate == 0)
|
||||
addFormNote(F("<span style=\"color:red\"> SDM630 only allows 2400 to 38400 baud with default 9600!</span>"));
|
||||
|
||||
String options_query[10] = { F("Voltage (V)"),
|
||||
F("Current (A)"),
|
||||
F("Power (W)"),
|
||||
F("Active Apparent Power (VA)"),
|
||||
F("Reactive Apparent Power (VAr)"),
|
||||
F("Power Factor (cos-phi)"),
|
||||
F("Frequency (Hz)"),
|
||||
F("Import Active Energy (Wh)"),
|
||||
F("Export Active Energy (Wh)"),
|
||||
F("Total Active Energy (Wh)") };
|
||||
addFormSelector(F("Query"), F("plugin_078_query"), 10, options_query, NULL, query );
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = getFormItemInt(F("plugin_078"));
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = getFormItemInt(F("plugin_078_meter_model"));
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = getFormItemInt(F("plugin_078_meter_baudrate"));
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][3] = getFormItemInt(F("plugin_078_query"));
|
||||
|
||||
Plugin_078_init = false; // Force device setup next time
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
Plugin_078_init = true;
|
||||
|
||||
// SDM<2400, Settings.TaskDevicePin1[event->TaskIndex],
|
||||
// Settings.TaskDevicePin2[event->TaskIndex]> Plugin_078_SDM;
|
||||
Plugin_078_SDM.begin();
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
|
||||
if (Plugin_078_init)
|
||||
{
|
||||
float _tempvar = 0;
|
||||
String log = F("EASTRON: ");
|
||||
switch(Settings.TaskDevicePluginConfig[event->TaskIndex][3])
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
_tempvar = Plugin_078_SDM.readVal(SDM120C_VOLTAGE);
|
||||
log += F("Voltage ");
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
_tempvar = Plugin_078_SDM.readVal(SDM120C_CURRENT);
|
||||
log += F("Current ");
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
_tempvar = Plugin_078_SDM.readVal(SDM120C_POWER);
|
||||
log += F("Power ");
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
_tempvar = Plugin_078_SDM.readVal(SDM120C_ACTIVE_APPARENT_POWER);
|
||||
log += F("Active Apparent Power ");
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
_tempvar = Plugin_078_SDM.readVal(SDM120C_REACTIVE_APPARENT_POWER);
|
||||
log += F("Reactive Apparent Power ");
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
_tempvar = Plugin_078_SDM.readVal(SDM120C_POWER_FACTOR);
|
||||
log += F("Power Factor ");
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
_tempvar = Plugin_078_SDM.readVal(SDM120C_FREQUENCY);
|
||||
log += F("Frequency ");
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
_tempvar = Plugin_078_SDM.readVal(SDM120C_IMPORT_ACTIVE_ENERGY);
|
||||
log += F("Import Active Energy ");
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
_tempvar = Plugin_078_SDM.readVal(SDM120C_EXPORT_ACTIVE_ENERGY);
|
||||
log += F("Export Active Energy ");
|
||||
break;
|
||||
}
|
||||
case 9:
|
||||
{
|
||||
_tempvar = Plugin_078_SDM.readVal(SDM120C_TOTAL_ACTIVE_ENERGY);
|
||||
log += F("Total Active Energy ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UserVar[event->BaseVarIndex] = _tempvar;
|
||||
log += _tempvar;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif // USES_P078
|
||||
@@ -444,6 +444,8 @@ To create/register a plugin, you have to :
|
||||
#define USES_P073 // 7DG
|
||||
#define USES_P074 // TSL2561
|
||||
#define USES_P075 // Nextion
|
||||
|
||||
#define USES_P078 // Eastron Modbus Energy meters
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user