smorgasbord Posted November 7 Posted November 7 I'm slowly groking how EISY/ISY programming works. My first learning was that If-Then-Else is really When-Then-Else. That is the If() block is called when something inside it changes (assuming your variables, if any, are State and not Integer). The second was that programs are not re-entrant. If a program is called while it is still running, that first "instance" will terminate at the next Wait or Repeat line. No passing Go or collecting $200 - the rest of that program won't be called. Instead the new "instance" of the program runs. After instrumenting my code with lots of UD Mobile notifications, I'm seeing that if in MyProgram1 you have: Run Program 'MyProgram2' (If) Then MyProgram2 will run the If block and execute either Then or Else...BUT The execution of MyProgram1 does NOT wait for MyProgram2 to finish executing. It's not on a Call Stack, it's just you have multiple programs running simultaneously. I assume this is the same whether calling the (If) or (Then) or (Else) blocks directly. If I'm correct, this means that I can't use this mechanism to have subroutines. Which I'd really like to have since it prevents duplicating the same code in multiple programs. So, my real question is: How to have subroutines? TIA Quote
dbwarner5 Posted November 7 Posted November 7 If your goal is to have Program 2 run "in the middle" of program 1, you can put a wait in program one, right after the "call" for a length of time you need for program 2 to complete. Just be aware that program 2 can NOT change the If state of program one in any way, or program one will either start over or run false etc, as it will be re-evaluated at the WAIT. Quote
larryllix Posted November 8 Posted November 8 Just call program2 from program1, and if you don't want program2 to be self-triggered just disable it. Enable/disable of any program only affects the If section triggers. The code will still run and the conditions will only act as conditions/filters. However program1 will not wait for program2 to return. All programs surrender their current time slice to the ISY executive logic engine, and I/O handlers, when encountering a Wait or Repeat program line, to be continued when the system "gets the chance" at the end of the programmed Wait or Repeat time. Quote
smorgasbord Posted November 8 Author Posted November 8 (edited) I just ran into a related issue with a hot water recirculating pump routine. I wanted movement in a bathroom to run the pump for 2 minutes to get the hot water into the pipes. But, if the pump has been recently run (say 15 minutes), it shouldn't run because it's wasteful. So, I wrote this program: If 'Bathroom Motion-Sensor' is switched On And $RecirRanRecently is not 1 Then $RecirRanRecently = 1 Set 'Recir Pump' On Wait 2 minutes Set 'Recir Pump' Off Wait 13 minutes $RecirRanRecently = 0 Else - No Actions - (To add one, press 'Action') Now, given that there is no Reentrancy and no Call Stack, I understand why it fails, but don't know the best way to fix. The first time through it works. And the second time through it'll work, too. But, if that second time is rejected for being too soon (RecirRanRecently is 1), then first instance is terminated at one of the two Waits, and so RecirRanRecently is never reset to 0. And so the pump would never run again until reboot initializes RecirRanRecently to 0. EDIT: I'm not using the time-out in the motion sensor hardware because I have another program that runs the pump on timed intervals (every half hour) and it uses the same RecirRanRecently variable in an attempt to get this motion program to not run soon after the timer program rang What's the best way to accomplish this? Edited November 8 by smorgasbord Quote
dbwarner5 Posted November 8 Posted November 8 @smorgasbord Try making your if statement Bathroom Motion-Sensor' is switched On And $RecirRanRecently is 0 And then eliminate the first line in your THEN. As you have it written, when it hits the first WAIT, the IF is re-evaluated. Since you just changed the variable to a 1, it fails the IF and turns False, stopping the program. Quote
smorgasbord Posted November 8 Author Posted November 8 RecirRanRecently is not a State variable, so the IF isn't re-evaluated. Isn't convention to put a lower-case "s" in front of State variable names? I'm trying new program logic now, where I have double-stacked routines to perform the test and then the run. I'll post here in a little bit if it looks like it's working. Quote
dbwarner5 Posted November 8 Posted November 8 19 minutes ago, smorgasbord said: RecirRanRecently is not a State variable, so the IF isn't re-evaluated. Isn't convention to put a lower-case "s" in front of State variable names? I'm trying new program logic now, where I have double-stacked routines to perform the test and then the run. I'll post here in a little bit if it looks like it's working. Ok.. that makes more sense then now.. Your motion sensor could be turning off, which would also stop the program, and then back on, restarting the program. How do you have that set up? Quote
smorgasbord Posted November 9 Author Posted November 9 (edited) OK, I ended up with 2 variables and 4 programs: RecirRanRecently: An integer (not state) that is True (1) if pump has recently run sOnVacay: A state variable that is True if we've set a Vacation Mode, which stops the pump from running automatically and turns lights on/off semi-randomly. Repeat Loop(): A "Repeat While" loop that asks to run the Pump every 35 minutes. Started at 7am and stopped at 10:30pm. Bathroom Motion(): When the Motion Sensor detects motion, asks to run the Pump Run If(): If Pump hasn't been run in last 15 minutes, runs the Pump routine Run Once(): The routine that runs the pump. Only the "THEN" block is called and only from Run If(), so the Waits don't get interrupted. Uses $RecirRanRecently variable to prevent Run If() from calling it when it shouldn't. Runs pump for 1.75 minutes and then Waits for 13.25 minutes. Run Once: If - No Conditions - (To add one, press 'Schedule' or 'Condition') Then $RecirRanRecently = 1 Set 'Recir Pump' On Wait 1 minute and 45 seconds Set 'Recir Pump' Off Wait 13 minutes and 15 seconds $RecirRanRecently = 0 Else - No Actions - (To add one, press 'Action') —— Run If: If $RecirRanRecently is not 1 Then Run Program 'Run Once' (Then Path) Else - No Actions - (To add one, press 'Action') —— Bathroom Motion: If 'Bathroom Motion-Sensor' is switched On And $sOnVacay is not 1 And $RecirRanRecently is not 1 Then Run Program 'Run If' (If) Else - No Actions - (To add one, press 'Action') —— Repeat Loop: If From 6:59:00AM To 10:31:00PM (same day) And $sOnVacay is not 1 Then Repeat While $sOnVacay is not 1 Run Program 'Run If' (If) Wait 35 minutes Else - No Actions - (To add one, press 'Action') Run If() has two Waits that combine for a 15 minute minimum time period between successive pump runs. The Repeat Loop() program only asks for pump runs every 35 minutes. Motion in the bathroom will ask for a pump run if the 15 minute minimum time has elapsed. While Repeat Loop() only runs during waking hours, motion in the bathroom at any time can run the pump. I thought about trying to reduce this to 3 programs instead of 4, but since Repeat Loop() might ask for a pump run soon after a Bathroom Motion requested and granted pump run I think it's needed. If we could compound the While clause of the Repeat instruction, such as: Repeat While ( ($sOnVacay is not 1) AND (sRecirRanRecently is not 1) ) Which isn't possible as I understand it. I could maybe create a third variable and have it be the sum of those two variables, and then have Repeat While ThirdVariable is 0, but I don't know about addition and of an integer and a state. Thoughts/ideas welcome. Edited November 9 by smorgasbord Quote
smorgasbord Posted November 9 Author Posted November 9 12 hours ago, dbwarner5 said: Your motion sensor could be turning off, which would also stop the program, and then back on, restarting the program. How do you have that set up? Motion sensors set to ON Commands only, and there are no programs looking for a "switched Off." I also have about a 5 minute time-out so the motion sensor isn't constantly sending commands. Quote
apostolakisl Posted November 10 Posted November 10 (edited) Typically you disable the program rather than using lots of variables. Also, for flags, just use a PGM status rather than a 0/1 variable. Pgm1 If motion And PGM on vacation false Then Run then pgm2 Pgm2 disabled If blank Then Disable pgm1 Turn on pump Wait 15 minutes Enable pgm1 Turn off pump Only caveat is if you happen to reboot during the 15 minute wait, the program will be disabled at start and be stuck. So I use a single program that runs at startup to ensure that all of those programs are set to the correct state. As a side note, programs with blank if will run true if set to run at startup. Edited November 10 by apostolakisl Quote
larryllix Posted November 10 Posted November 10 (edited) Rethought logic Edited November 10 by larryllix Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.