Go To Cgtech Help Library
Go To Cgtech Help Library
A CAM system generates toolpaths that are largely independent of the machines that will
be used to manufacture a design. The syntax, or language, of these toolpaths is typically a
variant of APT CL. The machine controllers require files with a different syntax, often
referred to as machine code or G-Code. The purpose of an NC post-processor is to
convert the machine independent toolpaths to G-Code files.
An early strategy for creating post-processors was to have a tailored program for each
machine/control combination needed. Such a program required no input from the user
other than the machine independent toolpath files. But development of these post-
processors was time consuming and maintenance of a full suite of them quickly became a
nightmare in large organizations.
The next step in the evolution of post-processors was the "generalized post". With this
approach a single program would access a file of parameters for a given machine/control
combination, then process machine independent toolpaths according to the values and
settings of the parameters. As machines became more complex and controllers
correspondingly more capable, the parameter files grew rapidly from a few flags and
limit values to a very complex set of inter-related choices. Effectively the parameter files
were required to express some logic handling abilities.
So the next required evolutionary step became clear. The machine/control parameter files
were enhanced with the syntax of their own language, so that they could express the
complex logic required for modern machines and controls. The post-processor program
became simpler as the language got more powerful, so that now the principal role of the
post-processor is to interpret the language.
Unfortunately post-processor technology has not matured to the point that there is just
one language for describing how to convert machine independent toolpaths to G-Code.
Each post-processor vendor requires a different syntax and language. The language of the
CGTech Post-Processor borrows heavily from the syntax of BASIC (Beginner's All-
purpose Symbolic Instruction Code).
Why BASIC? The CAD/CAM world doesn't need another new language, so why not
BASIC? There is an inherent danger in borrowing the syntax of an established general-
purpose language for a specific task. Users who are familiar with the language can be
irritated by minor departures from the "standard". On the other hand, the fact that there
are users who don't have to learn the language from scratch, is a big plus. We have
attempted to minimize departures from BASIC syntax as much as possible. Where there
are extensions, we have borrowed from Visual-Basic's syntax.
The post-processor reads a machine independent toolpath, usually in some flavor of APT
CL, and processes one statement at a time. A statement can span several lines of the input
file. For each statement it invokes a "Sub" or subroutine which is a section of a
nominated machine/control dependent language file. Which "Sub" gets called depends on
the statement's major word. If there is no "Sub" for a particular major word, nothing
happens and no error message is generated. More typically the "Sub" will format a G-
Code line or lines, for output to a machine dependent toolpath and a log.
If you are new to the CGTech Post-Processor, it is suggested that you browse the Post-
Processor Language topics in the order they are presented. If you are already familiar
with the language and only need to apply it to VERICUT's Inspection Programming
capabilities, you could jump directly to the Probe Cycle Programming topic.
Post-Processor Language
The file that contains all of the post-processor language to define how machine
independent toolpaths are to be converted to G-Code files for a single machine/control
combination, is often incorrectly referred to as a "Post". It is the logic embedded in such a
file, together with the CGTech Post-Processor program that performs the processing task,
but we have no intention of fighting the nomenclature.
A "post" file must contain all the language needed for a machine/control combination. It
cannot make reference to other language files, even for subroutines that are common to
many machine/control combinations. Each subroutine needed must be present in the
single file that will be accessed by the CGTech post-processor. The default file extension
for a "post" file is ".VcPost".
A VcPost file is typically encoded with ASCII. The language does not require the use of
any non-ASCII characters, but if a user needs to generate comments in the output G-
Code, or in the post-processor's log, with accented vowels or Eastern languages, a VcPost
file can be encoded with UTF-8 or Unicode. Any suitable text editor can be used to create
and maintain VcPost files. A word-processor can be used if you take great care to avoid
saving the files with any formatting information. The text editor embedded in VERICUT
is viable.
It is strongly recommended that you follow good programming practice in terms of
indenting blocks of logic to make the code more legible. Recognizing that we haven't yet
explained any of the language's syntax, the following snippet may make it clear what is
meant by indenting.
Sub GOTO
If (G = 0) Then
If (Z < Z.Previous) Then
Out "<N><G><X><Y>"
Out "<N><G><Z>"
Else
Out "<N><G><Z>"
Out "<N><G><X><Y>"
End If
Else
Out "<N><G><X><Y><Z><F>"
End If
End Sub
Statements, Continuations and Comments
Statements
... has seven statements. Many programming languages use a particular character to
denote the end of a statement, such as the semi-colon in C and Java. This is not the case
in BASIC, nor in our post-processor language. The end of a statement is the end of the
line, unless the rightmost pair of characters indicate a continuation.
Continuations
The continuation characters are a space followed by an underscore, " _". It is easy to
think of the underscore alone as being the continuation character, but an underscore can
be used at the end of a variable name, such as "Radius_". We are not recommending this
because it would make the code more difficult to read. But if a name like this appeared at
the end of a line, the post-processor would treat the next line as the first of another
statement. An underscore which is intended to signify a continuation of the current line's
statement should be separated from the rest of the characters by at least one space. For
example;
Trying to split a function name or variable name between two lines of a statement is a
bad idea. It makes the code hard to read, and won't work. We haven't covered the topic of
string constants yet, but they consist of any characters between double-quotation marks.
"Any" includes the underscore character, so a single string constant cannot span two lines
of a statement. It is necessary to split the string into two or more, and concatenate them as
follows;
Strictly it is not necessary to use continuation characters at all. There is no practical limit
on the length of a line of code. But it makes sense to restrict lines to the width that can be
displayed by your text editor without having to scroll horizontally.
Comments
A comment can be appended to any line of code, simply by adding a single-quotation
mark and any characters for the comment.
It is also possible for a line to contain nothing but a comment, and this may well be the
better style to adopt for legibility.
A line with the continuation characters can also end with a comment, but this really gets
ugly because it makes it more difficult to see the continuations.
While you can append comments to continued lines, it is not possible, nor necessary, to
split extensive comments into continuation lines. Since a comment can contain any
characters, a space and underscore on the right end will not cause the next line to be
treated as a continuation. If you need a multi-line comment, just use several individual
comment lines.
No other syntax to denote a comment is supported. In particular the "Rem" style that
appears in some flavors of BASIC cannot be used.
Variables
Variables
There are just three types of variable in the post-processor language; numeric values, text
strings and an object analogous to a control's register that has both numeric and text
properties. We will refer to these three variable types as simply numbers, strings and
registers. There is no boolean variable type.
Variable names can be any combination of letters of the alphabet, numerals and the
underscore character, but must begin with a letter. There is no practical limit to their
length, so you can make them very descriptive. Names are case insensitive, so "radius",
"Radius" and "RADIUS" are synonyms. This slack attitude also applies to reserved words
in the language such as "If", "Then" and "Else", and also to subroutine and function
names. There are two schools of thought when it comes to compound names. One uses
uppercase for the first letter of each word, such as "CircleRadius", while the other
separates the words with an underscore, such as "circle_radius". We suggest that you pick
a style and stick with it. Having both in the same VcPost would be an invitation to bugs,
since "CircleRadius" and "circle_radius" are not synonyms.
Unlike BASIC, the post-processor language has no declaration statements, such as
"Dim". There are no arrays. We will leave the topic of registers for a while, but if the
following statements are the first to be executed that refer to "Radius" and "Tool", then
their types will be number and string respectively.
Radius = 0.125
Tool = "Drill"
Tool = 5
Strings
A string variable retains a sequence of characters. There is no practical limit on the
number of characters. A string constant is a sequence of characters enclosed by double-
quotation marks.
If a string constant needs to contain a double-quotation mark, then two such marks should
be used. For example;
Mixing
Number and string variable types cannot be mixed in arithmetic, string concatenation or
logical expressions. Thus if "Radius1" and "Radius2" are defined by;
Radius1 = 3.5
Radius2 = "1.25"
X.Prefix = "X"
X.Format = "s3.3sm"
X.Minimum = -499.999
X.Maximum = 500
If (X.Scale < 0) Then
DeltaX = X.Current - X.Previous
Message = "Set vernier to " & X.Output
A new variable is defined as a register as soon as the variable name is encountered with a
trailing period. Many registers are predefined and have reserved names, such as X, Y and
Z for the first 3 machine axes.
To shorten code and perhaps make it more comprehensible, a register variable name can
appear without a trailing period. If it appears in an arithmetic expression, an unqualified
register name implies its .Current property, thus the following lines of code have the
same effect;
Diameter = 2.0 + Z
Diameter = 2.0 + Z.Current
Zap R
will reset the previous value of register R to an undefined state. This is useful for a modal
register when it is necessary to force output of the current value even when it may not
have changed, perhaps after a tool change.
Properties
Name Description
ArcRadius Radius of current arc.
ClearRetract Default clearance plane retract distance.
GOHOME retract distance. Zero if GOHOME without axis minor
HomeRetract
words should use FROM point.
Cumulative value of NURBS knot at current point (CATIA style
NurbsKnot
NURBS only).
NurbsOrder Order of current NURBS.
NurbsWeight Weight for current NURBS control point.
PathX Current X coordinate transformed by toolpath matrix.
PathY Current Y coordinate transformed by toolpath matrix.
PathZ Current Z coordinate transformed by toolpath matrix.
PathI Current I coordinate transformed by toolpath matrix.
PathJ Current J coordinate transformed by toolpath matrix.
PathK Current K coordinate transformed by toolpath matrix.
PathCenterX Current X coordinate of arc center, transformed by toolpath matrix.
PathCenterY Current Y coordinate of arc center, transformed by toolpath matrix.
PathCenterZ Current Z coordinate of arc center, transformed by toolpath matrix.
PathCenterI Current I coordinate of arc axis, transformed by toolpath matrix.
PathCenterJ Current J coordinate of arc axis, transformed by toolpath matrix.
PathCenterK Current K coordinate of arc axis, transformed by toolpath matrix.
RawX Current raw X coordinate from APT source.
RawY Current raw Y coordinate from APT source.
RawZ Current raw Z coordinate from APT source.
RawI Current raw I coordinate from APT source.
RawJ Current raw J coordinate from APT source.
RawK Current raw K coordinate from APT source.
RawCenterX Current raw X coordinate of arc center, from APT source.
RawCenterY Current raw Y coordinate of arc center, from APT source.
RawCenterZ Current raw Z coordinate of arc center, from APT source.
RawCenterI Current raw I coordinate of arc axis, from APT source.
RawCenterJ Current raw J coordinate of arc axis, from APT source.
RawCenterK Current raw K coordinate of arc axis, from APT source.
Strings
Name Description
Current APT statement.
APTLine All of the statement's parameters are concatenated into a single line,
even if the source has continuation lines.
Next APT statement.
APTNext All of the statement's parameters are concatenated into a single line,
even if the source has continuation lines.
Current APT statement's comment.
If the statement has text following "$$" characters, this variable is that
text with any leading and trailing spaces trimmed. For a DISPLY,
Comment
HEADER, INSERT, PARTNO, PPRINT or REMARK statement, this
variable is the text following the major word and its delimiter, with
leading and trailing spaces trimmed.
Today's date.
Date In the localized "short" format, so for example in the USA, Christmas
day would be "12/25/04".
Current time of day.
Time In the localized "medium" format, so for example in the UK, tea-time
would be "16:00:00".
Unit Linear unit, "in" or "mm".
Registers
Name Description
A Machine A axis.
B Machine B axis.
C Machine C axis.
F Feed rate.
G G-code.
H Head number.
I Machine X of arc axis.
J Machine Y of arc axis.
K Machine Z of arc axis.
M M-code.
N Sequence number.
R Radius.
S Spindle speed.
T Tool number.
U Machine U axis.
V Machine V axis.
W Machine W axis.
X Machine X axis.
Y Machine Y axis.
Z Machine Z axis.
Language Keywords
(Cannot be used as variable names.)
Math Functions
Signature Description
number = abs(number) Absolute value.
number = acos(number)
or Inverse cosine (result in degrees).
number = inverseCosine(number)
number = alogE(number)
or
number = antiLogarithm(number) Natural anti-logarithm.
or
number = exp(number)
number = alog10(number) Base 10 anti-logarithm.
number = asin(number)
or Inverse sine (result in degrees).
number = inverseSine(number)
number = atn(number)
or
number = atan(number) Inverse tangent (result in degrees).
or
number = inverseTangent(number)
Inverse tangent of first argument divided by
number = atan2(number, number)
second argument (result in degrees).
number = cos(number)
or Cosine (argument in degrees).
number = cosine(number)
number = fix(number)
or Integer part.
number = int(number)
number = logE(number)
Natural logarithm.
or
number = logarithm(number)
number = log10(number) Base 10 logarithm.
number = root(number)
or
number = sqr(number)
or Square root.
number = sqrt(number)
or
number = squareRoot(number)
number = round(number)
or Round to nearest integer.
number = nint(number,)
number = sgn(number)
or Sign (-1, 0, or +1).
number = sign(number)
number = sin(number)
or Sine (argument in degrees).
number = sine(number)
number = tan(number)
or Tangent (argument in degrees).
number = tangent(number)
String Manipulation
(all positions are base 1)
Signature Description
number = Asc(string)
or Returns ASCII code of first character in argument.
number = Ascii(string)
string = Chr(number)
Returns string containing just the character with the
or
specified ASCII code.
string = Char(number)
number = InStr(string,
string) Returns position of first occurrence of second argument in
or first argument. If there is no such occurrence, returns
number = inString(string, zero.
string)
string = LCase(string)
Produces lowercase version of argument.
or
string = lowercase(string)
Returns characters from left of first argument, the number
string = Left(string, number)
of them being specified by the second argument.
number = Len(string)
or Returns number of characters in first argument.
number = Length(string)
string = LTrim(string)
or Trims whitespace from left of argument.
string = leftTrim(string)
string = Mid(string, number,
number) Returns characters from middle of first argument, from
or position specified by second argument, the number of
string = Middle(string, them being defined by the third argument.
number, number)
string = Right(string, Returns characters from right of first argument, the
number) number of them being specified by the second argument.
string = RTrim(string)
or Trims whitespace from right of argument.
string = rightTrim(string)
string = Trim(string) Trims whitespace from left and right of argument.
string = UCase(string)
or Produces uppercase version of argument.
string = uppercase(string)
Register Related
Signature Description
Zap register Sets previous value of register to an undefined state.
Input Related
Signature Description
Gets the word at the specified parameter position in
the current APT line.
string = getWord(number) Parameters are numbered from 1 for the major
word.
If the requested parameter is numeric, its text is
returned.
Gets the numeric value at the specified parameter
position in the current APT line.
Parameters are numbered from 1 for the major
number = getValue(number)
word.
If the requested parameter is not numeric, zero is
returned.
Gets the n'th non-numeric parameter in the current
APT line.
string = getNthWord(number)
If there are not enough non-numeric parameters, an
empty string is returned.
Gets the n'th numeric parameter in the current APT
line.
number = getNthValue(number)
If there are not enough numeric parameters, a zero
is returned.
Gets the cumulative knot value at the specified
NURBS point.
number = getKnotValue(number)
Points are numbered from 1.
If there are not enough points, a zero is returned.
Sets a flag so that the next FROM or GOTO point
will become the new HOME position.
zapFrom
Typically used during a tool change or tool axis
adjustment.
Output Related
Signature Description
Displays a dialog box with the current state of all
Debug
numbers, strings and registers.
or
The string in the statement, if present, is used for the
Debug string
dialog title.
Log string Sends a string to the log.
Sends a string to both the output G-Code file and the
Out string
log.
Subroutines
As the post-processor reads each APT statement from the input toolpath, it attempts to
invoke a subroutine, or "Sub", from the VcPost file. The names of the subroutines are
simply the corresponding APT major words. So when the post-processor encounters a
RAPID statement, it will try to call the RAPID subroutine. The syntax of the start and
end of such a subroutine is;
Sub RAPID
....
....
End Sub
Note that a subroutine has no arguments. Because all variables are global in scope, there
is no need to pass them as arguments between subroutines. The code between the "Sub"
and "End Sub" statements will be executed each time a RAPID statement is read.
If at some point within a subroutine you wish to bypass the remaining code, you can use
an "Exit" statement.
Sub PPRINT
....
....
If (display = 0) Then
Exit Sub
End If
....
....
End Sub
It is not necessary to write a subroutine for every APT major word that the post-processor
may encounter. If there is no subroutine for a particular major word, the post-processor
does nothing, and does not generate an error message.
Do not be surprised to see code statements in a VcPost file that are not in any subroutine.
While such lines can appear anywhere in the file, it is good practice to put them up front.
They get executed by the post-processor before any statements are read from the input
toolpath. Typically they are used to establish the output format of registers and specify
initial values. For example;
X.Prefix = "X"
X.Format = "s3.4sm"
Y.Prefix = "Y"
Y.Format = "s3.4sm"
Machine = "Horizontal Lathe"
Author = "I. B. Nutz"
Calls
It is not normally necessary for a subroutine named for a major word to invoke one
named for another major word. But you can do so. You can also write a subroutine which
is not associated with a major word, which will never be invoked directly by the post-
processor. To call such a subroutine, you simply place its name in a statement on its own.
There are no arguments because all variables are global in scope. For example you could
write a subroutine to calculate rotate the current X and Y machine axis locations through
an angle.
Sub RotateXY
ca = cos(Angle)
sa = sin(Angle)
XRotated = X * ca - Y * sa
YRotated = Y * ca + X * sa
End Sub
Then to use this subroutine you would need to set up the "Angle" variable, invoke the
Sub and access the results.
Angle = 5
RotateXY
NewX = XRotated
NewY = YRotated
Assignment and Operators
Assignment
Assignment of a value to a variable is achieved using the equal sign, "=". The variable's
name goes on the left of the equal sign, and an expression that generates the required
value goes on the right. This is true for numbers, strings and register properties.
Diameter = R.Current * 2
Message = "Load tool " & T.Current
F.Prefix = " F"
If the variable or register on the left of the equal sign does not already exist, it will be
created by the assignment statement. If it does exist, its value or the value of its property,
will be adjusted.
Arithmetic Operators
Order of precedence is from top to bottom.
String Operators
Logical Operators
Order of precedence is from top to bottom.
Note that the "Like", "Is", "Eqv" and "Imp" operators available in some flavors of
BASIC, are not supported by the post-processor language.
Branching
There are two types of logic branching available in the post-processor language, the "If ...
Then ... Else" technique, and the "Select ... Case method.
If condition Then
statements
[ElseIf condition Then
statements]
[ElseIf condition Then
statements]
[Else
statements]
End If
Note that a statement never appears on the same line following "Then", in an "If" or
"ElseIf". This is possible in BASIC but we have chosen not to support it, to encourage
more easily maintainable code. An "If" branch can be as simple as;
The parentheses around the condition are not strictly necessary but help improve
legibility. Stepping up in complexity, an "If" can represent an either/or condition;
The expression can be a number, string or register property. Each condition should
involve the same variable type, with numeric register properties treated as numbers, and
text register properties treated as strings. There is a wide choice of condition syntax as
defined in the following table, in which variable denotes an expression that evaluates to a
number or string.
Note that the operator "Is", available in some flavors of BASIC, is not supported by the
post-processor language. Nor are compound conditions that would require use of the
logical operators "Not", "And", "Or" or "Xor". At most one block of statements will be
executed during a pass through the "Select" construct, regardless of the value of the
expression and the conditions. If the expression matches more than one of the conditions,
only the statements following the first such condition will be executed.
Following is an example of the use of "Select ... Case" which parallels the last example
for the "If ... Then ... Else" technique.
And here is an example that uses a number variable and illustrates more of the possible
conditions.
There are three types of looping available in the post-processor language, "For ... Next",
"Do ... Loop" and "While ... Wend.
The counter must be a number, or a register if its current value is to be used. The
elements start, end and step, if present, must all be expressions that evaluate to a number.
The value of the count and components of any of the expressions, can be altered within
the loop, but this tends to make debugging much more difficult. If step is missing, a value
of -1 is assumed if start is greater than end, otherwise +1 is used.
For a positive or zero step, the contents of the loop are executed provided counter is less
than or equal to end, and the counter gets increased by step. For a negative step, the
contents of the loop are executed provided counter is greater than or equal to end, and the
counter gets decreased by step. It is possible for the content of the loop to never be
executed, as would be the case with the following example.
Do ... Loop
Using "[" and "]" to bracket optional elements, and "|" to indicate a choice of keywords,
the syntax is;
Do [While|Until condition]
statements
[Exit Do
statements]
[Exit Do
statements]
Loop [While|Until condition]
It would be very unusual to have While or Until conditions at both ends of the same
loop. With a While in the Do statement, the content of the loop will be executed if the
condition is true. With an Until in the Do statement, a false condition is required for the
loop content to be processed. A While in the Loop statement needs a true condition for
control to return to the Do, and an Until would require a false condition.
You can write a "Do ... Loop" with no conditions at either end, but you had better have
an "Exit Do" somewhere within it, or you could wait a while for the post-processor to
finish.
While condition
statements
Wend
There is no "Exit" statement for a "While ... Wend" so it is vital that condition is changed
within the loop, and that it becomes false at some point.
Post-Processor Output
There are two types of post-processor language statement that generate output to files,
"Log" and "Out". "Log" only writes to a log file of the post-processor's activities, but
"Out" directs output both to the log file and to the G-Code file. Input lines from the APT
source are also sent to the log file, but this does not require any language statements in
the VcPost. The syntax for the output statements is;
Log string_expression
Out string_expression
But in each case the string_expression can take advantage of some extra features of the
language. In its simplest form an expression could be a string constant;
Log "Job " & jobName & ", Spindle Speed " & S.Output
Remember that a string expression cannot contain a number variable, because there is no
way to specify the format required. If you need to output a number, you should probably
be using a register instead. If necessary, you could use a register just for this purpose;
Temp.Format = "s4.2"
Temp.Current = toolDia
Log "Tool Diameter = " & Temp.Output & "mm"
A reference to a register variable that does not have a property qualifier will use the
.Current property if a number is expected, and the .Output property when a string
would make sense. Thus this last example could be simplified to;
Temp.Format = "s4.2"
Temp = toolDia
Log "Tool Diameter = " & Temp & "mm"
To explore this topic further, let's use a sample that will be much more common. The
GOTO subroutine for a 3-axis machine needs to output lines similar to the following;
N12 G01 X1.25 Y2.375 Z4.5 F200
Probably the G, X, Y, Z and F registers will be modal, so that their values will only be
output when they have changed. The N register will always change so it doesn't matter
whether we think of this as being modal or not. Let's assume that the .Prefix property for
each register except N includes a leading space. With the rules that we have introduced so
far, you could write a statement to generate the required G-Code lines as follows;
Out N.Output & G.Output & X.Output & Y.Output & Z.Output & F.Output
Or more concisely;
Here is another way, that may not initially seem to have any advantage over the prior
implementation.
Out "<N><G><X><Y><Z><F>"
The key here is that the register references are now embedded in a string constant, using
the "<" and ">" characters. So if the output line has some constant elements and some
register values, it can be specified without using concatenation. The last line of our earlier
example could be written;
Zap F
somewhere in one of the subroutines involved in a tool change. The other technique is a
variant of the "<register>" syntax. By placing an exclamation point in front of the
register name, "<!register>", you will force output of that register's value.
The .Increment property of the N register should always be set to a positive value, in the
segment of your VcPost that is outside all subroutines.
N.Increment = 1
Each time an "Out" statement includes the N register, its value will automatically be
incremented. If the balance of the output line is modal registers, and none of them have
changed, then no output is generated and the N register will not be changed. To illustrate
this, we will go back to our early sample GOTO subroutine.
Sub GOTO
If (G = 0) Then
If (Z < Z.Previous) Then
Out "<N><G><X><Y>"
Out "<N><G><Z>"
Else
Out "<N><G><Z>"
Out "<N><G><X><Y>"
End If
Else
Out "<N><G><X><Y><Z><F>"
End If
End Sub
RAPID
GOTO/1,2,6
RAPID
GOTO/1,2,2
N21G00X1.Y2.
N22Z6.
N23Z2.
Note that there is only one output line corresponding to the second GOTO, when both X
and Y are unchanged.
Post-Processor Debugging
Debug title_string
The title_string is optional, and if present will be used in the title bar of the window.
You could have just one "Debug" statement outside all the subroutines in the VcPost.
Then the window would appear as soon you start processing the input toolpath. As you
step through the toolpath, you can refresh the content of the Debug window at any time,
just by clicking on its icon.
Alternatively you can place "Debug" statements in several places, with different titles,
and a window will be added to the display each time the post-processor reaches such a
statement. Putting a "Debug" statement inside a loop would not be a good idea. You can
close any of the Debug windows by clicking on its icon.
A icon within the register table indicates that a property has no defined value.
Probe Cycle Programming
Introduction
VERICUT can be used to generate G-Code files that drive an NC machine through the
steps required to inspect a workpiece with one or more probes. You will find this
capability in the menus at Analysis menu > Inspection. Once you have picked the
features that are to inspected, you can use the (Use probe for all features) icon to
specify that each of them will be probed. Then the (Program probe cycles) icon will
present the Inspection Programming window, and prompt you to select a post-processor
language file. By convention such a file should have the extension ".VcPost".
Probe cycle programming uses the post-processor language file to determine how to
format the output G-Code files. In addition, comments within the file are used to define
the names of the probe cycles available on the target machine, and the names of each
cycle's parameters. Both types of names get displayed in the programming dialog's table,
and the user is expected to pick a cycle which is appropriate for measuring each feature,
and to provide numeric values for at least some of its parameters. This document is
primarily concerned with defining the syntax of the comments.
There are eight keywords used in the probe cycle comments, each of which starts with the
character "#". The keywords are;
A subroutine or "Sub" within the post-processor language file can employ at most just
one of these keywords. It may have more than one comment line with the same keyword.
Such comment lines must be between the "Sub" and "End Sub" statements.
In addition to the keyword, any of the comment lines can also contain parameter names,
which should be separated by spaces. Each parameter name will be used as the name of a
register in the post-processor, so the name must conform to the rules for variable names.
They must start with a letter and can only contain letters, numerals and the underscore
character, "_". Note that there are language words that cannot be used as parameter
names. Parameters can be essential to the interpretation of a probe cycle, or optional. An
exclamation mark, "!", preceding a parameter's name in the comment line declares it as
mandatory. The syntax should become much clearer in the following examples.
#Init
There should only be one subroutine containing a comment line with the #Init keyword,
and it will be invoked once, before any other subroutines, when the post-processor is run.
For example, if the following is defined in the post-processor language file,
Sub Initialize()
' #Init Offset Clearance FeedRate
Out "<N> G17"
End Sub
then the first row in the inspection programming table will initially look like this.
Note that it is the name of the subroutine, "Initialize", that appears in the "Cycle" column
of the table. So you can alter the prompt in the table to match the user's language and
preferences. The parameter names that follow the #Init keyword on the comment line will
appear in the numbered columns, in the order they are listed. If you need more
parameters than can comfortably fit on one comment line, simply add more lines, each
with the #Init keyword. There is a maximum of 16 parameters per subroutine. As with the
subroutine name, the parameter names can be localized for language and user taste.
In this example the three parameters are optional, so none of their names are preceded by
an exclamation mark. Note too that none of the parameters are used in the subroutine. If
the user provides a value for one of them in the table, that value will be established as the
current value of the register of the same name, before the subroutine is invoked.
#End
There should only be one subroutine containing a comment line with the #End keyword,
and it will be invoked once, after all other subroutines. For example,
Sub Terminate()
' #End
End Sub
This subroutine has no parameters, and more unusually, no executable statements, but its
name will appear in the last row of the table.
#Rapid
One or more rows for rapid motion can be inserted in the programming table before the
approach to any feature that is to be measured. There should only be one subroutine
containing a comment line with the #Rapid keyword, and it will be invoked for each of
the corresponding rows in the table. This example will "square" the rapid motion. Note
that all three parameters are mandatory, so their names are preceded by exclamation
marks.
Sub Rapid()
' #Rapid !X !Y !Z
If (Z < Z.Previous) Then
Out "<N> G0<X><Y>"
Out "<N><Z>"
Else
Out "<N> G0<Z>"
Out "<N><X><Y>"
End If
End Sub
The background of table cells for mandatory parameters is pink. As the user replaces the
parameter names with numeric values, the pink will be removed. He or she should aim to
eliminate all the pink before running the post-processor.
#Move
Like rapid motions, one or more feedrate motions can be inserted in the programming
table before the approach to a feature that is to be measured. There should only be one
subroutine containing a comment line with the #Move keyword, and it will be invoked
for each of the corresponding rows in the table. This example has a mix of mandatory and
optional parameters.
Sub Move()
' #Move !X !Y !Z FeedRate
Out "<N> G1<X><Y><Z><FeedRate>"
End Sub
If the user leaves the word "FeedRate" in the last parameter's cell, the register with the
same name will not be altered from its prior state.
#Approach
There should only be one subroutine containing a comment line with the #Approach
keyword, and it will be invoked immediately before each of the cycle routines that
measure a feature. For example,
Sub Approach()
' #Approach !X !Y !Z Clearance FeedRate
Z = Z + Clearance
If (Z < Z.Previous) Then
Out "<N> G1<X><Y><FeedRate>"
Out "<N><Z>"
Else
Out "<N> G1<Z><FeedRate>"
Out "<N><X><Y>"
End If
Z = Z - Clearance
GoFeel
End Sub
If you find that there are several parameters that are common to almost all of your cycle
subroutines, you may wish to move them to the approach subroutine. Since this is always
called before the cycle, you can reduce the number of columns used in the table and
provide a more consistent user interface across different cycle types.
#Retract
There should only be one subroutine containing a comment line with the #Retract
keyword, and it will be invoked after each of the cycle routines that measure a feature.
For example,
Sub Retract()
' #Retract Clearance FeedRate
Z = Z + Clearance
Out "<N> G1<Z><FeedRate>"
End Sub
#Cycle
There should as many subroutines containing a comment line with the #Cycle keyword as
there are probe cycles available on the target machine. Typically each such subroutine
will have numerous parameters, and we suggest listing the mandatory ones before the
optional ones. In this example the parameter list is spread across two comment lines, both
beginning with the #Cycle keyword.
Sub WallThick()
' #Cycle !X !Y !Width !Depth !Angle
' #Cycle !Correction Offset MaxSafe
MVAR =4
CPA =X
CPO =Y
SETVAL = Width
ID = Depth
STA1 = Angle
Out "<N><MVAR><CPA><CPO><SETVAL><ID><STA1>"
Out "<N><Correction><Offset><MaxSafe>"
Out "<N> CYCLE979"
End Sub
The alphabetically sorted set of all cycle subroutines is offered in a drop-down list in the
fourth column of each feature row of the table.
Once a cycle type has been selected, the parameters of the corresponding subroutine will
be inserted into the table. Not all of them are included in this illustration.
#Save
Some suites of probe cycles have the ability to save the result of one measurement and
compare it with other measurements in a later cycle. For example, if you wanted to check
that the Z dimension of one surface matched that of another, you could save the result of
probing the first surface, then on the second one use a cycle that compared the new
probed Z with the stored value. If your target machine has this capability, you need a
single subroutine containing the #Save keyword. For example,
Sub Store()
' #Save
Out "<N> G65 P9834"
End Sub
The user will then be able to insert a "save" row prior to any retract.
As with any of the keyword identified subroutines, the #Save subroutine can have
parameters if needed.