As requested in issue 824# by ascillato2, implement split interlock.

=> Split interlock of SONOFF with more than 2 channel into 2 groups
=> This is needed for shutter and similar utilization
This commit is contained in:
lobocobra 2019-01-13 11:00:02 +01:00
parent 72bc9b8107
commit 15e4918238
2 changed files with 41 additions and 2 deletions

View File

@ -76,7 +76,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint32_t sleep_normal : 1; // bit 10 (v6.3.0.15) - SetOption60 - Enable normal sleep instead of dynamic sleep uint32_t sleep_normal : 1; // bit 10 (v6.3.0.15) - SetOption60 - Enable normal sleep instead of dynamic sleep
uint32_t button_switch_force_local : 1;// bit 11 (v6.3.0.16) - SetOption61 - Force local operation when button/switch topic is set uint32_t button_switch_force_local : 1;// bit 11 (v6.3.0.16) - SetOption61 - Force local operation when button/switch topic is set
uint32_t no_pullup : 1; // bit 12 (v6.4.1.7) - SetOption62 - Force no pull-up (0 = (no)pull-up, 1 = no pull-up) uint32_t no_pullup : 1; // bit 12 (v6.4.1.7) - SetOption62 - Force no pull-up (0 = (no)pull-up, 1 = no pull-up)
uint32_t spare13 : 1; uint32_t split_interlock : 1; // bit 13 (v6.4.1.8) - SetOption63 - Split interlock on CH4
uint32_t spare14 : 1; uint32_t spare14 : 1;
uint32_t spare15 : 1; uint32_t spare15 : 1;
uint32_t spare16 : 1; uint32_t spare16 : 1;

View File

@ -319,6 +319,23 @@ void SetDevicePower(power_t rpower, int source)
power = (1 << devices_present) -1; power = (1 << devices_present) -1;
rpower = power; rpower = power;
} }
if (Settings.flag3.split_interlock) {
Settings.flag.interlock = 1; // prevent the situation where interlock is off and split-interlock is on
uint8_t mask = 0x01;
uint8_t count = 0;
byte result1 = 0;
byte result2 = 0;
for (byte i = 0; i < devices_present; i++) {
if (rpower & mask) {
if (i <2) { result1++;}//increment if low part is ON
if (i >1) { result2++;}//increment if high part is ON
}
mask <<= 1; // shift the bitmask one left (1,2,4,8) to find out what is on
}
if ((result1) >1 && (result2 >1)) {power = 0; rpower = 0;} // all 4 switch are on, something is wrong, so we turn all off
if ((result1) >1 && (result2 <2)) {power = power & 0x0C; rpower = power;} // 1/2 are both on and 3/4 max one is on
if ((result1) <2 && (result2 >1)) {power = power & 0x03; rpower = power;} // 1/2 max one is on and 3/4 both are on
} else {
if (Settings.flag.interlock) { // Allow only one or no relay set if (Settings.flag.interlock) { // Allow only one or no relay set
power_t mask = 1; power_t mask = 1;
uint8_t count = 0; uint8_t count = 0;
@ -331,6 +348,7 @@ void SetDevicePower(power_t rpower, int source)
rpower = 0; rpower = 0;
} }
} }
}
XdrvMailbox.index = rpower; XdrvMailbox.index = rpower;
XdrvCall(FUNC_SET_POWER); // Signal power state XdrvCall(FUNC_SET_POWER); // Signal power state
@ -1389,7 +1407,28 @@ void ExecuteCommandPower(byte device, byte state, int source)
blink_mask &= (POWER_MASK ^ mask); // Clear device mask blink_mask &= (POWER_MASK ^ mask); // Clear device mask
MqttPublishPowerBlinkState(device); MqttPublishPowerBlinkState(device);
} }
if (Settings.flag.interlock && !interlock_mutex) { // Clear all but masked relay if (Settings.flag3.split_interlock && !Settings.flag.interlock ) Settings.flag.interlock=1; // ensure interlock is on, in case split_interlock is on
// check if channel 1/2 or 3/4 are to be changed
if (device <= 2 && Settings.flag3.split_interlock ) { // channel 1/2 are changed
if (Settings.flag3.split_interlock && !interlock_mutex) { // Clear all but masked relay, but only if we are not already doing something
interlock_mutex = 1;
for (byte i = 0; i < 2; i++) {
byte imask = 0x01 << i;
if ((power & imask) && (mask != imask)) { ExecuteCommandPower(i +1, POWER_OFF, SRC_IGNORE); delay(50); }// example, first power is ON but the pushed button is not the first, then powerOFF the first one
}
interlock_mutex = 0; // avoid infinite loop due to recursive requests
}
} else { // channel 3/4 are changed
if (Settings.flag3.split_interlock && !interlock_mutex) { // only start if we are on interlock split and have no re-call
interlock_mutex = 1;
for (byte i = 2; i < devices_present; i++) {
byte imask = 0x01 << i;
if ((power & imask) && (mask != imask)) ExecuteCommandPower(i +1, POWER_OFF, SRC_IGNORE);
}
interlock_mutex = 0;
}
}
if ( Settings.flag.interlock && !interlock_mutex && !Settings.flag3.split_interlock) { //execute regular interlock-mode as interlock-split is off
interlock_mutex = 1; interlock_mutex = 1;
for (byte i = 0; i < devices_present; i++) { for (byte i = 0; i < devices_present; i++) {
power_t imask = 1 << i; power_t imask = 1 << i;