How to scale user-defined tags used in data samplinghttps://forum.weintekusa.com/uploads/db0776/original/2X/7/7e1f2c3578f009635449dd9d866e26c39c5c4571.png
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.
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.
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.
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 )
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.
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 ?
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.
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: