From e927e3307ef1625d0e913c57967e9fec4e395db0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 25 Feb 2023 16:44:04 +0100 Subject: [PATCH] Add DevicesPresent limit check - Increase supported relays and buttons to 32 --- tasmota/include/tasmota.h | 4 +- tasmota/tasmota_support/support.ino | 16 ++ tasmota/tasmota_xdrv_driver/xdrv_04_light.ino | 6 +- .../tasmota_xdrv_driver/xdrv_13_display.ino | 4 +- .../xdrv_16_tuyamcu_v1.ino | 4 +- .../xdrv_16_tuyamcu_v2.ino | 4 +- .../xdrv_18_armtronix_dimmers.ino | 2 +- .../xdrv_19_ps16dz_dimmer.ino | 2 +- .../tasmota_xdrv_driver/xdrv_28_pcf8574.ino | 9 +- .../xdrv_30_exs_dimmer.ino | 2 +- .../xdrv_35_pwm_dimmer.ino | 2 +- .../tasmota_xdrv_driver/xdrv_37_sonoff_d1.ino | 2 +- .../tasmota_xdrv_driver/xdrv_44_miel_hvac.ino | 3 +- .../xdrv_45_shelly_dimmer.ino | 2 +- .../xdrv_53_projector_ctrl.ino | 3 +- .../tasmota_xdrv_driver/xdrv_60_shift595.ino | 3 +- .../tasmota_xdrv_driver/xdrv_66_tm1638.ino | 2 +- .../xdrv_86_esp32_sonoff_spm.ino | 2 +- .../xdrv_88_esp32_shelly_pro.ino | 2 +- .../xdrv_88_esp32_shelly_pro_v1.ino | 177 ++++++++++++++++++ .../xdrv_90_esp32_dingtian_relay.ino | 5 +- 21 files changed, 225 insertions(+), 31 deletions(-) create mode 100644 tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v1.ino diff --git a/tasmota/include/tasmota.h b/tasmota/include/tasmota.h index ec68438ba..19d098a26 100644 --- a/tasmota/include/tasmota.h +++ b/tasmota/include/tasmota.h @@ -52,8 +52,8 @@ const uint8_t MAX_INTERLOCKS = 14; // Max number of interlock groups (u const uint8_t MAX_SWITCHES = 28; // Max number of switches selectable on GPIO const uint8_t MAX_KEYS = 28; // Max number of keys or buttons selectable on GPIO #endif // ESP32 -const uint8_t MAX_RELAYS_SET = 28; // Max number of relays -const uint8_t MAX_KEYS_SET = 28; // Max number of keys +const uint8_t MAX_RELAYS_SET = 32; // Max number of relays +const uint8_t MAX_KEYS_SET = 32; // Max number of keys // Changes to the following MAX_ defines will impact settings layout const uint8_t MAX_INTERLOCKS_SET = 14; // Max number of interlock groups (MAX_RELAYS_SET / 2) diff --git a/tasmota/tasmota_support/support.ino b/tasmota/tasmota_support/support.ino index 7c8c90f5e..d39d2b8bb 100755 --- a/tasmota/tasmota_support/support.ino +++ b/tasmota/tasmota_support/support.ino @@ -757,6 +757,22 @@ bool NewerVersion(char* version_str) { return (version > VERSION); } +int32_t UpdateDevicesPresent(int32_t change) { + int32_t difference = 0; + int32_t devices_present = TasmotaGlobal.devices_present; // Between 0 and 32 + devices_present += change; + if (devices_present < 0) { // Support down to 0 + difference = devices_present; + devices_present = 0; + } + else if (devices_present >= POWER_SIZE) { // Support up to uint32_t as bitmask + difference = devices_present - POWER_SIZE; + devices_present = POWER_SIZE; + } + TasmotaGlobal.devices_present = devices_present; + return difference; +} + char* GetPowerDevice(char* dest, uint32_t idx, size_t size, uint32_t option) { strncpy_P(dest, S_RSLT_POWER, size); // POWER diff --git a/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino b/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino index bbad6d364..c8d728b7d 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_04_light.ino @@ -1116,17 +1116,17 @@ bool LightModuleInit(void) #endif // USE_PWM_DIMMER if (TasmotaGlobal.light_type > LT_BASIC) { - TasmotaGlobal.devices_present++; + UpdateDevicesPresent(1); } // post-process for lights uint32_t pwm_channels = (TasmotaGlobal.light_type & 7) > LST_MAX ? LST_MAX : (TasmotaGlobal.light_type & 7); if (Settings->flag3.pwm_multi_channels) { // SetOption68 - Enable multi-channels PWM instead of Color PWM if (0 == pwm_channels) { pwm_channels = 1; } - TasmotaGlobal.devices_present += pwm_channels - 1; // add the pwm channels controls at the end + UpdateDevicesPresent(pwm_channels - 1); // add the pwm channels controls at the end } else if ((Settings->param[P_RGB_REMAP] & 128) && (LST_RGBW <= pwm_channels)) { // SetOption37 // if RGBW or RGBCW, and SetOption37 >= 128, we manage RGB and W separately, hence adding a device - TasmotaGlobal.devices_present++; + UpdateDevicesPresent(1); } else { #ifdef USE_LIGHT_VIRTUAL_CT initCTRange(pwm_channels); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino b/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino index bbd9802aa..f55947bce 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_13_display.ino @@ -1875,10 +1875,10 @@ void DisplayInitDriver(void) { for (uint8_t count = 0; count < NUM_GRAPHS; count++) { graph[count] = 0; } #endif - TasmotaGlobal.devices_present++; + UpdateDevicesPresent(1); if (!PinUsed(GPIO_BACKLIGHT)) { if (TasmotaGlobal.light_type && (4 == Settings->display_model)) { - TasmotaGlobal.devices_present--; // Assume PWM channel is used for backlight + UpdateDevicesPresent(-1); // Assume PWM channel is used for backlight } } disp_device = TasmotaGlobal.devices_present; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino index bd316122e..3ad56d84a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino @@ -1181,13 +1181,13 @@ bool TuyaModuleSelected(void) { if ((Settings->tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1 && Settings->tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8 ) || (Settings->tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1_INV && Settings->tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8_INV )) { relaySet = true; - TasmotaGlobal.devices_present++; + UpdateDevicesPresent(1); } } if (!relaySet && TuyaGetDpId(TUYA_MCU_FUNC_DUMMY) == 0) { //by default the first relay is created automatically the dummy let remove it if not needed TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1); - TasmotaGlobal.devices_present++; + UpdateDevicesPresent(1); SettingsSaveAll(); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino index 6c3eb15d5..24370ef8c 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino @@ -1981,13 +1981,13 @@ bool TuyaModuleSelected(void) { if ((Settings->tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1 && Settings->tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8 ) || (Settings->tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1_INV && Settings->tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8_INV )) { relaySet = true; - TasmotaGlobal.devices_present++; + UpdateDevicesPresent(1); } } if (!relaySet && TuyaGetDpId(TUYA_MCU_FUNC_DUMMY) == 0) { //by default the first relay is created automatically the dummy let remove it if not needed TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1); - TasmotaGlobal.devices_present++; + UpdateDevicesPresent(1); SettingsSaveAll(); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino b/tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino index 674ee9b3c..e070e5d82 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_18_armtronix_dimmers.ino @@ -86,7 +86,7 @@ void ArmtronixRequestState(void) bool ArmtronixModuleSelected(void) { - TasmotaGlobal.devices_present++; + UpdateDevicesPresent(1); TasmotaGlobal.light_type = LT_SERIAL2; return true; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino index d23058b39..69d0a69c0 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_19_ps16dz_dimmer.ino @@ -196,7 +196,7 @@ void PS16DZInit(void) bool PS16DZModuleSelected(void) { - TasmotaGlobal.devices_present++; + UpdateDevicesPresent(1); TasmotaGlobal.light_type = LT_SERIAL1; return true; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574.ino b/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574.ino index 891e07f44..a889fe3aa 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_28_pcf8574.ino @@ -148,7 +148,8 @@ void Pcf8574Init(void) for (uint32_t i = 0; i < sizeof(Pcf8574.pin); i++) { Pcf8574.pin[i] = 99; } - TasmotaGlobal.devices_present = TasmotaGlobal.devices_present - Pcf8574.max_connected_ports; // reset no of devices to avoid duplicate ports on duplicate init. + UpdateDevicesPresent(-Pcf8574.max_connected_ports); // reset no of devices to avoid duplicate ports on duplicate init. + Pcf8574.max_connected_ports = 0; // reset no of devices to avoid duplicate ports on duplicate init. for (uint32_t idx = 0; idx < Pcf8574.max_devices; idx++) { // suport up to 8 boards PCF8574 uint8_t gpio = Pcf8574Read(idx); @@ -173,7 +174,7 @@ void Pcf8574Init(void) bitWrite(Settings->power, TasmotaGlobal.devices_present, power_state); } //else AddLog(LOG_LEVEL_DEBUG, PSTR("PCF: DON'T set power from chip state")); - TasmotaGlobal.devices_present++; + UpdateDevicesPresent(1); Pcf8574.max_connected_ports++; } } @@ -314,7 +315,7 @@ void Pcf8574SaveSettings(void) count++; } if (count <= TasmotaGlobal.devices_present) { - TasmotaGlobal.devices_present = TasmotaGlobal.devices_present - count; + UpdateDevicesPresent(-count); } for (byte i = 0; i < 8; i++) { snprintf_P(stemp, sizeof(stemp), PSTR("i2cs%d"), i+8*idx); @@ -322,7 +323,7 @@ void Pcf8574SaveSettings(void) byte _value = (!strlen(tmp)) ? 0 : atoi(tmp); if (_value) { Settings->pcf8574_config[idx] = Settings->pcf8574_config[idx] | 1 << i; - TasmotaGlobal.devices_present++; + UpdateDevicesPresent(1); Pcf8574.max_connected_ports++; } else { Settings->pcf8574_config[idx] = Settings->pcf8574_config[idx] & ~(1 << i ); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino index 597f3b9e6..7579072b3 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_30_exs_dimmer.ino @@ -354,7 +354,7 @@ bool ExsModuleSelected(void) Settings->flag3.pwm_multi_channels = 1; // SetOption68 - Enable multi-channels PWM instead of Color PWM SetSeriallog(LOG_LEVEL_NONE); - TasmotaGlobal.devices_present = +2; + UpdateDevicesPresent(2); TasmotaGlobal.light_type = LT_SERIAL2; return true; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_35_pwm_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_35_pwm_dimmer.ino index 5ce566548..76e9e7bca 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_35_pwm_dimmer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_35_pwm_dimmer.ino @@ -137,7 +137,7 @@ void PWMModulePreInit(void) first_device_group_is_local = false; // Back out the changes made in the light module under the assumtion we have a relay or PWM. - TasmotaGlobal.devices_present--; + UpdateDevicesPresent(-1); TasmotaGlobal.light_type = 0; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_37_sonoff_d1.ino b/tasmota/tasmota_xdrv_driver/xdrv_37_sonoff_d1.ino index fde6dc1c9..a727b6080 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_37_sonoff_d1.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_37_sonoff_d1.ino @@ -163,7 +163,7 @@ bool SonoffD1ModuleSelected(void) { SetSerial(9600, TS_SERIAL_8N1); - TasmotaGlobal.devices_present++; + UpdateDevicesPresent(1); TasmotaGlobal.light_type = LT_SERIAL1; return true; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino b/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino index 65ab1ecdd..acdd3fa6a 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_44_miel_hvac.ino @@ -1085,7 +1085,8 @@ miel_hvac_pre_init(void) SetSerial(baudrate, TS_SERIAL_8E1); } - sc->sc_device = TasmotaGlobal.devices_present++; /* claim a POWER device slot */ + UpdateDevicesPresent(1); /* claim a POWER device slot */ + sc->sc_device = TasmotaGlobal.devices_present; miel_hvac_sc = sc; return; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino b/tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino index 0ed553765..42ba5df0b 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_45_shelly_dimmer.ino @@ -725,7 +725,7 @@ bool ShdSerialInput(void) bool ShdModuleSelected(void) { if (PinUsed(GPIO_SHELLY_DIMMER_BOOT0) && PinUsed(GPIO_SHELLY_DIMMER_RST_INV)) { - TasmotaGlobal.devices_present++; + UpdateDevicesPresent(1); TasmotaGlobal.light_type = LT_SERIAL1; Shd.present = true; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino b/tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino index dc31523df..999f6a738 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_53_projector_ctrl.ino @@ -123,7 +123,8 @@ projector_ctrl_pre_init(void) SetSerial(baudrate, TS_SERIAL_8N1); } - sc->sc_device = ++(TasmotaGlobal.devices_present); /* claim a POWER device slot */ + UpdateDevicesPresent(1); /* claim a POWER device slot */ + sc->sc_device = TasmotaGlobal.devices_present; AddLog(LOG_LEVEL_INFO, PSTR(PROJECTOR_CTRL_LOGNAME ": new RELAY%d, polling serial for Projector status"), sc->sc_device); diff --git a/tasmota/tasmota_xdrv_driver/xdrv_60_shift595.ino b/tasmota/tasmota_xdrv_driver/xdrv_60_shift595.ino index d18410afb..f477fc8ff 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_60_shift595.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_60_shift595.ino @@ -58,7 +58,8 @@ void Shift595Init(void) { Shift595->first = TasmotaGlobal.devices_present; Shift595->outputs = Settings->shift595_device_count * 8; - TasmotaGlobal.devices_present += Shift595->outputs; + UpdateDevicesPresent(Shift595->outputs); + Shift595->connected = true; AddLog(LOG_LEVEL_DEBUG, PSTR("595: Controlling relays POWER%d to POWER%d"), Shift595->first + 1, Shift595->first + Shift595->outputs); } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_66_tm1638.ino b/tasmota/tasmota_xdrv_driver/xdrv_66_tm1638.ino index f693de10e..4065b212c 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_66_tm1638.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_66_tm1638.ino @@ -164,7 +164,7 @@ void TmInit(void) { digitalWrite(Tm1638.strobe_pin, HIGH); Tm1638.led_offset = TasmotaGlobal.devices_present; - TasmotaGlobal.devices_present += TM1638_MAX_LEDS; + UpdateDevicesPresent(TM1638_MAX_LEDS); Tm1638.key_offset = -1; Tm1638.detected = true; } diff --git a/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino b/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino index 058f83813..3a222f91f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_86_esp32_sonoff_spm.ino @@ -1195,7 +1195,7 @@ void SSPMHandleReceivedData(void) { TasmotaGlobal.power |= current_state; Sspm->old_power = TasmotaGlobal.power; - TasmotaGlobal.devices_present += 4; + UpdateDevicesPresent(4); } SSPMSendGetOps(Sspm->module_selected -1); break; diff --git a/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro.ino b/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro.ino index 16dd8db3e..05ca7aa3f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro.ino @@ -372,7 +372,7 @@ void ShellyProPreInit(void) { } if (SPro.detected) { - TasmotaGlobal.devices_present += SPro.detected; + UpdateDevicesPresent(SPro.detected); // Shelly Pro 1 SPro.pin_register_cs = Pin(GPIO_SPI_CS); digitalWrite(SPro.pin_register_cs, (4 == SPro.detected) ? 1 : 0); // Prep 74HC595 rclk diff --git a/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v1.ino b/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v1.ino new file mode 100644 index 000000000..6af3d65b7 --- /dev/null +++ b/tasmota/tasmota_xdrv_driver/xdrv_88_esp32_shelly_pro_v1.ino @@ -0,0 +1,177 @@ +/* + xdrv_88_shelly_pro.ino - Shelly pro family support for Tasmota + + Copyright (C) 2022 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 ESP32 +#ifdef USE_SPI +#ifdef USE_SHELLY_PRO_V1 +/*********************************************************************************************\ + * Shelly Pro support + * + * {"NAME":"Shelly Pro 1","GPIO":[0,1,0,1,768,0,0,0,672,704,736,0,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,0,0,0,32,4736,0,160,0],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,10000,10000,3350"} + * {"NAME":"Shelly Pro 1PM","GPIO":[9568,1,9472,1,768,0,0,0,672,704,736,0,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,3459,0,0,32,4736,0,160,0],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,10000,10000,3350"} + * {"NAME":"Shelly Pro 2","GPIO":[0,1,0,1,768,0,0,0,672,704,736,0,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,0,0,0,32,4736,4737,160,161],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,10000,10000,3350;AdcParam2 2,10000,10000,3350"} + * {"NAME":"Shelly Pro 2PM","GPIO":[9568,1,9472,1,768,0,0,0,672,704,736,9569,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,3460,0,0,32,4736,4737,160,161],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,10000,10000,3350;AdcParam2 2,10000,10000,3350"} + * + * Shelly Pro uses SPI to control one 74HC595 for relays/leds and one ADE7953 (1PM) or two ADE7953 (2PM) for energy monitoring +\*********************************************************************************************/ + +#define XDRV_88 88 + +struct SPro { + uint32_t last_update; + uint8_t pin_shift595_rclk; + uint8_t ledlink; + uint8_t power; + bool detected; +} SPro; + +void ShellyProUpdate(void) { + // Shelly Pro 595 register + // bit 0 = relay/led 1 + // bit 1 = relay/led 2 + // bit 2 = wifi led blue + // bit 3 = wifi led green + // bit 4 = wifi led red + // bit 5 - 7 = nc + // OE is connected to Gnd with 470 ohm resistor R62 AND a capacitor C81 to 3V3 + // - this inhibits output of signals (also relay state) during power on for a few seconds + uint8_t val = SPro.power | SPro.ledlink; + SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); + SPI.transfer(val); // Write 74HC595 shift register + SPI.endTransaction(); +// delayMicroseconds(2); // Wait for SPI clock to stop + digitalWrite(SPro.pin_shift595_rclk, 1); // Latch data + delayMicroseconds(1); // Shelly 10mS + digitalWrite(SPro.pin_shift595_rclk, 0); +} + +void ShellyProPreInit(void) { + if ((SPI_MOSI_MISO == TasmotaGlobal.spi_enabled) && + PinUsed(GPIO_SPI_CS) && + TasmotaGlobal.gpio_optiona.shelly_pro) { // Option_A7 + + if (PinUsed(GPIO_SWT1) || PinUsed(GPIO_KEY1)) { + UpdateDevicesPresent(1); // Shelly Pro 1 + + if (PinUsed(GPIO_SWT1, 1) || PinUsed(GPIO_KEY1, 1)) { + UpdateDevicesPresent(1); // Shelly Pro 2 + } + + SPro.pin_shift595_rclk = Pin(GPIO_SPI_CS); + digitalWrite(SPro.pin_shift595_rclk, 0); + pinMode(SPro.pin_shift595_rclk, OUTPUT); + // Does nothing if SPI is already initiated (by ADE7953) so no harm done + SPI.begin(Pin(GPIO_SPI_CLK), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_MOSI), -1); + + SPro.ledlink = 0x18; // Blue led on - set by first call ShellyProPower() + SPro.detected = true; + } + } +} + +void ShellyProInit(void) { + int pin_lan_reset = 5; // GPIO5 = LAN8720 nRST +// delay(30); // (t-purstd) This pin must be brought low for a minimum of 25 mS after power on + digitalWrite(pin_lan_reset, 0); + pinMode(pin_lan_reset, OUTPUT); + delay(1); // (t-rstia) This pin must be brought low for a minimum of 100 uS + digitalWrite(pin_lan_reset, 1); + + AddLog(LOG_LEVEL_INFO, PSTR("HDW: Shelly Pro %d%s initialized"), + TasmotaGlobal.devices_present, (PinUsed(GPIO_ADE7953_CS))?"PM":""); +} + +void ShellyProPower(void) { + SPro.power = XdrvMailbox.index &3; + ShellyProUpdate(); +} + +void ShellyProUpdateLedLink(uint32_t ledlink) { + if (ledlink != SPro.ledlink) { + SPro.ledlink = ledlink; + ShellyProUpdate(); + } +} + +void ShellyProLedLink(void) { + /* + bit 2 = blue, 3 = green, 4 = red + Shelly Pro documentation + - Blue light indicator will be on if in AP mode. + - Red light indicator will be on if in STA mode and not connected to a Wi-Fi network. + - Yellow light indicator will be on if in STA mode and connected to a Wi-Fi network. + - Green light indicator will be on if in STA mode and connected to a Wi-Fi network and to the Shelly Cloud. + - The light indicator will be flashing Red/Blue if OTA update is in progress. + Tasmota behaviour + - Blue light indicator will blink if no wifi or mqtt. + - Green light indicator will be on if in STA mode and connected to a Wi-Fi network. + */ + SPro.last_update = TasmotaGlobal.uptime; + uint32_t ledlink = 0x1C; // All leds off + if (XdrvMailbox.index) { + ledlink &= 0xFB; // Blue blinks if wifi/mqtt lost + } + else if (!TasmotaGlobal.global_state.wifi_down) { + ledlink &= 0xF7; // Green On + } + + ShellyProUpdateLedLink(ledlink); +} + +void ShellyProLedLinkWifiOff(void) { + /* + bit 2 = blue, 3 = green, 4 = red + - Green light indicator will be on if in STA mode and connected to a Wi-Fi network. + */ + if (SPro.last_update +1 < TasmotaGlobal.uptime) { + ShellyProUpdateLedLink((TasmotaGlobal.global_state.wifi_down) ? 0x1C : 0x14); // Green off if wifi OFF + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv88(uint32_t function) { + bool result = false; + + if (FUNC_PRE_INIT == function) { + ShellyProPreInit(); + } else if (SPro.detected) { + switch (function) { + case FUNC_EVERY_SECOND: + ShellyProLedLinkWifiOff(); + break; + case FUNC_SET_POWER: + ShellyProPower(); + break; + case FUNC_LED_LINK: + ShellyProLedLink(); + break; + case FUNC_INIT: + ShellyProInit(); + break; + } + } + return result; +} + +#endif // USE_SHELLY_PRO +#endif // USE_SPI +#endif // ESP32 diff --git a/tasmota/tasmota_xdrv_driver/xdrv_90_esp32_dingtian_relay.ino b/tasmota/tasmota_xdrv_driver/xdrv_90_esp32_dingtian_relay.ino index 459775dba..6e4e9005f 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_90_esp32_dingtian_relay.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_90_esp32_dingtian_relay.ino @@ -98,10 +98,7 @@ void DingtianInit(void) { DINGTIAN_SET_OUTPUT(Dingtian->pin_rck, 0); Dingtian->first = TasmotaGlobal.devices_present; - TasmotaGlobal.devices_present += Dingtian->count; - if (TasmotaGlobal.devices_present > POWER_SIZE) { - TasmotaGlobal.devices_present = POWER_SIZE; - } + UpdateDevicesPresent(Dingtian->count); AddLog(LOG_LEVEL_DEBUG, PSTR("DNGT: Dingtian relays: POWER%d to POWER%d"), Dingtian->first + 1, TasmotaGlobal.devices_present); } }