6.2.1.17 Changes and Adds

6.2.1.17 20181017
 * Enable updated non-blocking PubSubClient as default MQTT client
 * Update TasmotaModbus and TasmotaSerial libraries for support of serial 8N2 communication
 * Add support for Pzem-003/017 DC Energy monitoring module (#3694)
 * Change support for Pzem-014/016 AC Energy monitoring module (#3694)
This commit is contained in:
Theo Arends 2018-10-17 12:27:05 +02:00
parent b2ca987195
commit 0ab43909c3
45 changed files with 446 additions and 254 deletions

View File

@ -1,6 +1,6 @@
{
"name": "TasmotaModbus",
"version": "1.0.0",
"version": "1.1.0",
"keywords": [
"serial", "io", "TasmotaModbus"
],

View File

@ -1,5 +1,5 @@
name=TasmotaModbus
version=1.0.0
version=1.1.0
author=Theo Arends
maintainer=Theo Arends <theo@arends.com>
sentence=Basic modbus wrapper for TasmotaSerial for ESP8266.

View File

@ -21,10 +21,7 @@
TasmotaModbus::TasmotaModbus(int receive_pin, int transmit_pin) : TasmotaSerial(receive_pin, transmit_pin, 1)
{
}
TasmotaModbus::~TasmotaModbus()
{
mb_address = 0;
}
uint16_t CalculateCRC(uint8_t *frame, uint8_t num)
@ -46,11 +43,11 @@ uint16_t CalculateCRC(uint8_t *frame, uint8_t num)
return crc;
}
int TasmotaModbus::Begin(long speed)
int TasmotaModbus::Begin(long speed, int stop_bits)
{
int result = 0;
if (begin(speed)) {
if (begin(speed, stop_bits)) {
result = 1;
if (hardwareSerial()) { result = 2; }
}
@ -61,7 +58,9 @@ void TasmotaModbus::Send(uint8_t device_address, uint8_t function_code, uint16_t
{
uint8_t frame[8];
frame[0] = device_address; // 0xFE default device address or dedicated like 0x01
mb_address = device_address; // Save address for receipt check
frame[0] = mb_address; // 0xFE default device address or dedicated like 0x01
frame[1] = function_code;
frame[2] = (uint8_t)(start_address >> 8);
frame[3] = (uint8_t)(start_address);
@ -85,10 +84,17 @@ uint8_t TasmotaModbus::ReceiveBuffer(uint8_t *buffer, uint8_t register_count)
uint8_t len = 0;
uint32_t last = millis();
while ((available() > 0) && (len < (register_count *2) + 5) && (millis() - last < 10)) {
buffer[len++] = (uint8_t)read();
if (3 == len) {
if (buffer[1] & 0x80) { // fe 84 02 f2 f1
return buffer[2]; // 1 = Illegal Function, 2 = Illegal Address, 3 = Illegal Data, 4 = Slave Error
uint8_t data = (uint8_t)read();
if (!len) { // Skip leading data as provided by hardware serial
if (mb_address == data) {
buffer[len++] = data;
}
} else {
buffer[len++] = data;
if (3 == len) {
if (buffer[1] & 0x80) { // 01 84 02 f2 f1
return buffer[2]; // 1 = Illegal Function, 2 = Illegal Address, 3 = Illegal Data, 4 = Slave Error
}
}
}
last = millis();

View File

@ -28,9 +28,9 @@
class TasmotaModbus : public TasmotaSerial {
public:
TasmotaModbus(int receive_pin, int transmit_pin);
~TasmotaModbus();
virtual ~TasmotaModbus() {}
int Begin(long speed = TM_MODBUS_BAUDRATE);
int Begin(long speed = TM_MODBUS_BAUDRATE, int stop_bits = 1);
void Send(uint8_t device_address, uint8_t function_code, uint16_t start_address, uint16_t register_count);
@ -49,6 +49,9 @@ class TasmotaModbus : public TasmotaSerial {
uint8_t ReceiveBuffer(uint8_t *buffer, uint8_t register_count);
uint8_t Receive16BitRegister(uint16_t *value);
uint8_t Receive32BitRegister(float *value);
private:
uint8_t mb_address;
};
#endif // TasmotaModbus_h

View File

@ -1,6 +1,6 @@
{
"name": "TasmotaSerial",
"version": "2.0.0",
"version": "2.1.0",
"keywords": [
"serial", "io", "TasmotaSerial"
],

View File

@ -1,5 +1,5 @@
name=TasmotaSerial
version=2.0.0
version=2.1.0
author=Theo Arends
maintainer=Theo Arends <theo@arends.com>
sentence=Implementation of software serial with hardware serial fallback for ESP8266.

View File

@ -80,6 +80,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fa
{
m_valid = false;
m_hardserial = 0;
m_stop_bits = 1;
if (!((isValidGPIOpin(receive_pin)) && (isValidGPIOpin(transmit_pin) || transmit_pin == 16))) {
return;
}
@ -106,15 +107,33 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fa
m_valid = true;
}
TasmotaSerial::~TasmotaSerial()
{
if (!m_hardserial) {
if (m_rx_pin > -1) {
detachInterrupt(m_rx_pin);
tms_obj_list[m_rx_pin] = NULL;
if (m_buffer) {
free(m_buffer);
}
}
}
}
bool TasmotaSerial::isValidGPIOpin(int pin)
{
return (pin >= -1 && pin <= 5) || (pin >= 12 && pin <= 15);
}
bool TasmotaSerial::begin(long speed) {
bool TasmotaSerial::begin(long speed, int stop_bits) {
m_stop_bits = ((stop_bits -1) &1) +1;
if (m_hardserial) {
Serial.flush();
Serial.begin(speed, SERIAL_8N1);
if (2 == m_stop_bits) {
Serial.begin(speed, SERIAL_8N2);
} else {
Serial.begin(speed, SERIAL_8N1);
}
} else {
// Use getCycleCount() loop to get as exact timing as possible
m_bit_time = ESP.getCpuFreqMHz() *1000000 /speed;
@ -195,9 +214,11 @@ size_t TasmotaSerial::write(uint8_t b)
TM_SERIAL_WAIT;
b >>= 1;
}
// Stop bit
digitalWrite(m_tx_pin, HIGH);
TM_SERIAL_WAIT;
// Stop bit(s)
for (int i = 0; i < m_stop_bits; i++) {
digitalWrite(m_tx_pin, HIGH);
TM_SERIAL_WAIT;
}
if (m_high_speed) sei();
return 1;
}
@ -220,8 +241,12 @@ void TasmotaSerial::rxRead()
rec >>= 1;
if (digitalRead(m_rx_pin)) rec |= 0x80;
}
// Stop bit
// Stop bit(s)
TM_SERIAL_WAIT;
if (2 == m_stop_bits) {
digitalRead(m_rx_pin);
TM_SERIAL_WAIT;
}
// Store the received value in the buffer unless we have an overflow
int next = (m_in_pos+1) % TM_SERIAL_BUFFER_SIZE;
if (next != (int)m_out_pos) {

View File

@ -33,12 +33,15 @@
#define TM_SERIAL_USE_IRAM // Enable to use iram (+368 bytes)
#endif
#include <inttypes.h>
#include <Stream.h>
class TasmotaSerial : public Stream {
public:
TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fallback = false);
bool begin(long speed);
virtual ~TasmotaSerial();
bool begin(long speed, int stop_bits = 1);
bool begin();
bool hardwareSerial();
int peek();
@ -62,6 +65,7 @@ class TasmotaSerial : public Stream {
bool m_high_speed;
int m_rx_pin;
int m_tx_pin;
int m_stop_bits;
unsigned long m_bit_time;
unsigned int m_in_pos;
unsigned int m_out_pos;

View File

@ -1,4 +1,10 @@
/* 6.2.1.16 20181015
/* 6.2.1.17 20181017
* Enable updated non-blocking PubSubClient as default MQTT client
* Update TasmotaModbus and TasmotaSerial libraries for support of serial 8N2 communication
* Add support for Pzem-003/017 DC Energy monitoring module (#3694)
* Change support for Pzem-014/016 AC Energy monitoring module (#3694)
*
* 6.2.1.16 20181015
* Add TasmotaModbus library for very basic modbus wrapper for TasmotaSerial
* Change xsns_17_senseair.ino to use TasmotaModbus library
* Fix xnrg_05_pzem2.ino for PZEM-014/016 support using TasmotaModbus library (#3694)

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRRecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IR RX"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "RécptIR"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRvevő"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHz Rx"
#define D_SENSOR_MHZ_TX "MHz Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAIR Rx"
#define D_SENSOR_SAIR_TX "SAIR Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -482,8 +482,10 @@
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM_RX "PZEM Rx"
#define D_SENSOR_PZEM_TX "PZEM Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"

View File

@ -136,7 +136,8 @@ void KNX_CB_Action(message_t const &msg, void *arg);
#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor
#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor
#undef USE_PZEM004T // Disable PZEM004T energy sensor
#undef USE_PZEM2 // Disable PZEM003,014,016,017 Energy monitor
#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor
#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor
#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge
#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter
#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter

View File

@ -86,8 +86,8 @@ enum UserSelectablePins {
GPIO_LED4_INV,
GPIO_MHZ_TXD, // MH-Z19 Serial interface
GPIO_MHZ_RXD, // MH-Z19 Serial interface
GPIO_PZEM_TX, // PZEM004T Serial interface
GPIO_PZEM_RX, // PZEM004T Serial interface
GPIO_PZEM0XX_TX, // PZEM0XX Serial interface
GPIO_PZEM004_RX, // PZEM004T Serial interface
GPIO_SAIR_TX, // SenseAir Serial interface
GPIO_SAIR_RX, // SenseAir Serial interface
GPIO_SPI_CS, // SPI Chip Select
@ -122,8 +122,8 @@ enum UserSelectablePins {
GPIO_CNTR2_NP,
GPIO_CNTR3_NP,
GPIO_CNTR4_NP,
GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface
GPIO_PZEM2_RX, // PZEM-003,014,016,017 Serial interface
GPIO_PZEM016_RX, // PZEM-014,016 Serial Modbus interface
GPIO_PZEM017_RX, // PZEM-003,017 Serial Modbus interface
GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player
GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface
GPIO_HX711_SCK, // HX711 Load Cell clock
@ -168,7 +168,7 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_LED "1|" D_SENSOR_LED "2|" D_SENSOR_LED "3|" D_SENSOR_LED "4|"
D_SENSOR_LED "1i|" D_SENSOR_LED "2i|" D_SENSOR_LED "3i|" D_SENSOR_LED "4i|"
D_SENSOR_MHZ_TX "|" D_SENSOR_MHZ_RX "|"
D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|"
D_SENSOR_PZEM0XX_TX "|" D_SENSOR_PZEM004_RX "|"
D_SENSOR_SAIR_TX "|" D_SENSOR_SAIR_RX "|"
D_SENSOR_SPI_CS "|" D_SENSOR_SPI_DC "|" D_SENSOR_BACKLIGHT "|"
D_SENSOR_PMS5003 "|" D_SENSOR_SDS0X1_RX "|"
@ -180,7 +180,7 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_SWITCH "1n|" D_SENSOR_SWITCH "2n|" D_SENSOR_SWITCH "3n|" D_SENSOR_SWITCH "4n|" D_SENSOR_SWITCH "5n|" D_SENSOR_SWITCH "6n|" D_SENSOR_SWITCH "7n|" D_SENSOR_SWITCH "8n|"
D_SENSOR_BUTTON "1n|" D_SENSOR_BUTTON "2n|" D_SENSOR_BUTTON "3n|" D_SENSOR_BUTTON "4n|"
D_SENSOR_COUNTER "1n|" D_SENSOR_COUNTER "2n|" D_SENSOR_COUNTER "3n|" D_SENSOR_COUNTER "4n|"
D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|"
D_SENSOR_PZEM016_RX "|" D_SENSOR_PZEM017_RX "|"
D_SENSOR_DFR562 "|" D_SENSOR_SDS0X1_TX "|"
D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT;
@ -354,10 +354,10 @@ const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = {
GPIO_SAIR_RX, // SenseAir Serial interface
GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface
GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface
GPIO_PZEM_TX, // PZEM004T Serial interface
GPIO_PZEM_RX, // PZEM004T Serial interface
GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface
GPIO_PZEM2_RX, // PZEM-003,014,016,017 Serial interface
GPIO_PZEM0XX_TX, // PZEM0XX Serial interface
GPIO_PZEM004_RX, // PZEM004T Serial interface
GPIO_PZEM016_RX, // PZEM-014,016 Serial Modbus interface
GPIO_PZEM017_RX, // PZEM-003,017 Serial Modbus interface
GPIO_SDM120_TX, // SDM120 Serial interface
GPIO_SDM120_RX, // SDM120 Serial interface
GPIO_SDM630_TX, // SDM630 Serial interface

View File

@ -20,7 +20,7 @@
#ifndef _SONOFF_VERSION_H_
#define _SONOFF_VERSION_H_
#define VERSION 0x06020110
#define VERSION 0x06020111
#define D_PROGRAMNAME "Sonoff-Tasmota"
#define D_AUTHOR "Theo Arends"

View File

@ -647,14 +647,22 @@ boolean GetUsedInModule(byte val, uint8_t *arr)
if (GPIO_MHZ_TXD == val) { return true; }
if (GPIO_MHZ_RXD == val) { return true; }
#endif
int pzem = 3;
#ifndef USE_PZEM004T
if (GPIO_PZEM_TX == val) { return true; }
if (GPIO_PZEM_RX == val) { return true; }
pzem--;
if (GPIO_PZEM004_RX == val) { return true; }
#endif
#ifndef USE_PZEM2
if (GPIO_PZEM2_TX == val) { return true; }
if (GPIO_PZEM2_RX == val) { return true; }
#ifndef USE_PZEM_AC
pzem--;
if (GPIO_PZEM016_RX == val) { return true; }
#endif
#ifndef USE_PZEM_DC
pzem--;
if (GPIO_PZEM017_RX == val) { return true; }
#endif
if (!pzem && (GPIO_PZEM0XX_TX == val)) { return true; }
#ifndef USE_SENSEAIR
if (GPIO_SAIR_TX == val) { return true; }
if (GPIO_SAIR_RX == val) { return true; }
@ -1166,14 +1174,17 @@ void GetFeatures()
#ifdef USE_MCP39F501
feature_sns2 |= 0x00000100; // xnrg_04_mcp39f501.ino
#endif
#ifdef USE_PZEM2
feature_sns2 |= 0x00000200; // xnrg_05_pzem2.ino
#ifdef USE_PZEM_AC
feature_sns2 |= 0x00000200; // xnrg_05_pzem_ac.ino
#endif
#ifdef USE_DS3231
feature_sns2 |= 0x00000400; // xsns_33_ds3231.ino
#endif
#ifdef USE_HX711
feature_sns2 |= 0x00000400; // xsns_34_hx711.ino
feature_sns2 |= 0x00000800; // xsns_34_hx711.ino
#endif
#ifdef USE_PZEM_DC
feature_sns2 |= 0x00001000; // xnrg_06_pzem_dc.ino
#endif
}

View File

@ -220,11 +220,11 @@
* Select ONE of possible MQTT library types below
\*-------------------------------------------------------------------------------------------*/
// Default MQTT driver for both non-TLS and TLS connections. Latest library version (20181016) does not block network if MQTT server is unavailable.
//#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library
#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library
// Alternative MQTT driver does not block network when MQTT server is unavailable. No TLS support
//#define MQTT_LIBRARY_TYPE MQTT_TASMOTAMQTT // Use TasmotaMqtt library (+4k4 (core 2.3.0), +14k4 (core 2.4.2 lwip2) code, +4k mem) - non-TLS only
// Alternative MQTT driver does not block network when MQTT server is unavailable. TLS should work but needs to be tested.
#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Use arduino-mqtt (lwmqtt) library (+3k3 code, +2k mem)
//#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Use arduino-mqtt (lwmqtt) library (+3k3 code, +2k mem)
// -- MQTT ----------------------------------------
#define MQTT_TELE_RETAIN 0 // Tele messages may send retain flag (0 = off, 1 = on)
@ -356,7 +356,8 @@
// Power monitoring sensors -----------------------
#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code)
#define USE_PZEM2 // Add support for PZEM003,014,016,017 Energy monitor (+1k1 code)
#define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code)
#define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code)
#define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code)
// -- Low level interface devices -----------------

View File

@ -25,7 +25,7 @@
* Source: Victor Ferrer https://github.com/vicfergar/Sonoff-MQTT-OTA-Arduino
* Based on: PZEM004T library https://github.com/olehs/PZEM004T
*
* Hardware Serial will be selected if GPIO1 = [PZEM Rx] and [GPIO3 = PZEM Tx]
* Hardware Serial will be selected if GPIO1 = [63 PZEM004 Rx] and GPIO3 = [62 PZEM0XX Tx]
\*********************************************************************************************/
#define XNRG_03 3
@ -203,7 +203,7 @@ void PzemEvery200ms()
void PzemSnsInit()
{
// Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions
PzemSerial = new TasmotaSerial(pin[GPIO_PZEM_RX], pin[GPIO_PZEM_TX], 1);
PzemSerial = new TasmotaSerial(pin[GPIO_PZEM004_RX], pin[GPIO_PZEM0XX_TX], 1);
if (PzemSerial->begin(9600)) {
if (PzemSerial->hardwareSerial()) { ClaimSerial(); }
} else {
@ -214,7 +214,7 @@ void PzemSnsInit()
void PzemDrvInit()
{
if (!energy_flg) {
if ((pin[GPIO_PZEM_RX] < 99) && (pin[GPIO_PZEM_TX] < 99)) { // Any device with a Pzem004T
if ((pin[GPIO_PZEM004_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { // Any device with a Pzem004T
energy_flg = XNRG_03;
}
}

View File

@ -1,162 +0,0 @@
/*
xnrg_06_pzem2.ino - PZEM-003,017 and PZEM-014,016 Modbus energy sensor support for Sonoff-Tasmota
Copyright (C) 2018 Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_ENERGY_SENSOR
#ifdef USE_PZEM2
/*********************************************************************************************\
* PZEM-003 - DC 300V 10A Energy
* PZEM-014 - AC 220V 10A Energy
* PZEM-016 - AC 220V 100A Energy
* PZEM-017 - DC 300V 50A - 300A Energy
*
* Based on:
* PZEM-003,017 docs Https://pan.baidu.com/s/1V9bDWj3RK2u6_fbBJ3GtqQ password rq37
* PZEM-014,016 docs https://pan.baidu.com/s/1B0MdMgURyjtO1oQa2lavKw password ytkv
*
* Hardware Serial will be selected if GPIO1 = [99 PZEM Rx] and GPIO3 = [98 PZEM Tx]
\*********************************************************************************************/
#define XNRG_05 5
#define PZEM2_MODBUS_SPEED 9600
#define PZEM2_DEVICE_ADDRESS 0x01 // PZEM default address
#define PZEM2_READ_RESULT 0x04 // Command Read result
#define PZEM2_TYPES_003_017 8 // Result 8 x 16 bit register count
#define PZEM2_TYPES_014_016 10 // Result 10 x 16 bit register count
#include <TasmotaModbus.h>
TasmotaModbus *Pzem2Modbus;
uint8_t pzem2_type = PZEM2_TYPES_014_016;
uint8_t pzem2_sendRetry = 0;
void Pzem2EverySecond()
{
bool data_ready = Pzem2Modbus->ReceiveReady();
if (data_ready) {
uint8_t buffer[26];
uint8_t error = Pzem2Modbus->ReceiveBuffer(buffer, pzem2_type);
AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer));
if (error) {
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PZEM2 response error %d"), error);
AddLog(LOG_LEVEL_DEBUG);
// if (9 == error) {
/*
if (PZEM2_TYPES_014_016 == pzem2_type) {
pzem2_type = PZEM2_TYPES_003_017;
} else {
pzem2_type = PZEM2_TYPES_014_016;
}
*/
// }
} else {
float energy = 0;
if (PZEM2_TYPES_003_017 == pzem2_type) {
energy_type_dc = true;
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// 01 04 10 27 10 00 64 03 E8 00 00 00 00 00 00 00 00 00 00 HH LL = PZEM-017
// Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc--
energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V
energy_current = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A
energy_active_power = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; // 429496729.0 W
energy = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh
if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any
energy_kWhtoday += (energy - energy_start) * 100;
energy_start = energy;
EnergyUpdateToday();
}
else if (PZEM2_TYPES_014_016 == pzem2_type) { // PZEM-014,016
energy_type_dc = false;
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// 01 04 14 08 D1 00 6C 00 00 00 F4 00 00 00 26 00 00 01 F4 00 64 00 00 51 34 = PZEM-014
// Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc--
energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V
energy_current = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; // 4294967.000 A
energy_active_power = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; // 429496729.0 W
energy_frequency = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz
energy_power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00
energy = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh
if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any
energy_kWhtoday += (energy - energy_start) * 100;
energy_start = energy;
EnergyUpdateToday();
}
}
}
if (0 == pzem2_sendRetry || data_ready) {
pzem2_sendRetry = 5;
Pzem2Modbus->Send(PZEM2_DEVICE_ADDRESS, PZEM2_READ_RESULT, 0, pzem2_type);
}
else {
pzem2_sendRetry--;
}
}
void Pzem2SnsInit()
{
Pzem2Modbus = new TasmotaModbus(pin[GPIO_PZEM2_RX], pin[GPIO_PZEM2_TX]);
uint8_t result = Pzem2Modbus->Begin(PZEM2_MODBUS_SPEED);
if (result) {
if (2 == result) { ClaimSerial(); }
} else {
energy_flg = ENERGY_NONE;
}
}
void Pzem2DrvInit()
{
if (!energy_flg) {
if ((pin[GPIO_PZEM2_RX] < 99) && (pin[GPIO_PZEM2_TX] < 99)) { // Any device with a Pzem-003,014,016,017
energy_flg = XNRG_05;
}
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
int Xnrg05(byte function)
{
int result = 0;
if (FUNC_PRE_INIT == function) {
Pzem2DrvInit();
}
else if (XNRG_05 == energy_flg) {
switch (function) {
case FUNC_INIT:
Pzem2SnsInit();
break;
case FUNC_EVERY_SECOND:
Pzem2EverySecond();
break;
}
}
return result;
}
#endif // USE_PZEM2
#endif // USE_ENERGY_SENSOR

126
sonoff/xnrg_05_pzem_ac.ino Normal file
View File

@ -0,0 +1,126 @@
/*
xnrg_05_pzem_ac.ino - PZEM-014,016 Modbus AC energy sensor support for Sonoff-Tasmota
Copyright (C) 2018 Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_ENERGY_SENSOR
#ifdef USE_PZEM_AC
/*********************************************************************************************\
* PZEM-014 - AC 220V 10A Energy
* PZEM-016 - AC 220V 100A Energy
*
* Based on:
* PZEM-014,016 docs https://pan.baidu.com/s/1B0MdMgURyjtO1oQa2lavKw password ytkv
*
* Hardware Serial will be selected if GPIO1 = [98 PZEM016 Rx] and GPIO3 = [62 PZEM0XX Tx]
\*********************************************************************************************/
#define XNRG_05 5
#define PZEM_AC_DEVICE_ADDRESS 0x01 // PZEM default address
#include <TasmotaModbus.h>
TasmotaModbus *PzemAcModbus;
void PzemAcEverySecond()
{
static uint8_t send_retry = 0;
bool data_ready = PzemAcModbus->ReceiveReady();
if (data_ready) {
uint8_t buffer[26];
uint8_t error = PzemAcModbus->ReceiveBuffer(buffer, 10);
AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer));
if (error) {
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PzemAc response error %d"), error);
AddLog(LOG_LEVEL_DEBUG);
} else {
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// 01 04 14 08 D1 00 6C 00 00 00 F4 00 00 00 26 00 00 01 F4 00 64 00 00 51 34
// Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc--
energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V
energy_current = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; // 4294967.000 A
energy_active_power = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; // 429496729.0 W
energy_frequency = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz
energy_power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00
float energy = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh
if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any
energy_kWhtoday += (energy - energy_start) * 100;
energy_start = energy;
EnergyUpdateToday();
}
}
if (0 == send_retry || data_ready) {
send_retry = 5;
PzemAcModbus->Send(PZEM_AC_DEVICE_ADDRESS, 0x04, 0, 10);
}
else {
send_retry--;
}
}
void PzemAcSnsInit()
{
PzemAcModbus = new TasmotaModbus(pin[GPIO_PZEM016_RX], pin[GPIO_PZEM0XX_TX]);
uint8_t result = PzemAcModbus->Begin(9600);
if (result) {
if (2 == result) { ClaimSerial(); }
} else {
energy_flg = ENERGY_NONE;
}
}
void PzemAcDrvInit()
{
if (!energy_flg) {
if ((pin[GPIO_PZEM016_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) {
energy_flg = XNRG_05;
}
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
int Xnrg05(byte function)
{
int result = 0;
if (FUNC_PRE_INIT == function) {
PzemAcDrvInit();
}
else if (XNRG_05 == energy_flg) {
switch (function) {
case FUNC_INIT:
PzemAcSnsInit();
break;
case FUNC_EVERY_SECOND:
PzemAcEverySecond();
break;
}
}
return result;
}
#endif // USE_PZEM_AC
#endif // USE_ENERGY_SENSOR

125
sonoff/xnrg_06_pzem_dc.ino Normal file
View File

@ -0,0 +1,125 @@
/*
xnrg_06_pzem_dc.ino - PZEM-003,017 Modbus DC energy sensor support for Sonoff-Tasmota
Copyright (C) 2018 Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_ENERGY_SENSOR
#ifdef USE_PZEM_DC
/*********************************************************************************************\
* PZEM-003 - DC 300V 10A Energy
* PZEM-017 - DC 300V 50A - 300A Energy
*
* Based on:
* PZEM-003,017 docs Https://pan.baidu.com/s/1V9bDWj3RK2u6_fbBJ3GtqQ password rq37
*
* Hardware Serial will be selected if GPIO1 = [99 PZEM017 Rx] and GPIO3 = [62 PZEM0XX Tx]
\*********************************************************************************************/
#define XNRG_06 6
#define PZEM_DC_DEVICE_ADDRESS 0x01 // PZEM default address
#include <TasmotaModbus.h>
TasmotaModbus *PzemDcModbus;
void PzemDcEverySecond()
{
static uint8_t send_retry = 0;
bool data_ready = PzemDcModbus->ReceiveReady();
if (data_ready) {
uint8_t buffer[22];
uint8_t error = PzemDcModbus->ReceiveBuffer(buffer, 8);
AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer));
if (error) {
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PzemDc response error %d"), error);
AddLog(LOG_LEVEL_DEBUG);
} else {
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
// 01 04 10 05 40 00 0A 00 0D 00 00 00 02 00 00 00 00 00 00 D6 29
// Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc--
energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V
energy_current = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A
energy_active_power = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; // 429496729.0 W
float energy = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh
if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any
energy_kWhtoday += (energy - energy_start) * 100;
energy_start = energy;
EnergyUpdateToday();
}
}
if (0 == send_retry || data_ready) {
send_retry = 5;
PzemDcModbus->Send(PZEM_DC_DEVICE_ADDRESS, 0x04, 0, 8);
}
else {
send_retry--;
}
}
void PzemDcSnsInit()
{
PzemDcModbus = new TasmotaModbus(pin[GPIO_PZEM017_RX], pin[GPIO_PZEM0XX_TX]);
uint8_t result = PzemDcModbus->Begin(9600, 2); // Uses two stop bits!!
if (result) {
if (2 == result) { ClaimSerial(); }
energy_type_dc = true;
} else {
energy_flg = ENERGY_NONE;
}
}
void PzemDcDrvInit()
{
if (!energy_flg) {
if ((pin[GPIO_PZEM017_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) {
energy_flg = XNRG_06;
}
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
int Xnrg06(byte function)
{
int result = 0;
if (FUNC_PRE_INIT == function) {
PzemDcDrvInit();
}
else if (XNRG_06 == energy_flg) {
switch (function) {
case FUNC_INIT:
PzemDcSnsInit();
break;
case FUNC_EVERY_SECOND:
PzemDcEverySecond();
break;
}
}
return result;
}
#endif // USE_PZEM_DC
#endif // USE_ENERGY_SENSOR

View File

@ -39,7 +39,15 @@ int (* const xnrg_func_ptr[])(byte) PROGMEM = { // Energy driver Function Poin
#endif
#ifdef XNRG_06
&Xnrg06
&Xnrg06,
#endif
#ifdef XNRG_07
&Xnrg07,
#endif
#ifdef XNRG_08
&Xnrg08
#endif
};

View File

@ -127,8 +127,8 @@ a_features = [[
],[
"USE_MCP230xx","USE_MPR121","USE_CCS811","USE_MPU6050",
"USE_MCP230xx_OUTPUT","USE_MCP230xx_DISPLAYOUTPUT","USE_HLW8012","USE_CSE7766",
"USE_MCP39F501","USE_PZEM2","USE_DS3231","USE_HX711",
"","","","",
"USE_MCP39F501","USE_PZEM_AC","USE_DS3231","USE_HX711",
"USE_PZEM_DC","","","",
"","","","",
"","","","",
"","","","",