From c6fede2bf4ddd9c2ef215f23be668c1d1848f0e5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 7 Jun 2020 17:21:29 +0200 Subject: [PATCH] Basic support for BL0940 Basic support for BL0940 (#8175) --- tasmota/language/bg_BG.h | 1 + tasmota/language/cs_CZ.h | 1 + tasmota/language/de_DE.h | 1 + tasmota/language/el_GR.h | 1 + tasmota/language/en_GB.h | 1 + tasmota/language/es_ES.h | 1 + tasmota/language/fr_FR.h | 1 + tasmota/language/he_HE.h | 1 + tasmota/language/hu_HU.h | 1 + tasmota/language/it_IT.h | 1 + tasmota/language/ko_KO.h | 1 + tasmota/language/nl_NL.h | 1 + tasmota/language/pl_PL.h | 1 + tasmota/language/pt_BR.h | 1 + tasmota/language/pt_PT.h | 1 + tasmota/language/ro_RO.h | 1 + tasmota/language/ru_RU.h | 1 + tasmota/language/sk_SK.h | 1 + tasmota/language/sv_SE.h | 1 + tasmota/language/tr_TR.h | 1 + tasmota/language/uk_UA.h | 1 + tasmota/language/zh_CN.h | 1 + tasmota/language/zh_TW.h | 1 + tasmota/my_user_config.h | 13 +- tasmota/support_features.ino | 5 +- tasmota/tasmota.h | 1 + tasmota/tasmota_template.h | 13 +- tasmota/xnrg_14_bl0940.ino | 307 +++++++++++++++++++++++++++++++++++ tools/decode-status.py | 7 +- 29 files changed, 354 insertions(+), 15 deletions(-) create mode 100644 tasmota/xnrg_14_bl0940.ino diff --git a/tasmota/language/bg_BG.h b/tasmota/language/bg_BG.h index a40df8551..935704e74 100644 --- a/tasmota/language/bg_BG.h +++ b/tasmota/language/bg_BG.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/cs_CZ.h b/tasmota/language/cs_CZ.h index 33839ed4d..a04a6b16b 100644 --- a/tasmota/language/cs_CZ.h +++ b/tasmota/language/cs_CZ.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/de_DE.h b/tasmota/language/de_DE.h index aa83ec0c2..02464daa6 100644 --- a/tasmota/language/de_DE.h +++ b/tasmota/language/de_DE.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/el_GR.h b/tasmota/language/el_GR.h index ec6275dbd..333458c72 100644 --- a/tasmota/language/el_GR.h +++ b/tasmota/language/el_GR.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/en_GB.h b/tasmota/language/en_GB.h index 48208a0bb..92637b350 100644 --- a/tasmota/language/en_GB.h +++ b/tasmota/language/en_GB.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/es_ES.h b/tasmota/language/es_ES.h index de021791e..701f3e107 100644 --- a/tasmota/language/es_ES.h +++ b/tasmota/language/es_ES.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/fr_FR.h b/tasmota/language/fr_FR.h index dbe9c597a..f91bd7fbd 100644 --- a/tasmota/language/fr_FR.h +++ b/tasmota/language/fr_FR.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/he_HE.h b/tasmota/language/he_HE.h index fe77159c1..3550a1abd 100644 --- a/tasmota/language/he_HE.h +++ b/tasmota/language/he_HE.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/hu_HU.h b/tasmota/language/hu_HU.h index 844fa2f8f..1a58472e4 100644 --- a/tasmota/language/hu_HU.h +++ b/tasmota/language/hu_HU.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/it_IT.h b/tasmota/language/it_IT.h index 09dcc266b..f1af3765f 100644 --- a/tasmota/language/it_IT.h +++ b/tasmota/language/it_IT.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 - TX" #define D_SENSOR_LE01MR_RX "LE-01MR - RX" #define D_SENSOR_LE01MR_TX "LE-01MR - TX" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 - GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 - GDO2" #define D_SENSOR_HRXL_RX "HRXL - RX" diff --git a/tasmota/language/ko_KO.h b/tasmota/language/ko_KO.h index 5ab580ce8..a004ecec7 100644 --- a/tasmota/language/ko_KO.h +++ b/tasmota/language/ko_KO.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/nl_NL.h b/tasmota/language/nl_NL.h index 84ce656e3..ab6a28485 100644 --- a/tasmota/language/nl_NL.h +++ b/tasmota/language/nl_NL.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/pl_PL.h b/tasmota/language/pl_PL.h index 8ee529292..aea969baf 100644 --- a/tasmota/language/pl_PL.h +++ b/tasmota/language/pl_PL.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/pt_BR.h b/tasmota/language/pt_BR.h index 39e7affb0..02c4b4ecc 100644 --- a/tasmota/language/pt_BR.h +++ b/tasmota/language/pt_BR.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/pt_PT.h b/tasmota/language/pt_PT.h index aabd353fe..4507cecba 100644 --- a/tasmota/language/pt_PT.h +++ b/tasmota/language/pt_PT.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/ro_RO.h b/tasmota/language/ro_RO.h index 77a2240ca..66e82ad55 100644 --- a/tasmota/language/ro_RO.h +++ b/tasmota/language/ro_RO.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/ru_RU.h b/tasmota/language/ru_RU.h index 0e5cd24ac..7c7fc770b 100644 --- a/tasmota/language/ru_RU.h +++ b/tasmota/language/ru_RU.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/sk_SK.h b/tasmota/language/sk_SK.h index d8bdd2ece..e242f9bc1 100644 --- a/tasmota/language/sk_SK.h +++ b/tasmota/language/sk_SK.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/sv_SE.h b/tasmota/language/sv_SE.h index 64a540f96..1649b7f5f 100644 --- a/tasmota/language/sv_SE.h +++ b/tasmota/language/sv_SE.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/tr_TR.h b/tasmota/language/tr_TR.h index c62981f8d..8a1063d7a 100644 --- a/tasmota/language/tr_TR.h +++ b/tasmota/language/tr_TR.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/uk_UA.h b/tasmota/language/uk_UA.h index 0b90eaf53..a16675ae4 100644 --- a/tasmota/language/uk_UA.h +++ b/tasmota/language/uk_UA.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/zh_CN.h b/tasmota/language/zh_CN.h index e521054f5..0da3126fd 100644 --- a/tasmota/language/zh_CN.h +++ b/tasmota/language/zh_CN.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/language/zh_TW.h b/tasmota/language/zh_TW.h index bfa967b6d..1fb664d08 100644 --- a/tasmota/language/zh_TW.h +++ b/tasmota/language/zh_TW.h @@ -672,6 +672,7 @@ #define D_SENSOR_HM10_TX "HM10 TX" #define D_SENSOR_LE01MR_RX "LE-01MR Rx" #define D_SENSOR_LE01MR_TX "LE-01MR Tx" +#define D_SENSOR_BL0940_RX "BL0940 Rx" #define D_SENSOR_CC1101_GDO0 "CC1101 GDO0" #define D_SENSOR_CC1101_GDO2 "CC1101 GDO2" #define D_SENSOR_HRXL_RX "HRXL Rx" diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 466a8991e..edf920e74 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -394,18 +394,18 @@ // -- Ping ---------------------------------------- // #define USE_PING // Enable Ping command (+2k code) -#define USE_UNISHOX_COMPRESSION // add support for string compression for RULES or SCRIPT +// -- Compression --------------------------------- +#define USE_UNISHOX_COMPRESSION // Add support for string compression in Rules or Scripts // -- Rules or Script ---------------------------- // Select none or only one of the below defines USE_RULES or USE_SCRIPT #define USE_RULES // Add support for rules (+8k code) - // with USE_UNISHOX_COMPRESSION // Compresses rules in Flash at about ~50% (+3.3k code) -//#define USE_SCRIPT // Add support for script (+17k code) - // supports USE_UNISHOX_COMPRESSION - //#define USE_SCRIPT_FATFS 4 // Script: Add FAT FileSystem Support - // #define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem) // #define SUPPORT_IF_STATEMENT // Add support for IF statement in rules (+4k2 code, -332 bytes mem) + +//#define USE_SCRIPT // Add support for script (+17k code) + //#define USE_SCRIPT_FATFS 4 // Script: Add FAT FileSystem Support + // #define SUPPORT_MQTT_EVENT // Support trigger event with MQTT subscriptions (+3k5 code) // -- Optional modules ---------------------------- @@ -611,6 +611,7 @@ //#define USE_LE01MR // Add support for F&F LE-01MR Modbus energy monitor (+1k code) #define LE01MR_SPEED 9600 // LE-01MR modbus baudrate (default: 9600) #define LE01MR_ADDR 1 // LE-01MR modbus address (default: 0x01) +#define USE_BL0940 // Add support for BL0940 Energy monitor as used in Blitzwolf SHP-10 (+1k6 code) // -- Low level interface devices ----------------- #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor (1k6 code) diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 5622bcde9..20bb9acf3 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -572,8 +572,9 @@ void GetFeatures(void) #ifdef USE_MCP9808 feature6 |= 0x00002000; // xsns_72_mcp9808.ino #endif - -// feature6 |= 0x00004000; +#ifdef USE_BL0940 + feature6 |= 0x00004000; // xnrg_14_bl0940.ino +#endif // feature6 |= 0x00008000; // feature6 |= 0x00010000; diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index fdace042c..949acec1b 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -293,6 +293,7 @@ enum SettingsTextIndex { SET_OTAURL, SET_TEMPLATE_NAME, SET_DEV_GROUP_NAME1, SET_DEV_GROUP_NAME2, SET_DEV_GROUP_NAME3, SET_DEV_GROUP_NAME4, SET_DEVICENAME, + SET_TELEGRAMTOKEN, SET_MAX }; enum DevGroupMessageType { DGR_MSGTYP_FULL_STATUS, DGR_MSGTYP_PARTIAL_UPDATE, DGR_MSGTYP_UPDATE, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_MSGTYP_UPDATE_DIRECT, DGR_MSGTYPE_UPDATE_COMMAND }; diff --git a/tasmota/tasmota_template.h b/tasmota/tasmota_template.h index b3d3b48ba..8b44a547b 100644 --- a/tasmota/tasmota_template.h +++ b/tasmota/tasmota_template.h @@ -233,6 +233,7 @@ enum UserSelectablePins { GPIO_BOILER_OT_RX, // OpenTherm Boiler RX pin GPIO_BOILER_OT_TX, // OpenTherm Boiler TX pin GPIO_WINDMETER_SPEED, // WindMeter speed counter pin + GPIO_BL0940_RX, // BL0940 serial interface GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -322,7 +323,8 @@ const char kSensorNames[] PROGMEM = D_SENSOR_ELECTRIQ_MOODL "|" D_SENSOR_AS3935 "|" D_SENSOR_PMS5003_TX "|" D_SENSOR_BOILER_OT_RX "|" D_SENSOR_BOILER_OT_TX "|" - D_SENSOR_WINDMETER_SPEED + D_SENSOR_WINDMETER_SPEED "|" + D_SENSOR_BL0940_RX ; const char kSensorNamesFixed[] PROGMEM = @@ -553,15 +555,18 @@ const uint8_t kGpioNiceList[] PROGMEM = { #ifdef USE_DDSU666 GPIO_DDSU666_TX, // DDSU666 Serial interface GPIO_DDSU666_RX, // DDSU666 Serial interface -#endif // USE_DDSU666 +#endif #ifdef USE_SOLAX_X1 GPIO_SOLAXX1_TX, // Solax Inverter tx pin GPIO_SOLAXX1_RX, // Solax Inverter rx pin -#endif // USE_SOLAX_X1 +#endif #ifdef USE_LE01MR GPIO_LE01MR_RX, // F7F LE-01MR energy meter rx pin GPIO_LE01MR_TX, // F7F LE-01MR energy meter tx pin -#endif // IFDEF:USE_LE01MR +#endif +#ifdef USE_BL0940 + GPIO_BL0940_RX, // BL0940 Serial interface +#endif #endif // USE_ENERGY_SENSOR // Serial diff --git a/tasmota/xnrg_14_bl0940.ino b/tasmota/xnrg_14_bl0940.ino new file mode 100644 index 000000000..ff5d61ff2 --- /dev/null +++ b/tasmota/xnrg_14_bl0940.ino @@ -0,0 +1,307 @@ +/* + xnrg_14_bl0940.ino - BL0940 energy sensor support for Tasmota + + Copyright (C) 2020 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_BL0940 +/*********************************************************************************************\ + * BL0940 - Energy (Blitzwolf SHP10) + * + * Template {"NAME":"BW-SHP10","GPIO":[0,148,0,207,158,21,0,0,0,17,0,0,0],"FLAG":0,"BASE":18} + * + * Based on datasheet from http://www.belling.com.cn/media/file_object/bel_product/BL0940/datasheet/BL0940_V1.1_en.pdf +\*********************************************************************************************/ + +#define XNRG_14 14 + +#define BL0940_PULSES_NOT_INITIALIZED -1 + +#define BL0940_BUFFER_SIZE 36 + +#define BL0940_WRITE_COMMAND 0xA0 // 0xA8 according to documentation +#define BL0940_REG_I_FAST_RMS_CTRL 0x10 +#define BL0940_REG_MODE 0x18 +#define BL0940_REG_SOFT_RESET 0x19 +#define BL0940_REG_USR_WRPROT 0x1A +#define BL0940_REG_TPS_CTRL 0x1B + +#define BL0940_READ_COMMAND 0x50 // 0x58 according to documentation +#define BL0940_FULL_PACKET 0xAA +#define BL0940_PACKET_HEADER 0x55 // 0x58 according to documentation + +#include + +TasmotaSerial *Bl0940Serial = nullptr; + +struct BL0940 { + long voltage = 0; + long current = 0; + long power = 0; + long power_cycle_first = 0; + long cf_pulses = 0; + long cf_pulses_last_time = BL0940_PULSES_NOT_INITIALIZED; + float temperature; + + int byte_counter = 0; + uint8_t *rx_buffer = nullptr; + uint8_t power_invalid = 0; + bool received = false; +} Bl0940; + +const uint8_t bl0940_init[5][6] = { + { BL0940_WRITE_COMMAND, BL0940_REG_SOFT_RESET, 0x5A, 0x5A, 0x5A, 0x38 }, // Reset to default + { BL0940_WRITE_COMMAND, BL0940_REG_USR_WRPROT, 0x55, 0x00, 0x00, 0xF0 }, // Enable User Operation Write + { BL0940_WRITE_COMMAND, BL0940_REG_MODE, 0x00, 0x10, 0x00, 0x37 }, // 0x0100 = CF_UNABLE energy pulse, AC_FREQ_SEL 50Hz, RMS_UPDATE_SEL 800mS + { BL0940_WRITE_COMMAND, BL0940_REG_TPS_CTRL, 0xFF, 0x47, 0x00, 0xFE }, // 0x47FF = Over-current and leakage alarm on, Automatic temperature measurement, Interval 100mS + { BL0940_WRITE_COMMAND, BL0940_REG_I_FAST_RMS_CTRL, 0x1C, 0x18, 0x00, 0x1B }}; // 0x181C = Half cycle, Fast RMS threshold 6172 + +void Bl0940Received(void) { + // 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 25 26 27 28 29 30 31 32 33 34 + // 55 F2 03 00 00 00 00 7E 02 00 D4 B0 72 AC 01 00 00 00 00 02 01 00 00 00 00 00 00 00 BA 01 00 FE 03 00 83 + // 55 88 02 00 49 00 00 FE 02 00 AF EF 71 D2 01 00 EB FF FF 49 01 00 00 00 00 02 00 00 CF 01 00 FE 03 00 9F + // 55 B9 33 00 DE 45 00 94 02 00 CF E4 70 63 02 00 6C 4C 00 13 01 00 09 00 00 00 00 00 E4 01 00 FE 03 00 72 + // Hd IFRms--- Current- Reserved Voltage- Reserved Power--- Reserved CF------ Reserved TPS1---- TPS2---- Ck + + if (Bl0940.rx_buffer[0] != BL0940_PACKET_HEADER) { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("BL9: Invalid data")); + return; + } + + Bl0940.voltage = Bl0940.rx_buffer[12] << 16 | Bl0940.rx_buffer[11] << 8 | Bl0940.rx_buffer[10]; + Bl0940.current = Bl0940.rx_buffer[6] << 16 | Bl0940.rx_buffer[5] << 8 | Bl0940.rx_buffer[4]; + Bl0940.power = Bl0940.rx_buffer[18] << 16 | Bl0940.rx_buffer[17] << 8 | Bl0940.rx_buffer[16]; + Bl0940.cf_pulses = Bl0940.rx_buffer[24] << 16 | Bl0940.rx_buffer[23] << 8 | Bl0940.rx_buffer[22]; + uint16_t tps1 = Bl0940.rx_buffer[29] << 8 | Bl0940.rx_buffer[28]; + Bl0940.temperature = ((170.0f/448.0f)*(((float)tps1/2.0f)-32.0f))-45.0f; + + if (Energy.power_on) { // Powered on + Energy.voltage[0] = (float)Bl0940.voltage / Settings.energy_voltage_calibration; + if (power != 0) { + Energy.active_power[0] = (float)Bl0940.power / Settings.energy_power_calibration; + Energy.current[0] = (float)Bl0940.current / (Settings.energy_current_calibration * 100); + } else { + Energy.active_power[0] = 0; + Energy.current[0] = 0; + } + } else { // Powered off + Bl0940.power_cycle_first = 0; + Energy.voltage[0] = 0; + Energy.active_power[0] = 0; + Energy.current[0] = 0; + } +} + +bool Bl0940SerialInput(void) { + while (Bl0940Serial->available()) { + yield(); + uint8_t serial_in_byte = Bl0940Serial->read(); + if (!Bl0940.received && (BL0940_PACKET_HEADER == serial_in_byte)) { // Packet header + Bl0940.received = true; + Bl0940.byte_counter = 0; + } + if (Bl0940.received) { + Bl0940.rx_buffer[Bl0940.byte_counter++] = serial_in_byte; + if (BL0940_BUFFER_SIZE == Bl0940.byte_counter) { + + AddLogBuffer(LOG_LEVEL_DEBUG_MORE, Bl0940.rx_buffer, BL0940_BUFFER_SIZE -1); + + uint8_t checksum = BL0940_READ_COMMAND; + for (uint32_t i = 0; i < BL0940_BUFFER_SIZE -2; i++) { checksum += Bl0940.rx_buffer[i]; } + checksum ^= 0xFF; + if (checksum == Bl0940.rx_buffer[34]) { + Energy.data_valid[0] = 0; + Bl0940Received(); + Bl0940.received = false; + return true; + } else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("BL9: " D_CHECKSUM_FAILURE)); + do { // Sync buffer with data (issue #1907 and #3425) + memmove(Bl0940.rx_buffer, Bl0940.rx_buffer +1, BL0940_BUFFER_SIZE -1); + Bl0940.byte_counter--; + } while ((Bl0940.byte_counter > 1) && (BL0940_PACKET_HEADER != Bl0940.rx_buffer[0])); + if (BL0940_PACKET_HEADER != Bl0940.rx_buffer[0]) { + Bl0940.received = false; + Bl0940.byte_counter = 0; + } + } + } + } + } +} + +/********************************************************************************************/ + +void Bl0940EverySecond(void) { + if (Energy.data_valid[0] > ENERGY_WATCHDOG) { + Bl0940.voltage = 0; + Bl0940.current = 0; + Bl0940.power = 0; + } else { + long cf_frequency = 0; + + if (BL0940_PULSES_NOT_INITIALIZED == Bl0940.cf_pulses_last_time) { + Bl0940.cf_pulses_last_time = Bl0940.cf_pulses; // Init after restart + } else { + if (Bl0940.cf_pulses < Bl0940.cf_pulses_last_time) { // Rolled over after 16777215 pulses + cf_frequency = (0x1000000 - Bl0940.cf_pulses_last_time) + Bl0940.cf_pulses; + } else { + cf_frequency = Bl0940.cf_pulses - Bl0940.cf_pulses_last_time; + } + if (cf_frequency && Energy.active_power[0]) { + unsigned long delta = (cf_frequency * Settings.energy_power_calibration) / 36; + // prevent invalid load delta steps even checksum is valid (issue #5789): +// if (delta <= (3680*100/36) * 10 ) { // max load for S31/Pow R2: 3.68kW + // prevent invalid load delta steps even checksum is valid but allow up to 4kW (issue #7155): + if (delta <= (4000*100/36) * 10 ) { // max load for S31/Pow R2: 4.00kW + Bl0940.cf_pulses_last_time = Bl0940.cf_pulses; + Energy.kWhtoday_delta += delta; + } + else { + AddLog_P(LOG_LEVEL_DEBUG, PSTR("BL9: Load overflow")); + Bl0940.cf_pulses_last_time = BL0940_PULSES_NOT_INITIALIZED; + } + EnergyUpdateToday(); + } + } + } + + Bl0940Serial->flush(); + Bl0940Serial->write(BL0940_READ_COMMAND); + Bl0940Serial->write(BL0940_FULL_PACKET); +} + +void Bl0940SnsInit(void) { + // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions + Bl0940Serial = new TasmotaSerial(Pin(GPIO_BL0940_RX), Pin(GPIO_TXD), 1); + if (Bl0940Serial->begin(4800, 2)) { + if (Bl0940Serial->hardwareSerial()) { + ClaimSerial(); + } + if (HLW_UREF_PULSE == Settings.energy_voltage_calibration) { + Settings.energy_voltage_calibration = 33003; + Settings.energy_current_calibration = 2243; + Settings.energy_power_calibration = 1414; + } + + for (uint32_t i = 0; i < 5; i++) { + for (uint32_t j = 0; j < 6; j++) { + Bl0940Serial->write(bl0940_init[i][j]); +// Bl0940Serial->write(pgm_read_byte(bl0940_init + (6 * i) + j)); // Wrong byte order! + } + delay(1); + } + + } else { + energy_flg = ENERGY_NONE; + } +} + +void Bl0940DrvInit(void) { + if (PinUsed(GPIO_BL0940_RX) && PinUsed(GPIO_TXD)) { + Bl0940.rx_buffer = (uint8_t*)(malloc(BL0940_BUFFER_SIZE)); + if (Bl0940.rx_buffer != nullptr) { + energy_flg = XNRG_14; + } + } +} + +bool Bl0940Command(void) { + bool serviced = true; + + uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100); // 1.23 = 123 + + if (CMND_POWERSET == Energy.command_code) { + if (XdrvMailbox.data_len && Bl0940.power) { + Settings.energy_power_calibration = (Bl0940.power * 100) / value; + } + } + else if (CMND_VOLTAGESET == Energy.command_code) { + if (XdrvMailbox.data_len && Bl0940.voltage) { + Settings.energy_voltage_calibration = (Bl0940.voltage * 100) / value; + } + } + else if (CMND_CURRENTSET == Energy.command_code) { + if (XdrvMailbox.data_len && Bl0940.current) { + Settings.energy_current_calibration = Bl0940.current / value; + } + } + else serviced = false; // Unknown command + + return serviced; +} + +void Bl0940Show(bool json) +{ + char temperature[33]; + dtostrfd(Bl0940.temperature, Settings.flag2.temperature_resolution, temperature); + + if (json) { + ResponseAppend_P(JSON_SNS_TEMP, "BL0940", temperature); + if (0 == tele_period) { +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_TEMP, temperature); +#endif // USE_DOMOTICZ +#ifdef USE_KNX + KnxSensor(KNX_TEMPERATURE, Bl0940.temperature); +#endif // USE_KNX + } +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TEMP, "", temperature, TempUnit()); +#endif // USE_WEBSERVER + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xnrg14(uint8_t function) +{ + bool result = false; + + switch (function) { + case FUNC_LOOP: + if (Bl0940Serial) { Bl0940SerialInput(); } + break; + case FUNC_ENERGY_EVERY_SECOND: + Bl0940EverySecond(); + break; + case FUNC_JSON_APPEND: + Bl0940Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Bl0940Show(0); + break; +#endif // USE_WEBSERVER + case FUNC_COMMAND: + result = Bl0940Command(); + break; + case FUNC_INIT: + Bl0940SnsInit(); + break; + case FUNC_PRE_INIT: + Bl0940DrvInit(); + break; + } + return result; +} + +#endif // USE_BL0940 +#endif // USE_ENERGY_SENSOR diff --git a/tools/decode-status.py b/tools/decode-status.py index 67898d784..1ce04951e 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -148,7 +148,8 @@ a_setoption = [[ "Enable light fading at start/power on", "Set PWM Mode from regular PWM to ColorTemp control","", "Keep uncompressed rules in memory to avoid CPU load of uncompressing at each tick", - "","","", + "Implement simpler MAX6675 protocol instead of MAX31855", + "","", "","","","", "","","","", "","","","", @@ -204,7 +205,7 @@ a_features = [[ "USE_KEELOQ","USE_HRXL","USE_SONOFF_D1","USE_HDC1080", "USE_IAQ","USE_DISPLAY_SEVENSEG","USE_AS3935","USE_PING", "USE_WINDMETER","USE_OPENTHERM","USE_THERMOSTAT","USE_VEML6075", - "USE_VEML7700","USE_MCP9808","","", + "USE_VEML7700","USE_MCP9808","USE_BL0940","", "","","","", "","","","", "","","","", @@ -242,7 +243,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v20200510 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v20200607 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj))