Structured Text (Analog Input Scaler Formula)

slope-intercept form ‘y = mx + b’ where
y is your output (also known as engineering units value),
x is your input (Raw Value),
m is your slope (also known as scale factor), and
b is your y-intercept (also known as offset).
 
slope-intercept form ‘y = mx + b’ where
y is your output (also known as engineering units value),
x is your input (Raw Value),
m is your slope (also known as scale factor), and
b is your y-intercept (also known as offset).

Can you give me an Example: I can't figure this out with your description.

Also, I'm looking for a scaler that has a Analog Input - InMin, InMax and a OutMin, OutMax, = Output.

And as said before I wanting this to be a formula so I can tweak it to my needs in Structured Text.

Thanks
 
This is my FB from Codesys for 4-20mA analog output but you can easily modify for analog input as well.
My output value range is between 4000 and 20.000.
The IF block checks for zero division.

Code:
FUNCTION_BLOCK PUBLIC FB_AnalogOutput
VAR_INPUT
	uiInputEngUnits : UINT;
	uiInpScaleLowLimit : UINT;
	uiInpScaleHighLimit : UINT;
END_VAR
	
VAR_OUTPUT
	uiOutput4_20mA : UINT;
END_VAR
VAR
	rOut : REAL;
END_VAR

Code:
//y = y0 + (x - x0)* ((y1 - y0) / (x1 - x0))
IF uiInpScaleHighLimit = 0 THEN
	rOut := 0;
	uiOutput4_20mA:=REAL_TO_UINT(rOUt);
ELSE
	rOut:=4000+((uiInputEngUnits-uiInpScaleLowLimit)*(UINT_TO_REAL(16000)/(UINT_TO_REAL(uiInpScaleHighLimit)-UINT_TO_REAL(uiInpScaleLowLimit))));
	uiOutput4_20mA:=REAL_TO_UINT(rOUt);
END_IF
 
Last edited:
I have only one in Mitsubishi & it's not ST but I'm sure you can format it into ST
It has inputs for Raw value, Inputs for in low & High, , Inputs for out low/out high & a floating point value for the scaled output. Note as the raw in & low/high raw values are integers they have been converted to reals before doing the maths, the one segment checks for zero so that the processor does not fault on a divide by zero.

Scale with In_Out Scale.png
 
The slope (m) is equal to:

(Maximum scaled value - Minimum scaled value) / (Maximum raw value - Minimum raw value)

The offset is equal to the scaled value when the raw value equals zero.

Example:

The raw value ranges from 4000 to 20000.
The scaled value ranges from zero to 100 percent.

The slope is easy to calculate. Slope = (100 - 0) / (20000 - 4000) = 0.00625

The offset is a little trickier. You have to mentally extend the range of the raw value from 4000 down to zero.

Try thinking of it this way. An increase of 4000 in the raw value is twenty five percent of the way from minimum to maximum which corresponds to a scaled value of 25. So, a decrease of 4000 corresponds to a scaled value of -25. That's the offset.

So the formula becomes:

Scaled value = (0.00625 * Raw Value) - 25

Let's try a couple of sample calculations as a sanity check.

First, Raw Value = 4000
Scaled Value = (4000 * 0.00625) - 25 = 0

Second, Raw Value = 20000
Scaled Value = (20000 * 0.00625) - 25 = 100

Third, Raw Value = 12000
Scaled Value = (12000 * 0.00625) - 25 = 50
 
Here is a quick ST of the one I posted, be aware that this was done on another platform and I have split the calculation up so it can be easily monitored. I have tested it & it works but as this was a quickie excuse the variable names.

ST Scaling Fyunction.png
 
Thanks everyone - I finally got my head around this, I could not have done it without all of the examples, and explanations.
 
I have a few systems with 4-20mA load cells. Here is what I used on the last set that had four load cells:


Code:
    // map values from block.
        frontLeft := xclosingWinchIOBmappedData.I.Port_0.Value;
        frontRight := xclosingWinchIOBmappedData.I.Port_1.Value;
        rearLeft := xclosingWinchIOBmappedData.I.Port_2.Value;
        rearRight := xclosingWinchIOBmappedData.I.Port_3.Value;
        
        frontLeftLow := 4000; // use if calibration sheets are provided with amps.
        frontLeftHigh := 20000;
        frontRightLow := 4000;
        frontRightHigh := 20000;
        rearLeftLow := 4000;
        rearLeftHigh := 20000;
        rearRightLow:= 4000;
        rearRightHigh := 20000;
        
        frontLeftLBF := 50000*((frontLeft-frontLeftLow)/(frontLeftHigh-frontLeftLow));
        frontRightLBF := 50000*((frontRight-frontRightLow)/(frontRightHigh-frontRightLow));
        rearLeftLBF := 50000*((rearLeft-rearLeftLow)/(rearLeftHigh-rearLeftLow));
        rearRightLBF := 50000*((rearRight-rearRightLow)/(rearRightHigh-rearRightLow));
 
My example in post #8 could have been reduced by integrating some of the code within others for example rather than converting the integers separately could be enclosed in the math calcs, however, it would be a little more difficult to understand.
 
Here is the logic for an AOI I've created to do scaling. There are two pictures attached also.

###################
// AOI to scale an input, filter and limit its output.


// First we want to remember the last output value. Used in the filter calculation.
LastEngVal := Engr_Out;
LastSigVal := Signal_Out;


// Now calculate the analog signal value from the input data. THis will give us the output of ex 4.25 or 9.87

NewSigVal := (Input - Input_Min) * ( ( Input_Sig_Max - Input_Sig_Min) / (Input_Max - Input_Min)) + Input_Sig_Min;


// For now lets not filter the calculated signal value.
Signal_Out:= NewSigVal;


// Now we will calculate the engineering value using the signal value, Sensor signal min/max and engineering min/max

NewEngVal := (Signal_Out - Sensor_Sig_Min) * ( ( Sensor_Engr_Max - Sensor_Engr_Min) / (Sensor_Sig_Max - Sensor_Sig_Min)) + Sensor_Engr_Min;

// Use the New value, last value, and filter coefficient to filter the output. Limit the filter coefficient to 0-1
//Filter coefficient . Value from 0-1. Filter calculation performed is:
// [(NewValue * (1-Filter_Coeff))] + [LastValue * Filter_Coeff]. A value fo 0 is no filtering, and value of .99 is highly filtered.
If Filter_Coeff < 0 then
Filter_Coeff := 0;
Elsif Filter_Coeff > 1 then
Filter_Coeff :=1 ;
End_if;


Engr_Out := ( NewEngVal * (1-Filter_Coeff)) + ( LastEngVal * Filter_Coeff);

// If the clamp bool is true, then limit the output to the min/max engr values

if ClampOutput then
if Engr_Out < Sensor_Engr_Min then
Engr_Out := Sensor_Engr_Min;
Elsif Engr_Out > Sensor_Engr_Max then
Engr_Out := Sensor_Engr_Max;
End_if;
End_If;

##############################

AOI_Ana_In_Logic.PNG AOI_AnaIn_Used.PNG
 

Similar Topics

Hello, I have a small programming task that I need help solving. I have to: * Create an analog input (4-20v)and a digital output * The analog...
Replies
45
Views
24,976
Good morning. I'm doing a rehab and I need to recycle some part of the old code that won't change and that I need. This is a calculation that...
Replies
22
Views
1,163
I'm writing some structured text that's handling a data structure that comes from a PC. The PC structure is in the "new" LREAL 64-bit floating...
Replies
3
Views
437
Trying to put these equations in structured text program in a Micro 830. when I run the verify I get this error. ;:expected before this new...
Replies
4
Views
394
Hey all, Studio v20.05 Background. We are piggy backing another system to record attributes for product travelling down the line and several...
Replies
21
Views
3,418
Back
Top Bottom