ON/OFF PATTERN SEQUENCER
Ever wanted a set of Vera-controlled devices to turn themselves ON and OFF according to a preset repeating pattern? With lots of options for customizing the timing and complexity of that pattern?
My criteria for designing this “Pattern Sequencer” were as follows:
- It had to use Reactor as its foundation, and be easy to create;
- It must ‘start’ and ‘stop’ using a virtual switch (e.g. Switchboard device);
- The sequencer must run indefinitely with low processing overhead;
- Each step of its pattern must be completely configurable;
- Use Expressions wherever possible to simplify setup.
Here’s what I came up with…
STEP 1 - GATHER THE DEVICES
A. Set up a fresh ‘NUL’ Reactor sensor expressly for this project.
B. Also select (or use Switchboard to create) a virtual switch.
(We will refer to this virtual switch as ‘runSw’ in the setup below)
C. Decide which device(s) you will want to be turned on/off.
(We will refer to these 3 devices as ‘dev1’, ‘dev2’ and ‘dev3’ below)
STEP 2 - DECLARE THE REACTOR EXPRESSIONS
devIndex := (no expression / leave blank)
devNext := if(devIndex+1<=len(devSequence),devIndex+1,1)
devSequence := "abcdefg"
devSeq := sub(devSequence,devIndex,devIndex)
dev1Patt := "acdfg"
dev2Patt := "bceg"
dev3Patt := "def"
STEP 3 - CREATE THE CONDITIONS
The Reactor (set to ‘NUL’ mode) requires a minimum of 2 Condition subgroups, but ideally will contain N+1 subgroups (all set to ‘AND’ mode) to control N devices, defined as follows:
Subgroup ‘devCycle’
▼Output Control (for the subgroup, not the Condition inside it)
:= [PULSE] true for [4] seconds [repeat] after [8] seconds
Condition := [Device State] [runSw] [Status] [equals] [1]
Subgroup ‘dev1’
Condition := [Expression Variable] [dev1Patt] [contains] [ {devSeq} ]
Subgroup ‘dev2’
Condition := [Expression Variable] [dev2Patt] [contains] [ {devSeq} ]
Subgroup ‘dev3’
Condition := [Expression Variable] [dev3Patt] [contains] [ {devSeq} ]
(…continue this same pattern adding subgroups ‘dev4’, ‘dev5’, etc. and their corresponding dev4Patt, dev5Patt, etc. Expression variable declarations, as needed for your particular setup.)
STEP 4 - ASSIGN THE ACTIVITIES
When ‘devCycle’ is TRUE
[Set Variable] [devIndex] = [ {devNext} ]
When ‘dev1’ is TRUE
[Device Action] [‘dev1’] [Turn on or off] [1]
When ‘dev1’ is FALSE
[Device Action] [‘dev1’] [Turn on or off] [0]
(Repeat this TRUE/FALSE 1/0 pattern for remaining devices)
SETUP IS COMPLETE!
To run the Pattern Sequencer, simply turn ON the virtual switch you selected in Step 1B, above. Your selected devices will begin alternating ON and OFF according to the match-pattern defined for them in variables ‘dev1Patt’, ‘dev2Patt’, etc. Turning off ‘runSw’ stops it.
HOW IT WORKS
The length of the string declared in the devSequence variable determines how many distinct ‘steps’ your pattern will contain. The characters comprising devSequence – in conjunction with the strings in dev1Patt, dev2Patt, etc. – will directly govern which devices switch ON at each step.
For example, in its initial configuration, devSequence=“abcdefg” gives the Pattern Sequencer 7 discrete steps (with no repeats), for which dev1Patt=“acdfg” will cause device ‘dev1’ to be turned ON, OFF, ON, ON, OFF, ON, ON.
Similarly, dev3Patt=“def” causes device ‘dev3’ to be turned OFF, OFF, OFF, ON, ON, ON during the same cycle. The cycle then restarts from the beginning, and continues cycling until switch ‘runSw’ is turned OFF.
This lexicon enables you to create patterns ranging from very short-and-simple (“ABBA”) to incredibly complex (“abcbWrgb123A”), using character sequences of arbitrary length. The only requirement is that the characters used in the devXPatt strings be some subset (e.g. “aWb2A”) of those in devSequence, since alphabetic matching between these two elements determines when subgroup devX will activate.
NOTE: Order is unimportant here, since with devSequence=“abcbWrgb123A”, both dev1Patt=“aWb2A” and dev1Patt=“Aab2W” mean the same thing to the Pattern Sequencer; namely, “Turn ON device ‘dev1’ during the 1st, 2nd, 4th, 5th, 8th and last steps”.
STEP 5 - FINE TUNING AND CUSTOMIZATION
You may want to adjust such things as the Pattern Sequencer’s speed of execution, or whether it resets the pattern every time it stops running.
OPTION A: Reset pattern to 1st step when sequence stops.
This seemingly simple modification requires yet another subgroup, let’s call it ‘devReset’, with the following:
Condition := [Device State] [runSw] [Whenever the device is turned on or off / Status::SwitchPower1] [equals] [ 0 ]
and
Activity ‘When devReset is TRUE’ := [Set Variable] [devIndex] = [ 1 ]
NOTE: One might be tempted to try placing this action inside ‘When devCycle is FALSE’, but that would cause the sequence to reset itself continually, instead of solely when the cycling has stopped.
OPTION B: Slow down sequencer speed (faster possible, but not recommended!).
In the ‘devCycle’ subgroup under Conditions, click the ▼Output Control drop-down and replace ‘output goes true for [ 4 ] seconds after [ 8 ] seconds’ with any numeric values of the form X | 2X (e.g. 5 | 10, or 120 | 240), although really anything goes.
OPTION C: Return all devices to OFF when sequence stops running.
First perform Option A (above), then make sure each devXPatt string does not contain the first character of the devSequence string. All devices will then turn off when sequencing stops.
To avoid this ‘All OFF’ effect every time the sequence repeats, modify the Expression variable:
devNext := if(devIndex+1<=len(devSequence),devIndex+1,**2**)
This forces the pattern to resume from the 2nd step instead of the 1st.
==========================