Centroid CNC control sales, service, training and support
Unless otherwise noted, the methods and examples below are for current CNC11 and CNC12 software, on Mill controls.
Use the M115, M116, M125 and M126 codes to move a touch probe in custom probing cycles.
Whenever possible, specify a bounding position, even with M115 and M116 codes.
Note that the positions you specify with these codes are either absolute positions or incremental distance, depending on the current G90/G91 state.
For example:
G90 M105/X2.0/Y3.0 P15 F20will move towards an absolute position of X2 Y3, at 20 in/min, until the switch on INP15 closes.
In contrast:
G91 M105/X2.0/Y3.0 P15 F20will move in a direction of +2" along X, +3" along Y, at 20 in/min, until the switch on INP15 closes.
Also note that M115 and M116 are interchangeable (as are M125 and M126) when bounding positions are provided, because the direction to the bounding position determines the direction of movement.
Use M115 and M116 when you intend to locate a surface with the probe. The bounding position, if given, should be beyond the farthest likely position of the surface.
With M115 and M116, if the movement proceeds all the way to the bounding position without triggering the input (tripping the probe), then the cycle will be cancelled with an Error.
Use M125 or M126 for positioning moves during which no probe contact is expected.
Like M115 and M116, M125 and M126 will stop if the input is triggered (the probe is tripped); but M125 and M126 will then cancel the cycle with an error. This protects against probe breakage in case of an unexpected obstacle.
M115, M116, M125 and M126 are most commonly used with a touch probe, but they can be used with any switch input, or other PLC bit.
The P parameter used with these codes is either positive or negative, depending on whether you are watching for an open switch to close, or watching for a closed switch to open.
To complicate matters, the meaning of positive/negative P values was changed between CNC10 and CNC11. If you are updating CNC10 macros to run on a CNC11 or CNC12 system, you will need to account for this.
To further complicate matters, the M105 and M106 codes, which are similar to M115 and M116, may also interpret the sign of the P parameter differently.
The behavior for positive and negative P values with the different codes in different software versions is as follows:
Code | CNC10 | CNC11/CNC12 | ||
+P | -P | +P | -P | |
M105/M106 | Move until open (0 -> 1) | Not allowed | Move until open (1 -> 0) | Move until close (0 -> 1) |
M115/M116/ M125/M126 | Move until open (0 -> 1) | Move until close (1 -> 0) | Move until close (0 -> 1) | Move until open (1 -> 0) |
The M105 and M106 codes are useful for axis homing, in situations where the normal M91 and M92 codes are not well suited.
For example, suppose we have a mill X axis which we want to quickly home near the center of travel, regardless of where the axis may be be sitting when the machine is powered up.
We install a dedicated home switch, which will be a normally-open proximity sensor that detects a steel rib that runs from near the mid-point, all the way to the plus limit of travel. We wire it to INP7 on the PLC board. Therefore, we expect INP7 to be open when we are in the minus half of travel, and closed when we are in the plus half.
Our homing macro can contain the following lines for the X axis:
M105/X P7 F100 ; move X- until INP7 is open M106/X P-7 F100 ; move X+ until INP7 is closed M91/X ; run the normal homing sequence
The first line will quickly move us to the minus side of the edge, if we were on the plus side to begin with. If we are already on the minus side (if the sensor is already open) then there will be no movement.
The second line will quickly move us (back) to the plus side of the edge, where the sensor is closed.
The third line will start the usual minus homing sequence: slow-jog speed minus until the switch opens; slow jog plus until the switch closes again; and slow movement further plus until the encoder index pulse comes around.
The complete sequence will end at the first encoder index pulse to the plus (sensor-closed) side of the edge.
This same general approach could be used with a dedicated home switch that is at one end of travel as well, as long as it trips prior to the limit switch.
This approach cannot be used with a home switch that is also a limit, because M105 and M106 will stop with an Error if a designated limit switch is tripped during the movement. Only M91 and M92 are allowed a one-time pass on tripping a limit switch (and then only for the limit switch they are looking for).
If you do home to a dedicated home switch, separate from the limit switch, it is highly desirable that the switch be set up with an extended ramp, so that the home switch remains tripped from its initial trip point, all the way out to the overtravel limit. Otherwise -- if it is physically possible to be inside the limit switches, on either side of the home switch, with the home switch not tripped -- then the homing macro cannot know whether to move plus or minus when seeking the home switch.
You cannot reliably use M115 and M116 in homing sequences, because those codes always attempt to apply software travel limits. They do not recognize that the software limits are not yet valid when machine home has not yet been set, and so will apply invalid restrictions to axis movement.
M105 and M106 do not apply software travel limits, even if the machine has been homed.
In many applications, it is desirable to save control state information either in Machine Parameter values or in static user variables (those CNC variables from #150 to #159).
For example, you might set Machine Parameter 987 (part of the 900-series block set aside for PLC applications) to the desired RPM of a subspindle; or you might use variable #159 to record which tool is currently in the spindle of a router with a rack-type tool changer.
Your custom macros would store new values in the parameter or variable as needed. For example, the code which starts the subspindle might say:
G10 P987 R3500 ; store desired RPM where the PLC can read it M33 ; send subspindle start request to PLCor the router's tool-changing macro might say:
#159 = #4120 ; record that the newly requested tool is in the spindle
There are two crucial components missing from both examples above.
First, the parameter or variable should not be updated during a graphic preview of the program, nor should the variable be updated when that line is read during a mid-program search or restart either.
Second, the control's G code parser must be prevented from processing the assignment while reading ahead, pre-processing codes and queuing them up for later execution by the control. If that is allowed, then the Machine Parameters table will get updated early, and the subspindle may start using an RPM value from much later in the program. Also, if the control reads ahead past an upcoming tool change on the router, but the program is then cancelled before that tool change actually takes place, then variable #159 will hold the wrong value: it will think that the later tool is already in the spindle, when in fact the earlier tool is still there. This generally results in a tool changer crash, as the control tries to put away the tool in the wrong (already-occupied) pocket.
The first issue is solved by skipping the assignment during graph and/or search processing. This can be done by checking system variables #4201 and #4202.
The second issue is solved by forcing a wait, so that machine execution is fully caught up to CNC processing (the queue is empty) before doing the update.
With those corrections, the code examples above would look like this:
IF [#50001] IF [#4201==0] G10 P987 R3500 ; store desired RPM where the PLC can read it M33 ; send subspindle start request to PLCand this:
IF [#50001] IF [#4201==0 && #4202==0] #159 = #4120 ; record that the newly requested tool is in the spindle
The code "IF [#50001]" is an idiom. Literally, it means "if INP1 on the PLC is closed, then do nothing". Because it is implicit that any CNC code that is conditioned upon a PLC input point is intended to test that input at the time the code actually runs, the parser concludes that it cannot test the input -- and cannot process any farther in the job -- until machine execution has caught up to that point. Any PLC bit could be used; INP1 is just the common convention.
The CNC system variable #4201 will have a value of 0 if the control is running the job on the machine, and a value of 1 if the control is generating a graphic preview.
System variable #4202 will have a value of 0 if the control is running the codes it is processing, and a value of 1 or greater if it is processing codes leading up to a mid-program start or resume (in these latter cases the codes are not sent to the machine, but instead are used to determine the CNC state at the point where job execution is to begin).
In our examples above, it makes sense to store any new values for Parameter 987 as we come across them in a search, so that when we get to the search point, the correct (latest) value is in place in the parameter table.
It does not make sense to update the tool number in variable #159 in any condition except an actual tool change.
M98 and G65 can both be used to call a CNC subprogram.
The most significant difference between the two is that G65 allows arguments (parameters, variables) to be passed in as part of the subprogram call.
The arguments provided with a G65 call are accessible within the subprogram as CNC variables #1 through #33. For example, any value given with the letter 'A' in a G65 call will appear in variable #1 within the subprogram.
Any CNC program or subprogram can use variables #1 through #33 for their own purposes, whether or not they were given values through a G65 call.
However, therein lies a key difference between M98 and G65: a G65 call advances the "stack", so that the #1 - #33 variables in the called subprogram are a fresh set, independent of the #1 - #33 variables in the calling program. An M98 call, in contrast, does not advance the stack. Variables #1 - #33 in the M98-called subprogram are the same ones used by the calling program.
Consider this example:
; define a macro subprogram, for later use O9001 #3 = #1 + #2 G0 Y#3 M99 ; main program starts here #1 = 10.0 #2 = 5.0 #3 = 1.234 G0 X#3 ; moves X to X1.234 G65 P9001 A3.2 B0.6 ; macro moves Y to Y3.8 G0 Z#3 ; moves Z to Z1.234Because the variables #1, #2 and #3 in the macro subprogram are independent of the ones in the main program, the main program's values are unchanged after the G65 call.
Compare that with the following, identical except that G65 has been replaced with M98:
; define a macro subprogram, for later use O9001 #3 = #1 + #2 G0 Y#3 M99 ; main program starts here #1 = 10.0 #2 = 5.0 #3 = 1.234 G0 X#3 ; moves X to X1.234 M98 P9001 A3.2 B0.6 ; A and B do nothing, macro moves Y to Y15.0 G0 Z#3 ; moves Z to Z15.0Using M98 instead, the A and B arguments are non-sensical and are ignored. The macro reads and writes the same local variables as the main program. It therefore calculates #3 = 10.0 + 5.0 = 15.0, and moves Y there. When we get back to the main program, local variable #3 has been changed, so the Z move is affected as well.
As a rule, if you want to use #1 - #33 as local or temporary variables, you should call your macro subprograms with G65.
If you have previously worked with older controls, you might have avoided using G65 when you did not need to pass arguments, because the number of nested G65 calls was limited. For example, on early Fanuc controls, you could nest subprogram (M98 and G65) calls up to 20 levels deep, but only four of those levels could use G65: there was only enough memory for four sets of local variables.
The Centroid control allows G65 calls up to 20 levels deep, each with its own set of local variables. Computer memory has come a long way.
It is often necessary to round fractional values to whole numbers (integers). For example, if you need to bring a rotary table, which may be at any angle, to the nearest whole turn (whole multiple of 360°), then you would want to round its position (converted to turns) to the nearest integer, then convert back to degrees and send the axis to that position.
Beginning with CNC12 version 4.14, you can use the functions FIX and FUP to round down or up to the next integer value. Note that for negative values, FIX still rounds down (thus away from zero) and FUP still rounds up (towards zero).
With CNC12 v4.14 or newer, then, you can round to the nearest integer by first adding 0.5, then rounding down:
#100 = FIX[#5044/360.0 + 0.5] * 360.0 G90 G0 A#100
With software prior to CNC12 v4.14, one way to force rounding to an integer is by applying the bit-wise OR operator. Since it only makes sense to perform bitwise operations on integers, CNC11 and CNC12 implicitly convert floating point values to integers before applying OR.
A bitwise OR operation with a second operand of zero (no bits set) returns the first operand unchanged, except for the implicit integer conversion.
When a fractional value is converted to integer using "OR 0", it is always truncated towards zero: positive values are rounded down, while negative values are rounded up. Therefore finding the nearest integer for both positive and negative values requires separate steps:
IF [#5044 >= 0.0] THEN #100 = [#5044/360.0 + 0.5] OR 0 IF [#5044 < 0.0] THEN #100 = [#5044/360.0 - 0.5] OR 0 #100 = #100 * 360.0 G90 G0 A#100
When writing CNC macros for a lathe, some care is required when accessing axis and position information in CNC system variables.
Internally to the control software, the Z axis is axis #1, and the X axis is axis #2. Externally, the X axis is usually given the first position, and the Z axis second.
In most CNC system variables, X is first.
Also, most lathes are set up to run in Diameter mode, where X axis positions and distances represent part diameter quantities. Internally, the actual X distances are radius amounts: half of the specified diameter amounts.
In most CNC system variables, X values are radius values. Local position in #5041 is an exception: it is a diameter value.
#5021 #5022 | X axis machine position (radius) Z axis machine position |
#5041 #5042 | X axis local position (diameter) Z axis local position |
#24101 #24102 | X axis tool-measuring reference (radius) Z axis tool-measuring reference |
#10000 - #10099 #11000 - #11099 | X axis tool offsets (radius) Z axis tool offsets |
Note that, while #5041 returns a diameter value which can be used directly in a G0 or G1 move, #5021 returns a radius value, but G53 moves expect a diameter value for X. Therefore any value read from #5021 must be converted to diameter before use with G53.
Note also that M115, M116, M125 and M126 -- used in probing applications -- expect a radius value when an X axis limiting position is specified. Therefore any position retrieved from #5041 must be converted to radius before it is used as a limit for a probing M code.
The current tool number ("T" code) display in the status window, and the initial value of the CNC system variable #4120, depend on several factors. If you are writing PLC and macro code, for example to work with an unusual tool changer arrangement, then it is important to know what to expect on the display and in #4120.
The last modal tool number (The 'T' code on a mill control, or the first two digits of the T code on a lathe control) is saved from job to job and from day to day, in the "modal_tool_number" element in the job.xml file. In a fresh CNC12 install, or if the job.xml file has been deleted, then the modal tool number is reset to 255.
If the modal tool number has been initiliazed to 255, then the status window display will show "T---", and CNC sytem variable #4120 will return 255.
Once a valid CNC 'T' code has been executed, then that number will appear in the status window, and that same number will be returned in #4120.
When an automatic tool changer is selected by setting Parameter 6 = 1, then the "modal_tool_number" element in job.xml is ignored.
CNC12 expects the PLC program to report the current tool number, in BCD format, in PLC system variable SV_PLC_CAROUSEL_POSITION.
The 'T' number in the status window display will always be the PLC-reported value.
At the start of any new CNC program cycle, before any codes have been processed, #4120 is initialized to the PLC-reported value.
Once a CNC 'T' code has been processed, then #4120 will return the most recent CNC 'T' code.
If one program cycle ends, and then another one begins, #4120 will reset to the PLC-reported tool number. It will not retain the last 'T' code from the preceding program cycle.
Because this scenario depends on a PLC-reported tool number, the PLC program must have code that determines the current tool, and reports it back to CNC12 &emdash; in BCD format &emdash; through SV_PLC_CAROUSEL_POSITION. The form of that code varies, depending on the type of tool changer.
With a typical lathe turret, or a star-type mill ATC (Burgmeister, Robodrill, Acroloc, Emco VMC), the PLC would usually be directly involved in rotating the turret to the desired tool position, and would have that position stored in one of its word variables. In that case the PLC simply needs to convert to BCD format and send the result to CNC12:
IF True THEN Temp_W = TurretPosition_W, BCD Temp_W, SV_PLC_CAROUSEL_POSITION = Temp_W
On the other hand, if the machine is a router with a rack-type tool changer, or if it has a tool turret that is positioned using an axis servo motor, then the tool is selected using axis-positioning commands that are known to CNC12, but not known to the PLC. In this case, it is usually necessary to make the M6 tool-change macro, upon successful completion, store the just-loaded tool number in a Machine Parameter value that can be retrieved by the PLC.
For example, the M6 macro on a mill or router could end with:
IF [#50001] ; wait for execution to catch up before updating parameter value G10 P700 R#4120
... or the cnctch macro on a lathe could end with:
IF [#50001] ; wait for execution to catch up before updating parameter value G10 P1700 R#4120
... and then, in either case, the PLC program could include:
IF True THEN Temp_W = SV_MACHINE_PARAMETER_700, BCD Temp_W, SV_PLC_CAROUSEL_POSITION = Temp_W
The following is what I assume is correct, but has not been verified through testing.
When the enhanced ATC feature set is used, CNC12 tracks its best idea of the tool in the spindle. This is the tool number that was loaded during the last M6 tool change that ran to a successful completion. It is stored in the "modal_tool_number" element in the job.xml file.
The 'T' number in the status window display is that last-loaded tool number.
At the start of a CNC program cycle, #4120 is initialized to this same last-loaded tool number.
As a CNC program cycle runs, once a CNC 'T' code has been processed, then #4120 will return the most recent CNC 'T' code.
If one program cycle ends, and then another one begins, #4120 will reset to the last-loaded tool number. It will not retain the last 'T' code from the preceding program cycle.
Note that with enhanced ATC, CNC12 depends on the PLC program to report the carousel position from which the most recent tool was loaded, in binary format, in SV_PLC_CAROUSEL_POSITION. This is used to maintain the put-back bin number in the tool library. With enhanced ATC, the PLC program generally does not know, or need to know, the logical tool numbers. It only uses carousel bin numbers.
Copyright © 2024 Marc Leonard
Last updated 15-Oct MBL