IPx[yyyy] and IPINVx[yyyy]

CAI_Support

Senior Member
Sometimes, user has need to delay an action after a switch is flipped.  In one recent support case, a customer wants a motor reacting to a switch connected to a TTL input, so that when switch is turned to on, the motor turns on after two seconds, then after switch is turned off, the motor will be turned off after 5 seconds.
 
He developed this logic:

TSTEQ IP4[5000] 0
SET OP1 0
TSTEQ IP4[2000] 1
SET OP1 1

It does turn on output after switch on for two seconds. But when switch set to off, its output immediately turned off.
The correct logic should be

TSTEQ IPINV4[5000] 1
SET OP1 0
TSTEQ IP4[2000] 1
SET OP1 1

That is because the non-blocking delay counts positive going pulse. When it goes from 1 to 0, it should use IPINVx[yyyy] to measure if the timer time out reached.
 
Since I could not post picture on this forum,  I will try to picture it using characters:
for IPx[y] to work, input normally LOW, when high pulse comes, it must stay high longer than y mS to have it reads TRUE
input looks like
           _____y___
__|___|                |_____    input pin  INx[y]
 
                    ____
__________|       |_____    PLC output reading from IPx[y]
 
 
For IPINVx[y], it supposed IPx is normally high, and it will filter out short 0 going pulses.  This is for complementing IPx[y] for different logic needs
 
________                     ___________   input  pin at IPINVBx[y]
     |          |_____y____|
 
______________         ____________ PLC output reading at IPINVx[y]
                            |____|
 
In both cases, short input pulses are filtered out.
 
 
VARx[y] is different from IPx and IPINVx, since VAR can store 32bit signed number.  When it was referenced, it will return previous value that set before, when its timer y mS expired, it will then return current set value.  It only has ONE timer and ONE current value and ONE previous value associated with each VAR.
 
 
OPx[y] can be set to TRUE, before y mS expires, it will return FALSE when reading its state.
 
These non-blocking delays have always caused me issues. Depending on firmware version, it either hasn't worked, hasn't worked as described or hasn't worked reliably. That, or I've simply never clicked with how it works!
 
Adding "active high" and "active low" versions seems to me like a kludge to work around an intrinsic and underlying flaw in the logic.
Might I propose a possible way to fix this for once and for all, that will let you use a single command, with a completely consistent result and syntax?
 
If, on any transition of the selected input, you merely note a precision timestamp of the event - that is all - if it goes low-to-high, or high-to-low, just store the time. Period.
 
Now, in the userspace,   [delay] is simply a test for the difference between the recorded timestamp and the current time. If it's more than the delay, it's true. If less, then false.
And of course, the rest of the command is simply testing the state....  thus
 
    testeq   ip1[1000] 1    reads as  "if input1 has not changed state for 1000ms or more, and is now 1" then the condition is true, and means unambiguously that the input is, and has been high, for a second or more.
 
   testeq   ip1[1000] 0   reads as "if input 1 has not changed state for 1000ms or more, and is now 0" then the condition is true, and means unambiguously that the input is, and has been low, for a second or more. No special case or command required for the inverse logic, no odd behavior, easy to read, can be applied to VARs etc just as suitably.
 
If I've missed a key part of the function, I'd be glad to have it explained, but otherwise perhaps consider this as an enhancement for a subsequent release?
 
If, on any transition of the selected input, you merely note a precision timestamp of the event - that is all - if it goes low-to-high, or high-to-low, just store the time. Period.

Hi Ross,  that was the original logic, but it did not work.  That is why we comes up with IPx[y] and IPINVx[y], after carefully thinking.
 
It might looks straightforward like our original code in 3.02.16 and older firmware.  However, the hardware gate connected to the external input is already changed state by external sources.  So that we can not determine the logic state based on the TTL input hardware pin.  That input state flipping could happen million times in a second with many short pulses, render the logic not working.
 
After careful consideration, we think the best way is to separate them into two operands, one for detecting the incoming 0 -> 1 pulse length, one for detecting the incoming 1->0 pulse length.  Since the system designer always know what orientation and  kind of pulse length he is expecting, this will work.  PLC got the logic 1 or 0 reading from IPx[y] and IPINVx[y] from software logic state, not from hardware direct reading.  
 
IPx without delay/pulse length filtering still read input pins instantly.
 
Older boards really should be updated to newest firmware, so that it will perform consistently.
 
Merry Christmas!
 
CAI_Support said:
If, on any transition of the selected input, you merely note a precision timestamp of the event - that is all - if it goes low-to-high, or high-to-low, just store the time. Period.

Hi Ross,  that was the original logic, but it did not work.  That is why we comes up with IPx[y] and IPINVx[y], after carefully thinking.
 
It might looks straightforward like our original code in 3.02.16 and older firmware.  However, the hardware gate connected to the external input is already changed state by external sources.  So that we can not determine the logic state based on the TTL input hardware pin.  That input state flipping could happen million times in a second with many short pulses, render the logic not working.
 
But... if it was changing even a thousand times a second, a test for   ip1[100] would *always* be false, regardless if the input was 0 or 1, because it wouldn't have been stable for the requesit number of milliseconds ??
 
I suppose there could, in theory, be a very small window of oportunity where it HAS been stable for >100ms (in the above example), but right while you are testing, the input may change. However, that situation could exist under the way you've implemented it now too, I would think? Race conditions can be very hard to trigger.
 
CAI_Support said:
After careful consideration, we think the best way is to separate them into two operands, one for detecting the incoming 0 -> 1 pulse length, one for detecting the incoming 1->0 pulse length.  Since the system designer always know what orientation and  kind of pulse length he is expecting, this will work. 
 
Not sure I agree with you. A device I am about to implement a design with, has an internal current to frequency converter. It has a 1:1 mark/space ratio. I will need to test for it stopping running. It could stop high, or it could stop low. Or, it may not stop at all.
 
I could imagine using a construct like    
    tsteq  ip1[500] ip1
    goto   running
    (do stuff if no signal)
 
The logic of this being "If input1 is the same as input1, and has been for 500ms or more, then go to 'running' else do failed stuff"
Since input1 should always be the same as input1 (and thus, true), it will only be true if it has not changed state for >=500ms
 
How to code THAT using the other two operands, and be readable??
 
Hi Ross,
 
When defining TRUE or FALSE, we can define that as logic high and low, or both high or both low. There must be a reference point for that.  If a TTL input without noise filter, it can alter its internal state millions times in a second on the TTL input pin reading inside CPU. Without prior knowledge looking for positive going pulse or negative going pulse, the logic return is meaningless. A system designer always look for exact signal length and 1 or 0 to make his logic work.
 
Since firmware 3.02.17F, inside WebControl PLC:
IPx is direct driven by TTL IPx pin, that PLC reading is exact the state of the pin on terminal. 
IPx[y] is an internal software state for IPx has been from 0->1 longer than y mS or not.
IPINVx[y] is an internal software state for IPx has been from 1->0 longer than y mS or not(true return 0 indicating actual TTL input state).
 
There are customers wanting to implement detecting both side of pulses by
 
TSTEQ IP1[y] 1
GOTO runP
TSTEQ IPINV1[y] 0
GOTO runN
GOTO again
...
 
So that positive going pulse longer than y mS goes to execute runP code section for positive going pulse,
negative going pulse longer than y mS goes to execute runN section of code for negative going pulses.
 
We analyzed many users' setup and found most users don't have filter on TTL input pins to filter false signals.  IPx[y] and IPINVx[y] are actually software filters inside WC firmware to actually filter out the noises and provide a reliable logic sate for system designers.
_____________
 
This code :

tsteq ip1[500] ip1
goto running
(do stuff if no signal)

showed exactly the problem many system designers facing in older way. when many noise pulses coming without filter, it can be falsely triggered. considering the design need for IP1 normally high to detect longer negative going pulses, that code does not work, TSTEQ will always true even there is no negative going pulses. or the need to detect positive going pulse,  for pulses from 0->1 longer than 500mS, it will not work either, since TSTEQ will always return true after no signal for 500mS.  Prior to 3.02.17f firmware, ipx[y] before y mS expired returns prior state.  But that state can be 1 or 0, does not matter what actually designer wanted to detect is 0->1 or 1->0,  By splitting them into two operands, it is easier to implement a logic reliably.
 
Back
Top