Multi-D Arrays Question
I am trying to shorten the code I wrote for a 232-controlled relay unit. I don't know what type of variable, constant, array, etc. to use for this. Here is what I have:
BUTTON_EVENT[dvCV7Tp,40] //Relay8Net Zone 1 (open)
{
PUSH:
{
If (nRelay2Status = 1)
{
CANCEL_WAIT 'relay 2 on'
SEND_STRING dvRelay, "$40,$01,$42" //releases relay 2
}
If (nRelay3Status = 1)
{
CANCEL_WAIT 'relay 3 on'
SEND_STRING dvRelay, "$40,$01,$43" //releases relay 3
}
Wait 2 //delay needed to give relay unit time to recover after above command
SEND_STRING dvRelay, "$40,$01,$31"
Wait 50 'relay 1 on'
SEND_STRING dvRelay, "$40,$01,$41"
}
}
BUTTON_EVENT[dvCV7Tp,41] //Relay8Net Zone 2 (close)
{
PUSH:
{
If (nRelay1Status = 1)
{
CANCEL_WAIT 'relay 1 on'
SEND_STRING dvRelay, "$40,$01,$41"
}
IF (nRelay3Status = 1)
{
CANCEL_WAIT 'relay 3 on'
SEND_STRING dvRelay, "$40,$01,$43"
}
Wait 2 //delay needed to give relay unit time to recover after above command
SEND_STRING dvRelay, "$40,$01,$32"
Wait 50 'relay 2 on'
SEND_STRING dvRelay, "$40,$01,$42"
}
}
BUTTON_EVENT[dvCV7Tp,42] //Relay8Net Zone 3(STOP)
{
PUSH:
{
If (nRelay1Status=1)
{
CANCEL_WAIT 'relay 1 on'
SEND_STRING dvRelay, "$40,$01,$41"
}
If (nRelay2Status=1)
{
CANCEL_WAIT 'relay 2 on'
SEND_STRING dvRelay, "$40,$01,$42"
}
Wait 2 //delay needed to give relay unit time to recover after above command
SEND_STRING dvRelay, "$40,$01,$33"
Wait 50 'relay 3 on'
SEND_STRING dvRelay, "$40,$01,$43"
}
}
Basically, I have the relays programmed so that when one relay is triggered, the other two open. (Its for shades UP, DOWN, and STOP). As you can see, I am accomplishing this with the use of a variable for each relay. I would like to stack the button events, but I think I need a multi-dimensional array and get_lasts to make this happen. Something like:
VOLATILE INTEGER nTotal_Relays[] = {43,44,45}
VOLATILE INTEGER Curr_Relay
BUTTON_EVENT[dvCV7Tp,nTotal_Relays] //relay control, buttons 43,44,45
{
PUSH:
{
Curr_Relay = get_last(nTotal_Relays) //chooses relay1,2or3
Switch (Curr_Relay)
{
Case 43:
{}
Case 44:
{}
Case 45:
{}
}
}
}
Where I get stuck is trying to determine the state of my other variables, one for each relay. I was thinking of a multi-dimensional array for those as well, so that I could store the 1 and 0 values for each, and then simply reference the array, but what would I do if i want it to cross-check multiple items to then send the appropriate string, as I did the long way, up above? I don't think I have a grasp on the Multi's yet.
Comments
DEFINE_MUTUALLY_EXCLUSIVE
( [dv_Relay,1] , [dv_relay,2], [dv_relay,3] , etc... )
or if your channels are consecutive
( [dv_realy,1] .. [dv_realy,5] )
this will kill any on relays when you turn on some other relay in the bunch automatically.
now for the array question.
I would probably run the array through a for loop, check for new on state and kill all, then tun on new relay.
Hope that helps
e
The nice thing about arrays is you can loop them. The problem with your code is that you're using named waits, which you wouldn't be able to avoid a switch/case. What you could use instead of named waits would be timelines. This way, in the start of your button event you can run a quick for-loop to check if the relay was on or off. Sort of something like this:
FOR(i=1;i<=3;i++) { IF(relays[i] && i != currRelay) { // Equal to canceling a named wait IF(TIMELINE_ACTIVE(RELAY_TL[i])) TIMELINE_KILL(RELAY_TL[i]); // Send the string to the specific relay SEND_STRING dvRelay, "$40,$01,$40 + i" } }This would check only the relays, if the timeline is active, kill it (essentially destroying a named wait), and the string is modified by which relay we're checking. Storing things in variables can be rather powerful and used to shorten a lot of code.
The later in the button event, you'd go on to recreate any timelines, again modifying the strings based on which relay we're controlling. (I.e. "$40,$01,$40 + CurRelay" or "$40,$01,$30 + CurRelay")
One thing on the GET_LAST, I'd store that value in a STACK_VAR rather than a global variable. This way it's destroyed when the code is finished. No need to keep the value after the button event is finished.
Just my 2 cents.
I don't think this will work as it appears the relays reside on a third-party controller.
As to the code question, I would probably create a functions for sending the commands like so:
define_constant integer RelayOn = 1; integer RelayOff = 0; integer nRelayBtns[] = {40,41,42}; define_variable integer nActiveRelay; define_function fnSendRelayCmd(integer nRelay, integer nState){ stack_var char cmd; cmd = $30 + ((!nState) << 4) + nRelay; send_string dvRelay,"$40,$01,cmd"; if(nState){ nActiveRelay = nRelay; cancel_wait 'PulseTime';//Reset off delay. wait 50 'PulseTime' fnSendRelayCmd(nActiveRelay, RelayOff); // Turn off relay after 5 seconds. } else if(nRelay == nActiveRelay) nActiveRelay = 0; } define_function fnDoExclusiveRelayOn(integer nRelay){ if(nActiveRelay){ if(nRelay <> nActiveRelay){ fnSendRelayCmd(nActiveRelay,RelayOff); wait 2 fnSendRelayCmd(nRelay,RelayOn); } }else{ fnSendRelayCmd(nRelay,RelayOn); } } define_event button_event[dvCv7Tp,nRelayBtns]{ push:{ fnDoExclusiveRelayOn(get_last(nRelayBtns)); } }I think I have the logic correct, but I generally code a 1 in place of a 0 on the first try and have to find it after loading and testing
Jeff