mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-23 18:56:38 +00:00
Bump version v12.3.1.6
- Add ESP32 preliminary support for Matter protocol, milestone 1 (commissioning) by Stephan Hadinger - Add basic support for Shelly Pro 4PM
This commit is contained in:
parent
5025e86d75
commit
8bc03bbc06
18
CHANGELOG.md
18
CHANGELOG.md
@ -3,15 +3,27 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
## [Unreleased] - Development
|
## [Unreleased] - Development
|
||||||
|
|
||||||
|
## [12.3.1.6]
|
||||||
|
### Added
|
||||||
|
- ESP32 preliminary support for Matter protocol, milestone 1 (commissioning) by Stephan Hadinger
|
||||||
|
- Basic support for Shelly Pro 4PM
|
||||||
|
|
||||||
|
### Breaking Changed
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
## [12.3.1.5]
|
## [12.3.1.5]
|
||||||
### Added
|
### Added
|
||||||
- ESP32 support for eigth energy phases/channels
|
- ESP32 support for eigth energy phases/channels
|
||||||
- ESP32 command ``EnergyCols 1..8`` to change number of GUI columns
|
- ESP32 command ``EnergyCols 1..8`` to change number of GUI columns
|
||||||
- ESP32 command ``EnergyDisplay 1..3`` to change GUI column presentation
|
- ESP32 command ``EnergyDisplay 1..3`` to change GUI column presentation
|
||||||
- support for SEN5X gas and air quality sensor by Tyeth Gundry (#17736)
|
- Support for SEN5X gas and air quality sensor by Tyeth Gundry (#17736)
|
||||||
- Berry add ``mdns`` advanced features and query
|
- Berry add ``mdns`` advanced features and query
|
||||||
- ESP32 support for Biomine BioPDU 625x12 (#17857)
|
- ESP32 support for Biomine BioPDU 625x12 (#17857)
|
||||||
- ESP32 preliminary support for Matter protocol, milestone 1 (commissioning)
|
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
- Berry energy_ctypes changed with new energy driver
|
- Berry energy_ctypes changed with new energy driver
|
||||||
@ -27,8 +39,6 @@ All notable changes to this project will be documented in this file.
|
|||||||
- Broken I2C priority regression from v12.3.1.3 (#17810)
|
- Broken I2C priority regression from v12.3.1.3 (#17810)
|
||||||
- Energy usage and return migrated too small (/10000) regression from v12.3.1.3
|
- Energy usage and return migrated too small (/10000) regression from v12.3.1.3
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
## [12.3.1.4] 20230127
|
## [12.3.1.4] 20230127
|
||||||
### Added
|
### Added
|
||||||
- Berry ``crypto.EC_P256`` ECDSA signature (required by Matter protocol)
|
- Berry ``crypto.EC_P256`` ECDSA signature (required by Matter protocol)
|
||||||
|
@ -110,24 +110,28 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
|
|||||||
|
|
||||||
[Complete list](BUILDS.md) of available feature and sensors.
|
[Complete list](BUILDS.md) of available feature and sensors.
|
||||||
|
|
||||||
## Changelog v12.3.1.5
|
## Changelog v12.3.1.6
|
||||||
### Added
|
### Added
|
||||||
- Support for up to 3 single phase modbus energy monitoring device using generic Energy Modbus driver- Support for RGB displays [#17414](https://github.com/arendst/Tasmota/issues/17414)
|
- Support for up to 3 (ESP8266) or 8 (ESP32) phase modbus energy monitoring device using generic Energy Modbus driver
|
||||||
|
- Support for RGB displays [#17414](https://github.com/arendst/Tasmota/issues/17414)
|
||||||
- Support for IPv6 DNS records (AAAA) and IPv6 ``Ping`` for ESP32 and ESP8266 [#17417](https://github.com/arendst/Tasmota/issues/17417)
|
- Support for IPv6 DNS records (AAAA) and IPv6 ``Ping`` for ESP32 and ESP8266 [#17417](https://github.com/arendst/Tasmota/issues/17417)
|
||||||
- Support for IPv6 only networks on Ethernet (not yet Wifi)
|
- Support for IPv6 only networks on Ethernet (not yet Wifi)
|
||||||
- Support for TM1650 display as used in some clocks by Stefan Oskamp [#17594](https://github.com/arendst/Tasmota/issues/17594)
|
- Support for TM1650 display as used in some clocks by Stefan Oskamp [#17594](https://github.com/arendst/Tasmota/issues/17594)
|
||||||
- Support for PCA9632 4-channel 8-bit PWM driver as light driver by Pascal Heinrich [#17557](https://github.com/arendst/Tasmota/issues/17557)
|
- Support for PCA9632 4-channel 8-bit PWM driver as light driver by Pascal Heinrich [#17557](https://github.com/arendst/Tasmota/issues/17557)
|
||||||
- support for SEN5X gas and air quality sensor by Tyeth Gundry [#17736](https://github.com/arendst/Tasmota/issues/17736)
|
- support for SEN5X gas and air quality sensor by Tyeth Gundry [#17736](https://github.com/arendst/Tasmota/issues/17736)
|
||||||
|
- Basic support for Shelly Pro 4PM
|
||||||
- Berry support for ``crypto.SHA256`` [#17430](https://github.com/arendst/Tasmota/issues/17430)
|
- Berry support for ``crypto.SHA256`` [#17430](https://github.com/arendst/Tasmota/issues/17430)
|
||||||
- Berry crypto add ``EC_P256`` and ``PBKDF2_HMAC_SHA256`` algorithms required by Matter protocol [#17473](https://github.com/arendst/Tasmota/issues/17473)
|
- Berry crypto add ``EC_P256`` and ``PBKDF2_HMAC_SHA256`` algorithms required by Matter protocol [#17473](https://github.com/arendst/Tasmota/issues/17473)
|
||||||
- Berry crypto add ``random`` to generate series of random bytes
|
- Berry crypto add ``random`` to generate series of random bytes
|
||||||
- Berry crypto add ``HKDF_HMAC_SHA256``
|
- Berry crypto add ``HKDF_HMAC_SHA256``
|
||||||
- Berry crypto add ``SPAKE2P_Matter`` for Matter support
|
- Berry crypto add ``SPAKE2P_Matter`` for Matter support
|
||||||
|
- Berry add ``mdns`` advanced features and query
|
||||||
- ESP32 command ``EnergyCols 1..8`` to change number of GUI columns
|
- ESP32 command ``EnergyCols 1..8`` to change number of GUI columns
|
||||||
- ESP32 command ``EnergyDisplay 1..3`` to change GUI column presentation
|
- ESP32 command ``EnergyDisplay 1..3`` to change GUI column presentation
|
||||||
- ESP32 support for eigth energy phases/channels
|
- ESP32 support for eigth energy phases/channels
|
||||||
- ESP32 support for BMPxxx sensors on two I2C busses [#17643](https://github.com/arendst/Tasmota/issues/17643)
|
- ESP32 support for BMPxxx sensors on two I2C busses [#17643](https://github.com/arendst/Tasmota/issues/17643)
|
||||||
- ESP32 support for Biomine BioPDU 625x12 [#17857](https://github.com/arendst/Tasmota/issues/17857)
|
- ESP32 support for Biomine BioPDU 625x12 [#17857](https://github.com/arendst/Tasmota/issues/17857)
|
||||||
|
- ESP32 preliminary support for Matter protocol, milestone 1 (commissioning) by Stephan Hadinger
|
||||||
|
|
||||||
### Breaking Changed
|
### Breaking Changed
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
|||||||
uint32_t stop_flash_rotate : 1; // bit 12 (v5.2.0) - SetOption12 - (Settings) Switch between dynamic (0) or fixed (1) slot flash save location
|
uint32_t stop_flash_rotate : 1; // bit 12 (v5.2.0) - SetOption12 - (Settings) Switch between dynamic (0) or fixed (1) slot flash save location
|
||||||
uint32_t button_single : 1; // bit 13 (v5.4.0) - SetOption13 - (Button) Support only single press (1) to speed up button press recognition
|
uint32_t button_single : 1; // bit 13 (v5.4.0) - SetOption13 - (Button) Support only single press (1) to speed up button press recognition
|
||||||
uint32_t interlock : 1; // bit 14 (v5.6.0) - CMND_INTERLOCK - Enable (1) /disable (0) interlock
|
uint32_t interlock : 1; // bit 14 (v5.6.0) - CMND_INTERLOCK - Enable (1) /disable (0) interlock
|
||||||
uint32_t pwm_control : 1; // bit 15 (v5.8.1) - SetOption15 - (Light) Switch between commands PWM (1) or COLOR/DIMMER/CT/CHANNEL (0)
|
uint32_t pwm_control : 1; // bit 15 (v5.8.1) - SetOption15 - (Light) Switch between commands PWM (0) or COLOR/DIMMER/CT/CHANNEL (1)
|
||||||
uint32_t ws_clock_reverse : 1; // bit 16 (v5.8.1) - SetOption16 - (WS2812) Switch between clockwise (0) or counter-clockwise (1)
|
uint32_t ws_clock_reverse : 1; // bit 16 (v5.8.1) - SetOption16 - (WS2812) Switch between clockwise (0) or counter-clockwise (1)
|
||||||
uint32_t decimal_text : 1; // bit 17 (v5.8.1) - SetOption17 - (Light) Switch between decimal (1) or hexadecimal (0) output
|
uint32_t decimal_text : 1; // bit 17 (v5.8.1) - SetOption17 - (Light) Switch between decimal (1) or hexadecimal (0) output
|
||||||
uint32_t light_signal : 1; // bit 18 (v5.10.0c) - SetOption18 - (Light) Pair light signal (1) with CO2 sensor
|
uint32_t light_signal : 1; // bit 18 (v5.10.0c) - SetOption18 - (Light) Pair light signal (1) with CO2 sensor
|
||||||
|
@ -20,6 +20,6 @@
|
|||||||
#ifndef _TASMOTA_VERSION_H_
|
#ifndef _TASMOTA_VERSION_H_
|
||||||
#define _TASMOTA_VERSION_H_
|
#define _TASMOTA_VERSION_H_
|
||||||
|
|
||||||
const uint32_t VERSION = 0x0C030105; // 12.3.1.5
|
const uint32_t VERSION = 0x0C030106; // 12.3.1.6
|
||||||
|
|
||||||
#endif // _TASMOTA_VERSION_H_
|
#endif // _TASMOTA_VERSION_H_
|
||||||
|
@ -873,8 +873,9 @@ void ResponseAppendFeatures(void)
|
|||||||
#if defined(USE_I2C) && defined(USE_SEN5X)
|
#if defined(USE_I2C) && defined(USE_SEN5X)
|
||||||
feature9 |= 0x00008000; // xsns_103_sen5x.ino
|
feature9 |= 0x00008000; // xsns_103_sen5x.ino
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(USE_ENERGY_SENSOR) && defined(USE_BIOPDU)
|
||||||
// feature9 |= 0x00010000;
|
feature9 |= 0x00010000; // xnrg_24_biopdu.ino
|
||||||
|
#endif
|
||||||
// feature9 |= 0x00020000;
|
// feature9 |= 0x00020000;
|
||||||
// feature9 |= 0x00040000;
|
// feature9 |= 0x00040000;
|
||||||
// feature9 |= 0x00080000;
|
// feature9 |= 0x00080000;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
xdrv_88_shelly_pro.ino - Shelly pro family support for Tasmota
|
xdrv_88_esp32_shelly_pro.ino - Shelly pro family support for Tasmota
|
||||||
|
|
||||||
Copyright (C) 2022 Theo Arends
|
Copyright (C) 2022 Theo Arends
|
||||||
|
|
||||||
@ -19,86 +19,393 @@
|
|||||||
|
|
||||||
#ifdef ESP32
|
#ifdef ESP32
|
||||||
#ifdef USE_SPI
|
#ifdef USE_SPI
|
||||||
#ifdef USE_SHELLY_PRO_V1
|
#ifdef USE_SHELLY_PRO
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Shelly Pro support
|
* 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 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,5600,4700,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 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,5600,4700,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 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,5600,4700,3350;AdcParam2 2,5600,4700,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"}
|
* {"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,5600,4700,3350;AdcParam2 2,5600,4700,3350"}
|
||||||
|
* {"NAME":"Shelly Pro 4PM","GPIO":[0,6210,0,6214,9568,0,0,0,0,0,9569,0,768,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,736,704,3461,0,4736,0,0,672],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,5600,4700,3350"}
|
||||||
*
|
*
|
||||||
* Shelly Pro uses SPI to control one 74HC595 for relays/leds and one ADE7953 (1PM) or two ADE7953 (2PM) for energy monitoring
|
* Shelly Pro 1/2 uses SPI to control one 74HC595 for relays/leds and one ADE7953 (1PM) or two ADE7953 (2PM) for energy monitoring
|
||||||
|
* Shelly Pro 4 uses an SPI to control one MCP23S17 for buttons/switches/relays/leds and two ADE7953 for energy monitoring and a second SPI for the display
|
||||||
|
* To use display enable defines USE_DISPLAY, USE_UNIVERSAL_DISPLAY and SHOW_SPLASH. Load file ST7735S_Pro4PM_display.ini as display.ini
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
#define XDRV_88 88
|
#define XDRV_88 88
|
||||||
|
|
||||||
|
#define SHELLY_PRO_PIN_LAN8720_RESET 5
|
||||||
|
#define SHELLY_PRO_4_PIN_SPI_CS 16
|
||||||
|
#define SHELLY_PRO_4_PIN_MCP23S17_INT 35
|
||||||
|
#define SHELLY_PRO_4_MCP23S17_ADDRESS 0x40
|
||||||
|
|
||||||
struct SPro {
|
struct SPro {
|
||||||
uint32_t last_update;
|
uint32_t last_update;
|
||||||
uint8_t pin_shift595_rclk;
|
uint16_t input_state;
|
||||||
|
int8_t switch_offset;
|
||||||
|
int8_t button_offset;
|
||||||
|
uint8_t pin_register_cs;
|
||||||
|
uint8_t pin_mcp23s17_int;
|
||||||
uint8_t ledlink;
|
uint8_t ledlink;
|
||||||
uint8_t power;
|
uint8_t power;
|
||||||
bool detected;
|
bool init_done;
|
||||||
|
uint8_t detected;
|
||||||
} SPro;
|
} SPro;
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Shelly Pro MCP23S17 support
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
enum SP4MCP23X17GPIORegisters {
|
||||||
|
// A side
|
||||||
|
SP4_MCP23S17_IODIRA = 0x00,
|
||||||
|
SP4_MCP23S17_IPOLA = 0x02,
|
||||||
|
SP4_MCP23S17_GPINTENA = 0x04,
|
||||||
|
SP4_MCP23S17_DEFVALA = 0x06,
|
||||||
|
SP4_MCP23S17_INTCONA = 0x08,
|
||||||
|
SP4_MCP23S17_IOCONA = 0x0A,
|
||||||
|
SP4_MCP23S17_GPPUA = 0x0C,
|
||||||
|
SP4_MCP23S17_INTFA = 0x0E,
|
||||||
|
SP4_MCP23S17_INTCAPA = 0x10,
|
||||||
|
SP4_MCP23S17_GPIOA = 0x12,
|
||||||
|
SP4_MCP23S17_OLATA = 0x14,
|
||||||
|
// B side
|
||||||
|
SP4_MCP23S17_IODIRB = 0x01,
|
||||||
|
SP4_MCP23S17_IPOLB = 0x03,
|
||||||
|
SP4_MCP23S17_GPINTENB = 0x05,
|
||||||
|
SP4_MCP23S17_DEFVALB = 0x07,
|
||||||
|
SP4_MCP23S17_INTCONB = 0x09,
|
||||||
|
SP4_MCP23S17_IOCONB = 0x0B,
|
||||||
|
SP4_MCP23S17_GPPUB = 0x0D,
|
||||||
|
SP4_MCP23S17_INTFB = 0x0F,
|
||||||
|
SP4_MCP23S17_INTCAPB = 0x11,
|
||||||
|
SP4_MCP23S17_GPIOB = 0x13,
|
||||||
|
SP4_MCP23S17_OLATB = 0x15,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t sp4_mcp23s17_olata = 0;
|
||||||
|
uint8_t sp4_mcp23s17_olatb = 0;
|
||||||
|
|
||||||
|
void SP4Mcp23S17Enable(void) {
|
||||||
|
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
|
||||||
|
digitalWrite(SPro.pin_register_cs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SP4Mcp23S17Disable(void) {
|
||||||
|
SPI.endTransaction();
|
||||||
|
digitalWrite(SPro.pin_register_cs, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SP4Mcp23S17Read16(uint8_t reg) {
|
||||||
|
// Read 16-bit registers: (regb << 8) | rega
|
||||||
|
SP4Mcp23S17Enable();
|
||||||
|
SPI.transfer(SHELLY_PRO_4_MCP23S17_ADDRESS | 1);
|
||||||
|
SPI.transfer(reg);
|
||||||
|
uint32_t value = SPI.transfer(0xFF); // RegA
|
||||||
|
value |= (SPI.transfer(0xFF) << 8); // RegB
|
||||||
|
SP4Mcp23S17Disable();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SP4Mcp23S17Read(uint8_t reg) {
|
||||||
|
SP4Mcp23S17Enable();
|
||||||
|
SPI.transfer(SHELLY_PRO_4_MCP23S17_ADDRESS | 1);
|
||||||
|
SPI.transfer(reg);
|
||||||
|
uint32_t value = SPI.transfer(0xFF);
|
||||||
|
SP4Mcp23S17Disable();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SP4Mcp23S17Write(uint8_t reg, uint8_t value) {
|
||||||
|
SP4Mcp23S17Enable();
|
||||||
|
SPI.transfer(SHELLY_PRO_4_MCP23S17_ADDRESS);
|
||||||
|
SPI.transfer(reg);
|
||||||
|
SPI.transfer(value);
|
||||||
|
SP4Mcp23S17Disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SP4Mcp23S17Update(uint8_t pin, bool pin_value, uint8_t reg_addr) {
|
||||||
|
uint8_t bit = pin % 8;
|
||||||
|
uint8_t reg_value = 0;
|
||||||
|
if (reg_addr == SP4_MCP23S17_OLATA) {
|
||||||
|
reg_value = sp4_mcp23s17_olata;
|
||||||
|
} else if (reg_addr == SP4_MCP23S17_OLATB) {
|
||||||
|
reg_value = sp4_mcp23s17_olatb;
|
||||||
|
} else {
|
||||||
|
reg_value = SP4Mcp23S17Read(reg_addr);
|
||||||
|
}
|
||||||
|
if (pin_value) {
|
||||||
|
reg_value |= 1 << bit;
|
||||||
|
} else {
|
||||||
|
reg_value &= ~(1 << bit);
|
||||||
|
}
|
||||||
|
SP4Mcp23S17Write(reg_addr, reg_value);
|
||||||
|
if (reg_addr == SP4_MCP23S17_OLATA) {
|
||||||
|
sp4_mcp23s17_olata = reg_value;
|
||||||
|
} else if (reg_addr == SP4_MCP23S17_OLATB) {
|
||||||
|
sp4_mcp23s17_olatb = reg_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
if (flags == INPUT) {
|
||||||
|
SP4Mcp23S17Update(pin, true, iodir);
|
||||||
|
SP4Mcp23S17Update(pin, false, gppu);
|
||||||
|
} else if (flags == (INPUT | PULLUP)) {
|
||||||
|
SP4Mcp23S17Update(pin, true, iodir);
|
||||||
|
SP4Mcp23S17Update(pin, true, gppu);
|
||||||
|
} else if (flags == OUTPUT) {
|
||||||
|
SP4Mcp23S17Update(pin, false, iodir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SP4Mcp23S17DigitalRead(uint8_t pin) {
|
||||||
|
uint8_t bit = pin % 8;
|
||||||
|
uint8_t reg_addr = pin < 8 ? SP4_MCP23S17_GPIOA : SP4_MCP23S17_GPIOB;
|
||||||
|
uint8_t value = SP4Mcp23S17Read(reg_addr);
|
||||||
|
return value & (1 << bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SP4Mcp23S17DigitalWrite(uint8_t pin, bool value) {
|
||||||
|
uint8_t reg_addr = pin < 8 ? SP4_MCP23S17_OLATA : SP4_MCP23S17_OLATB;
|
||||||
|
SP4Mcp23S17Update(pin, value, reg_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Shelly Pro 4
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
const uint8_t sp4_relay_pin[] = { 8, 13, 14, 12 };
|
||||||
|
const uint8_t sp4_switch_pin[] = { 6, 1, 0, 15 };
|
||||||
|
const uint8_t sp4_button_pin[] = { 5, 2, 3 };
|
||||||
|
|
||||||
|
void ShellyPro4Init(void) {
|
||||||
|
/*
|
||||||
|
Shelly Pro 4PM MCP23S17 registers
|
||||||
|
bit 0 = input, inverted - Switch3
|
||||||
|
bit 1 = input, inverted - Switch2
|
||||||
|
bit 2 = input - Button Down
|
||||||
|
bit 3 = input - Button OK
|
||||||
|
bit 4 = output - Reset, display, ADE7953
|
||||||
|
bit 5 = input - Button Up
|
||||||
|
bit 6 = input, inverted - Switch1
|
||||||
|
bit 7
|
||||||
|
bit 8 = output - Relay O1
|
||||||
|
bit 9
|
||||||
|
bit 10
|
||||||
|
bit 11
|
||||||
|
bit 12 = output - Relay O4
|
||||||
|
bit 13 = output - Relay O2
|
||||||
|
bit 14 = output - Relay O3
|
||||||
|
bit 15 = input, inverted - Switch4
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
sp4_mcp23s17_olata = SP4Mcp23S17Read(SP4_MCP23S17_OLATA);
|
||||||
|
sp4_mcp23s17_olatb = SP4Mcp23S17Read(SP4_MCP23S17_OLATB);
|
||||||
|
|
||||||
|
SP4Mcp23S17PinMode(4, OUTPUT); // Reset display, ADE7943
|
||||||
|
SP4Mcp23S17DigitalWrite(4, 1);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < 3; i++) {
|
||||||
|
SP4Mcp23S17PinMode(sp4_button_pin[i], INPUT); // Button Up, Down, OK (RC with 10k to 3V3 and button shorting C)
|
||||||
|
}
|
||||||
|
SPro.button_offset = -1;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < 4; i++) {
|
||||||
|
SP4Mcp23S17PinMode(sp4_switch_pin[i], INPUT); // Switch1..4
|
||||||
|
SP4Mcp23S17PinMode(sp4_relay_pin[i], OUTPUT); // Relay O1..O4
|
||||||
|
}
|
||||||
|
SPro.switch_offset = -1;
|
||||||
|
|
||||||
|
// Read current input register state
|
||||||
|
SPro.input_state = SP4Mcp23S17Read16(SP4_MCP23S17_GPIOA) & 0x806F; // Read gpio and clear interrupt
|
||||||
|
attachInterrupt(SPro.pin_mcp23s17_int, ShellyProUpdateIsr, CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShellyPro4Reset(void) {
|
||||||
|
SP4Mcp23S17DigitalWrite(4, 0); // Reset pin display, ADE7953
|
||||||
|
delay(1); // To initiate a hardware reset, this pin must be brought low for a minimum of 10 μs.
|
||||||
|
SP4Mcp23S17DigitalWrite(4, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShellyProAddButton(void) {
|
||||||
|
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; } // Support three buttons
|
||||||
|
uint32_t state = bitRead(SPro.input_state, sp4_button_pin[index]); // 1 on power on and restart
|
||||||
|
XdrvMailbox.index = state;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShellyProAddSwitch(void) {
|
||||||
|
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; } // Support four switches
|
||||||
|
uint32_t state = bitRead(SPro.input_state, sp4_switch_pin[index]); // 0 on power on and restart
|
||||||
|
XdrvMailbox.index = state ^1; // Invert
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShellyProUpdateIsr(void) {
|
||||||
|
/*
|
||||||
|
The goal if this function is to minimize SPI and SetVirtualPinState calls
|
||||||
|
*/
|
||||||
|
uint32_t input_state = SP4Mcp23S17Read16(SP4_MCP23S17_INTCAPA); // Read intcap and clear interrupt
|
||||||
|
input_state &= 0x806F; // Only test input bits
|
||||||
|
|
||||||
|
// AddLog(LOG_LEVEL_DEBUG, PSTR("SHP: Input from %04X to %04X"), SPro.input_state, input_state);
|
||||||
|
|
||||||
|
if (TasmotaGlobal.uptime < 3) { return; } // Flush interrupt for 3 seconds after poweron
|
||||||
|
|
||||||
|
uint32_t mask = 1;
|
||||||
|
for (uint32_t j = 0; j < 16; j++) {
|
||||||
|
if ((input_state & mask) != (SPro.input_state & mask)) {
|
||||||
|
uint32_t state = (input_state >> j) &1;
|
||||||
|
|
||||||
|
// AddLog(LOG_LEVEL_DEBUG, PSTR("SHP: Change pin %d to %d"), j, state);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < 4; i++) {
|
||||||
|
if (j == sp4_switch_pin[i]) {
|
||||||
|
SwitchSetVirtualPinState(SPro.switch_offset +i, state ^1); // Invert
|
||||||
|
}
|
||||||
|
else if ((i < 3) && (j == sp4_button_pin[i])) {
|
||||||
|
ButtonSetVirtualPinState(SPro.button_offset +i, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mask <<= 1;
|
||||||
|
}
|
||||||
|
SPro.input_state = input_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShellyProButton(void) {
|
||||||
|
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; } // Only support Up, Down, Ok
|
||||||
|
|
||||||
|
uint32_t button = XdrvMailbox.payload;
|
||||||
|
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);
|
||||||
|
|
||||||
|
// Do something with the Up,Down,Ok button
|
||||||
|
switch (button_index) {
|
||||||
|
case 0: // Up
|
||||||
|
break;
|
||||||
|
case 1: // Down
|
||||||
|
break;
|
||||||
|
case 2: // Ok
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true; // Disable further button processing
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Shelly Pro 1/2
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
void ShellyProUpdate(void) {
|
void ShellyProUpdate(void) {
|
||||||
// Shelly Pro 595 register
|
/*
|
||||||
// bit 0 = relay/led 1
|
Shelly Pro 1/2/PM 74HC595 register
|
||||||
// bit 1 = relay/led 2
|
bit 0 = relay/led 1
|
||||||
// bit 2 = wifi led blue
|
bit 1 = relay/led 2
|
||||||
// bit 3 = wifi led green
|
bit 2 = wifi led blue
|
||||||
// bit 4 = wifi led red
|
bit 3 = wifi led green
|
||||||
// bit 5 - 7 = nc
|
bit 4 = wifi led red
|
||||||
// OE is connected to Gnd with 470 ohm resistor R62 AND a capacitor C81 to 3V3
|
bit 5 - 7 = nc
|
||||||
// - this inhibits output of signals (also relay state) during power on for a few seconds
|
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;
|
uint8_t val = SPro.power | SPro.ledlink;
|
||||||
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
|
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
|
||||||
SPI.transfer(val); // Write 74HC595 shift register
|
SPI.transfer(val); // Write 74HC595 shift register
|
||||||
SPI.endTransaction();
|
SPI.endTransaction();
|
||||||
// delayMicroseconds(2); // Wait for SPI clock to stop
|
// delayMicroseconds(2); // Wait for SPI clock to stop
|
||||||
digitalWrite(SPro.pin_shift595_rclk, 1); // Latch data
|
digitalWrite(SPro.pin_register_cs, 1); // Latch data
|
||||||
delayMicroseconds(1); // Shelly 10mS
|
delayMicroseconds(1); // Shelly 10mS
|
||||||
digitalWrite(SPro.pin_shift595_rclk, 0);
|
digitalWrite(SPro.pin_register_cs, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Shelly Pro
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
void ShellyProPreInit(void) {
|
void ShellyProPreInit(void) {
|
||||||
if ((SPI_MOSI_MISO == TasmotaGlobal.spi_enabled) &&
|
if ((SPI_MOSI_MISO == TasmotaGlobal.spi_enabled) &&
|
||||||
PinUsed(GPIO_SPI_CS) &&
|
PinUsed(GPIO_SPI_CS) && // 74HC595 rclk / MCP23S17
|
||||||
TasmotaGlobal.gpio_optiona.shelly_pro) { // Option_A7
|
TasmotaGlobal.gpio_optiona.shelly_pro) { // Option_A7
|
||||||
|
|
||||||
if (PinUsed(GPIO_SWT1) || PinUsed(GPIO_KEY1)) {
|
if (PinUsed(GPIO_SWT1) || PinUsed(GPIO_KEY1)) {
|
||||||
TasmotaGlobal.devices_present++; // Shelly Pro 1
|
SPro.detected = 1; // Shelly Pro 1
|
||||||
if (PinUsed(GPIO_SWT1, 1) || PinUsed(GPIO_KEY1, 1)) {
|
if (PinUsed(GPIO_SWT1, 1) || PinUsed(GPIO_KEY1, 1)) {
|
||||||
TasmotaGlobal.devices_present++; // Shelly Pro 2
|
SPro.detected = 2; // Shelly Pro 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.pin_shift595_rclk = Pin(GPIO_SPI_CS);
|
if (SPro.detected) {
|
||||||
digitalWrite(SPro.pin_shift595_rclk, 0);
|
TasmotaGlobal.devices_present += SPro.detected;
|
||||||
pinMode(SPro.pin_shift595_rclk, OUTPUT);
|
|
||||||
|
SPro.pin_register_cs = Pin(GPIO_SPI_CS);
|
||||||
|
digitalWrite(SPro.pin_register_cs, (4 == SPro.detected) ? 1 : 0); // Prep 74HC595 rclk
|
||||||
|
pinMode(SPro.pin_register_cs, OUTPUT);
|
||||||
// Does nothing if SPI is already initiated (by ADE7953) so no harm done
|
// 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);
|
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()
|
if (4 == SPro.detected) {
|
||||||
SPro.detected = true;
|
SPro.pin_mcp23s17_int = SHELLY_PRO_4_PIN_MCP23S17_INT; // GPIO35 = MCP23S17 common interrupt
|
||||||
|
pinMode(SPro.pin_mcp23s17_int, INPUT);
|
||||||
|
ShellyPro4Init(); // Init MCP23S17
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShellyProInit(void) {
|
void ShellyProInit(void) {
|
||||||
int pin_lan_reset = 5; // GPIO5 = LAN8720 nRST
|
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);
|
digitalWrite(pin_lan_reset, 0);
|
||||||
pinMode(pin_lan_reset, OUTPUT);
|
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);
|
digitalWrite(pin_lan_reset, 1);
|
||||||
|
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("HDW: Shelly Pro %d%s initialized"),
|
AddLog(LOG_LEVEL_INFO, PSTR("HDW: Shelly Pro %d%s initialized"),
|
||||||
TasmotaGlobal.devices_present, (PinUsed(GPIO_ADE7953_CS))?"PM":"");
|
SPro.detected, (PinUsed(GPIO_ADE7953_CS))?"PM":"");
|
||||||
|
|
||||||
|
SPro.init_done = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShellyProPower(void) {
|
void ShellyProPower(void) {
|
||||||
SPro.power = XdrvMailbox.index &3;
|
if (SPro.detected != 4) {
|
||||||
ShellyProUpdate();
|
SPro.power = XdrvMailbox.index &3;
|
||||||
|
ShellyProUpdate();
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShellyProUpdateLedLink(uint32_t ledlink) {
|
void ShellyProUpdateLedLink(uint32_t ledlink) {
|
||||||
@ -109,37 +416,42 @@ void ShellyProUpdateLedLink(uint32_t ledlink) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ShellyProLedLink(void) {
|
void ShellyProLedLink(void) {
|
||||||
/*
|
if (!SPro.init_done) { return; } // Block write before first power update
|
||||||
bit 2 = blue, 3 = green, 4 = red
|
if (SPro.detected != 4) {
|
||||||
Shelly Pro documentation
|
/*
|
||||||
- Blue light indicator will be on if in AP mode.
|
bit 2 = blue, 3 = green, 4 = red
|
||||||
- Red light indicator will be on if in STA mode and not connected to a Wi-Fi network.
|
Shelly Pro documentation
|
||||||
- Yellow light indicator will be on if in STA mode and connected to a Wi-Fi network.
|
- Blue light indicator will be on if in AP mode.
|
||||||
- Green light indicator will be on if in STA mode and connected to a Wi-Fi network and to the Shelly Cloud.
|
- Red light indicator will be on if in STA mode and not connected to a Wi-Fi network.
|
||||||
- The light indicator will be flashing Red/Blue if OTA update is in progress.
|
- Yellow light indicator will be on if in STA mode and connected to a Wi-Fi network.
|
||||||
Tasmota behaviour
|
- Green light indicator will be on if in STA mode and connected to a Wi-Fi network and to the Shelly Cloud.
|
||||||
- Blue light indicator will blink if no wifi or mqtt.
|
- The light indicator will be flashing Red/Blue if OTA update is in progress.
|
||||||
- Green light indicator will be on if in STA mode and connected to a Wi-Fi network.
|
Tasmota behaviour
|
||||||
*/
|
- Blue light indicator will blink if no wifi or mqtt.
|
||||||
SPro.last_update = TasmotaGlobal.uptime;
|
- Green light indicator will be on if in STA mode and connected to a Wi-Fi network.
|
||||||
uint32_t ledlink = 0x1C; // All leds off
|
*/
|
||||||
if (XdrvMailbox.index) {
|
SPro.last_update = TasmotaGlobal.uptime;
|
||||||
ledlink &= 0xFB; // Blue blinks if wifi/mqtt lost
|
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);
|
||||||
}
|
}
|
||||||
else if (!TasmotaGlobal.global_state.wifi_down) {
|
|
||||||
ledlink &= 0xF7; // Green On
|
|
||||||
}
|
|
||||||
|
|
||||||
ShellyProUpdateLedLink(ledlink);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShellyProLedLinkWifiOff(void) {
|
void ShellyProLedLinkWifiOff(void) {
|
||||||
/*
|
if (!SPro.init_done) { return; }
|
||||||
bit 2 = blue, 3 = green, 4 = red
|
if (SPro.detected != 4) {
|
||||||
- Green light indicator will be on if in STA mode and connected to a Wi-Fi network.
|
/*
|
||||||
*/
|
bit 2 = blue, 3 = green, 4 = red
|
||||||
if (SPro.last_update +1 < TasmotaGlobal.uptime) {
|
- Green light indicator will be on if in STA mode and connected to a Wi-Fi network.
|
||||||
ShellyProUpdateLedLink((TasmotaGlobal.global_state.wifi_down) ? 0x1C : 0x14); // Green off if wifi OFF
|
*/
|
||||||
|
if (SPro.last_update +1 < TasmotaGlobal.uptime) {
|
||||||
|
ShellyProUpdateLedLink((TasmotaGlobal.global_state.wifi_down) ? 0x1C : 0x14); // Green off if wifi OFF
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,22 +462,33 @@ void ShellyProLedLinkWifiOff(void) {
|
|||||||
bool Xdrv88(uint32_t function) {
|
bool Xdrv88(uint32_t function) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
if (FUNC_PRE_INIT == function) {
|
if (FUNC_MODULE_INIT == function) {
|
||||||
ShellyProPreInit();
|
ShellyProPreInit();
|
||||||
} else if (SPro.detected) {
|
} else if (SPro.detected) {
|
||||||
switch (function) {
|
switch (function) {
|
||||||
|
/*
|
||||||
|
case FUNC_BUTTON_PRESSED:
|
||||||
|
result = ShellyProButton();
|
||||||
|
break;
|
||||||
|
*/
|
||||||
case FUNC_EVERY_SECOND:
|
case FUNC_EVERY_SECOND:
|
||||||
ShellyProLedLinkWifiOff();
|
ShellyProLedLinkWifiOff();
|
||||||
break;
|
break;
|
||||||
case FUNC_SET_POWER:
|
case FUNC_SET_POWER:
|
||||||
ShellyProPower();
|
ShellyProPower();
|
||||||
break;
|
break;
|
||||||
case FUNC_LED_LINK:
|
|
||||||
ShellyProLedLink();
|
|
||||||
break;
|
|
||||||
case FUNC_INIT:
|
case FUNC_INIT:
|
||||||
ShellyProInit();
|
ShellyProInit();
|
||||||
break;
|
break;
|
||||||
|
case FUNC_ADD_BUTTON:
|
||||||
|
result = ShellyProAddButton();
|
||||||
|
break;
|
||||||
|
case FUNC_ADD_SWITCH:
|
||||||
|
result = ShellyProAddSwitch();
|
||||||
|
break;
|
||||||
|
case FUNC_LED_LINK:
|
||||||
|
ShellyProLedLink();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -1,498 +0,0 @@
|
|||||||
/*
|
|
||||||
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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef ESP32
|
|
||||||
#ifdef USE_SPI
|
|
||||||
#ifdef USE_SHELLY_PRO
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* 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,5600,4700,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,5600,4700,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,5600,4700,3350;AdcParam2 2,5600,4700,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,5600,4700,3350;AdcParam2 2,5600,4700,3350"}
|
|
||||||
* {"NAME":"Shelly Pro 4PM","GPIO":[0,6210,0,6214,9568,0,0,0,0,0,9569,0,768,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,736,704,3461,0,4736,0,0,672],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,5600,4700,3350"}
|
|
||||||
*
|
|
||||||
* Shelly Pro 1/2 uses SPI to control one 74HC595 for relays/leds and one ADE7953 (1PM) or two ADE7953 (2PM) for energy monitoring
|
|
||||||
* Shelly Pro 4 uses an SPI to control one MCP23S17 for buttons/switches/relays/leds and two ADE7953 for energy monitoring and a second SPI for the display
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
#define XDRV_88 88
|
|
||||||
|
|
||||||
#define SHELLY_PRO_PIN_LAN8720_RESET 5
|
|
||||||
#define SHELLY_PRO_4_PIN_SPI_CS 16
|
|
||||||
#define SHELLY_PRO_4_PIN_MCP23S17_INT 35
|
|
||||||
#define SHELLY_PRO_4_MCP23S17_ADDRESS 0x40
|
|
||||||
|
|
||||||
struct SPro {
|
|
||||||
uint32_t last_update;
|
|
||||||
uint16_t input_state;
|
|
||||||
int8_t switch_offset;
|
|
||||||
int8_t button_offset;
|
|
||||||
uint8_t pin_register_cs;
|
|
||||||
uint8_t pin_mcp23s17_int;
|
|
||||||
uint8_t ledlink;
|
|
||||||
uint8_t power;
|
|
||||||
bool init_done;
|
|
||||||
uint8_t detected;
|
|
||||||
} SPro;
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* Shelly Pro MCP23S17 support
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
enum SP4MCP23X17GPIORegisters {
|
|
||||||
// A side
|
|
||||||
SP4_MCP23S17_IODIRA = 0x00,
|
|
||||||
SP4_MCP23S17_IPOLA = 0x02,
|
|
||||||
SP4_MCP23S17_GPINTENA = 0x04,
|
|
||||||
SP4_MCP23S17_DEFVALA = 0x06,
|
|
||||||
SP4_MCP23S17_INTCONA = 0x08,
|
|
||||||
SP4_MCP23S17_IOCONA = 0x0A,
|
|
||||||
SP4_MCP23S17_GPPUA = 0x0C,
|
|
||||||
SP4_MCP23S17_INTFA = 0x0E,
|
|
||||||
SP4_MCP23S17_INTCAPA = 0x10,
|
|
||||||
SP4_MCP23S17_GPIOA = 0x12,
|
|
||||||
SP4_MCP23S17_OLATA = 0x14,
|
|
||||||
// B side
|
|
||||||
SP4_MCP23S17_IODIRB = 0x01,
|
|
||||||
SP4_MCP23S17_IPOLB = 0x03,
|
|
||||||
SP4_MCP23S17_GPINTENB = 0x05,
|
|
||||||
SP4_MCP23S17_DEFVALB = 0x07,
|
|
||||||
SP4_MCP23S17_INTCONB = 0x09,
|
|
||||||
SP4_MCP23S17_IOCONB = 0x0B,
|
|
||||||
SP4_MCP23S17_GPPUB = 0x0D,
|
|
||||||
SP4_MCP23S17_INTFB = 0x0F,
|
|
||||||
SP4_MCP23S17_INTCAPB = 0x11,
|
|
||||||
SP4_MCP23S17_GPIOB = 0x13,
|
|
||||||
SP4_MCP23S17_OLATB = 0x15,
|
|
||||||
};
|
|
||||||
|
|
||||||
uint8_t sp4_mcp23s17_olata = 0;
|
|
||||||
uint8_t sp4_mcp23s17_olatb = 0;
|
|
||||||
|
|
||||||
void SP4Mcp23S17Enable(void) {
|
|
||||||
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
|
|
||||||
digitalWrite(SPro.pin_register_cs, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SP4Mcp23S17Disable(void) {
|
|
||||||
SPI.endTransaction();
|
|
||||||
digitalWrite(SPro.pin_register_cs, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t SP4Mcp23S17Read16(uint8_t reg) {
|
|
||||||
// Read 16-bit registers: (regb << 8) | rega
|
|
||||||
SP4Mcp23S17Enable();
|
|
||||||
SPI.transfer(SHELLY_PRO_4_MCP23S17_ADDRESS | 1);
|
|
||||||
SPI.transfer(reg);
|
|
||||||
uint32_t value = SPI.transfer(0xFF); // RegA
|
|
||||||
value |= (SPI.transfer(0xFF) << 8); // RegB
|
|
||||||
SP4Mcp23S17Disable();
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t SP4Mcp23S17Read(uint8_t reg) {
|
|
||||||
SP4Mcp23S17Enable();
|
|
||||||
SPI.transfer(SHELLY_PRO_4_MCP23S17_ADDRESS | 1);
|
|
||||||
SPI.transfer(reg);
|
|
||||||
uint32_t value = SPI.transfer(0xFF);
|
|
||||||
SP4Mcp23S17Disable();
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SP4Mcp23S17Write(uint8_t reg, uint8_t value) {
|
|
||||||
SP4Mcp23S17Enable();
|
|
||||||
SPI.transfer(SHELLY_PRO_4_MCP23S17_ADDRESS);
|
|
||||||
SPI.transfer(reg);
|
|
||||||
SPI.transfer(value);
|
|
||||||
SP4Mcp23S17Disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SP4Mcp23S17Update(uint8_t pin, bool pin_value, uint8_t reg_addr) {
|
|
||||||
uint8_t bit = pin % 8;
|
|
||||||
uint8_t reg_value = 0;
|
|
||||||
if (reg_addr == SP4_MCP23S17_OLATA) {
|
|
||||||
reg_value = sp4_mcp23s17_olata;
|
|
||||||
} else if (reg_addr == SP4_MCP23S17_OLATB) {
|
|
||||||
reg_value = sp4_mcp23s17_olatb;
|
|
||||||
} else {
|
|
||||||
reg_value = SP4Mcp23S17Read(reg_addr);
|
|
||||||
}
|
|
||||||
if (pin_value) {
|
|
||||||
reg_value |= 1 << bit;
|
|
||||||
} else {
|
|
||||||
reg_value &= ~(1 << bit);
|
|
||||||
}
|
|
||||||
SP4Mcp23S17Write(reg_addr, reg_value);
|
|
||||||
if (reg_addr == SP4_MCP23S17_OLATA) {
|
|
||||||
sp4_mcp23s17_olata = reg_value;
|
|
||||||
} else if (reg_addr == SP4_MCP23S17_OLATB) {
|
|
||||||
sp4_mcp23s17_olatb = reg_value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
if (flags == INPUT) {
|
|
||||||
SP4Mcp23S17Update(pin, true, iodir);
|
|
||||||
SP4Mcp23S17Update(pin, false, gppu);
|
|
||||||
} else if (flags == (INPUT | PULLUP)) {
|
|
||||||
SP4Mcp23S17Update(pin, true, iodir);
|
|
||||||
SP4Mcp23S17Update(pin, true, gppu);
|
|
||||||
} else if (flags == OUTPUT) {
|
|
||||||
SP4Mcp23S17Update(pin, false, iodir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SP4Mcp23S17DigitalRead(uint8_t pin) {
|
|
||||||
uint8_t bit = pin % 8;
|
|
||||||
uint8_t reg_addr = pin < 8 ? SP4_MCP23S17_GPIOA : SP4_MCP23S17_GPIOB;
|
|
||||||
uint8_t value = SP4Mcp23S17Read(reg_addr);
|
|
||||||
return value & (1 << bit);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SP4Mcp23S17DigitalWrite(uint8_t pin, bool value) {
|
|
||||||
uint8_t reg_addr = pin < 8 ? SP4_MCP23S17_OLATA : SP4_MCP23S17_OLATB;
|
|
||||||
SP4Mcp23S17Update(pin, value, reg_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* Shelly Pro 4
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
const uint8_t sp4_relay_pin[] = { 8, 13, 14, 12 };
|
|
||||||
const uint8_t sp4_switch_pin[] = { 6, 1, 0, 15 };
|
|
||||||
const uint8_t sp4_button_pin[] = { 5, 2, 3 };
|
|
||||||
|
|
||||||
void ShellyPro4Init(void) {
|
|
||||||
/*
|
|
||||||
Shelly Pro 4PM MCP23S17 registers
|
|
||||||
bit 0 = input, inverted - Switch3
|
|
||||||
bit 1 = input, inverted - Switch2
|
|
||||||
bit 2 = input - Button Down
|
|
||||||
bit 3 = input - Button OK
|
|
||||||
bit 4 = output - Reset, display, ADE7953
|
|
||||||
bit 5 = input - Button Up
|
|
||||||
bit 6 = input, inverted - Switch1
|
|
||||||
bit 7
|
|
||||||
bit 8 = output - Relay O1
|
|
||||||
bit 9
|
|
||||||
bit 10
|
|
||||||
bit 11
|
|
||||||
bit 12 = output - Relay O4
|
|
||||||
bit 13 = output - Relay O2
|
|
||||||
bit 14 = output - Relay O3
|
|
||||||
bit 15 = input, inverted - Switch4
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
sp4_mcp23s17_olata = SP4Mcp23S17Read(SP4_MCP23S17_OLATA);
|
|
||||||
sp4_mcp23s17_olatb = SP4Mcp23S17Read(SP4_MCP23S17_OLATB);
|
|
||||||
|
|
||||||
SP4Mcp23S17PinMode(4, OUTPUT); // Reset display, ADE7943
|
|
||||||
SP4Mcp23S17DigitalWrite(4, 1);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < 3; i++) {
|
|
||||||
SP4Mcp23S17PinMode(sp4_button_pin[i], INPUT); // Button Up, Down, OK (RC with 10k to 3V3 and button shorting C)
|
|
||||||
}
|
|
||||||
SPro.button_offset = -1;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < 4; i++) {
|
|
||||||
SP4Mcp23S17PinMode(sp4_switch_pin[i], INPUT); // Switch1..4
|
|
||||||
SP4Mcp23S17PinMode(sp4_relay_pin[i], OUTPUT); // Relay O1..O4
|
|
||||||
}
|
|
||||||
SPro.switch_offset = -1;
|
|
||||||
|
|
||||||
// Read current input register state
|
|
||||||
SPro.input_state = SP4Mcp23S17Read16(SP4_MCP23S17_GPIOA) & 0x806F; // Read gpio and clear interrupt
|
|
||||||
attachInterrupt(SPro.pin_mcp23s17_int, ShellyProUpdateIsr, CHANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShellyPro4Reset(void) {
|
|
||||||
SP4Mcp23S17DigitalWrite(4, 0); // Reset pin display, ADE7953
|
|
||||||
delay(1); // To initiate a hardware reset, this pin must be brought low for a minimum of 10 μs.
|
|
||||||
SP4Mcp23S17DigitalWrite(4, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShellyProAddButton(void) {
|
|
||||||
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; } // Support three buttons
|
|
||||||
uint32_t state = bitRead(SPro.input_state, sp4_button_pin[index]); // 1 on power on and restart
|
|
||||||
XdrvMailbox.index = state;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShellyProAddSwitch(void) {
|
|
||||||
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; } // Support four switches
|
|
||||||
uint32_t state = bitRead(SPro.input_state, sp4_switch_pin[index]); // 0 on power on and restart
|
|
||||||
XdrvMailbox.index = state ^1; // Invert
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShellyProUpdateIsr(void) {
|
|
||||||
/*
|
|
||||||
The goal if this function is to minimize SPI and SetVirtualPinState calls
|
|
||||||
*/
|
|
||||||
uint32_t input_state = SP4Mcp23S17Read16(SP4_MCP23S17_INTCAPA); // Read intcap and clear interrupt
|
|
||||||
input_state &= 0x806F; // Only test input bits
|
|
||||||
|
|
||||||
// AddLog(LOG_LEVEL_DEBUG, PSTR("SHP: Input from %04X to %04X"), SPro.input_state, input_state);
|
|
||||||
|
|
||||||
if (TasmotaGlobal.uptime < 3) { return; } // Flush interrupt for 3 seconds after poweron
|
|
||||||
|
|
||||||
uint32_t mask = 1;
|
|
||||||
for (uint32_t j = 0; j < 16; j++) {
|
|
||||||
if ((input_state & mask) != (SPro.input_state & mask)) {
|
|
||||||
uint32_t state = (input_state >> j) &1;
|
|
||||||
|
|
||||||
// AddLog(LOG_LEVEL_DEBUG, PSTR("SHP: Change pin %d to %d"), j, state);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < 4; i++) {
|
|
||||||
if (j == sp4_switch_pin[i]) {
|
|
||||||
SwitchSetVirtualPinState(SPro.switch_offset +i, state ^1); // Invert
|
|
||||||
}
|
|
||||||
else if ((i < 3) && (j == sp4_button_pin[i])) {
|
|
||||||
ButtonSetVirtualPinState(SPro.button_offset +i, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mask <<= 1;
|
|
||||||
}
|
|
||||||
SPro.input_state = input_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShellyProButton(void) {
|
|
||||||
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; } // Only support Up, Down, Ok
|
|
||||||
|
|
||||||
uint32_t button = XdrvMailbox.payload;
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Do something with the Up,Down,Ok button
|
|
||||||
switch (button_index) {
|
|
||||||
case 0: // Up
|
|
||||||
break;
|
|
||||||
case 1: // Down
|
|
||||||
break;
|
|
||||||
case 2: // Ok
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true; // Disable further button processing
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* Shelly Pro 1/2
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
void ShellyProUpdate(void) {
|
|
||||||
/*
|
|
||||||
Shelly Pro 1/2/PM 74HC595 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_register_cs, 1); // Latch data
|
|
||||||
delayMicroseconds(1); // Shelly 10mS
|
|
||||||
digitalWrite(SPro.pin_register_cs, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* Shelly Pro
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
void ShellyProPreInit(void) {
|
|
||||||
if ((SPI_MOSI_MISO == TasmotaGlobal.spi_enabled) &&
|
|
||||||
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
|
|
||||||
if (PinUsed(GPIO_SWT1, 1) || PinUsed(GPIO_KEY1, 1)) {
|
|
||||||
SPro.detected = 2; // Shelly Pro 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SPro.detected) {
|
|
||||||
TasmotaGlobal.devices_present += SPro.detected;
|
|
||||||
|
|
||||||
SPro.pin_register_cs = Pin(GPIO_SPI_CS);
|
|
||||||
digitalWrite(SPro.pin_register_cs, (4 == SPro.detected) ? 1 : 0); // Prep 74HC595 rclk
|
|
||||||
pinMode(SPro.pin_register_cs, 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);
|
|
||||||
|
|
||||||
if (4 == SPro.detected) {
|
|
||||||
SPro.pin_mcp23s17_int = SHELLY_PRO_4_PIN_MCP23S17_INT; // GPIO35 = MCP23S17 common interrupt
|
|
||||||
pinMode(SPro.pin_mcp23s17_int, INPUT);
|
|
||||||
ShellyPro4Init(); // Init MCP23S17
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
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"),
|
|
||||||
SPro.detected, (PinUsed(GPIO_ADE7953_CS))?"PM":"");
|
|
||||||
|
|
||||||
SPro.init_done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShellyProPower(void) {
|
|
||||||
if (SPro.detected != 4) {
|
|
||||||
SPro.power = XdrvMailbox.index &3;
|
|
||||||
ShellyProUpdate();
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShellyProUpdateLedLink(uint32_t ledlink) {
|
|
||||||
if (ledlink != SPro.ledlink) {
|
|
||||||
SPro.ledlink = ledlink;
|
|
||||||
ShellyProUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ShellyProLedLink(void) {
|
|
||||||
if (!SPro.init_done) { return; } // Block write before first power update
|
|
||||||
if (SPro.detected != 4) {
|
|
||||||
/*
|
|
||||||
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) {
|
|
||||||
if (!SPro.init_done) { return; }
|
|
||||||
if (SPro.detected != 4) {
|
|
||||||
/*
|
|
||||||
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_MODULE_INIT == function) {
|
|
||||||
ShellyProPreInit();
|
|
||||||
} else if (SPro.detected) {
|
|
||||||
switch (function) {
|
|
||||||
/*
|
|
||||||
case FUNC_BUTTON_PRESSED:
|
|
||||||
result = ShellyProButton();
|
|
||||||
break;
|
|
||||||
*/
|
|
||||||
case FUNC_EVERY_SECOND:
|
|
||||||
ShellyProLedLinkWifiOff();
|
|
||||||
break;
|
|
||||||
case FUNC_SET_POWER:
|
|
||||||
ShellyProPower();
|
|
||||||
break;
|
|
||||||
case FUNC_INIT:
|
|
||||||
ShellyProInit();
|
|
||||||
break;
|
|
||||||
case FUNC_ADD_BUTTON:
|
|
||||||
result = ShellyProAddButton();
|
|
||||||
break;
|
|
||||||
case FUNC_ADD_SWITCH:
|
|
||||||
result = ShellyProAddSwitch();
|
|
||||||
break;
|
|
||||||
case FUNC_LED_LINK:
|
|
||||||
ShellyProLedLink();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // USE_SHELLY_PRO
|
|
||||||
#endif // USE_SPI
|
|
||||||
#endif // ESP32
|
|
@ -1,15 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
xnrg_24_biopdu.ino - BioPDU-625x12 (based on xnrg_05_pzem_ac.ino)
|
xnrg_24_biopdu.ino - BioPDU-625x12 (based on xnrg_05_pzem_ac.ino)
|
||||||
Biomine 625x12 Custom Board
|
|
||||||
6 x 25A Relays
|
|
||||||
6 x Independent PZEM-004V3 Modbus AC energy sensor
|
|
||||||
3bit serial switch
|
|
||||||
Integrated MCP23008
|
|
||||||
|
|
||||||
Template {"NAME":"Olimex ESP32-PoE-BioPDU","GPIO":[1,10209,10210,1,10144,1,0,0,5536,640,1,1,608,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,1,10208,1,1,10176,0,0,1],"FLAG":0,"BASE":1}
|
Copyright (C) 2023 Fabrizio Amodio
|
||||||
|
|
||||||
Copyright (C) 2021 Theo Arends
|
|
||||||
Copyright (C) 2022-2023 Fabrizio Amodio
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -27,8 +19,15 @@
|
|||||||
|
|
||||||
#if defined(USE_ENERGY_SENSOR_ESP32) && defined(USE_I2C)
|
#if defined(USE_ENERGY_SENSOR_ESP32) && defined(USE_I2C)
|
||||||
#ifdef USE_BIOPDU
|
#ifdef USE_BIOPDU
|
||||||
|
/*********************************************************************************************\
|
||||||
|
Biomine 625x12 Custom Board
|
||||||
|
6 x 25A Relays
|
||||||
|
6 x Independent PZEM-004V3 Modbus AC energy sensor
|
||||||
|
3bit serial switch
|
||||||
|
Integrated MCP23008
|
||||||
|
|
||||||
|
Template {"NAME":"Olimex ESP32-PoE-BioPDU","GPIO":[1,10209,10210,1,10144,1,0,0,5536,640,1,1,608,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,1,10208,1,1,10176,0,0,1],"FLAG":0,"BASE":1}
|
||||||
|
|
||||||
/*
|
|
||||||
BioPDU 625x12 Factory Settings:
|
BioPDU 625x12 Factory Settings:
|
||||||
|
|
||||||
Template {"NAME":"Olimex ESP32-PoE-BioPDU","GPIO":[1,10209,10210,1,10144,1,0,0,5536,640,1,1,608,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,1,10208,1,1,10176,0,0,1],"FLAG":0,"BASE":1}
|
Template {"NAME":"Olimex ESP32-PoE-BioPDU","GPIO":[1,10209,10210,1,10144,1,0,0,5536,640,1,1,608,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,1,10208,1,1,10176,0,0,1],"FLAG":0,"BASE":1}
|
||||||
@ -62,7 +61,7 @@
|
|||||||
USE_MCP230xx_ADDR=0x20
|
USE_MCP230xx_ADDR=0x20
|
||||||
USE_MCP230xx_OUTPUT
|
USE_MCP230xx_OUTPUT
|
||||||
USE_BIOPDU
|
USE_BIOPDU
|
||||||
*/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
#define XNRG_24 24
|
#define XNRG_24 24
|
||||||
|
|
||||||
|
@ -206,7 +206,8 @@ a_setoption = [[
|
|||||||
"(Light) start DMX ArtNet at boot, listen to UDP port as soon as network is up",
|
"(Light) start DMX ArtNet at boot, listen to UDP port as soon as network is up",
|
||||||
"(Wifi) prefer IPv6 DNS resolution to IPv4 address when available. Requires `#define USE_IPV6`",
|
"(Wifi) prefer IPv6 DNS resolution to IPv4 address when available. Requires `#define USE_IPV6`",
|
||||||
"(Energy) Force no voltage/frequency common",
|
"(Energy) Force no voltage/frequency common",
|
||||||
"","","",
|
"(Matter) Enable Matter protocol over Wifi",
|
||||||
|
"","",
|
||||||
"","","","",
|
"","","","",
|
||||||
"","","","",
|
"","","","",
|
||||||
"","","","",
|
"","","","",
|
||||||
@ -292,7 +293,7 @@ a_features = [[
|
|||||||
"USE_MODBUS_ENERGY","USE_SHELLY_PRO","USE_DALI","USE_BP1658CJ",
|
"USE_MODBUS_ENERGY","USE_SHELLY_PRO","USE_DALI","USE_BP1658CJ",
|
||||||
"USE_DINGTIAN_RELAY","USE_HMC5883L","USE_LD2410","USE_ME007",
|
"USE_DINGTIAN_RELAY","USE_HMC5883L","USE_LD2410","USE_ME007",
|
||||||
"USE_DISPLAY_TM1650","USE_PCA9632","USE_TUYAMCUBR","USE_SEN5X",
|
"USE_DISPLAY_TM1650","USE_PCA9632","USE_TUYAMCUBR","USE_SEN5X",
|
||||||
"","","","",
|
"USE_BIOPDU","","","",
|
||||||
"","","","",
|
"","","","",
|
||||||
"","","","",
|
"","","","",
|
||||||
"","","",""
|
"","","",""
|
||||||
@ -323,7 +324,7 @@ else:
|
|||||||
obj = json.load(fp)
|
obj = json.load(fp)
|
||||||
|
|
||||||
def StartDecode():
|
def StartDecode():
|
||||||
print ("\n*** decode-status.py v12.3.1.5 by Theo Arends and Jacek Ziolkowski ***")
|
print ("\n*** decode-status.py v12.3.1.6 by Theo Arends and Jacek Ziolkowski ***")
|
||||||
|
|
||||||
# print("Decoding\n{}".format(obj))
|
# print("Decoding\n{}".format(obj))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user