mirror of https://github.com/arendst/Tasmota.git
Fix Shift595 output offsets and restart relay toggles
This commit is contained in:
parent
5dd132bb5f
commit
5a32df5e81
|
@ -23,6 +23,7 @@ All notable changes to this project will be documented in this file.
|
||||||
- Wrong GUI Module and Template drop down list indexes regression
|
- Wrong GUI Module and Template drop down list indexes regression
|
||||||
- Use HTML escape on File System Edit File load (#22492)
|
- Use HTML escape on File System Edit File load (#22492)
|
||||||
- Magic switch applying masking window to any power change (#22535)
|
- Magic switch applying masking window to any power change (#22535)
|
||||||
|
- Shift595 output offsets and restart relay toggles
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
|
|
@ -169,6 +169,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- FUNC_COMMAND linked list command buffer corruption by shutter driver
|
- FUNC_COMMAND linked list command buffer corruption by shutter driver
|
||||||
|
- Shift595 output offsets and restart relay toggles
|
||||||
- Use HTML escape on File System Edit File load [#22492](https://github.com/arendst/Tasmota/issues/22492)
|
- Use HTML escape on File System Edit File load [#22492](https://github.com/arendst/Tasmota/issues/22492)
|
||||||
- Prevent crashing when `display.ini` is missing end `#` [#22471](https://github.com/arendst/Tasmota/issues/22471)
|
- Prevent crashing when `display.ini` is missing end `#` [#22471](https://github.com/arendst/Tasmota/issues/22471)
|
||||||
- Magic switch applying masking window to any power change [#22535](https://github.com/arendst/Tasmota/issues/22535)
|
- Magic switch applying masking window to any power change [#22535](https://github.com/arendst/Tasmota/issues/22535)
|
||||||
|
|
|
@ -832,12 +832,28 @@ int32_t UpdateDevicesPresent(int32_t change) {
|
||||||
else if (devices_present >= POWER_SIZE) { // Support up to uint32_t as bitmask
|
else if (devices_present >= POWER_SIZE) { // Support up to uint32_t as bitmask
|
||||||
difference = devices_present - POWER_SIZE;
|
difference = devices_present - POWER_SIZE;
|
||||||
devices_present = POWER_SIZE;
|
devices_present = POWER_SIZE;
|
||||||
AddLog(LOG_LEVEL_DEBUG, PSTR("APP: Max number of devices reached"));
|
// AddLog(LOG_LEVEL_DEBUG, PSTR("APP: Max 32 devices supported"));
|
||||||
}
|
}
|
||||||
TasmotaGlobal.devices_present = devices_present;
|
TasmotaGlobal.devices_present = devices_present;
|
||||||
return difference;
|
return difference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DevicesPresentNonDisplayOrLight(uint32_t &devices_claimed) {
|
||||||
|
uint32_t display_and_lights = 0;
|
||||||
|
#ifdef USE_LIGHT
|
||||||
|
display_and_lights += LightDevices(); // Skip light(s)
|
||||||
|
#endif // USE_LIGHT
|
||||||
|
#ifdef USE_DISPLAY
|
||||||
|
if (disp_device) {
|
||||||
|
display_and_lights++; // Skip display
|
||||||
|
}
|
||||||
|
#endif // USE_DISPLAY
|
||||||
|
uint32_t devices_present = TasmotaGlobal.devices_present - display_and_lights;
|
||||||
|
if (devices_claimed > devices_present) {
|
||||||
|
devices_claimed = devices_present; // Reduce amount of claimed devices
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char* GetPowerDevice(char* dest, uint32_t idx, size_t size, uint32_t option)
|
char* GetPowerDevice(char* dest, uint32_t idx, size_t size, uint32_t option)
|
||||||
{
|
{
|
||||||
strncpy_P(dest, S_RSLT_POWER, size); // POWER
|
strncpy_P(dest, S_RSLT_POWER, size); // POWER
|
||||||
|
|
|
@ -293,6 +293,13 @@ uint8_t LightDevice(void)
|
||||||
return Light.device; // Make external
|
return Light.device; // Make external
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t LightDevices(void) {
|
||||||
|
if (0 == Light.device) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return TasmotaGlobal.devices_present - Light.device +1; // Make external
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t min3(uint32_t a, uint32_t b, uint32_t c) {
|
static uint32_t min3(uint32_t a, uint32_t b, uint32_t c) {
|
||||||
return (a < b && a < c) ? a : (b < c) ? b : c;
|
return (a < b && a < c) ? a : (b < c) ? b : c;
|
||||||
}
|
}
|
||||||
|
|
|
@ -374,6 +374,7 @@ void Pcf8574Power(void) {
|
||||||
rpower >>= Pcf8574.relay_offset;
|
rpower >>= Pcf8574.relay_offset;
|
||||||
relay_max = Pcf8574.relay_max;
|
relay_max = Pcf8574.relay_max;
|
||||||
}
|
}
|
||||||
|
DevicesPresentNonDisplayOrLight(relay_max); // Skip display and/or light(s)
|
||||||
for (uint32_t index = 0; index < relay_max; index++) {
|
for (uint32_t index = 0; index < relay_max; index++) {
|
||||||
power_t state = rpower &1;
|
power_t state = rpower &1;
|
||||||
if (Pcf8574PinUsed(GPIO_REL1, index)) {
|
if (Pcf8574PinUsed(GPIO_REL1, index)) {
|
||||||
|
|
|
@ -31,15 +31,28 @@ struct Shift595 {
|
||||||
uint8_t pinOE;
|
uint8_t pinOE;
|
||||||
uint8_t outputs;
|
uint8_t outputs;
|
||||||
uint8_t first;
|
uint8_t first;
|
||||||
bool connected = false;
|
|
||||||
} *Shift595 = nullptr;
|
} *Shift595 = nullptr;
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Low level Shift 74x595
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
void Shift595ConfigurePin(uint8_t pin, uint8_t value = 0) {
|
void Shift595ConfigurePin(uint8_t pin, uint8_t value = 0) {
|
||||||
pinMode(pin, OUTPUT);
|
pinMode(pin, OUTPUT);
|
||||||
digitalWrite(pin, value);
|
digitalWrite(pin, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shift595Init(void) {
|
void Shift595LatchPin(uint8_t pin) {
|
||||||
|
digitalWrite(pin, 1);
|
||||||
|
digitalWrite(pin, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* FUNC_SETUP_RING2 at T +1
|
||||||
|
* Claim devices_present
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
void Shift595ModuleInit(void) {
|
||||||
if (PinUsed(GPIO_SHIFT595_SRCLK) && PinUsed(GPIO_SHIFT595_RCLK) && PinUsed(GPIO_SHIFT595_SER)) {
|
if (PinUsed(GPIO_SHIFT595_SRCLK) && PinUsed(GPIO_SHIFT595_RCLK) && PinUsed(GPIO_SHIFT595_SER)) {
|
||||||
Shift595 = (struct Shift595*)calloc(1, sizeof(struct Shift595));
|
Shift595 = (struct Shift595*)calloc(1, sizeof(struct Shift595));
|
||||||
if (Shift595) {
|
if (Shift595) {
|
||||||
|
@ -53,40 +66,60 @@ void Shift595Init(void) {
|
||||||
|
|
||||||
if (PinUsed(GPIO_SHIFT595_OE)) {
|
if (PinUsed(GPIO_SHIFT595_OE)) {
|
||||||
Shift595->pinOE = Pin(GPIO_SHIFT595_OE);
|
Shift595->pinOE = Pin(GPIO_SHIFT595_OE);
|
||||||
Shift595ConfigurePin(Shift595->pinOE, 1);
|
if (ResetReasonPowerOn()) { // Fix relay toggle at restart
|
||||||
|
Shift595ConfigurePin(Shift595->pinOE, 1); // Set all outputs to 3-state (3-state converted to OFF by ULN2803 relay drivers)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Shift595->first = TasmotaGlobal.devices_present;
|
Shift595->first = TasmotaGlobal.devices_present; // devices_present offset
|
||||||
Shift595->outputs = Settings->shift595_device_count * 8;
|
Shift595->outputs = Settings->shift595_device_count * 8; // Max number of outputs present
|
||||||
UpdateDevicesPresent(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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shift595LatchPin(uint8_t pin) {
|
/*********************************************************************************************\
|
||||||
digitalWrite(pin, 1);
|
* FUNC_SET_POWER at T +2
|
||||||
digitalWrite(pin, 0);
|
* Reduce devices_present with display and/or lights not known before
|
||||||
}
|
* Add offset for previous defined relays
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
void Shift595SwitchRelay(void) {
|
void Shift595SwitchRelay(void) {
|
||||||
if (Shift595 && Shift595->connected == true) {
|
// XdrvMailbox.index = 32-bit rpower bit mask
|
||||||
for (uint32_t i = 0; i < Shift595->outputs; i++) {
|
// Use relative and sequential relay indexes
|
||||||
uint8_t relay_state = bitRead(XdrvMailbox.index, Shift595->first + Shift595->outputs -1 -i);
|
power_t rpower = XdrvMailbox.index;
|
||||||
digitalWrite(Shift595->pinSER, Settings->flag5.shift595_invert_outputs ? !relay_state : relay_state);
|
uint32_t relay_max = Shift595->outputs; // Total number of outputs
|
||||||
Shift595LatchPin(Shift595->pinSRCLK);
|
DevicesPresentNonDisplayOrLight(relay_max); // Skip display and/or light(s)
|
||||||
}
|
uint32_t relay_offset = Shift595->outputs - relay_max + Shift595->first;
|
||||||
|
|
||||||
Shift595LatchPin(Shift595->pinRCLK);
|
static bool first = false;
|
||||||
|
if (!first) {
|
||||||
|
AddLog(LOG_LEVEL_DEBUG, PSTR("595: Output 1 to %d use POWER%d to POWER%d"), Shift595->outputs - relay_offset, Shift595->first + 1, relay_max);
|
||||||
|
first = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (PinUsed(GPIO_SHIFT595_OE)) {
|
uint32_t power_bit = relay_max -1; // Start at highest non display and/or light power bit
|
||||||
digitalWrite(Shift595->pinOE, 0);
|
for (uint32_t i = 0; i < Shift595->outputs; i++) { // We need to set all shift outputs even if not used
|
||||||
|
uint32_t relay_state = 0; // Unused state
|
||||||
|
if (i >= relay_offset) {
|
||||||
|
relay_state = bitRead(rpower, power_bit); // Shift-in from high to low
|
||||||
|
power_bit--;
|
||||||
}
|
}
|
||||||
|
digitalWrite(Shift595->pinSER, Settings->flag5.shift595_invert_outputs ? !relay_state : relay_state); // SetOption133 - (Shift595) Invert outputs of 74x595 shift registers
|
||||||
|
Shift595LatchPin(Shift595->pinSRCLK);
|
||||||
|
}
|
||||||
|
|
||||||
|
Shift595LatchPin(Shift595->pinRCLK);
|
||||||
|
|
||||||
|
if (PinUsed(GPIO_SHIFT595_OE)) {
|
||||||
|
digitalWrite(Shift595->pinOE, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Commands
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
void CmndShift595Devices(void) {
|
void CmndShift595Devices(void) {
|
||||||
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload * 8 <= MAX_RELAYS_SET - Shift595->first)) {
|
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload * 8 <= MAX_RELAYS_SET - Shift595->first)) {
|
||||||
Settings->shift595_device_count = (1 == XdrvMailbox.payload) ? SHIFT595_DEVICE_COUNT : XdrvMailbox.payload;
|
Settings->shift595_device_count = (1 == XdrvMailbox.payload) ? SHIFT595_DEVICE_COUNT : XdrvMailbox.payload;
|
||||||
|
@ -102,8 +135,8 @@ void CmndShift595Devices(void) {
|
||||||
bool Xdrv60(uint32_t function) {
|
bool Xdrv60(uint32_t function) {
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
if (FUNC_PRE_INIT == function) {
|
if (FUNC_SETUP_RING2 == function) {
|
||||||
Shift595Init();
|
Shift595ModuleInit();
|
||||||
} else if (Shift595) {
|
} else if (Shift595) {
|
||||||
switch (function) {
|
switch (function) {
|
||||||
case FUNC_SET_POWER:
|
case FUNC_SET_POWER:
|
||||||
|
|
|
@ -762,6 +762,7 @@ void MCP23xPower(void) {
|
||||||
rpower >>= Mcp23x.relay_offset;
|
rpower >>= Mcp23x.relay_offset;
|
||||||
relay_max = Mcp23x.relay_max;
|
relay_max = Mcp23x.relay_max;
|
||||||
}
|
}
|
||||||
|
DevicesPresentNonDisplayOrLight(relay_max); // Skip display and/or light(s)
|
||||||
for (uint32_t index = 0; index < relay_max; index++) {
|
for (uint32_t index = 0; index < relay_max; index++) {
|
||||||
power_t state = rpower &1;
|
power_t state = rpower &1;
|
||||||
if (MCP23xPinUsed(GPIO_REL1, index)) {
|
if (MCP23xPinUsed(GPIO_REL1, index)) {
|
||||||
|
|
Loading…
Reference in New Issue