smorgasbord Posted June 13, 2020 Posted June 13, 2020 (edited) I'm trying to get the most control options out of each IOLinc in the hopes of buying fewer of them. I've got an external system that has contact closure/relay outputs and have connected them to IOLinc Sensor inputs. That works well - the external system closes a relay and the IOLinc senses that and a scene gets run to turn on a light or ISY runs a program in which I write to decide what to do. Cool. Now, the light I want to control is on an Insteon Dimmer (2477D) and depending on what was done on the external system I'd like to have the light go to one of two different levels. Is there a way I can write the ISY program to detect a "double-tap" for instance? That would be the ISY program getting a close/open/close within a second or less (maybe ½ second would be better) from the IOLinc and doing something different. My idea is that on first IOLinc Sense Close the ISY program would turn the light to 35% Dim level (perhaps as programmed in the 2477D itself), and then if a second IOLinc Sense Close came in within a ½ second the ISY program would ramp the light up to an 80% Dim level. I assume to do this I would not use a Scene but instead have the IOLinc sense run a program with something like "Control IOLinc1_Sense is On" and inside the Then have a Wait for ½ second and use the ISY program's reentrant capabilities to capture the second On. I don't know how to write this - can someone help? In thinking about this more, since my external system is programmable as well, could I setup a Morse-code like communication channel? Dots and Dashes to have the other system tell the ISY what to do? I know there would be some delay, but for non-timing important things, that would be really cool (and IOLinc buying reducing!). Or, if there's a better way to do this, I'm totally open. thanks! Edited June 13, 2020 by smorgasbord
lilyoyo1 Posted June 13, 2020 Posted June 13, 2020 (edited) You can't send a double tap from the iolinc unless you physically press the button on the side. You could use variables to keep track of how many times a switch is turned on to trigger programs. Edited June 13, 2020 by lilyoyo1
Brian H Posted June 14, 2020 Posted June 14, 2020 (edited) I don't think an I/OLinc Sensor Input can react that fast. You would still have the time needed to send the status change to the ISY994i on the power lines and be processed. The I/OLinc is strictly a power line only module. Edited June 14, 2020 by Brian H
smorgasbord Posted June 14, 2020 Author Posted June 14, 2020 @lilyoyo1 , I'm not sending the double-tap from the IOLinc, I'm sending it to the IOLinc. @Brian H, what timing is the IOLinc capable of discerning? Since this is system to system, I could have the double-tap be within 2 seconds even and that might work (first tap goes to 35% and second tap within 2 seconds goes to 80%). If I wanted to try this out, what would the program look like? Thanks!
mwester Posted June 14, 2020 Posted June 14, 2020 I'm not Brian H, but I can tell you what sort of delays I see from the ISY994i and various devices... generally the ISY is notified of an event almost immediately - one can see the delay, but it's far less than a second. The big problem is that it isn't always so. Sometimes, it's a full second until the ISY appears to notice the event. The worst case is when one has Insteon traffic underway -- it's slow, and I've seen multi-second delays when (for example) I'm syncing the link table on an older Insteon device. So, it might work if you had a one-second delay, or perhaps seconds. But it won't be completely reliable.
Brian H Posted June 14, 2020 Posted June 14, 2020 (edited) I can't help you on if it would work. I don't think the Sensor Input on an I/OLinc is fast enough to see a rapid On, Off, On sequence. I would not be too surprised if it had a small time delay detecting changes. So contact bounce didn't cause errors. I don't think I got an I/OLinc Developers Notes paper. I can check and see if I have anything on it. I did a reverse schematic of the Sensor Input just to see how it roughly worked. Edited June 14, 2020 by Brian H Add Data
ELA Posted June 14, 2020 Posted June 14, 2020 I had tested the reaction time of the I/O linc a while back and my notes say it will detect pulses longer than approx. 40 msec in duration. So it can detect relatively short pulses - however as others have pointed out you need to wait several seconds between "taps" to assure that all communication on the overall network have settled down. That amount of time will be variable depending upon how reliable the network communication may be ( retries take time if the network is marginal). I would wait a minimum of 2 seconds between "tap" events. Write some program/s and try it out. You can use a variable that increments when the "tap" is detected and when the second is detected act on that. Remember to reset the tap counter variable both after the double tap is detected and also after a time delay, if a first is detected but the second is not - within so many seconds. Make an attempt at writing the programs. There are lots of people here that can help if you struggle.
smorgasbord Posted June 14, 2020 Author Posted June 14, 2020 (edited) Frankly, I'm having trouble getting started with the programming. I''ve done a half dozen things in ISY that worked out fine, but I'm used to full-on programming languages like "C" that can have if-then-else's placed anywhere in a routine instead of having to call a program to get and if-then-else clause. And this seems more complicated than the usual. For instance, how do I store Time in a variable so that I can compare the timing of the second tap relative to the first tap? Do I have to manually break down the hours, minutes, seconds into a combined integer? Are there any existing subroutines or code snippets for that? EDIT: I'm running the latest release V4 software. Should I update to V5 to get more functionality? Edited June 14, 2020 by smorgasbord
jfai Posted June 14, 2020 Posted June 14, 2020 (edited) The ISY programming language is geared towards event-driven state machines. Here's a state diagram for your use case (UML): It's straightforward to implement this state machine with the ISY. The state ids are values of an ISY state variable (sTapState). The state transitions are implemented by ISY programs. ISY pseudo code: Program "First tap" if $sTapState is 0 and iolinc.sensor is on then $sTapState = 1 Program "Idle after one tap" if $sTapState = 1 then wait 2s $sTapState = 0 Program "Second tap" if $sTapState = 1 and iolinc.sensor is on then $sTapState = 2 Program "Idle after two taps" if $sTapState = 2 then wait 1s $sTapState = 0 You can use sTapState as condition in other programs, e.g., to set the on level of the dimmer. These programs can probably be "optimized" by using special features of the ISY language (e.g. conditions based on the time elapsed since the last time a program ran, program condition, enabling/disabling programs), but I usually don't bother with optimizations. When the ISY restarts, variables are set to their "init values", which by default is 0, which is the state id of the start state. WAIT statements have special semantics: they cause reevaluation of the program condition and depending on the result may stop program execution - refer to the Wiki. Edited June 14, 2020 by jfai
smorgasbord Posted June 15, 2020 Author Posted June 15, 2020 @jfai, thanks so much! That's 4 programs, two of which start with the same iolinc.sensor event, which means at best they run sequentially. What about this dual-program: KitCab GetTap If Control 'Kitchen Cabinet Pucks / IOL1 Sense from LT KitCabPuck' is switched On Then Run Program 'KitCab DoTap' (If) Else KitCab DoTap If $sTapState is 0 Then $sTapState = 1 Set 'Kitchen Cabinet Pucks / Kitchen Cabinet Pucks Dimmer' 40% Wait 2 seconds $sTapState = 0 Else Set 'Kitchen Cabinet Pucks / Kitchen Cabinet Pucks Dimmer' 85% $sTapState = 0 I'm assuming that KitCab DoTap can be reentrant. Thoughts?
jfai Posted June 15, 2020 Posted June 15, 2020 Quote 6 minutes ago, smorgasbord said: That's 4 programs, two of which start with the same iolinc.sensor event, which means at best they run sequentially. What do you mean by "at best run sequentially"? Maybe your optimized state machine would work. You'd have to test. As I wrote, by and large I don't find optimizations worthwhile. One more advice: I would not add the dimmer control commands to the state transition programs and rather use the state variable as trigger in separate programs (separation of concerns).
smorgasbord Posted June 15, 2020 Author Posted June 15, 2020 1 hour ago, jfai said: What do you mean by "at best run sequentially"? Two of the four programs are based on the iolink.sensor control (sensor status being changed). Since I assume the ISY is single processor/single threaded, only one of those programs can be running at any one time. So, either "First Tap" or "Second Tap" gets run, and then the other program is run. Since the program has a conditional, I imagine they run pretty quickly, though. 1 hour ago, jfai said: One more advice: I would not add the dimmer control commands to the state transition programs and rather use the state variable as trigger in separate programs (separation of concerns). Can you explain this more? Is it a debugging thing or something else? It seems pretty straightforward to have a program that gets called when the iolinc sensor changes state ("control") and then that program done one thing for first tap and another thing for second tap. I've seen that the kind of programming I'm used to is different than what ISY supports, so perhaps there are considerations of which I'm not aware. thanks again.
smorgasbord Posted June 15, 2020 Author Posted June 15, 2020 (edited) OK, I think I see what you mean by "separation of concerns." You're using the 4 programs to set a sTapState variable that is then used by other programs doing the actual On/Off. Separating those makes the logic easier - one set of programs for a variable and then just one program to turn the light on according to the variable. I think you're doing this because ISY doesn't operate like a typical "C" compiler. For instance, calling another program doesn't transfer flow to that program or wait until that program finishes before doing on to the next line after calling the program. I think I got that, but.... I'm also struggling with the "Wait" functionality. The Wiki says (edited for clarity): Quote A program's conditions are reevaluated each time a Wait statement is encountered. What this means is that if a program's Then clause changes a condition which causes the program's overall condition to become false, the current atomic statement group will complete, and at that point execution will transfer from the Then clause to the Else clause. I assumed that the reevaluation driven by a Wait statement occured after the wait. But, that doesn't appear to be true. This program doesn't work: KitCab FirstTap If Control 'Kitchen Cabinet Pucks / IOL1 Sense from LT KitCabPuck' is switched On And $sTapState is 0 Then $sTapState = 1 Set 'Kitchen Cabinet Pucks / Kitchen Cabinet Pucks Dimmer' 35% Wait 2 seconds $sTapState = 0 Else - No Actions - (To add one, press 'Action') What seems to be happening is that the program terminates at the Wait (or I guess the Else clause is getting executed). So, @jfai's separate routines for seeing the state variable work because the state variable isn't changed until after the Wait. Not sure I'm getting this.... Edited June 15, 2020 by smorgasbord
smorgasbord Posted June 15, 2020 Author Posted June 15, 2020 OK, so I caved and created the 4 programs as described, adding the dimmer set to low on FirstTap and dimmer set to high on SecondTap, and I also added a DoOff program. Works well! But, I'm still not understanding how the Wait and condition re-evaluation works. I also came across this old post doing something very similar without variables:
smorgasbord Posted June 16, 2020 Author Posted June 16, 2020 (edited) On 6/14/2020 at 8:06 AM, ELA said: I had tested the reaction time of the I/O linc a while back and my notes say it will detect pulses longer than approx. 40 msec in duration. The system I'm using to close and open relays sensed by the IOLinc has 1/10 second (100msec) granularity. It did appear that 100msec was detected, but I didn't need it to be quite that quick so I set it at 200msec. Seems OK so far. EDIT: After a few days, I've found that I needed to increase the time the contact is closed and/or time spacing between the contacts. I'm now at 0.4 seconds close, then 0.4 open, then 0.4 close. I haven't experimented enough to see if I can have different timings for close and open and still detect the double-tap. Edited June 21, 2020 by smorgasbord
smorgasbord Posted June 21, 2020 Author Posted June 21, 2020 BTW, to help other C programmers coming to ISY, I think it would be worthwhile considering the "If-Then-Else" in programs as a "WhenIf-Then-Else." In other words, the program is automatically invoked when any of the "If" statements have changed status. That is, as long as the program is enabled. If you want to have an If-then-else section inside an existing program, then you should put that into a new program, disable that program, and call that program (Program Run (If)) when you want.
larryllix Posted June 21, 2020 Posted June 21, 2020 5 hours ago, smorgasbord said: BTW, to help other C programmers coming to ISY, I think it would be worthwhile considering the "If-Then-Else" in programs as a "WhenIf-Then-Else." In other words, the program is automatically invoked when any of the "If" statements have changed status. That is, as long as the program is enabled. If you want to have an If-then-else section inside an existing program, then you should put that into a new program, disable that program, and call that program (Program Run (If)) when you want. Wait and Repeat statements ALLOW the system engine to re-evaluate all program triggers, if any condition has changed. This includes the same program's If section as the one containing the Wait or Repeat. Think of them like a surrender of their time slice in a multitasking system. If any condition changes in a program containing that same condition the program will stop what it is doing (if running) and run Then or Else, depending on the outcome of the If section. Disabling does not disable the program, only the triggers in the If section. This affords subroutine style usage. Calling a program as a subroutine does NOT wait for it to return but the second program will launch simultaneously. There is no guarantee of running order. Simple in-line if-then constructs can be done with the ISY Repeat-while construct. Clumsy and ugly but it can be done. It takes the involvement of another variable. In many past threads users have wanted to change the program structure into a When-If-Then-Else sectionalised structure. Some want the same but each If line can be enabled/disabled individually. UDI is slow to respond to these requests as the bit off Zwave with it's constant updates, and dumping the java for HTML5/CSS/js admin console. Lastly, Integer variables do not cause event triggers. State variables do.
Recommended Posts