Hello Guest it is April 18, 2024, 07:51:30 PM

Author Topic: Conditional gcode execution is possible in Mach3  (Read 35085 times)

0 Members and 1 Guest are viewing this topic.

Conditional gcode execution is possible in Mach3
« on: December 04, 2009, 02:53:08 PM »

Hi Folks, 

I'm new to this forum, having purchased my first CNC machine earlier
this year (a Tormach PCNC1100).

I have been a computer hardware engineer for many years, and have done
a lot of low-level coding (assembly, microcode, RTL, FSM, etc). 
When I started out my gcode programming learning curve, at first I was
greatly disheartened to read that Mach3 does not support conditional
code execution, since I had been planning extensive use of fixturing
to get around the lack of a toolchanger on the Tormach, and conditionals
make a lot of complex functionality easy to implement. 
Working around the lack of conditionals started to get annoying.

However, I realized that since subroutine label numbers can be the result
of an expression evaluated at run-time, we can use expression math to effect
conditional execution.  As long as we can reduce our condition to a 1 or 0,
we can multiply this condition flag by the intended subroutine label number
to either execute the operation or else execute subroutine 0, which is
coded to always return immediately and thus provides the "false" path to
avoid execution of the other subroutine.  The same method can be used to
create an if-then-else clause if you use addition instead of multiplication.

For example, let's say my part discovery subroutine has finished probing
my 16-part fixture, discovered which slots are populated and which are empty,
and now we've got a set of parameter flags that enable or disable code execution
for that fixture slot.  Let's say the part enable flag for the current part
is stored in parameter #4.   If the part is present, we want to first
execute sub 21, and then call either sub 22 or sub 23 depending on parameter #5. 

An example of the condition code execution technique I've been using:
======================================================================
#4 = 0   (this flag is actually set by the part probing subroutine, set it here for this example)
#5 = 1   (this flag chooses between execution of sub 22 or sub 23)

     (here is an effective if-then conditional clause)
M98 P[ #4 * 21 ]  ( call either "dummy" sub 0 or "real" subroutine 21 if the part is enabled )
M30

O0   (this the "false" subroutine which always returns immediately)
M99

O21
 ...  (real code goes here)
  (here is an effective if-then-else conditional clause)
M98 P[ #5 + 22 ]      ( call sub 23 if flag #5 is set, or else call sub 22 if flag is not set)
M99

O22
 ...  (real code goes here)
M99

O23
 ...  (real code goes here)
M99
========================================================================

In order to use a wider assortment of conditions, we can use math to reduce an
arbitrary expression to a 0 or 1 value.

Say, for example, that we want to execute an additional facing subroutine
only if the probed part turns out to exceed our nominal raw stock allowance
of 1.25 inches.  The actual height of the part as discovered by the probing
routine is stored in parameter #6.

Here is the gcode to effect this pseudo-code:  if( #6 > 1.25 ) then { call sub P30 }.
========================================================================
#1 = [ 1.25 - #6 ]      ( subtract part actual height from intended - if result is negative, then actual is > 1.25)
#2 = [ #1 + ABS[ #1 ]]  ( adding the absolute value of a negative number to itself produces zero; a positive number yields non-zero)
#3 = [ 1 XOR #2 ]       ( this serves two purposes: invert the logic sense of #2, and force it from zero/non-zero to zero/one )
M98 P[ #3 * 30 ]
========================================================================

This could also be written more compactly like so:
========================================================================
M98 P[ 30 * [ 1 XOR [ [1.25 - #6] + ABS [ 1.25 - #6 ] ] ]   (same as above, but harder to read)
========================================================================

The same techniques can be used to code case statements, since a base
label number plus an offset effectively becomes a jump table. 
You could also store a table of operation subroutine numbers to
call for each of a number of different cases, and then use the switch
expression as an index into the parameter table to find which subroutine
number to call for that case value.

Here is the gcode to effect this pseudo-code:  switch (#6);   case(1): call sub P41;    case(2): call sub P42;   case(3): call sub P43;
========================================================================
M98 P[40 + #6]
========================================================================

Of course, I highly recommend being careful to make sure your expressions
will only result in valid label numbers.  In this case, we must make sure
that #6 can only be 1,2 or 3.  A default case statement could be constructed
with more math and range checking, etc.

One thing to note is that Mach seems to choke on this kind of code when
it comes to generating the toolpath display, so I get all kinds of bogus
screen displays for the toolpath, but it then executes the actual machine
operations just as I intended. 

I've been using these techniques for a few weeks now with my 16-part fixture,
which I can load with any number of parts and have the operations executed
only for the parts that are loaded.  With the data returned from my part
probing routine, I can also setup exact fixture offsets for each discovered part,
and optionally include a coordinate system rotation for that slot if the part
is a little skewed by burrs or swarf, etc.

Perhaps the biggest benefit I've gotten from using conditional code execution
has been when I setup a series of flags at the top of my part-program to enable or
disable certain operations or part slots.  For example, if I break a tool on the
seventh part during the fourth operation (out of many ops) then I can fix the problem,
and restart the code by disabling all operations except #4, and also disabling parts 1-6. 
Then parts 7-16 get finished, and I re-enable the remaining operations and all of
the part slots, then run the program again to complete execution.  This has saved me
tons of heartache from trying to use the "run from here" function or else lots of
cutting-and-pasting to execute code fragments in new files to complete a partial operation.



« Last Edit: December 04, 2009, 03:00:43 PM by bobeson »
Re: Conditional gcode execution is possible in Mach3
« Reply #1 on: December 06, 2009, 11:07:38 AM »
You can execute conditional G code inside vb scripts. I have a part program that exists entirely in a macro file. There are a number of conditional statements based on parameters and variables set at run time. The code that is visible in the G code window is simply M802. Everything else happens inside the M802 macro.
Re: Conditional gcode execution is possible in Mach3
« Reply #2 on: December 06, 2009, 12:15:21 PM »

I was specifically avoiding the use of VB macros in order to keep to straight g-code that would be more portable. 
I suppose portability isn't much of an issue since I only have one machine right now, but I'm in the habit of keeping
away from external dependencies whenever possible, so I'm glad that there exists a way to do conditionals
without going outside the main gcode body.