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
|
||||
- Use HTML escape on File System Edit File load (#22492)
|
||||
- Magic switch applying masking window to any power change (#22535)
|
||||
- Shift595 output offsets and restart relay toggles
|
||||
|
||||
### Removed
|
||||
|
||||
|
|
|
@ -169,6 +169,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
|
|||
|
||||
### Fixed
|
||||
- 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)
|
||||
- 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)
|
||||
|
|
|
@ -832,12 +832,28 @@ int32_t UpdateDevicesPresent(int32_t change) {
|
|||
else if (devices_present >= POWER_SIZE) { // Support up to uint32_t as bitmask
|
||||
difference = 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;
|
||||
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)
|
||||
{
|
||||
strncpy_P(dest, S_RSLT_POWER, size); // POWER
|
||||
|
|
|
@ -293,6 +293,13 @@ uint8_t LightDevice(void)
|
|||
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) {
|
||||
return (a < b && a < c) ? a : (b < c) ? b : c;
|
||||
}
|
||||
|
|
|
@ -374,6 +374,7 @@ void Pcf8574Power(void) {
|
|||
rpower >>= Pcf8574.relay_offset;
|
||||
relay_max = Pcf8574.relay_max;
|
||||
}
|
||||
DevicesPresentNonDisplayOrLight(relay_max); // Skip display and/or light(s)
|
||||
for (uint32_t index = 0; index < relay_max; index++) {
|
||||
power_t state = rpower &1;
|
||||
if (Pcf8574PinUsed(GPIO_REL1, index)) {
|
||||
|
|
|
@ -31,15 +31,28 @@ struct Shift595 {
|
|||
uint8_t pinOE;
|
||||
uint8_t outputs;
|
||||
uint8_t first;
|
||||
bool connected = false;
|
||||
} *Shift595 = nullptr;
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Low level Shift 74x595
|
||||
\*********************************************************************************************/
|
||||
|
||||
void Shift595ConfigurePin(uint8_t pin, uint8_t value = 0) {
|
||||
pinMode(pin, OUTPUT);
|
||||
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)) {
|
||||
Shift595 = (struct Shift595*)calloc(1, sizeof(struct Shift595));
|
||||
if (Shift595) {
|
||||
|
@ -53,40 +66,60 @@ void Shift595Init(void) {
|
|||
|
||||
if (PinUsed(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->outputs = Settings->shift595_device_count * 8;
|
||||
Shift595->first = TasmotaGlobal.devices_present; // devices_present offset
|
||||
Shift595->outputs = Settings->shift595_device_count * 8; // Max number of outputs present
|
||||
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);
|
||||
digitalWrite(pin, 0);
|
||||
}
|
||||
/*********************************************************************************************\
|
||||
* FUNC_SET_POWER at T +2
|
||||
* Reduce devices_present with display and/or lights not known before
|
||||
* Add offset for previous defined relays
|
||||
\*********************************************************************************************/
|
||||
|
||||
void Shift595SwitchRelay(void) {
|
||||
if (Shift595 && Shift595->connected == true) {
|
||||
for (uint32_t i = 0; i < Shift595->outputs; i++) {
|
||||
uint8_t relay_state = bitRead(XdrvMailbox.index, Shift595->first + Shift595->outputs -1 -i);
|
||||
digitalWrite(Shift595->pinSER, Settings->flag5.shift595_invert_outputs ? !relay_state : relay_state);
|
||||
Shift595LatchPin(Shift595->pinSRCLK);
|
||||
}
|
||||
// XdrvMailbox.index = 32-bit rpower bit mask
|
||||
// Use relative and sequential relay indexes
|
||||
power_t rpower = XdrvMailbox.index;
|
||||
uint32_t relay_max = Shift595->outputs; // Total number of outputs
|
||||
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)) {
|
||||
digitalWrite(Shift595->pinOE, 0);
|
||||
uint32_t power_bit = relay_max -1; // Start at highest non display and/or light power bit
|
||||
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) {
|
||||
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload * 8 <= MAX_RELAYS_SET - Shift595->first)) {
|
||||
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 result = false;
|
||||
|
||||
if (FUNC_PRE_INIT == function) {
|
||||
Shift595Init();
|
||||
if (FUNC_SETUP_RING2 == function) {
|
||||
Shift595ModuleInit();
|
||||
} else if (Shift595) {
|
||||
switch (function) {
|
||||
case FUNC_SET_POWER:
|
||||
|
|
|
@ -762,6 +762,7 @@ void MCP23xPower(void) {
|
|||
rpower >>= Mcp23x.relay_offset;
|
||||
relay_max = Mcp23x.relay_max;
|
||||
}
|
||||
DevicesPresentNonDisplayOrLight(relay_max); // Skip display and/or light(s)
|
||||
for (uint32_t index = 0; index < relay_max; index++) {
|
||||
power_t state = rpower &1;
|
||||
if (MCP23xPinUsed(GPIO_REL1, index)) {
|
||||
|
|
Loading…
Reference in New Issue