What's new
What's new

Sharing a Macro Conditional Branching Math Experience...

Nerdlinger

Stainless
Joined
Aug 10, 2013
Location
Chicago, IL
Hi Everyone! I recently ran into something that I thought I would share at the outside chance that someone who reads this might retain it and help them should they run into the same issue:

I was setting up a new process where I had to mill a slot .675" deep. It was polar interpolation on a lathe, something I had very little experience with, so I knew I was going to have to experiment with various cutting parameters including DOC. I wrote a subroutine for the individual mill path in X and "C" (Y) and instead of editing a bunch of individual Z depths every time I wanted to alter the DOC I wrote a macro that would increase the depth of cut by some amount that could readily be altered and keep calling up that sub routine until we were at full depth. From there it would jump to the finish pass (I left .002" on the walls for finishing.)

To make sure the roughing passes ended up at .675" I made sure the DOC I plugged in was an even multiple of .675". For instance, if I put in .100" for DOC I would either end up a .600", leaving .075" on the floor for finishing (too much for me), or at .700", blasting .025" past the nominal depth. I could have made a safer macro but that is not the point of this post. :dunce: The program looked something like this:

;
#501=0(ZEROING THE COUNTER);
;
#502=XXX(DEPTH OF CUT);
;
N100;
;
#501=[#501-#502];
;
Z[#501];
M98P200;
;
IF[#501GT-.675]GOTO100;
;
FINISH PASS;
M30;
;
N200;
ROUGH PASS;
M99;

So if we put .025 in for "XXX" it will step its way down 27 even passes to .675" then do the finish pass, and it did that just fine. But then I changed the DOC to .03375 (for 20 even passes) it went one roughing pass too far! I double checked the math, ran another part, saw (and took a picture of) the POS screen that displayed the Z position as precisely "-.675", which should have prevented the program from "GOTO100" and instead should have just gone to the finish pass. :willy_nilly:

I do not know EXACTLY what happened but I assume there is a binary rounding thing going on that rounded the .03375" down to .0337" so after 20 passes it would have been at Z-.674" and thusly qualify for another roughing pass, .0337" deeper. at about Z-.707". (I am sure the POS screen said "-.675" and not "-.674"....I took a picture!)

The part stick out was just enough that the extra pass didn't hit the collet but nevertheless I thought I would share the experience in case anyone else is left wondering "what went wrong" if it ever happens to them...

OH YEAH, in the meantime I just changed the condition to "IF[#501GT.670]GOTO100" I know that's super lazy but I just had to get the job done and knew any extra material left on the floors from a rounding error would be no more than .001/.002" so I was fine with that. :D
 
;
#501=0(ZEROING THE COUNTER);
;
#502=XXX(DEPTH OF CUT);
;
N100;
;
#501=[#501-#502];
;
Z[#501];
M98P200;
;
IF[#501GT-.675]GOTO100;
;
FINISH PASS;
M30;
;
N200;
ROUGH PASS;
M99;

:D


Hello Nerdlinger,

Calculations are carried out in binary and may result in unexpected results when comparing the values of two variables. Accordingly, subtract one variable from the other and compare the Absolute value with a tolerance value is the "work around". If the result is Greater or Smaller (depending on the logic you want to use) than the tolerance, then the Macro Statement will Test True. A logical tolerance to use when testing the two variables to be equal, would be the Least Programable Increment of the machine, as this will have insignificant, or no influence on the actual coordinate.

Therefore, your following Block

IF[#501GT-.675]GOTO100

could be replaced with

IF [ABS[ABS[-0.675] - ABS[#501]] GT 0.0001] GOTO100

Using Common, Nonvolatile variables (#500 Series) is poor practice when Local Scope variable would suffice. Also, a better way of writing your above program is as follows. This method doesn't require the Full Depth to be exactly divisible by the DOC.

(DECLARE VARIABLES HERE)
#1 = 0.0 (Z Start Point)
#2 = -0.03 (DOC INCLUDING DIRECTION)
#3 = -0.675 (FULL DEPTH)

WHILE [#1 GT #3] DO1
#1 = #1 + #2
IF[#1 LT #3] TH #1 = #3 (STOP OVER CUT IN Z)
G01 Z#1 F_ _
M98 P200
END1


Vancbiker said:
I think had you used GE rather than GT it would have worked as you intended.
Hello Kevin,
Using GE would actually force an extra DOC. The OP's Macro Statement with GT will Test True and return to N100 if Full Depth has not been reached. If #501 were to be Equal to -0.675 the program should not return to N100, but continue with the remainder of the program.

Regards,

Bill
 
Last edited:
I do not know EXACTLY what happened but I assume there is a binary rounding thing going on that rounded the .03375" down to .0337" so after 20 passes it would have been at Z-.674" and thusly qualify for another roughing pass, .0337" deeper. at about Z-.707". (I am sure the POS screen said "-.675" and not "-.674"....I took a picture!)

As explained by Bill, it was caused by floating point error in calculations, not because of rounding to 0.0337
If the DOC is added 20 times, it may not be exactly 0.675
Even if it is 0.67495, the position display would be the rounded 0.6750
For confirmation, check the value stored in #501 in the end.
 
Rounding/Truncation in axis addresses

Another thing to mention is, rounding/truncation is automatically done by the control if there are more number of decimal digits than the least-input-increment decimal digits (3 in metric and 4 in imperial, in increment system B) in an axis address. Rounding is done if the value is specified through a variable, and truncation is done if the value is directly specified as a constant. For example, in mm mode,

#1 = 100.2345
G00 X#1
would place the tool at X = 100.235
I refer to this as "implicit" rounding which is equivalent to
G00 X[ROUND[#1]] (In axis addresses, ROUNDing is done up to 3 decimal digits in mm mode)

But,
G00 X100.2345 would place the tool at X = 100.234
 
Hello Nerdlinger,

Calculations are carried out in binary and may result in unexpected results when comparing the values of two variables. Accordingly, subtract one variable from the other and compare the Absolute value with a tolerance value is the "work around". If the result is Greater or Smaller (depending on the logic you want to use) than the tolerance, then the Macro Statement will Test True. A logical tolerance to use when testing the two variables to be equal, would be the Least Programable Increment of the machine, as this will have insignificant, or no influence on the actual coordinate.

Therefore, your following Block

IF[#501GT-.675]GOTO100

could be replaced with

IF [ABS[ABS[-0.675] - ABS[#501]] GT 0.0001] GOTO100

Using Common, Nonvolatile variables (#500 Series) is poor practice when Local Scope variable would suffice. Also, a better way of writing your above program is as follows. This method doesn't require the Full Depth to be exactly divisible by the DOC.

(DECLARE VARIABLES HERE)
#1 = 0.0 (Z Start Point)
#2 = -0.03 (DOC INCLUDING DIRECTION)
#3 = -0.675 (FULL DEPTH)

WHILE [#1 GT #3] DO1
#1 = #1 + #2
IF[#1 LT #3] TH #1 = #3 (STOP OVER CUT IN Z)
G01 Z#1 F_ _
M98 P200
END1

Regards,

Bill

Thank you Bill! I knew I could have written a safer code but not as clean as the one you proposed. I should really get more comfy with the other functions, conditions, etc. available....there is more to life than just IF[...]GOTOn :). Thanks, again!
 
As explained by Bill, it was caused by floating point error in calculations, not because of rounding to 0.0337
If the DOC is added 20 times, it may not be exactly 0.675
Even if it is 0.67495, the position display would be the rounded 0.6750
For confirmation, check the value stored in #501 in the end.


Thank you, Sinha! I remember checking both the POS screen AND the MACRO screen and seeing "-.675" for the Z position and value for #501, so the error must have been retained somewhere behind the scenes. Interesting info regarding the differing aspects of rounding/truncation! Thank you, again!
 
......Hello Kevin,
Using GE would actually force an extra DOC. The OP's Macro Statement with GT will Test True and return to N100 if Full Depth has not been reached. If #501 were to be Equal to -0.675 the program should not return to N100, but continue with the remainder of the program.

Regards,

Bill

Oh duh. Yes. I didn't thoroughly read the code. :dunce:
 
Thank you, Sinha! I remember checking both the POS screen AND the MACRO screen and seeing "-.675" for the Z position and value for #501, so the error must have been retained somewhere behind the scenes. Interesting info regarding the differing aspects of rounding/truncation! Thank you, again!

Typically, an error of 10 to-the-power -10 gets introduced in each arithmetic calculation. Therefore, #501 is definitely not equal to -0.675 after 20 additions. However, it would not show up on the macro variable screen which can show only 8 digits, in the rounded form. Therefore, even though the display is -0.675, the value stored is slightly different.

Likewise, there are errors in all macro-function evaluations. For example,
the exact value of SQRT[2] is 1.414213562373095...
But the display would be 1.4142135624 while the value stored would be different from this, though not equal to the exact value.

For the same reasons, the condition [SIN[0] EQ 0] would be always FALSE unless parameter 6004#1 is set to 1 (which normalizes the result to 0 whenever the calculated value of SIN/COS/TAN is less than 10 to-the-power -8)
 
For these reasons, I will often use the number of passes as the branching factor, not an actual measurement resultant from a complex calculation. While the possibility exists that it could still screw up 1.00000000000 + 1.00000000000, the likelihood of it doing so is greatly diminished.
 
For these reasons, I will often use the number of passes as the branching factor, not an actual measurement resultant from a complex calculation. While the possibility exists that it could still screw up 1.00000000000 + 1.00000000000, the likelihood of it doing so is greatly diminished.

Hello Tony,
Error in Binary Calculations occur because of the fixed number of binary digits to represent a decimal number. Accordingly, some decimal numbers can’t be represented exactly in binary, resulting in small roundoff errors. The representation of Integers doesn't have this issue and therefore, 1.00000000000 + 1.00000000000 will equal 2.00000000000 and so on with further additions of Integers.

Regards,

Bill
 
Hello Tony,
Error in Binary Calculations occur because of the fixed number of binary digits to represent a decimal number. Accordingly, some decimal numbers can’t be represented exactly in binary, resulting in small roundoff errors.

Regards,

Bill

Hello Bill,

I for one didn't understand why or how any calculation errors occurred or could even happen until now. That's crystal clear and makes perfect sense.

Brent
 
What I still do not know is why, even today,

1. Memory is an issue with CNC ?
2. The in-built calculator of an ordinary computer is more accurate than CNC ?
 








 
Back
Top