OpenBK7231T_App
OpenBK7231T_App copied to clipboard
Inability to do proper mutexing seems to be able to kill relays in some setups
I have electric roller blinds that share live and have a two input wires for connecting live to them to either go up and down.
They should not be able to trigger both states at the same time.
OBK only seems to allow to turn another input off after the current one already went on, resulting in a short time where both inputs are on - this seems to have fried two 10A230V relays of mine so far.
I would like the ability to do a proper mutex on two channels, ideally with a delay between the two.
Some more context in https://www.elektroda.com/rtvforum/viewtopic.php?p=21587087#21587087 and in https://github.com/openshwprojects/OpenBK7231T_App/issues/703#issuecomment-2980716857
Workaround for the time being would be welcome, I did not manage to come up with any.
I can add some kind of mechanism, but how should it handle setChannel on mutexed channel? Should it delay setting new value? Or just skip set?
Let's say channel 1 and 2 are mutexed and you do: backlog setChannel 1 1; setChannel 2 1; setChannel 2 1; setChannel 2 0; What should happen internally?
In my case, it definitely should not skip.
Imagine user presses blinds down, but it won't do anything, because they already pressed blinds up accidentally x seconds earlier (the blinds take half a minute to move completely).
So I would expect
# 1. Channel 1 ON
setChannel 1 1;
# 2. Channel 1 OFF, delay 100ms, Channel 2 ON
setChannel 2 1;
# 3. Nothing, channel 2 is already on
setChannel 2 1;
# 4. Channel 2 OFF
setChannel 2 0;
Well, currently I can propose alternate solution. I have no solid ideas how to do what you said efficiently. We would need to queue set commands...
My alternate solution would be a driver that uses single channel to control two GPIOs. Value 0 is both down, value 1 is first high, value 2 is second high;
Here's my alternate solution self test. It should give you a basic idea how it will work. Do you think this can help for your scenario?:
`
CMD_ExecuteCommand("startDriver PinMutex", 0);
// setMutex
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(10) == 0);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(11) == 0);
Sim_RunMiliseconds(100, false);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(10) == 0);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(11) == 0);
CMD_ExecuteCommand("setChannel 0 1", 0);
// from 0 0 to 1 0 set is quick
Sim_RunMiliseconds(25, false);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(10) == 1);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(11) == 0);
CMD_ExecuteCommand("setChannel 0 2", 0);
Sim_RunMiliseconds(25, false);
// dead time
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(10) == 0);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(11) == 0);
Sim_RunMiliseconds(25, false);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(10) == 0);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(11) == 0);
Sim_RunMiliseconds(25, false);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(10) == 0);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(11) == 0);
Sim_RunMiliseconds(50, false);
// set
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(10) == 0);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(11) == 1);
CMD_ExecuteCommand("setChannel 0 1", 0);
Sim_RunMiliseconds(25, false);
// dead time
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(10) == 0);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(11) == 0);
Sim_RunMiliseconds(25, false);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(10) == 0);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(11) == 0);
Sim_RunMiliseconds(25, false);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(10) == 0);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(11) == 0);
Sim_RunMiliseconds(50, false);
// set
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(10) == 1);
SELFTEST_ASSERT(SIM_GetSimulatedPinValue(11) == 0);`
preview sample: https://github.com/openshwprojects/OpenBK7231T_App/pull/1704 tested only in self test
Are you able to convert your script logic to use the proposed approach? A single channel with 3 states - 0 "do nothing", 1 "move down", and "2 move up" ?
I will try flashing the artifact on my second board tomorrow, but how would I make this tri-state switch show up as "up" and "down" in home assistant?
i can add tristate channel type tomorrow, but for now, hm, a configuration.yaml custom entry?
I OTA'd from I believe .118 (had to do it twice for it to register from the web ui for some reason) to OpenBK7231N_pinmutex_e0b0bf44041f.rbl and I think I am doing the correct thing here but it won't work:
ah it was not enabled on beken, i pushned new commit
Looks like the documentation does not match the actual code, UP ends up being ms?
# OK
startDriver PinMutex
# Example in the code:
#// setMutex MutexIndex ChannelIndex PinUp PinDown DelayMs
# setMutex 0 1 10 11 50
# Bind first roller up/down
setMutex 0 1 1 2 500
> Error:GEN:PinMutex[0] = ch=1, up=500, down=2, t=1ms
# Bind second roller up/down
#setMutex 1 3 3 4 500
Later attempt here, ignore:
startDriver PinMutex
#setMutex MutexIndex ChannelIndex DelayMs PinDown PinUp
# Bind first roller up/down
setMutex 0 1 500 2 1
> Error:GEN:PinMutex[0] = ch=1, up=2, down=1, t=500ms
# Bind second roller up/down
#setMutex 1 3 500 4 3
ah yes, i moved pins to end, because i realized that the same approach could be used for N-pin mutexes
Okay I am failing here, mostly due to lack of understanding of channels/indexes.
setMutex 0 1 500 2 1
> Error:GEN:PinMutex[0] = ch=1, up=1, down=2, t=500ms
I don't get how to supply one channel when I am currently using two.
This is my current setup:
UP_1(1) / DOWN_1(2) / UP_2(3) / DOWN_2(4)
What am I doing wrong?
The ChannelIndex is a channel, PinDown/PinUp are PINS, like P9, etc, not channels. You dont need to set anything for them in www panel. #setMutex MutexIndex ChannelIndex DelayMs PinDown PinUp setMutex 0 0 500 9 10 setMutex 1 1 500 11 12
I don't need to, or shouldn't?
Should I unset the configuration for the buttons(8,9,10,11), the relays(24,6,26,14), or both?
Your example with 9,10,11,12 matches the buttons but somehow off-by one on purpose or were the pin numbers a random example?
Without unsetting anything I still get the GEN err:
setMutex 0 0 500 6 24
> Error:GEN:PinMutex[0] = ch=0, up=24, down=6, t=500ms
setMutex 0 0 500 9 10
>Error:GEN:PinMutex[0] = ch=0, up=10, down=9, t=500ms
I used random pin indexes. This gen err is just a log message for quick testing.
I think you should not have set pins in html page. That can interfere with driver.
Hmm, but if I don't set the pins for Rel and run this:
startDriver PinMutex
setMutex 0 0 500 6 24
setMutex 1 1 500 14 26
I don't have a way to control things anymore
If I do set them back, switching them to ON makes the relays turn on then immediately turn off, setting to OFF has no effect.
ahh, i see, obk automatically detects relays, if no relays are found, then no buttons are shown. if that's the case, you need to go to web app and manually set channel type for your channels to, idk, for now maybe to Toggle or to LowMidHigh as a placeholder, I need to add a channel type for you
So so far I have this:
startDriver PinMutex
setMutex 0 0 500 6 24
setMutex 1 1 500 14 26
// This aliased command will turn off relay on Channel after 10 seconds
// addRepeatingEvent [IntervalSeconds][RepeatsOr-1][CommandToRun]
alias turn_off_after_time_1 addRepeatingEvent 35 1 setChannel 0 0
alias turn_off_after_time_2 addRepeatingEvent 30 1 setChannel 0 0
alias turn_off_after_time_3 addRepeatingEvent 35 1 setChannel 1 0
alias turn_off_after_time_4 addRepeatingEvent 30 1 setChannel 1 0
// this will run the turn off command every time that Channel becomes 1 or 2
addChangeHandler Channel0 == 1 backlog turn_off_after_time_1
addChangeHandler Channel0 == 2 backlog turn_off_after_time_2
addChangeHandler Channel1 == 1 backlog turn_off_after_time_3
addChangeHandler Channel1 == 2 backlog turn_off_after_time_4
I have a couple issues with this setup (which otherwise now seems to work fine with the new driver):
- I don't understand what this extra button column that's missing in the web app is:
-
I am not able to make the physical buttons work properly, I do not see how I can now make them toggle the separate UP/DOWN states.
-
The turn_off_after_time aliases do not die if the channel is set to 0, so if I toggle up, then down, there will be two timers running to turn the channel off at pretty much random times.
hmm
for buttons, you could just use Btn_SCriptOnly and just script click event to do setChannel 1 2 or setChannel 1 1 or setChannel 1 0
"Remember that some pin roles require second channel field, which is only available on native interface right now."
Right, that extra field business is on me, my bad.
Now I only have the issue with the turn_off aliases not dying if the state is changed more than once, which is not that bad.
I have ended up with this so far:
startDriver PinMutex
setMutex 0 0 500 6 24
setMutex 1 1 500 14 26
// This aliased command will turn off relay on Channel after 10 seconds
// addRepeatingEvent [IntervalSeconds][RepeatsOr-1][CommandToRun]
alias turn_off_after_time_1 addRepeatingEvent 40 1 setChannel 0 0
alias turn_off_after_time_2 addRepeatingEvent 30 1 setChannel 0 0
alias turn_off_after_time_3 addRepeatingEvent 40 1 setChannel 1 0
alias turn_off_after_time_4 addRepeatingEvent 30 1 setChannel 1 0
// This will run the turn off command every time that Channel becomes 1 or 2
addChangeHandler Channel0 == 1 backlog turn_off_after_time_1
addChangeHandler Channel0 == 2 backlog turn_off_after_time_2
addChangeHandler Channel1 == 1 backlog turn_off_after_time_3
addChangeHandler Channel1 == 2 backlog turn_off_after_time_4
// Aliases to be able to toggle between on/off state with physical buttons
alias click_up_1 if $CH0!=2 then "setChannel 0 2" else "setChannel 0 0"
alias click_down_1 if $CH0!=1 then "setChannel 0 1" else "setChannel 0 0"
alias click_up_2 if $CH1!=2 then "setChannel 1 2" else "setChannel 1 0"
alias click_down_2 if $CH1!=1 then "setChannel 1 1" else "setChannel 1 0"
addEventHandler OnClick 8 click_up_1
addEventHandler OnClick 9 click_down_1
addEventHandler OnClick 10 click_up_2
addEventHandler OnClick 11 click_down_2
{
"vendor": "Tuya",
"bDetailed": "0",
"name": "Full Device Name Here",
"model": "enter short model name here",
"chip": "BK7231N",
"board": "TODO",
"flags": "1024",
"keywords": [
"TODO",
"TODO",
"TODO"
],
"pins": {
"7": "Btn_Tgl_All;0;0",
"8": "Btn_ScriptOnly;0;1",
"9": "Btn_ScriptOnly;0;2",
"10": "Btn_ScriptOnly;1;1",
"11": "Btn_ScriptOnly;1;2",
"22": "WifiLED_n;0"
},
"command": "",
"image": "https://obrazki.elektroda.pl/YOUR_IMAGE.jpg",
"wiki": "https://www.elektroda.com/rtvforum/topic_YOUR_TOPIC.html"
}
Looking forward to have this in officially, I'll try setting it up for real, fingers crossed no more relays eat it and this was truly the issue.
we can have it officialy, or just do a better shutter driver as a next step if you have time, would you be able to post later a summary and guide of our work to elektroda?
the most basic solution to "not canceling" is to use addRepeatingEventID and then cancelRepeatingEvent, or, should i say, first cancelRepeatingEvent and then add fresh event
maybe i could even do one step more and add addRepeatingEventUID (unique id) that automatically cancels previous instance?
channel type...
we can have it officialy, or just do a better shutter driver as a next step if you have time, would you be able to post later a summary and guide of our work to elektroda?
I don't mind, I'd be mostly copypasting from my last post here anyways.
Though I suppose I'll wait til this is merged into the main build, as to not to have to rewrite it later.
maybe i could even do one step more and add addRepeatingEventUID (unique id) that automatically cancels previous instance?
That sounds neat and simpler for the user to script
added addRepeatingEventUID , not tested yet
hey , any feedback, news?
I have not tried the repeating events, but I have been running the custom build (pinmutex_9c30a7621d99) without a hitch, so far the relays have survived, so I suppose lack of mutexing was indeed my root issue.
EDIT: I did the writeup, kept it small with keeping the scripting and config portions in one place - here on GH.
Anything I can do to help get this in master?
This can be easily merged, but probably not enabled by default due to flash size limitations
Does this mean it'd get a separate build, for example like IrRemoteESP does?