From 26361bd8c3af61748156c788a8c8923cc496d2cc Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 15 Sep 2019 17:06:23 +0200 Subject: [PATCH] Add driver USE_SDM630_2 Add driver USE_SDM630_2 as future replacement for USE_SDM630 - Pls test and report --- sonoff/_changelog.ino | 1 + sonoff/my_user_config.h | 4 +- sonoff/sonoff_post.h | 9 +- sonoff/xnrg_08_sdm120.ino | 2 +- sonoff/xnrg_10_sdm630.ino | 214 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 226 insertions(+), 4 deletions(-) create mode 100644 sonoff/xnrg_10_sdm630.ino diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index ce32138d4..34b6681a2 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -11,6 +11,7 @@ * Add initial support for up to three PZEM-014/-016 on serial modbus connection with addresses 1 (default), 2 and 3 (#2315) * Add initial support for up to three PZEM-004T on serial connection with addresses x.x.x.1 (default), 2 and 3 (#2315) * Add initial support for up to three PZEM-003/-017 on serial modbus connection with addresses 1 (default), 2 and 3 (#2315) + * Add driver USE_SDM630_2 as future replacement for USE_SDM630 - Pls test and report * * 6.6.0.11 20190907 * Change Settings crc calculation allowing short term backward compatibility diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 8507cd662..17954ac65 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -433,6 +433,8 @@ #define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) //#define USE_SDM120_2 // Add support for Eastron SDM120-Modbus energy monitor (+1k1 code) #define SDM120_SPEED 2400 // SDM120-Modbus RS485 serial speed (default: 2400 baud) +//#define USE_SDM630_2 // Add support for Eastron SDM630-Modbus energy monitor (+0k6 code) + #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) //#define USE_DDS2382 // Add support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #define DDS2382_SPEED 9600 // Hiking DDS2382 Modbus RS485 serial speed (default: 9600 baud) @@ -440,7 +442,7 @@ // #define SDM120_SPEED 2400 // SDM120-Modbus RS485 serial speed (default: 2400 baud) #define USE_SDM220 // Add extra parameters for SDM220 (+0k1 code) //#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) - #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) +// #define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud) //#define USE_SOLAX_X1 // Add support for Solax X1 series Modbus log info (+4k1 code) #define SOLAXX1_SPEED 9600 // Solax X1 Modbus RS485 serial speed (default: 9600 baud) #define SOLAXX1_PV2 // Solax X1 using second PV diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 802d8ad25..dacdf3b4b 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -149,7 +149,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #define USE_NOVA_SDS // Add support for SDS011 and SDS021 particle concentration sensor (+0k7 code) #define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code) //#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code) -#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) +//#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code) #define USE_MP3_PLAYER // Use of the DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop #define MP3_VOLUME 10 // Set the startup volume on init, the range can be 0..30(max) //#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger @@ -162,6 +162,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #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) #define USE_SDM120_2 // Add support for Eastron SDM120-Modbus energy monitor (+1k1 code) +#define USE_SDM630_2 // Add support for Eastron SDM630-Modbus energy monitor (+0k6 code) #define USE_DDS2382 // Add support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor @@ -247,6 +248,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor #undef USE_MCP39F501 // Disable support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor @@ -300,6 +302,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor #undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter + #undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem) #undef USE_DOMOTICZ // Disable Domoticz @@ -382,6 +385,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor #undef USE_MCP39F501 // Disable support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) //#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor @@ -478,11 +482,11 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor //#undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor #undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI -#undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_IR_REMOTE // Disable IR driver #undef USE_WS2812 // Disable WS2812 Led string #undef USE_ARILUX_RF // Disable support for Arilux RF remote controller @@ -563,6 +567,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c #undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor #undef USE_MCP39F501 // Disable MCP39F501 Energy monitor as used in Shelly 2 #undef USE_SDM120_2 // Disable support for Eastron SDM120-Modbus energy meter +#undef USE_SDM630_2 // Disable support for Eastron SDM630-Modbus energy monitor (+0k6 code) #undef USE_DDS2382 // Disable support for Hiking DDS2382 Modbus energy monitor (+0k6 code) #undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor diff --git a/sonoff/xnrg_08_sdm120.ino b/sonoff/xnrg_08_sdm120.ino index 592edc2f8..9b1cf6cbc 100644 --- a/sonoff/xnrg_08_sdm120.ino +++ b/sonoff/xnrg_08_sdm120.ino @@ -83,7 +83,7 @@ void SDM120Every250ms(void) AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, sizeof(buffer)); if (error) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM120 response error %d"), error); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: SDM120 error %d"), error); } else { Energy.data_valid = 0; diff --git a/sonoff/xnrg_10_sdm630.ino b/sonoff/xnrg_10_sdm630.ino new file mode 100644 index 000000000..5bdef0c9e --- /dev/null +++ b/sonoff/xnrg_10_sdm630.ino @@ -0,0 +1,214 @@ +/* + xnrg_10_sdm630.ino - Eastron SDM630-Modbus energy meter support for Sonoff-Tasmota + + Copyright (C) 2019 Gennaro Tortone and 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 . +*/ + +#ifdef USE_ENERGY_SENSOR +#ifdef USE_SDM630_2 +/*********************************************************************************************\ + * Eastron SDM630-Modbus energy meter + * + * Based on: https://github.com/reaper7/SDM_Energy_Meter +\*********************************************************************************************/ + +#define XNRG_10 10 + +// can be user defined in my_user_config.h +#ifndef SDM630_SPEED + #define SDM630_SPEED 9600 // default SDM630 Modbus address +#endif +// can be user defined in my_user_config.h +#ifndef SDM630_ADDR + #define SDM630_ADDR 1 // default SDM630 Modbus address +#endif + +#include +TasmotaModbus *Sdm630Modbus; + +const uint16_t sdm630_start_addresses[] { + 0x0000, // L1 - SDM630_VOLTAGE [V] + 0x0002, // L2 - SDM630_VOLTAGE [V] + 0x0004, // L3 - SDM630_VOLTAGE [V] + 0x0006, // L1 - SDM630_CURRENT [A] + 0x0008, // L2 - SDM630_CURRENT [A] + 0x000A, // L3 - SDM630_CURRENT [A] + 0x000C, // L1 - SDM630_POWER [W] + 0x000E, // L2 - SDM630_POWER [W] + 0x0010, // L3 - SDM630_POWER [W] + 0x0018, // L1 - SDM630_REACTIVE_POWER [VAR] + 0x001A, // L2 - SDM630_REACTIVE_POWER [VAR] + 0x001C, // L3 - SDM630_REACTIVE_POWER [VAR] + 0x001E, // L1 - SDM630_POWER_FACTOR + 0x0020, // L2 - SDM630_POWER_FACTOR + 0x0022, // L3 - SDM630_POWER_FACTOR + 0x0156 // Total - SDM630_TOTAL_ACTIVE_ENERGY [Wh] +}; + +struct SDM630 { + uint8_t read_state = 0; + uint8_t send_retry = 0; +} Sdm630; + +/*********************************************************************************************/ + +void SDM630Every250ms(void) +{ + bool data_ready = Sdm630Modbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[14]; // At least 5 + (2 * 2) = 9 + + uint32_t error = Sdm630Modbus->ReceiveBuffer(buffer, 2); + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, sizeof(buffer)); + + if (error) { + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDM: SDM630 error %d"), error); + } else { + Energy.data_valid = 0; + + // 0 1 2 3 4 5 6 7 8 + // SA FC BC Fh Fl Sh Sl Cl Ch + // 01 04 04 43 66 33 34 1B 38 = 230.2 Volt + float value; + ((uint8_t*)&value)[3] = buffer[3]; // Get float values + ((uint8_t*)&value)[2] = buffer[4]; + ((uint8_t*)&value)[1] = buffer[5]; + ((uint8_t*)&value)[0] = buffer[6]; + + switch(Sdm630.read_state) { + case 0: + Energy.voltage[0] = value; + break; + + case 1: + Energy.voltage[1] = value; + break; + + case 2: + Energy.voltage[2] = value; + break; + + case 3: + Energy.current[0] = value; + break; + + case 4: + Energy.current[1] = value; + break; + + case 5: + Energy.current[2] = value; + break; + + case 6: + Energy.active_power[0] = value; + break; + + case 7: + Energy.active_power[1] = value; + break; + + case 8: + Energy.active_power[2] = value; + break; + + case 9: + Energy.reactive_power[0] = value; + break; + + case 10: + Energy.reactive_power[1] = value; + break; + + case 11: + Energy.reactive_power[2] = value; + break; + + case 12: + Energy.power_factor[0] = value; + break; + + case 13: + Energy.power_factor[1] = value; + break; + + case 14: + Energy.power_factor[2] = value; + break; + + case 15: + EnergyUpdateTotal(value, true); + break; + } + + Sdm630.read_state++; + if (sizeof(sdm630_start_addresses)/2 == Sdm630.read_state) { + Sdm630.read_state = 0; + } + } + } // end data ready + + if (0 == Sdm630.send_retry || data_ready) { + Sdm630.send_retry = 5; + Sdm630Modbus->Send(SDM630_ADDR, 0x04, sdm630_start_addresses[Sdm630.read_state], 2); + } else { + Sdm630.send_retry--; + } +} + +void Sdm630SnsInit(void) +{ + Sdm630Modbus = new TasmotaModbus(pin[GPIO_SDM630_RX], pin[GPIO_SDM630_TX]); + uint8_t result = Sdm630Modbus->Begin(SDM630_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void Sdm630DrvInit(void) +{ + if ((pin[GPIO_SDM630_RX] < 99) && (pin[GPIO_SDM630_TX] < 99)) { + energy_flg = XNRG_10; + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xnrg10(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_EVERY_250_MSECOND: + if (uptime > 4) { SDM630Every250ms(); } + break; + case FUNC_INIT: + Sdm630SnsInit(); + break; + case FUNC_PRE_INIT: + Sdm630DrvInit(); + break; + } + return result; +} + +#endif // USE_SDM630_2 +#endif // USE_ENERGY_SENSOR