sperok Posted June 24, 2011 Posted June 24, 2011 I am implementing ISY control over EZIO8T relays (EZFLORA does not support multiple zones on at once) to create a very flexible irrigation system covering 40+ valves. In building the system one critical issue is how to deal with occasional communication failures. My experience is that if a program sends an insteon command to turn a valve on or off, and a communication failure occurs, the program simply continues and the valve state is indeterminate. A subsequent (non-error) query of the valve will return the correct state. How do experienced ISY programmers deal with this sort of error condition? Do you simply repeat sending the command until the status changes? Yes, getting rid of the communication failure would be a good thing to do, but these are very intermittent and tough to pin down. When it comes to leaving the water running, I'd really like a very reliable solution. The approach I have taken to solving the problem is illustrated below. I'd appreciate feedback on whether this actually adds any reliability or if it causes more problems than it solves. The huge downside of this approach is that it requires 3 variables and 3 programs per valve, so I'm now stuck maintaining 132+ programs for the 44 valves ... For anyone interested in taking a look, here are the main components of the "reliable" irrigation controller: ---- Functionality ----- 1. Reliably turn valves on/off 2. Allow grouping of related valves 3. Support concurrent start of valves in one group (for drip applications) with independent run times 4. Support sequential operation of valves in one group without the need to specify start times for each valve (run one after another) 5. All run-times managed through the "variables" tab without updating programs 6. Very flexible watering schedules 7. Mutual exclusion of groups to prevent overloading pump (can't run two groups at once) 8. Scaling allows all valves to be run at 0-100% of normal run-time ---- Variables used for each valve ----- INTEGER runtime. = xx /* Amount of time the valve should remain open */ STATE timer. = xx /* This gets set > 0 to enable a valve and counts down 1/minute */ group. = [LAWN|VINEYARD|OLIVES|LANDSCAPE] /* The valve needs to belong to a group */ ---- "Global" Variables ---- irrigation.master = [ENABLED|DISABLED] /* Turn the irrigation system on/off globally */ irrigation.scalefactor = [0-100] /* Scale the run-time for a valve by 0-100% */ irrigation.group = [iDLE|LAWN|VINEYARD|OLIVES|LANDSCAPE] /* Only valves that match the current group are allowed to run */ irrigation.counter = xx /* this is used to cycle through the valves in a group */ ---- Programs for each valve ----- /* To turn a valve on it is required to set $irrigation.group and $timer.. This should ** continually retry turning the valve on every 10 seconds while the status is Off, the timer is > 0 ** and the valve belongs to the current $irrigation.group. This sample code is for the valve ** named "vineyard_1" which is located on EZIO8T #1, Relay #1, designated S1V1 */ Program: S1V1-On If Status 'Irrigation and Sensors / Sprinkler 1 / 1.Vineyard 1' is Off And $timer.vineyard_1 > 0 And $irrigation.group is $group.vineyard_1 Then Repeat Every 10 seconds Set 'Irrigation and Sensors / Sprinkler 1 / 1.Vineyard 1' On /* Here is the corresponding code to turn a valve off when the timer pops or group changes. ** Keep trying until the status is off. This counts on the REPEAT clause running until the status changes. ** If the valve fails to shut off the timer will continue to pop with values < 0 every minute. */ Program: S1V1-Off If Status 'Irrigation and Sensors / Sprinkler 1 / 1.Vineyard 1' is On And ( $irrigation.group is not $group.vineyard_1 Or $timer.vineyard_1 <= 0 ) Then Repeat Every 10 seconds Set 'Irrigation and Sensors / Sprinkler 1 / 1.Vineyard 1' Off /* Decrement the valve timer every minute if the valve is on. ** We let this go negative so that it will cause a trigger to pop every minute if the valve fails to shut off at 0. */ Program: S1V1-Timer If Status 'Irrigation and Sensors / Sprinkler 1 / 1.Vineyard 1' is On Then Wait 1 minute $timer.vineyard_1 -= 1 /* If any valve in a group is on the status of this program is TRUE. ** Once all the valves in the group have turned off the status goes FALSE */ Program: Vineyard Group On If Status 'Irrigation and Sensors / Sprinkler 1 / 6.Vineyard 6' is On Or Status 'Irrigation and Sensors / Sprinkler 1 / 5.Vineyard 5' is On Or Status 'Irrigation and Sensors / Sprinkler 1 / 4.Vineyard 4' is On Or Status 'Irrigation and Sensors / Sprinkler 1 / 3.Vineyard 3' is On Or Status 'Irrigation and Sensors / Sprinkler 1 / 1.Vineyard 1' is On Then - No Actions - (To add one, press 'Action') /* Increment the $irrigation.counter to move to the next set of valves within a group ** Wait 5 seconds to "debounce" the Off signal */ Program: Increment Vineyard Group If Program 'Vineyard Group On' is False Then Wait 5 seconds $irrigation.counter += 1 /* If $irrigation.master is set to DISABLED then shut everything off */ Program: Force Everything Off If $irrigation.master is $DISABLED Then $irrigation.group = $IDLE $irrigation.counter = 0 Run Program 'Reset all timers' (Then Path) /* Turn everything off and water the vineyard. This can be invoked from ** a schedule or from a program bound to a keypad. By setting a group ** then setting the $irrigation_counter, the corresponding program within ** the group will get invoked (see below). */ Program: Water the Vineyard If - No Conditions - (To add one, press 'Schedule' or 'Condition') Then Run Program 'Force Everything Off' (Then Path) Wait 5 seconds $irrigation.group = $VINEYARD Wait 2 seconds $irrigation.counter = 1 /* Within the Vineyard group there are multiple programs which run in sequence. ** When $irrigation.counter is = 1 the "01-Vineyard Blocks 1 and 4" program will ** trigger. It will startup 2 valves a few minutes apart. Once these valves have ** finished (their run-times could be different) the "Vineyard Group On" will go ** FALSE. When that happens "Increment Vineyard Group" will trigger and $irrigation.counter will increment ** which will then trigger "02-Vineyard Block 3". ** ** Note the implementation of the scalefactor, allowing watering times to be globally modified by ** changing $irrigation.scalefactor to compensate for unusually wet, dry, hot or cool conditions. ** ** The good news - the state machine for the valves is easy to see based on the naming conventions ** and states don't need to know about each other. ** ** Folder: Group-Vineyard is enabled only when $irrigation.group = $VINEYARD ** These programs are inside the folder. */ Program: 01-Vineyard Blocks 1 and 3 If $irrigation.counter is 1 Then $timer.vineyard_1 = $runtime.vineyard_1 $timer.vineyard_1 *= $irrigation.scalefactor $timer.vineyard_1 /= 100 Wait 5 minutes $timer.vineyard_4 = $runtime.vineyard_4 $timer.vineyard_4 *= $irrigation.scalefactor $timer.vineyard_4 /= 100 /* Once $irrigation.counter increments, the next program is triggered */ Program: 02-Vineyard Block 3 If $irrigation.counter is 2 Then $timer.vineyard_3 = $runtime.vineyard_3 $timer.vineyard_3 *= $irrigation.scalefactor $timer.vineyard_3 /= 10 /* Set the schedule for the Vineyard */ Program: Schedule-Vineyard If On Tue Time is 10:00:00PM Then Run Program 'Water the Vineyard' (Then Path) /* Turn a group on from a keypad */ Program: Vineyard Manual On If Control 'Irrigation and Sensors / Vineyard-2' is switched On Then $irrigation.master = $ENABLED Run Program 'Water the Vineyard' (Then Path) /* And turn it off */ Program: Vineyard Manual Off If Control 'Irrigation and Sensors / Vineyard-2' is switched Off Then $irrigation.group = $IDLE /* Reflect the status of a group on Keypad LED's */ Program: Vineyard Scene If Program 'Vineyard Group On' is True Then Set Scene 'Scenes / Irrigation / Vineyard' On Else Set Scene 'Scenes / Irrigation / Vineyard' Off
Recommended Posts