Multiple condition Expression - Nested If Statement?

I am trying to make a comparison between 2 tags in an expression tag to show if my symbol is running, faulted, or stopped

what I am going for is

if Tag 1 and Tag 2 are both true = we are in a “running” state
if nothing is true = we are in a “stopped” state

if only tag 1 is true = “faulted”
if only tag 2 is true = “faulted”

I tried using the example from the user manual but I kept having it so if both tags were true it was giving me the “Tag 2 is positive” result instead of the “both tags are positive result” , So I don’t get it because I assumed that spot is for 1st condition false 2nd condition true ,but its the result I get for both conditions being true?

if ({tag1} > 0 , if ({tag2} > 0 , "Both Tags are positive." , "Tag 1 is positive." ), if ({tag2} > 0 , "Tag 2 is positive." , "Neither Tag is positive." ))

You say your tags can be true, so are they booleans ?
If so, I’d suggest something like this:

if (tag1 && tag2, "both are true",
    if (tag1 || tag2, "only one is true",
        "both are false"
    )
)

if they’re not, as your code suggest, simply replace tag1 and tag2 with a boolean expression:

if (tag1 > 0 && tag2 > 0, "both are above 0",
    if (tag1 > 0 || tag2 > 0, "only one is above 0",
        "both are 0"
    )
)

Technically, || isn’t an xor operator, but if you reach that point then the check for both are true has already been made, which means if a || b returns true then only one can be true.
The fallback then handles the both are false case.

one is a boolean and one is me checking if something is greater than 0 , would that still work?

Yes, just mix and match. Use the boolean value of the boolean tag directly, and use your comparison for the other one.

if (tag1 && tag2 > 0, "both conditions are true",
    if (tag1 || tag2 > 0, "only one is true",
        "both are false"
    )
)

If it makes it clearer, you can think of it like this:

if (tag1 = true && tag2 > 0, "both conditions are true",
    if (tag1 = true || tag2 > 0, "only one is true",
        "both are false"
    )
)

Except you don’t need to explicitly check for truth if your tag is already a boolean.

ah I see, because a true is a 1 right? so its just checking 1 >0

nice, thanks for the help , I didn’t even know you could use && and ||

ill let you know if it works after it runs again

Well, I guess you could technically think about true as 1, but that’s not why I write it like this.
It’s about readability. It doesn’t make much sense with names like tag1 and tag2, but with real names (if you’re following a logical naming convention) it makes things clear and simple.
Let’s say your boolean tag is named something like engine_started, and your value tag is named gear.
To know if you can get your car moving by stepping on the pedal, this is quite clear:

if (engine_started && gear > 0, "car moves",
    if (engine_started || gear > 0, "you're missing one step",
        "you need to turn on the engine and switch on first gear if you want to move"
    )
)

Now, technically, you don’t HAVE to compare gear’s value to 0. If it’s 0, using it in a boolean expression will return false, because it’s 0. You could write

if (engine_started && gear, "car moves",
    if (engine_started || gear, "you're missing one step",
        "you need to turn on the engine and switch on first gear if you want to move"
    )
)

if gear is above 0, then it will be considered true. It will work. But I find gear > 0 brings more meaning to the code. It’s more explicit.

1 Like

its looking like its working!! , thanks again

from the looks of it, it flickers a fault for a second during the transition

so it looks like I need to add a third condition checking that only 1 tag is on for longer then a certain period of time

any idea how I would go about that?

at least that is telling me all 3 of the current conditions are active when they should be

maybe a delay before that or check , does expression have delays?

I’m not sure I understand the issue…
What flickers, and what is the transition you’re talking about ? Can I see the actual thing you’re using ?

the issue is Tag 1 goes true and it takes about half a second before Tag 2 updates over 0

so it will show faulted during that half a second

the if statement you have is working as intended , I just didn’t think of that tiny time in between

You should use binEnc to combine your two tags into a single binary encoded integer. Then use case and test for 0, 1, 2, 4. Using ifs for this is overly complicated

Can you show me how you’re using that expression ? It shouldn’t flicker or anything, there’s no reason any amount of time between activations would lead to a fault…

I don’t find 2 simple ifs to be more complicated than abinEnc and a case :X

Ok so tag 1 is a solenoid and tag 2 is the output value that goes up when that solenoid is activated

if solenoid = true and output is greater than 0 then its running as intended

but i wanted to check if for some reason the solenoid comes on by itself, or there is only an output, then i have a problem I can go investigate on the machine

the flicker only happens on the way back down, the output is at 5 , so once the solenoid shuts off it takes a second for the output to go back to 0 , which is the time i get the fault

I don’t see how that would cause a fault (which I understand as ‘makes the expression error out’).
Show us (like, a screenshot or a gif) how you’re using it.

Expression

This expression creates a status based on the 2 tags

status

which is just bound to a pump symbol’s state in perspective , so i can visually see if running stopped or faulted

the output value goes between -.03 and 5 whenever the solenoid comes on so I just used 0 as the check since its default value when its not on is below 0

the output is quick to go from -.03 above 0 because its next to it, but once its up at 5 , it takes time on the way back down

so if the solenoid turns Off the 5 is tripping the Fault check until it gets back down to 0 because it takes 1 second for it to go from 5 - 0

OOOh okay I get it, when you say you get a fault, you mean it’s the status faulted returned by the expression !
I thought you were getting an error while the value was coming back down to 0…

Well, I guess you could throw in timestamp checks on {SolenoidON}… but that gets messy real quick.

is there any way to delay in expressions? if it did the or check 2 seconds after the both check it wouldnt hurt anything

I don’t think it’s a good idea to add a delay to the evaluation itself. But I guess using an intermediate custom property on your pump symbol, and doing some timestamp comparisons to determine if the evaluation should be run, you could manage to effectively delay it…

I can’t do that now (I have my own job to attend to ;p) but if I find some time I’ll see if I can figure something out - though someone else might just come in and give you the answer in the meantime.

1 Like