mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-23 18:56:38 +00:00
Fix Shelly Pro 4PM auto reset
This commit is contained in:
parent
3f73d5a49d
commit
88dd5f7f50
@ -27,6 +27,8 @@
|
||||
|
||||
#define MAX_RELAY_BUTTON1 5 // Max number of relay controlled by BUTTON1
|
||||
|
||||
#define BUTTON_INVERT 0x02 // Invert bitmask
|
||||
|
||||
const uint8_t BUTTON_PROBE_INTERVAL = 10; // Time in milliseconds between button input probe
|
||||
const uint8_t BUTTON_FAST_PROBE_INTERVAL = 2; // Time in milliseconds between button input probe for AC detection
|
||||
const uint8_t BUTTON_AC_PERIOD = (20 + BUTTON_FAST_PROBE_INTERVAL - 1) / BUTTON_FAST_PROBE_INTERVAL; // Duration of an AC wave in probe intervals
|
||||
@ -134,7 +136,7 @@ void ButtonProbe(void) {
|
||||
not_activated = (digitalRead(Pin(GPIO_KEY1, i)) != bitRead(Button.inverted_mask, i));
|
||||
}
|
||||
else if (bitRead(Button.virtual_pin_used, i)) {
|
||||
not_activated = bitRead(Button.virtual_pin, i);
|
||||
not_activated = (bitRead(Button.virtual_pin, i) != bitRead(Button.inverted_mask, i));
|
||||
}
|
||||
else { continue; }
|
||||
|
||||
@ -251,12 +253,23 @@ void ButtonInit(void) {
|
||||
else {
|
||||
XdrvMailbox.index = i;
|
||||
if (XdrvCall(FUNC_ADD_BUTTON)) {
|
||||
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("BTN: Add button %d"), i);
|
||||
|
||||
bitSet(Button.virtual_pin_used, i);
|
||||
/*
|
||||
At entry:
|
||||
XdrvMailbox.index = key index
|
||||
At exit:
|
||||
XdrvMailbox.index bit 0 = current state
|
||||
XdrvMailbox.index bit 1 = invert signal
|
||||
*/
|
||||
Button.present++;
|
||||
Button.last_state[i] = XdrvMailbox.payload;
|
||||
bitSet(Button.virtual_pin_used, i); // This pin is used
|
||||
bool state = (XdrvMailbox.index &1);
|
||||
ButtonSetVirtualPinState(i, state); // Virtual hardware pin state
|
||||
bool invert = (XdrvMailbox.index &BUTTON_INVERT);
|
||||
if (invert) { ButtonInvertFlag(i); } // Set inverted flag
|
||||
Button.last_state[i] = (bitRead(Button.virtual_pin, i) != bitRead(Button.inverted_mask, i));
|
||||
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("BTN: Add vButton%d, State %d, Info %02X"), Button.present, Button.last_state[i], XdrvMailbox.index);
|
||||
|
||||
used = true;
|
||||
}
|
||||
}
|
||||
@ -267,6 +280,9 @@ void ButtonInit(void) {
|
||||
}
|
||||
Button.debounced_state[i] = Button.last_state[i];
|
||||
}
|
||||
|
||||
// AddLog(LOG_LEVEL_DEBUG, PSTR("BTN: vPinUsed %08X, State %08X, Invert %08X"), Button.virtual_pin_used, Button.virtual_pin, Button.inverted_mask);
|
||||
|
||||
if (Button.present) {
|
||||
Button.first_change = true;
|
||||
TickerButton.attach_ms((ac_detect) ? BUTTON_FAST_PROBE_INTERVAL : BUTTON_PROBE_INTERVAL, ButtonProbe);
|
||||
@ -371,6 +387,7 @@ void ButtonHandler(void) {
|
||||
if (button_present) {
|
||||
XdrvMailbox.index = button_index;
|
||||
XdrvMailbox.payload = button;
|
||||
XdrvMailbox.command_code = Button.last_state[button_index];
|
||||
if (XdrvCall(FUNC_BUTTON_PRESSED)) {
|
||||
// Serviced
|
||||
}
|
||||
|
@ -236,12 +236,20 @@ void SwitchInit(void) {
|
||||
else {
|
||||
XdrvMailbox.index = i;
|
||||
if (XdrvCall(FUNC_ADD_SWITCH)) {
|
||||
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SWT: Add switch %d"), i);
|
||||
|
||||
bitSet(Switch.virtual_pin_used, i);
|
||||
/*
|
||||
At entry:
|
||||
XdrvMailbox.index = switch index
|
||||
At exit:
|
||||
XdrvMailbox.index bit 0 = current state
|
||||
*/
|
||||
Switch.present++;
|
||||
Switch.last_state[i] = XdrvMailbox.payload;
|
||||
bitSet(Switch.virtual_pin_used, i); // This pin is used
|
||||
bool state = (XdrvMailbox.index &1);
|
||||
SwitchSetVirtualPinState(i, state); // Virtual hardware pin state
|
||||
Switch.last_state[i] = bitRead(Switch.virtual_pin, i);
|
||||
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SWT: Add vSwitch%d, State %d, Info %02X"), Switch.present, Switch.last_state[i], XdrvMailbox.index);
|
||||
|
||||
used = true;
|
||||
}
|
||||
}
|
||||
@ -252,6 +260,9 @@ void SwitchInit(void) {
|
||||
}
|
||||
Switch.debounced_state[i] = Switch.last_state[i];
|
||||
}
|
||||
|
||||
// AddLog(LOG_LEVEL_DEBUG, PSTR("BTN: vPinUsed %08X, State %08X"), Switch.virtual_pin_used, Switch.virtual_pin);
|
||||
|
||||
if (Switch.present) {
|
||||
Switch.first_change = true;
|
||||
TickerSwitch.attach_ms((ac_detect) ? SWITCH_FAST_PROBE_INTERVAL : SWITCH_PROBE_INTERVAL, SwitchProbe);
|
||||
|
@ -47,7 +47,6 @@ struct SPro {
|
||||
uint32_t probe_pin;
|
||||
int switch_offset;
|
||||
int button_offset;
|
||||
uint8_t last_button[3];
|
||||
uint8_t pin_register_cs;
|
||||
uint8_t pin_mcp23s17_int;
|
||||
uint8_t ledlink;
|
||||
@ -151,16 +150,6 @@ void SP4Mcp23S17Update(uint8_t pin, bool pin_value, uint8_t reg_addr) {
|
||||
}
|
||||
}
|
||||
|
||||
void SP4Mcp23S17Setup(void) {
|
||||
SP4Mcp23S17Write(SP4_MCP23S17_IOCONA, 0b01011000); // Enable INT mirror, Slew rate disabled, HAEN pins for addressing
|
||||
SP4Mcp23S17Write(SP4_MCP23S17_GPINTENA, 0x6F); // Enable interrupt on change
|
||||
SP4Mcp23S17Write(SP4_MCP23S17_GPINTENB, 0x80); // Enable interrupt on change
|
||||
|
||||
// Read current output register state
|
||||
SP4Mcp23S17Read(SP4_MCP23S17_OLATA, &sp4_mcp23s17_olata);
|
||||
SP4Mcp23S17Read(SP4_MCP23S17_OLATB, &sp4_mcp23s17_olatb);
|
||||
}
|
||||
|
||||
void SP4Mcp23S17PinMode(uint8_t pin, uint8_t flags) {
|
||||
uint8_t iodir = pin < 8 ? SP4_MCP23S17_IODIRA : SP4_MCP23S17_IODIRB;
|
||||
uint8_t gppu = pin < 8 ? SP4_MCP23S17_GPPUA : SP4_MCP23S17_GPPUB;
|
||||
@ -216,7 +205,13 @@ void ShellyPro4Init(void) {
|
||||
bit 14 = output - Relay O3
|
||||
bit 15 = input - Switch4
|
||||
*/
|
||||
SP4Mcp23S17Setup();
|
||||
SP4Mcp23S17Write(SP4_MCP23S17_IOCONA, 0b01011000); // Enable INT mirror, Slew rate disabled, HAEN pins for addressing
|
||||
SP4Mcp23S17Write(SP4_MCP23S17_GPINTENA, 0x6F); // Enable interrupt on change
|
||||
SP4Mcp23S17Write(SP4_MCP23S17_GPINTENB, 0x80); // Enable interrupt on change
|
||||
|
||||
// Read current output register state
|
||||
SP4Mcp23S17Read(SP4_MCP23S17_OLATA, &sp4_mcp23s17_olata);
|
||||
SP4Mcp23S17Read(SP4_MCP23S17_OLATB, &sp4_mcp23s17_olatb);
|
||||
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
SP4Mcp23S17PinMode(sp4_switch_pin[i], INPUT); // Switch1..4
|
||||
@ -231,7 +226,6 @@ void ShellyPro4Init(void) {
|
||||
|
||||
SP4Mcp23S17PinMode(4, OUTPUT); // Reset display, ADE7943
|
||||
SP4Mcp23S17DigitalWrite(4, 1);
|
||||
|
||||
}
|
||||
|
||||
void ShellyPro4Reset(void) {
|
||||
@ -241,30 +235,30 @@ void ShellyPro4Reset(void) {
|
||||
}
|
||||
|
||||
bool ShellyProAddButton(void) {
|
||||
if (SPro.detected != 4) { return false; }
|
||||
if (SPro.detected != 4) { return false; } // Only support Shelly Pro 4
|
||||
if (SPro.button_offset < 0) { SPro.button_offset = XdrvMailbox.index; }
|
||||
uint32_t index = XdrvMailbox.index - SPro.button_offset;
|
||||
if (index > 2) { return false; }
|
||||
XdrvMailbox.payload = SP4Mcp23S17DigitalRead(sp4_button_pin[index]);
|
||||
if (index > 2) { return false; } // Support three buttons
|
||||
XdrvMailbox.index = SP4Mcp23S17DigitalRead(sp4_button_pin[index]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShellyProAddSwitch(void) {
|
||||
if (SPro.detected != 4) { return false; }
|
||||
if (SPro.detected != 4) { return false; } // Only support Shelly Pro 4
|
||||
if (SPro.switch_offset < 0) { SPro.switch_offset = XdrvMailbox.index; }
|
||||
uint32_t index = XdrvMailbox.index - SPro.switch_offset;
|
||||
if (index > 3) { return false; }
|
||||
XdrvMailbox.payload = SP4Mcp23S17DigitalRead(sp4_switch_pin[index]);
|
||||
if (index > 3) { return false; } // Support four switches
|
||||
XdrvMailbox.index = SP4Mcp23S17DigitalRead(sp4_switch_pin[index]);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShellyProUpdateSwitches(void) {
|
||||
if (SPro.detected != 4) { return; }
|
||||
if (digitalRead(SPro.pin_mcp23s17_int)) { return; }
|
||||
if (SPro.detected != 4) { return; } // Only support Shelly Pro 4
|
||||
if (digitalRead(SPro.pin_mcp23s17_int)) { return; } // Poll interrupt
|
||||
|
||||
uint32_t gpio = SP4Mcp23S17ReadGpio();
|
||||
uint32_t gpio = SP4Mcp23S17ReadGpio(); // Read gpio and clear interrupt
|
||||
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SHP: Input detected 0x%04X"), gpio);
|
||||
// AddLog(LOG_LEVEL_DEBUG, PSTR("SHP: Input detected 0x%04X"), gpio);
|
||||
|
||||
// Propagate state
|
||||
uint32_t state;
|
||||
@ -279,14 +273,14 @@ void ShellyProUpdateSwitches(void) {
|
||||
}
|
||||
|
||||
bool ShellyProButton(void) {
|
||||
if (SPro.detected != 4) { return false; }
|
||||
if (SPro.detected != 4) { return false; } // Only support Shelly Pro 4
|
||||
|
||||
uint32_t button_index = XdrvMailbox.index - SPro.button_offset;
|
||||
if (button_index > 2) { return false; } // We only support Up, Down, Ok
|
||||
if (button_index > 2) { return false; } // Only support Up, Down, Ok
|
||||
|
||||
bool result = false;
|
||||
uint32_t button = XdrvMailbox.payload;
|
||||
if ((PRESSED == button) && (NOT_PRESSED == SPro.last_button[button_index])) { // Button pressed
|
||||
uint32_t last_state = XdrvMailbox.command_code;
|
||||
if ((PRESSED == button) && (NOT_PRESSED == last_state)) { // Button pressed
|
||||
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SHP: Button %d pressed"), button_index +1);
|
||||
|
||||
@ -299,10 +293,8 @@ bool ShellyProButton(void) {
|
||||
case 2: // Ok
|
||||
break;
|
||||
}
|
||||
result = true; // Disable further button processing
|
||||
}
|
||||
SPro.last_button[button_index] = button;
|
||||
return result;
|
||||
return true; // Disable further button processing
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
@ -323,11 +315,11 @@ void ShellyProUpdate(void) {
|
||||
*/
|
||||
uint8_t val = SPro.power | SPro.ledlink;
|
||||
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
|
||||
SPI.transfer(val); // Write 74HC595 shift register
|
||||
SPI.transfer(val); // Write 74HC595 shift register
|
||||
SPI.endTransaction();
|
||||
// delayMicroseconds(2); // Wait for SPI clock to stop
|
||||
digitalWrite(SPro.pin_register_cs, 1); // Latch data
|
||||
delayMicroseconds(1); // Shelly 10mS
|
||||
// delayMicroseconds(2); // Wait for SPI clock to stop
|
||||
digitalWrite(SPro.pin_register_cs, 1); // Latch data
|
||||
delayMicroseconds(1); // Shelly 10mS
|
||||
digitalWrite(SPro.pin_register_cs, 0);
|
||||
}
|
||||
|
||||
@ -337,18 +329,18 @@ void ShellyProUpdate(void) {
|
||||
|
||||
void ShellyProPreInit(void) {
|
||||
if ((SPI_MOSI_MISO == TasmotaGlobal.spi_enabled) &&
|
||||
PinUsed(GPIO_SPI_CS) && // 74HC595 rclk / MCP23S17
|
||||
TasmotaGlobal.gpio_optiona.shelly_pro) { // Option_A7
|
||||
PinUsed(GPIO_SPI_CS) && // 74HC595 rclk / MCP23S17
|
||||
TasmotaGlobal.gpio_optiona.shelly_pro) { // Option_A7
|
||||
|
||||
if (PinUsed(GPIO_SWT1) || PinUsed(GPIO_KEY1)) {
|
||||
SPro.detected = 1; // Shelly Pro 1
|
||||
SPro.detected = 1; // Shelly Pro 1
|
||||
if (PinUsed(GPIO_SWT1, 1) || PinUsed(GPIO_KEY1, 1)) {
|
||||
SPro.detected = 2; // Shelly Pro 2
|
||||
SPro.detected = 2; // Shelly Pro 2
|
||||
}
|
||||
SPro.ledlink = 0x18; // Blue led on - set by first call ShellyProPower() - Shelly 1/2
|
||||
SPro.ledlink = 0x18; // Blue led on - set by first call ShellyProPower() - Shelly 1/2
|
||||
}
|
||||
if (SHELLY_PRO_4_PIN_SPI_CS == Pin(GPIO_SPI_CS)) {
|
||||
SPro.detected = 4; // Shelly Pro 4PM (No SWT or KEY)
|
||||
SPro.detected = 4; // Shelly Pro 4PM (No SWT or KEY)
|
||||
}
|
||||
|
||||
if (SPro.detected) {
|
||||
@ -360,13 +352,12 @@ void ShellyProPreInit(void) {
|
||||
SPI.begin(Pin(GPIO_SPI_CLK), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_MOSI), -1);
|
||||
|
||||
if (4 == SPro.detected) {
|
||||
digitalWrite(SPro.pin_register_cs, 1);
|
||||
digitalWrite(SPro.pin_register_cs, 1); // Prep MCP23S17 chip select
|
||||
SPro.pin_mcp23s17_int = SHELLY_PRO_4_PIN_MCP23S17_INT; // GPIO35 = MCP23S17 common interrupt
|
||||
pinMode(SPro.pin_mcp23s17_int, INPUT);
|
||||
// Init MCP23S17
|
||||
ShellyPro4Init();
|
||||
ShellyPro4Init(); // Init MCP23S17
|
||||
} else {
|
||||
digitalWrite(SPro.pin_register_cs, 0);
|
||||
digitalWrite(SPro.pin_register_cs, 0); // Prep 74HC595 rclk
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -374,10 +365,10 @@ void ShellyProPreInit(void) {
|
||||
|
||||
void ShellyProInit(void) {
|
||||
int pin_lan_reset = SHELLY_PRO_PIN_LAN8720_RESET; // GPIO5 = LAN8720 nRST
|
||||
// delay(30); // (t-purstd) This pin must be brought low for a minimum of 25 mS after power on
|
||||
// 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
|
||||
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"), SPro.detected, (PinUsed(GPIO_ADE7953_CS))?"PM":"");
|
||||
@ -386,13 +377,13 @@ void ShellyProInit(void) {
|
||||
void ShellyProPower(void) {
|
||||
if (4 == SPro.detected) {
|
||||
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("SHP: Set Power 0x%08X"), XdrvMailbox.index);
|
||||
// AddLog(LOG_LEVEL_DEBUG, PSTR("SHP: Set Power 0x%08X"), XdrvMailbox.index);
|
||||
|
||||
power_t rpower = XdrvMailbox.index;
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
power_t state = rpower &1;
|
||||
SP4Mcp23S17DigitalWrite(sp4_relay_pin[i], state);
|
||||
rpower >>= 1; // Select next power
|
||||
rpower >>= 1; // Select next power
|
||||
}
|
||||
} else {
|
||||
SPro.power = XdrvMailbox.index &3;
|
||||
@ -430,12 +421,12 @@ void ShellyProLedLink(void) {
|
||||
- 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
|
||||
uint32_t ledlink = 0x1C; // All leds off
|
||||
if (XdrvMailbox.index) {
|
||||
ledlink &= 0xFB; // Blue blinks if wifi/mqtt lost
|
||||
ledlink &= 0xFB; // Blue blinks if wifi/mqtt lost
|
||||
}
|
||||
else if (!TasmotaGlobal.global_state.wifi_down) {
|
||||
ledlink &= 0xF7; // Green On
|
||||
ledlink &= 0xF7; // Green On
|
||||
}
|
||||
ShellyProUpdateLedLink(ledlink);
|
||||
}
|
||||
@ -470,9 +461,11 @@ bool Xdrv88(uint32_t function) {
|
||||
case FUNC_EVERY_50_MSECOND:
|
||||
ShellyProUpdateSwitches();
|
||||
break;
|
||||
/*
|
||||
case FUNC_BUTTON_PRESSED:
|
||||
result = ShellyProButton();
|
||||
break;
|
||||
*/
|
||||
case FUNC_EVERY_SECOND:
|
||||
ShellyProLedLinkWifiOff();
|
||||
break;
|
||||
|
@ -274,19 +274,6 @@ void Ade7953Write(uint16_t reg, uint32_t val) {
|
||||
|
||||
#ifdef USE_ESP32_SPI
|
||||
if (Ade7953.pin_cs[0] >= 0) {
|
||||
/*
|
||||
digitalWrite(Ade7953.pin_cs[Ade7953.cs_index], 0);
|
||||
delayMicroseconds(1); // CS 1uS to SCLK edge
|
||||
SPI.beginTransaction(Ade7953.spi_settings);
|
||||
SPI.transfer16(reg);
|
||||
SPI.transfer(0x00); // Write
|
||||
while (size--) {
|
||||
SPI.transfer((val >> (8 * size)) & 0xFF); // Write data, MSB first
|
||||
}
|
||||
SPI.endTransaction();
|
||||
delayMicroseconds(2); // CS high 1.2uS after SCLK edge (when writing to COMM_LOCK bit)
|
||||
digitalWrite(Ade7953.pin_cs[Ade7953.cs_index], 1);
|
||||
*/
|
||||
Ade7953SpiEnable();
|
||||
SPI.transfer16(reg);
|
||||
SPI.transfer(0x00); // Write
|
||||
@ -294,7 +281,6 @@ void Ade7953Write(uint16_t reg, uint32_t val) {
|
||||
SPI.transfer((val >> (8 * size)) & 0xFF); // Write data, MSB first
|
||||
}
|
||||
Ade7953SpiDisable();
|
||||
|
||||
} else {
|
||||
#endif // USE_ESP32_SPI
|
||||
Wire.beginTransmission(ADE7953_ADDR);
|
||||
@ -318,18 +304,6 @@ int32_t Ade7953Read(uint16_t reg) {
|
||||
if (size) {
|
||||
#ifdef USE_ESP32_SPI
|
||||
if (Ade7953.pin_cs[0] >= 0) {
|
||||
/*
|
||||
digitalWrite(Ade7953.pin_cs[Ade7953.cs_index], 0);
|
||||
delayMicroseconds(1); // CS 1uS to SCLK edge
|
||||
SPI.beginTransaction(Ade7953.spi_settings);
|
||||
SPI.transfer16(reg);
|
||||
SPI.transfer(0x80); // Read
|
||||
while (size--) {
|
||||
response = response << 8 | SPI.transfer(0); // receive DATA (MSB first)
|
||||
}
|
||||
SPI.endTransaction();
|
||||
digitalWrite(Ade7953.pin_cs[Ade7953.cs_index], 1);
|
||||
*/
|
||||
Ade7953SpiEnable();
|
||||
SPI.transfer16(reg);
|
||||
SPI.transfer(0x80); // Read
|
||||
@ -337,7 +311,6 @@ int32_t Ade7953Read(uint16_t reg) {
|
||||
response = response << 8 | SPI.transfer(0xFF); // receive DATA (MSB first)
|
||||
}
|
||||
Ade7953SpiDisable();
|
||||
|
||||
} else {
|
||||
#endif // USE_ESP32_SPI
|
||||
Wire.beginTransmission(ADE7953_ADDR);
|
||||
|
Loading…
x
Reference in New Issue
Block a user