How to scale user-defined tags used in data sampling

How to scale user-defined tags used in data sampling
none 0.0 0


In my current project I am data sampling 6 different tags without any issue.
I have a option list from which we select a fluid type.

One of these tags has an interpolation that changes depending on the fluid type selected.

I am able to display the different values without any problem , but when I want to data sample that tag it only gives me the value before the scaling (interpolation).

How can I have the actual displaying value be the one saved on the data sampling.


Hi @gary14,

In this case, you will need to create a user defined tag and use a subroutine to scale the “read” value of this tag. Here is a subroutine that should accomplish this task:

sub short interpolate_1(short X)
	float userMin = -20, userMax = 93
	float actualMin = 4, actualMax = 20
	float m, b, T, sig
	float Y
	m = (userMax - userMin) / (actualMax - actualMin)	
	b = userMax - (m * actualMax)
	y = m * x + b
	return Y
end sub

This subroutine should be defined within the “Library” section of the macro manager:

To create a user-defined tag, please follow the instructions shown within this tutorial: Link

Note: That the macro subroutine may be assigned within the “Read conversion” drop-down list. However, the parameter type of the subroutine must match the data type of this tag. In your case the subroutine should begin with “sub unsigned short interpolate_1(unsigned short x)” since the numeric object in your project is an unsigned integer.

1 Like

I completely forgot about the subroutines and I have been trying to get it done with a macro.

So I wrote the subroutine with my changes and put a numeric value display just to see if it matches the other one I get 0 all the time.

This is the subroutine i am using

sub unsigned short interpolate_1(unsigned short X)

float  userMax =100
float actualMax 
float Y
GetData(actualMAX, "Fluid Matics HMI", RW, 117, 1)
y = (X * actualMax) / 100
return Y

end sub

I just need the reading to multiply by the value of rw117 ( depending on the selection on the option list) and at the end divided by 100.

When i compile I get no errors so I am unsure if the issue is in the subroutine or somewhere else


I just noticed my issue they were declared has float instead of unsigned short

I do get the correct value displayed when I select my first option in the option list when I select the 2nd and 3rd option I get a really different values from what I should , is there a different function I should be using


Can you please advise what value you receive and what the expected value should be? Also, please send an image of the updated subroutine and the option list’s user defined mapping so that I can attempt to replicate this within our office.

Here is the subroutine

sub unsigned short interpolate_1(unsigned short X)

unsigned short  userMax =100
unsigned short actualMax 
unsigned short Y
GetData(actualmax, "Fluid Matics HMI", RW, 117, 1)
y = X * actualMax / 100
return Y

end sub

Here are the values I am suppose to see ( lower one correct and upper one bad )



Here is my options list

And these are the properties on the numeric object the displays the correct values when selecting the option list


The issue is that multiplying the 16-bit short integer input ‘46’ by a scale value like 4800 will exceed the range of an unsigned short: 65535.To resolve this issue, I would recommend that you assign each value to an integer and prior to division:

sub unsigned short interpolate_2(unsigned short x)
	unsigned short  userMax = 100
	unsigned short actualMax = 800
	unsigned int temps[3] = {0,0,0} // Temp variables used for scaling
	unsigned short y = 0
	GetData(actualMax, "Local HMI", RW, 117, 1)
	temps[0] = actualMax
	temps[1] = x
	temps[2] = (temps[0] * temps[1]) / 100 // Divide as 32-bit integer
	y = temps[2] // Set 16-bit integer = to 32-bit integer
	return y
end sub

Then, set the short integer equal to the scaled down int value. However, please note that this solution runs the risk of exceeding the range of an unsigned short if the value of input ‘x’ is sufficiently large.

1 Like


I modified my routine only changing from short to int the actualMax.
And I am getting all the correct readings on the numeric display and on the data sampling.
I would need to make further tests to make sure they are accurate.
unsigned int temps[3] = {0,0,0} is this function suppose to be used with the option list ?

This subroutine should be used with the numeric display used to show the read value and is dependent on what option is seleted within the option list.


I will try out this function , I have never used it before.
I needed the value to be stored in the data sampling I really just used the numeric display to be able to check if it was giving me good readings.

Thanks for all the support

You are most welcome and just to clarify this statement “unsigned int temps[3] = {0,0,0}” is used to declare an unsigned integer array of 3 elements initialized to 0. But, based on your last statement:

You may not need to use this array.