Understanding the Messy Code in PLCs

System Learning

Life is like a marathon; sometimes you need to pause and fish a bit to go further.

The project team received a requirement to determine the deviation range of the servo and handle alarms. One expert completed it using a few loops, finding it too simple. So, he wrote a pure if-statement logic, and surprisingly, the PLC not only ran stably but also became much faster. This made me realize how impressive the messy code I had written for IoT projects was.

The requirements are as follows:

There are 32 servo drivers on site. I used the PLC to read the current positions of these 32 servos and created 32 variables to store their positions.Variable names are as follows:AxisStructParams[1].R_AxisCurrentPositionAxisStructParams[2].R_AxisCurrentPosition……..……..AxisStructParams[32].R_AxisCurrentPositionI now need to write a function that, when the deviation combination button 2 is pressed:If the positions of AxisStructParams[1].R_AxisCurrentPosition and AxisStructParams[2].R_AxisCurrentPosition are not equal (or the positive/negative deviation is 10), then register M100 is true.AxisStructParams[3].R_AxisCurrentPosition and AxisStructParams[4].R_AxisCurrentPosition: If these two axes’ positions are not equal (or the positive/negative deviation is 10), then register M100 is true.AxisStructParams[5].R_AxisCurrentPosition and AxisStructParams[6].R_AxisCurrentPosition: If these two axes’ positions are not equal (or the positive/negative deviation is 10), then register M100 is true.…..…..AxisStructParams[31].R_AxisCurrentPosition and AxisStructParams[32].R_AxisCurrentPosition: If these two axes’ positions are not equal (or the positive/negative deviation is 10), then register M100 is true.This means checking pairs to see if the current two axes’ positions are consistent or within a positive/negative deviation of 10.When I press deviation combination button 3:If the positions of AxisStructParams[1].R_AxisCurrentPosition, AxisStructParams[2].R_AxisCurrentPosition, and AxisStructParams[3].R_AxisCurrentPosition are not equal (or the positive/negative deviation is 10), then register M100 is true. AxisStructParams[4].R_AxisCurrentPosition, AxisStructParams[5].R_AxisCurrentPosition, and AxisStructParams[6].R_AxisCurrentPosition: If these three axes’ positions are not equal (or the positive/negative deviation is 10), then register M100 is true.….. ….. AxisStructParams[30].R_AxisCurrentPosition, AxisStructParams[31].R_AxisCurrentPosition, and AxisStructParams[32].R_AxisCurrentPosition: If these three axes’ positions are not equal (or the positive/negative deviation is 10), then register M100 is true.This means checking three axes to see if their positions are consistent or within a positive/negative deviation of 10.When I press deviation combination button 4:If the positions of AxisStructParams[1].R_AxisCurrentPosition, AxisStructParams[2].R_AxisCurrentPosition, AxisStructParams[3].R_AxisCurrentPosition, and AxisStructParams[4].R_AxisCurrentPosition are not equal (or the positive/negative deviation is 10), then register M100 is true.AxisStructParams[5].R_AxisCurrentPosition, AxisStructParams[6].R_AxisCurrentPosition, AxisStructParams[7].R_AxisCurrentPosition, and AxisStructParams[8].R_AxisCurrentPosition: If these four axes’ positions are not equal (or the positive/negative deviation is 10), then register M100 is true.…..…..AxisStructParams[29].R_AxisCurrentPosition, AxisStructParams[30].R_AxisCurrentPosition, AxisStructParams[31].R_AxisCurrentPosition, and AxisStructParams[32].R_AxisCurrentPosition: If these four axes’ positions are not equal (or the positive/negative deviation is 10), then register M100 is true.This means checking four axes to see if their positions are consistent or within a positive/negative deviation of 10.When I press the free combination button:I can use registers to customize which axes to combine and check if their current positions are consistent or within a positive/negative deviation of 10.

I wonder how everyone else writes this.

Here, I directly use if statements.Define a button register D, with the variable name:i_HMIDeviationCombinationSelection

Then, since it is said that as long as there is one deviation, an alarm will be triggered, I will directly define a variable:AnyGroupHasDeviation

b_DeviationAlarm := AnyGroupHasDeviation;

Here, I directly use the ABS function in ST language to subtract and check if it is within a reasonable range. If not, an alarm is triggered. The first 2, 3, and 4 axes are written in order: 1-2, 1-3, 1-4, then 2-3, 2-4, 3-4 for checking.

Later, for the free group, I used FB blocks to write 16 combination styles, also using the same pure if method.

The complete ST code is as follows:

//===========================Axis Deviation Stop====================================//b_DeviationAlarm := AnyGroupHasDeviation;CASE i_HMIDeviationCombinationSelection OF    2:// 2-axis combination detection    FOR ii := 1 TO 32 BY 2 DO        IF ABS(AxisStructParams[ii].R_AxisCurrentPosition - AxisStructParams[ii+1].R_AxisCurrentPosition) > R_HMICombinationDeviationValue THEN            b_AxisDeviation[ii] := TRUE;            b_AxisDeviation[ii+1] := TRUE;            AnyGroupHasDeviation := TRUE;            EXIT; // Exit the loop upon finding a deviation        END_IF;    END_FOR;    3: // 3-axis combination detection    FOR ii := 1 TO 32 BY 3 DO        IF ABS(AxisStructParams[ii].R_AxisCurrentPosition - AxisStructParams[ii+1].R_AxisCurrentPosition) > R_HMICombinationDeviationValue OR            ABS(AxisStructParams[ii].R_AxisCurrentPosition - AxisStructParams[ii+2].R_AxisCurrentPosition) > R_HMICombinationDeviationValue OR            ABS(AxisStructParams[ii+1].R_AxisCurrentPosition - AxisStructParams[ii+2].R_AxisCurrentPosition) > R_HMICombinationDeviationValue        THEN            AnyGroupHasDeviation := TRUE;            b_AxisDeviation[ii] := TRUE;            b_AxisDeviation[ii+1] := TRUE;            b_AxisDeviation[ii+2] := TRUE;            EXIT; // Exit the loop upon finding a deviation        END_IF;    END_FOR;    4: // 4-axis combination detection    FOR ii := 1 TO 32 BY 4 DO        IF ABS(AxisStructParams[ii].R_AxisCurrentPosition - AxisStructParams[ii+1].R_AxisCurrentPosition) > R_HMICombinationDeviationValue    OR            ABS(AxisStructParams[ii].R_AxisCurrentPosition - AxisStructParams[ii+2].R_AxisCurrentPosition) > R_HMICombinationDeviationValue   OR            ABS(AxisStructParams[ii].R_AxisCurrentPosition - AxisStructParams[ii+3].R_AxisCurrentPosition) > R_HMICombinationDeviationValue   OR            ABS(AxisStructParams[ii+1].R_AxisCurrentPosition - AxisStructParams[ii+2].R_AxisCurrentPosition) > R_HMICombinationDeviationValue OR            ABS(AxisStructParams[ii+1].R_AxisCurrentPosition - AxisStructParams[ii+3].R_AxisCurrentPosition) > R_HMICombinationDeviationValue OR            ABS(AxisStructParams[ii+2].R_AxisCurrentPosition - AxisStructParams[ii+3].R_AxisCurrentPosition) > R_HMICombinationDeviationValue        THEN            AnyGroupHasDeviation := TRUE;            b_AxisDeviation[ii] := TRUE;            b_AxisDeviation[ii+1] := TRUE;            b_AxisDeviation[ii+2] := TRUE;            b_AxisDeviation[ii+3] := TRUE;            EXIT; // Exit the loop upon finding a deviation        END_IF;    END_FOR;    5: // Free combination detection    FreeCombinationDeviationFBInstance[1](R_DeviationValue := Ri_HMIFreeCombinationDeviation[1].R_DeviationValue,                   i_CombinationAxis := Ri_HMIFreeCombinationDeviation[1].i_CombinationAxis,                   b_DeviationAlarm => AnyGroupHasDeviationFB[1]);    FreeCombinationDeviationFBInstance[2](R_DeviationValue := Ri_HMIFreeCombinationDeviation[2].R_DeviationValue,                   i_CombinationAxis := Ri_HMIFreeCombinationDeviation[2].i_CombinationAxis,                   b_DeviationAlarm => AnyGroupHasDeviationFB[2]);    FreeCombinationDeviationFBInstance[3](R_DeviationValue := Ri_HMIFreeCombinationDeviation[3].R_DeviationValue,                   i_CombinationAxis := Ri_HMIFreeCombinationDeviation[3].i_CombinationAxis,                   b_DeviationAlarm => AnyGroupHasDeviationFB[3]);    FreeCombinationDeviationFBInstance[4](R_DeviationValue := Ri_HMIFreeCombinationDeviation[4].R_DeviationValue,                   i_CombinationAxis := Ri_HMIFreeCombinationDeviation[4].i_CombinationAxis,                   b_DeviationAlarm => AnyGroupHasDeviationFB[4]);    FreeCombinationDeviationFBInstance[5](R_DeviationValue := Ri_HMIFreeCombinationDeviation[5].R_DeviationValue,                   i_CombinationAxis := Ri_HMIFreeCombinationDeviation[5].i_CombinationAxis,                   b_DeviationAlarm => AnyGroupHasDeviationFB[5]);    FreeCombinationDeviationFBInstance[6](R_DeviationValue := Ri_HMIFreeCombinationDeviation[6].R_DeviationValue,                   i_CombinationAxis := Ri_HMIFreeCombinationDeviation[6].i_CombinationAxis,                   b_DeviationAlarm => AnyGroupHasDeviationFB[6]);    FreeCombinationDeviationFBInstance[7](R_DeviationValue := Ri_HMIFreeCombinationDeviation[7].R_DeviationValue,                   i_CombinationAxis := Ri_HMIFreeCombinationDeviation[7].i_CombinationAxis,                   b_DeviationAlarm => AnyGroupHasDeviationFB[7]);    FreeCombinationDeviationFBInstance[8](R_DeviationValue := Ri_HMIFreeCombinationDeviation[8].R_DeviationValue,                   i_CombinationAxis := Ri_HMIFreeCombinationDeviation[8].i_CombinationAxis,                   b_DeviationAlarm => AnyGroupHasDeviationFB[8]);    FreeCombinationDeviationFBInstance[9](R_DeviationValue := Ri_HMIFreeCombinationDeviation[9].R_DeviationValue,                   i_CombinationAxis := Ri_HMIFreeCombinationDeviation[9].i_CombinationAxis,                   b_DeviationAlarm => AnyGroupHasDeviationFB[9]);    FreeCombinationDeviationFBInstance[10](R_DeviationValue := Ri_HMIFreeCombinationDeviation[10].R_DeviationValue,                   i_CombinationAxis := Ri_HMIFreeCombinationDeviation[10].i_CombinationAxis,                   b_DeviationAlarm => AnyGroupHasDeviationFB[10]);    FOR ii := 1 TO 10 BY 1 DO       IF  AnyGroupHasDeviationFB[ii] THEN           AnyGroupHasDeviation := TRUE;       END_IF;  END_FOR;    ;END_CASE;

Free Combination Judgment FB

Input parameters: Axis number, deviation valueOutput parameters: Deviation alarmThe axis number can be a free combination of 1 to 6, so it cannot exceed this.

For free combinations, please fill in the axis numbers in order; skipping numbers will not take effect, and an axis number of 0 will not take effect. The number of axes filled in must be 2 or more to take effect.

The complete FB block ST language code is as follows:

//===========================This FB is used for====================================////===========================Free Combination Deviation Setting====================================////===============================================================//i_CombinationAxisCount := 0;FOR ii := 1 TO 6 BY 1 DO    IF i_CombinationAxis[ii] > 0 THEN        i_CombinationAxisCount := i_CombinationAxisCount + 1;    END_IF;    IF b_HMIReset THEN        b_AnyDeviationAlarm := FALSE;    END_IF;END_FOR;b_DeviationAlarm := b_AnyDeviationAlarm;CASE i_CombinationAxisCount OF    2:    IF ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition) > R_DeviationValue THEN        b_AnyDeviationAlarm := TRUE;        b_AxisDeviation[i_CombinationAxis[1]] := TRUE;        b_AxisDeviation[i_CombinationAxis[2]] := TRUE;    END_IF;    3:    IF ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition) > R_DeviationValue    OR        ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[3]].R_AxisCurrentPosition) > R_DeviationValue   OR        ABS(AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[3]].R_AxisCurrentPosition) > R_DeviationValue    THEN        b_AnyDeviationAlarm := TRUE;        b_AxisDeviation[i_CombinationAxis[1]] := TRUE;        b_AxisDeviation[i_CombinationAxis[2]] := TRUE;        b_AxisDeviation[i_CombinationAxis[3]] := TRUE;    END_IF;    4:    IF ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[3]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[4]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[3]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[4]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[3]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[4]].R_AxisCurrentPosition) > R_DeviationValue          THEN        b_AnyDeviationAlarm := TRUE;        b_AxisDeviation[i_CombinationAxis[1]] := TRUE;        b_AxisDeviation[i_CombinationAxis[2]] := TRUE;        b_AxisDeviation[i_CombinationAxis[3]] := TRUE;        b_AxisDeviation[i_CombinationAxis[4]] := TRUE;    END_IF;    5:    IF ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[3]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[4]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[5]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[3]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[4]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[5]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[3]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[4]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[3]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[5]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[4]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[5]].R_AxisCurrentPosition) > R_DeviationValue          THEN        b_AnyDeviationAlarm := TRUE;        b_AxisDeviation[i_CombinationAxis[1]] := TRUE;        b_AxisDeviation[i_CombinationAxis[2]] := TRUE;        b_AxisDeviation[i_CombinationAxis[3]] := TRUE;        b_AxisDeviation[i_CombinationAxis[4]] := TRUE;        b_AxisDeviation[i_CombinationAxis[5]] := TRUE;    END_IF;    6:    IF ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[3]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[4]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[5]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[1]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[6]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[3]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[4]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[5]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[2]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[6]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[3]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[4]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[3]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[5]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[3]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[6]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[4]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[5]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[4]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[6]].R_AxisCurrentPosition) > R_DeviationValue    OR       ABS(AxisStructParams[i_CombinationAxis[5]].R_AxisCurrentPosition - AxisStructParams[i_CombinationAxis[6]].R_AxisCurrentPosition) > R_DeviationValue    THEN        b_AnyDeviationAlarm := TRUE;        b_AxisDeviation[i_CombinationAxis[1]] := TRUE;        b_AxisDeviation[i_CombinationAxis[2]] := TRUE;        b_AxisDeviation[i_CombinationAxis[3]] := TRUE;        b_AxisDeviation[i_CombinationAxis[4]] := TRUE;        b_AxisDeviation[i_CombinationAxis[5]] := TRUE;        b_AxisDeviation[i_CombinationAxis[6]] := TRUE;    END_IF;    ELSE    ;END_CASE;

HMI Limitations

For free combinations, please fill in the axis numbers in order; skipping numbers will not take effect, and an axis number of 0 will not take effect. The number of axes filled in must be 2 or more to take effect.Understanding the Messy Code in PLCs

This code has been safely running in a project, so feel free to use it.

XinJie PLC structure controls the servo.

The download link for the structure program shared a few days ago:

https://pan.quark.cn/s/dafab904266a

If you have better methods, please discuss them in the comments.

Teaching a man to fish is better than giving him a fish.

Understanding the Messy Code in PLCs

Leave a Comment