‖ 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.
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.
