Display query in ABB HMI using software panel builder 600

264 views Asked by At

I am using ABB HMI and programming it on panel builder 600. I have used meters to display angles and set the scale from -100 to +100. I have acheived success in displaying angles but the problem is the change in angle is very frequent and the needle of the meter gets out of control. For example: the angle is 5 degree then it suddenly increased to 10 degree and the decreased to 3 degree again in a very short span of time and my needle in display meter gets out of control. What should I do to resolve this issue? I am using ABB plc and writing my code in codesys in CFC language. Awaiting for the helpful replies TIA

2

There are 2 answers

16
Guiorgy On

Decreasing Sampling Rate

VAR
    plcValue: INT; // this value changes a lot
    hmiValue: INT := plcValue; // this value is sent to the HMI to be displayed
    sampleRate: TIME := T#2S; // hmiValue will change every 2 seconds
    timer: TON; // the timer
END_VAR
timer(IN := TRUE, PT := sampleRate);
IF (timer.Q) THEN
    hmiValue := plcValue;
    timer(IN := FALSE, PT := sampleRate); // reset
END_IF

Moving Average

VAR CONSTANT
    SIZE: INT := 100; // the number of values to average
END_VAR
VAR
    plcValue: INT; // this value changes a lot
    hmiValue: INT := plcValue; // this value is sent to the HMI to be displayed
    movingAverage: ARRAY [0..SIZE] OF INT; // last SIZE number of values of plcValue
    maIndex: INT := 0;
    maFilled: BOOL;
    sum: REAL;
    i: INT;
END_VAR
movingAverage[maIndex] := plcValue;
sum := 0;
IF (maFilled) THEN
    FOR i := 0 TO SIZE DO
        sum := sum + movingAverage[i];
    END_FOR
    hmiValue := REAL_TO_INT(sum / SIZE);
ELSE
    FOR i := 0 TO maIndex DO
        sum := sum + movingAverage[i];
    END_FOR
    hmiValue := REAL_TO_INT(sum / (maIndex + 1));
END_IF
IF (maIndex = SIZE) THEN
    maIndex := 0;
    maFilled := TRUE;
ELSE
    maIndex := maIndex + 1;
END_IF

Comparison

running this code:

IF (plcValue = 5) THEN
    plcValue := 10;
ELSIF (plcValue = 10) THEN
    plcValue := 3;
ELSE
    plcValue := 5;
END_IF

Reduced sampling rate results in the hmiValue still jumping every 2 seconds (or whatever sampleRate was set), while moving average was stuck at 6, which usually makes it the more preferred of the two, though a little bigger codewise, as well as slower to execute (though it shouldn't matter, unless you are counting thousands of averages every cycle). You can also change the average size: The bigger it is, the smoother the value, but also slower to react to change. Try not to make it too big

0
Sergey Romanov On

You can use some different blocks on OSCAT library (It's a 3rd party free library. You need to downloade it if you want to use it). I know you work in CFC and perhaps you are not familiar with ST, but this is best way to represent how to solve your task.

FADE

This block allows slowly change value from one value to another.

PROGRAM PLC_PRG
    VAR
        iValue: INT(-100..100); (* Value input *)
        iGauge: INT(-100..100); (* Smoothed Value for HMI *)
        fbFade: FADE; (* fade block *)
    END_VAR

    (* Play with TF parameter to achieve desired smoothness *)
    fbFade(IN1 := INT_TO_REAL(iValue), IN2 := INT_TO_REAL(iGauge), F := FALSE, TF := T#500MS);
    iGauge := REAL_TO_INT(fbFade.Y);
END_PROGRAM

FILTER_I

This block averages value for a given time interval. FILTER_I is a filter of the first degree for 16-bit INT data.

PROGRAM PLC_PRG
    VAR
        iValue: INT(-100..100); (* Value input *)
        iGauge: INT(-100..100); (* Smoothed Value for HMI *)
        fbFilter: FILETR_I; (* filter block *)
    END_VAR

    (* Play with T parameter to achieve desired smoothness *)
    fbFilter(X := iValue, T := T#500MS, Y => iGauge);
END_PROGRAM

FILTER_MAV_W

And another filter is like @Guiorgy made en example based not on time but on number of values stored which is called MA (Moving Average).

PROGRAM PLC_PRG
    VAR
        iValue: INT(-100..100); (* Value input *)
        iGauge: INT(-100..100); (* Smoothed Value for HMI *)
        fbFilter: FILTER_MAV_W; (* filter block *)
    END_VAR

    (* Play with N parameter to achieve desired smoothness *)
    fbFilter(X := INT_TO_WORD(iValue), N := INT#32);
    iGauge := WORD_TO_INT(fbFilter.Y);
END_PROGRAM