Expression Conversion from RSView SE to Ignition

I'm having trouble figuring out how to convert this expression from RSView SE to an ignition expression.

Expression:
If ({#1\TempSP} <= {#1\SP} + {#1\SP_TolUpr}) AND ({#1\TempSP} >= {#1\SP} - {#1\SP_TolLwr}) Then
#1\SP_TolUpr = #1\SP_TolUpr - (#1\TempSP - #1\SP);
#1\SP_TolLwr = #1\SP_TolLwr + (#1\TempSP - #1\SP);
#1\SP = #1\TempSP;

This expression runs when a setpoint value gets changed, it also changes the upper and lower tolerance values for that setpoint so the range doesn't change every time the setpoint changes.

TempSP-New Setpoint value
SP-old setpoint value
SP_TolUpr is the value from the setpoint to the upper range
SP_TolLwr is the value from the setpoint to the lower range

Example:
Current Setpoint is 70
Tolerance Upper is 30
Tolerance Lower is 20
Setpoint range 50-100

I can't figure out how to make the TolUpr and TolLwr update when the setpoint updates. Well I can but not correctly.

I thought the script below in a event.propertyName change script would make it work but it gives a "Parse error for event handler "propertyChange" SyntaxError: ("no viable alternative at input 'AND'", ('', 4, 67, '\tif (newSPvalue <= event.source.OldSetPt + event.source.OldTolUpr) AND (newSPvalue >= event.source.OldSetPt - event.source.OldTolLwr):\n'))" error.

if event.propertyName == "floatValue":
	newSPvalue = event.source.floatValue
	
	if (newSPvalue <= event.source.OldSetPt + event.source.OldTolUpr) AND (newSPvalue >= event.source.OldSetPt - event.source.OldTolLwr):
		
		event.source.SetTolUpr = event.source.OldTolUpr - (newSPvalue - event.source.OldSetPt)
		event.source.SetTolLwr = event.source.OldTolLwr + (newSPvalue - event.source.OldSetPt)
		
		paths = [
				"event.source.SetTolUpr"
				"event.source.SetTolLwr"
				]

		
			values =[
				"event.source.SetTolUpr"
				"event.source.SetTolLwr"
				]

		system.tag.writeBlocking(paths, values)

I also tried the script below to update the tag values and its always a step behind what it should be.

if event.propertyName == "floatValue":
	
	values = [event.source.NewTolUpr,event.source.NewTolLwr]

	[event.source.SetTolUpr,event.source.SetTolLwr] = values

The #1 is a substitution in RSview, IIRC. You will need to use a tag path view parameter or template property to re-implement that functionality.
The use indirect tag binding to combine that dynamic tag path with the static part of the tag name, for each tag in the expression, on a custom property.

Then the expression can use the custom properties directly.

Also: Ignition expressions are not scripts. You cannot do assignment within them. If you use a jython script, then you must use system.tag.readBlocking() to get all of those values into jython variables, and system.tag.writeBlocking() to send the result to the tag. The tag paths would be constructed from strings involving your dynamic tag path.

I don't know anything about RS View, but let's see if we can figure a few things out !

First, allow me to 'pseudocodify' the expression so I can make sense of it

if (temp <= sp + up) and (temp >= sp - low):
  up -= temp - sp
  low += temp - sp
  sp = temp

Does that seem correct ?
Well then there's something you need to know about ignition expressions: you can't assign things in them. You will not be able to change multiple values in an expression like you seem to be doing in RSView.
All you can do with an expression is process an input and return an output. No side effects.
An if in ignition's expression looks like this:

if (condition, return_this_if_true, return_that_if_false)

The other thing, is that expressions and scripts are two VERY different beasts.
Let's take a look at your scripts:

What this does is write to the tags in paths the values in values.
But those don't look like valid tag paths, and the values are string literals.
This will write event.source.SetTolUpr LITERALLY to the tag at path event.source.SetTolUpr. Which I doubt is what you want to do.
If you want to get values from tags in a script, you'll need to read them first, with system.tag.readBlocking

You don't need the brackets here, and you also don't need an intermediate value:

event.source.SetTolUpr, event.source.SetTolLwr = event.source.NewTolUpr, event.source.NewTolLwr

Thanks. I have custom properties setup on the button I'm using to change the setpoint and I can change the setpoint, so my indirect tagging is working on the popup. After I change the setpoint, I need to figure out how to also update the upper and lower tolerance tags in the PLC by the same amount as the setpoint changed. I know how to RSView expression works, I just don't know the correct way to go about that in Ignition. I'm not sure if I should be using a script on the tag change property to try and change the other two values, that's just where I started. Screenshot below for clarification.

Oh, and this:

Is because you wrote AND. It's and, lowercase.

Thanks. I have the custom properties below setup on the button i use to change the setpoint. So in that script I was basically just trying to copy out of two custom properties and into the two that are actually the ones indirectly tagged to the PLC tags.
script1

If you had three values coming from a PLC, setpoint, upper, and lower and when you clicked on a button and changed the setpoint value it also updated the upper and lower values, how would you go about doing that? That's where this script came from, was me backing up and trying to start back at scratch to work through this.

if event.propertyName == "floatValue": # my setpoint value changes
	
	values = [event.source.NewTolUpr,event.source.NewTolLwr] ######## take the values in these custom properties

	[event.source.SetTolUpr,event.source.SetTolLwr] = values ######## and copy them to these custom properties..

After googling it up, I found that event.source.something is used in vision to access the something property of the component that fired the event. Those are NOT tags, though the properties could be bound to tags.

If you're trying to update properties, then indeed you don't need to call system.tag.readBlocking and writeBlocking.

This is correct code, though I'd write it like that:

if event.propertyName == "floatValue":
	event.source.SetTolUpr, event.source.SetTolLwr = event.source.NewTolUpr, event.source.NewTolLwr
1 Like

That is correct.

Yes, custom properties of a component can be treated as attributes of the component object. If the binding was established with "Bidirectional" turned on, assignment to the attribute will pass through and write to the tag. This is one of the great conveniences of indirect binding.

I think I just understood what you're trying to do. Basically, a deadband, right ?
This all seem way too complicated for a deadband.

Can you go back from the top, and explain what you want, without ANY consideration for what you have ?

Never used vision, so I had to google it ;p

I would probably just set this up with 5 custom properties.

  1. Set point property that is just bound to the set point tag, indirectly or otherwise.
  2. Upper Tolerance property, bound to a tag if desired.
  3. Lower Tolerance property, bound to a tag if desired.
  4. Upper Limit with an expression binding:
{'set point property'} + {'Upper Tolerance property'}
  1. Lower Limit with an expression binding:
{'set point property'} - {'Lower Tolerance property'}

Note: Use the Property selector to get the correct paths

Now, if the set point or tolerance changes then your limits will automatically update.

1 Like

Yes, the upper and lower are recalculated after each setpoint change. Screenshot below.

I'm trying to reproduce the same logic that is in this formula. TempSp would be the new SetPt value.

The first row checks to see if the new value is in the range, I've done this somewhere else in Ignition so i don't need it.

The second row updates the TolUpr value to its new value

The third row updates the TolLwr value to its new value

The fourth row update the SetPt to be the new Setpt

If ({#1\TempSP} <= {#1\SP} + {#1\SP_TolUpr}) AND ({#1\TempSP} >= {#1\SP} - {#1\SP_TolLwr}) Then

#1\SP_TolUpr = #1\SP_TolUpr - (#1\TempSP - #1\SP);

#1\SP_TolLwr = #1\SP_TolLwr + (#1\TempSP - #1\SP);

#1\SP = #1\TempSP;

This script works the first time the popup opens but if it gets changed again it goes crazy. I think thats just the way i have the custom properties setup though.

if event.propertyName == "floatValue":
	newSPvalue = event.source.floatValue
	
	if (newSPvalue <= event.source.OldSetPt + event.source.OldTolUpr) and (newSPvalue >= event.source.OldSetPt - event.source.OldTolLwr):
		
		event.source.SetTolUpr = event.source.OldTolUpr - (newSPvalue - event.source.OldSetPt)
		event.source.SetTolLwr = event.source.OldTolLwr + (newSPvalue - event.source.OldSetPt)

I would probably just set this up with 5 custom properties.

  1. Set point property that is just bound to the set point tag, indirectly or otherwise.
  2. Upper Tolerance property, bound to a tag if desired.
  3. Lower Tolerance property, bound to a tag if desired.
  4. Upper Limit with an expression binding:
{'set point property'} + {'Upper Tolerance property'}
  1. Lower Limit with an expression binding:
{'set point property'} - {'Lower Tolerance property'}

Note: Use the Property selector to get the correct paths

Now, if the set point or tolerance changes then your limits will automatically update.

This is a lot simpler than what i have but where are you actually updating the upper and lower PLC tags? I can't do an expression and update the tag at the same time can I? I'm going to try this though to see if I'm just scatter brained.

lroseRegular

I would probably just set this up with 5 custom properties.

  1. Set point property that is just bound to the set point tag, indirectly or otherwise.
  2. Upper Tolerance property, bound to a tag if desired.
  3. Lower Tolerance property, bound to a tag if desired.
  4. Upper Limit with an expression binding:
{'set point property'} + {'Upper Tolerance property'}
  1. Lower Limit with an expression binding:
{'set point property'} - {'Lower Tolerance property'}

Note: Use the Property selector to get the correct paths

Now, if the set point or tolerance changes then your limits will automatically update.

This updates the upper and lower by the same amount as the set point changed. So if i change the setpoint up 5 the upper and lower limits also move up 5. I need the upper and lower limit to stay the same as the setpt changes. So the upper tolerance has to subtract 5 and the lower tolerance needs to add 5 so they stay the same.

What's 'crazy' ? Its behavior can be a hint as to what's going wrong.

python allows you to do a > x > b. Pretty handy.

if (event.source.OldSetPt - event.source.OldTolLwr <= newSPvalue <= event.source.OldSetPt + event.source.OldTolUpr:

I assumed, that the Tolerance was the "fixed" value and that the Limits were calculated. Just Filp it.

the Upper Tolerance would be:

{'Upper Limit Property'} - {'set point property'}

the lower tolerance would be

{'set point property'} - {'lower limit property'}

However, if this is used by the PLC, I would just do the calculation in the PLC.

Thinking through this a bit more. If all of the values are in the PLC, and you don't have access to the PLC/ or don't want to change the PLC then. Bind all properties to the appropriate tags bi-directionally. Then do the math in a property change script.

if event.propertyName == "floatValue":
    newSP = event.newValue

    event.source.TolUper = event.source.LimitUpr - newSP
    event.source.TolLwr = newSP - event.source.LimitLwr

I don't understand what the If statement is trying to accomplish.

Thanks for everyone's help. I ended up having to start back at scratch and remap all new custom properties because I had gotten all my paths and tags going all over the place once I got that straightened out the 5 properties from Irose and the script below got me going. Thanks again everyone.

if event.propertyName == "floatValue":
    newSP = event.newValue

    event.source.TolUper = event.source.LimitUpr - newSP
    event.source.TolLwr = newSP - event.source.LimitLwr
3 Likes