Everything in this chapter is an addition to the G-code of LinuxCNC ([cha:g-codes], [cha:m-codes]). The statements are written on a line of their own (no other words), names are case-insensitive, the text in parentheses keeps its case. The R parameters, expressions, variables, jumps and control structures of the Siemens program language have a chapter of their own, [cha:siemens-programming].

Axis words with machine axis names

When an axis letter exists in several channels (see [cha:multichannel-config]), the axis word carries the machine axis name and an equals sign:

G0 X2=120 Z2=290 W300     (channel 1: its X and Z are X2 and Z2, W exists once)
G1 X3=0 Y-60 F500         (channel 2: X3, the only Y)

The plain word X120 is refused in such a channel ("axis X is machine axis X2 here: write X2=value"); letters that exist once are written as usual. An axis word of an axis the channel does not hold is refused ("axis C1 is not in this channel, GETD(C1) first"). The GUIs and the tool-length / work-offset forms of mchmi write the names the same way.

Wait marks: M90 to M93

The channels synchronize each other with marks that are evaluated in the real-time controller, so the release is exact to the servo cycle and independent of the read-ahead of the interpreters.

Code Meaning

M90 P<mark> [Q<mask>]

Barrier. The channel reaches mark P with an exact stop and waits until every channel of Q has reached the same mark; all of them are released in the same servo cycle.

M91 P<mark>

Set the mark, no waiting. The mark counts as set when the segment is reached in the planner.

M92 P<mark> [Q<mask>]

Wait for the mark: holds until every channel of Q has set mark P with M91, then consumes the mark.

M93 [Q<mask>]

Wait for the program end of the channels of Q (M2/M30 sets the reserved mark 0 once the last motion is done).

P is the mark number 1..63, Q the channel mask (bit per channel index: channel 0 = 1, channel 1 = 2, channel 2 = 4; omitted or 0 = all other channels). [CHANNEL_n]WAIT_MARK_TIMEOUT limits the wait. An abort of a channel that others wait on aborts them too unless motion.N.wait-mark-abort-partners is 0. HAL: motion.N.wait-mark-active, -id, -set. With one channel M90/M92 return at once and M91 sets the mark.

(channel 0)                      (channel 1)
G1 Z1=-60 F200                   M92 P1 Q1        (wait until channel 0 has set mark 1)
M91 P1                           GET(C1)
RELEASE(C1)                      G1 C1=90 F1000
M92 P2 Q2                        RELEASE(C1)
GET(C1)                          M91 P2

Siemens notation: WAITM, WAITMC, WAITE, SETM, CLEARM

The same marks can be written as the program coordination statements of SINUMERIK. A statement stands alone on its line; a channel is given by its index (0, 1, …​ as with INIT/START) or by its [CHANNEL_n]NAME (case does not matter), and no channel means all channels. Both notations use the same marks and the same real-time evaluation, so they can be mixed between channels.

Statement M-code Meaning

WAITM(<mark>, <ch>, <ch>, …​)

M90 P<mark> Q<mask>

Barrier: the channel waits at the mark until the listed channels have reached it, then all go on together. The own channel may be listed.

WAITMC(<mark>, <ch>, …​)

M92 P<mark> Q<mask>

Conditional wait: holds only until the listed channels have set the mark with SETM; a mark that is set already does not stop the channel. The mark is consumed.

WAITE(<ch>, …​)

M93 Q<mask>

Wait for the program end of the listed channels.

SETM(<mark>, <mark>, …​)

M91 P<mark> per mark

Set the marks in the own channel, no waiting.

CLEARM(<mark>, …​), CLEARM()

-

Clear the listed marks of the own channel, CLEARM() all of them. The running machining is not affected; the marks are cleared in sequence with the program, like SETM.

Marks are 1..63; mark 0 is the program-end mark of WAITE (CLEARM(0) withdraws it). A reset of a channel withdraws the marks it has set, as with M91. The example of the two-turret machine, channel 0 named REVOLVER 1 in its [CHANNEL_0]NAME:

(channel 0, "REVOLVER 1")        (channel 1, "REVOLVER 2")
INIT(1, "revolver2.ngc", S)
START(1)
G0 X1=1                          G0 X2=1 Z2=1
WAITM(1, 0, 1)                   WAITM(1, REVOLVER 1, REVOLVER 2)
G0 X1=2                          G0 Z2=2
SETM(2)                          WAITMC(2, 0)
G0 X1=3                          G0 Z2=3
WAITE(1)                         M30
CLEARM()
M30

Axis exchange: GET, GETD, RELEASE

RELEASE(<axis>)

Gives the machine axis up: it leaves the channel’s axis list and holds its position. Released by the channel the INI assigns it to, it belongs to nobody until a GET; released by a channel that had borrowed it, it returns to its INI channel by itself as soon as that channel stands still (no planned motion, no jog), at the joint’s position - a program there which never writes GET keeps working after another channel used the axis (the SINUMERIK fetches an axis automatically when its channel programs it, MD AUTO_GET_TYPE; the returning channel’s interpreter sees the new position after its next read-ahead stop, e.g. M6). Releasing an axis the channel does not hold is no error, the program goes on.

GET(<axis>)

Takes the axis once it is free - the statement holds until the owning channel has released it (Siemens GET).

GETD(<axis>)

Takes the axis directly, without a RELEASE in the other channel: as soon as the owner does not move it, the owner loses the axis and no longer reports it; while the owner moves it, GETD waits for that move to end (Siemens GETD).

The axis appears in the channel’s pose at its letter slot (a free slot otherwise), the interpreter reads the position and the axis mask back after the statement (it is a read-ahead stop), and the axis word becomes available. A command axis of a synchronized action ([cha:synchronized-actions]) is taken over the same way once its motion has ended. Status: stat.pose_joint, stat.axis_mask.

Program chaining: INIT and START

INIT(<channel>, <program>[, N|S])

Loads a program into another channel (the name as written, with or without quotes, looked up in [DISPLAY]PROGRAM_PREFIX). N (default): no acknowledgement, S: wait until the other channel has loaded it.

START(<channel>)

Starts the loaded program of the other channel (its task must be on; the program then runs in that channel’s AUTO mode).

The channel is given by its index (0, 1, …​) or by its [CHANNEL_n]NAME, e.g. INIT(REVOLVER 2, "welle_kanal2.ngc").

Continuing an interrupted program: REPOSA

REPOSA (as well as REPOSL, REPOSQ, REPOSH) in an asynchronous subprogram asks for the program the ASUP interrupted to go on at the block it was in when the ASUP ends (see the configuration chapter, ASUP section). Without it the interrupted program stays aborted. The approach is a straight move from the ASUP’s end position to the end of that block; the modes of REPOSL/REPOSQ/REPOSH are accepted and treated alike.

Master spindle: SETMS

SETMS(<spindle>) chooses the spindle of the channel for CSS (G96) and feed per revolution (G95); default [CHANNEL_n]MASTER_SPINDLE. The spindle words of the channel act on it. Status stat.master_spindle.

Tool management statements

SETPIECE(<n>)

Counts n pieces on the tools of the channel with piece count monitoring (mctooldb).

TOOLSET(<id>, <key>, <value>)

Writes a parameter of the tool with identity id in the tool file (e.g. TOOLSET(3, actual, 0)).

#<_tool[<id>]<key>>

Reads a parameter of the tool file (e.g. #<_tool[3]actual>). The interpreter reads ahead: insert M66 E0 L0 before reading values a preceding statement changed.

Magazine places: MVTOOL, TCI, POSM, GETFREELOC

With magazines and buffer places configured ([sec:multichannel-toolmag]) the tool change program books the tool moves itself, with the SINUMERIK commands. Their arguments are Siemens expressions (program variables, R parameters, system variables, # parameters); a move the places do not allow (no tool on the source place, the target taken, reserved or locked, no free place) is reported as an error of the channel and stops its program - the Siemens state parameter of MVTOOL is accepted and set to 0. The statements wait for the queue like a tool change, so the lines after them read the new places.

MVTOOL([state,] magFrom, locFrom, magTo[, locTo])

Moves the tool on place locFrom of magazine magFrom to magTo / locTo. A missing or zero locTo in a real magazine searches a free place (the owner place first, then the magazine’s strategy); magTo 0 is the owner magazine. Moving a tool out of a real magazine records its owner place, moving it back clears it; the buffer place of kind SPINDLE makes it the loaded tool; a LOADPOINT removes it from the places.

TCI(locNo[, holder])

Moves the tool on buffer place locNo (a gripper, not the spindle) back into the magazine: its owner place or a free one.

$TC_MPP6[mag, place] = id

Puts tool id onto the place (it must be free); 0 removes the tool there from the places. Also written as TOOLPLACE(mag, place, id).

POSM(place[, mag[, ip[, im]]])

Positions magazine mag (default the first real one) so that place is at the change point: when the magazine has an AXIS and this channel owns it, a rapid move of that axis to ZERO + PITCH * (place - 1); in any case the position is booked, so $TC_MAP8[mag] reads it in every channel.

GETFREELOC(MAGVAR, LOCVAR, id[, mag])

Writes the magazine and place a free place search for tool id finds into the two DEF INT variables (0, 0 when there is none).

GETSELT(VAR)

Writes the tool number last programmed with T into the variable.

The system variables of the places, in Siemens expressions as $NAME[..] and as named parameters <_name[..]> (e.g. <_tc_mpp6[9998,2]>):

Variable Meaning

$TC_MPP6[m,p]

id of the tool on the place, 0 if free

$TC_MPP1[m,p]

kind of the place: 1 magazine, 2 spindle, 3 gripper, 4 loader, 5 transfer, 6 station, 7 load point

$TC_MPP4[m,p]

state: bit 0 locked, bit 1 occupied, bit 2 reserved for a tool in the buffer

$TC_MPP5[m,p]

index of the place among its kind (spindle 1, gripper 2 …​)

$TC_MAP1[m], $TC_MAP7[m], $TC_MAP8[m]

kind, number of places, place at the change point

$A_TOOLMN[id], $A_TOOLMLN[id]

magazine and place the tool is on now

$A_MYMN[id], $A_MYMLN[id]

owner magazine and place (the current place while it is in a real magazine)

$P_TOOLNO, $P_TOOLEXIST[id]

tool number in the spindle, 1 for a known id

Example of a change program with a double gripper (the tool of the requested place into gripper 1 and the spindle tool into gripper 2 at the first position of the arm, then the new tool into the spindle and the old one back home at the second; the DMU 60 sim does it this way, nc_files/wechsler.ngc, with the head checked at the tool change position before every swing):

DEF INT NEU, ALT
NEU = 7
ALT = $TC_MPP6[9998, 1]
POSM($A_TOOLMLN[NEU])          ; the magazine to the tool's place
WHILE $A_IN[2] == 0            ; the head at the change position (PLC cam)
G4 P0.05
ENDWHILE
G1 W=180 F6000                 ; take: gripper 1 at the magazine, 2 at the spindle
MVTOOL(1, $A_TOOLMLN[NEU], 9998, 2)   ; into gripper 1
IF ALT > 0
MVTOOL(9998, 1, 9998, 3)       ; the spindle tool into gripper 2
POSM($A_MYMLN[ALT])            ; the magazine to its owner place
ENDIF
G1 W=0                         ; put: gripper 1 at the spindle, 2 at the magazine
MVTOOL(9998, 2, 9998, 1)       ; the new tool into the spindle
IF ALT > 0
TCI(3)                         ; gripper 2 back to the owner place
ENDIF
G0 W90                         ; rest

Blank definition: WORKPIECE

The SINUMERIK statement defines the blank of the simulation in the program (Job Planning manual, "Define blank (WORKPIECE)"); the operator panel builds it in its material removal model ([cha:mchmi]) when the running program passes the statement. The interpreter checks the statement and performs no motion for it.

WORKPIECE("<name>", "<clamping>", "<offset>", "<type>", <bits>, <par6>, ...)
Type Parameters after <bits>

"CYLINDER"

Z0, Z1, ZB, d0 [, -, rotation]: reference point, length, machining dimension, outer diameter

"PIPE"

Z0, Z1, ZB, d0, d1 [, rotation]: d1 = wall thickness (incremental) or inner diameter (bit 8)

"RECTANGLE"

Z0, Z1, ZB, W, L [, rotation]: centered cuboid, width in X and length in Y

"BOX"

Z0, Z1, ZB, X0, Y0, X1, Y1: cuboid by two corners (X1/Y1 incremental unless bits 4/5)

"N_CORNER"

Z0, Z1, ZB, N, SW [, rotation]: polygon with N corners, width across flats (edge length with bit 9)

"STL"

"<file>", X, Y, Z [, scale]: a mesh file (binary or ASCII STL, mm) with its origin at X Y Z of the work offset; linuxcncMulti extension

Z1 and ZB are incremental to Z0 unless bit 6 (0x40) or bit 7 (0x80) is set; bit 12 (0x1000) puts the blank on the counterspindle, bit 13 (0x2000) leaves out the mirroring. The name, the clamping ("Table", "A", "B", "C") and the offset are optional; in the program the blank always refers to the active work offset. WORKPIECE() deletes every blank, WORKPIECE("<name>") one. Examples:

WORKPIECE(,,,"CYLINDER",0,0,-200,-150,100)      ; turning: Z0 0, Z1 -200, ZB -150, d0 100
WORKPIECE(,,,"PIPE",256,0,-200,-150,100,80)     ; inner diameter 80 absolute (bit 8)
WORKPIECE(,,,"CYLINDER",192,60,0,0,120)         ; milling: top at Z 60, bottom at Z 0 absolute (bits 6, 7)
WORKPIECE(,,,"STL","impeller_rohteil.stl",0,0,0) ; a preformed blank from a mesh

The blank model of the panel is a dexel model about the part axis (the spindle or the C axis of the table): a ray from the axis carries one outer and one inner radius, so a cuboid must contain the axis and a mesh is sampled by its outline at every height (undercuts behind a smaller radius are not kept). The file of "STL" is looked up in the program’s directory, then in [DISPLAY]PROGRAM_PREFIX.

Named parameters of the main run

The synchronized actions keep their variables in the real-time controller ([cha:synchronized-actions]). The program reads them (read-ahead applies, stop it with M66 E0 L0 where the order matters):

Parameter Meaning

#<_r[n]>

$R[n], the main-run R parameter n (0..31) of the channel

<_ac_marker[n]>, <_ac_param[n]>, #<_ac_timer[n]>

$AC_MARKER, $AC_PARAM, $AC_TIMER

#<_ac_delt>

$AC_DELT, the distance deleted by the last DELDTG

#<_aa_mm[<axis>]>

$AA_MM, the position measured by MEAWA on that machine axis (#<_aa_mm[X1]>)

#<_ac_mea[1]>

$AC_MEA[1], 1 when the probe switched in the MEAWA block

The program writes a main-run variable with the statement $R[5] = 42 (also $AC_PARAM[n]=, $AC_MARKER[n]=, $A_OUT[n]=): it is queued like a wait mark and takes effect in program order.

Kinematic transformations

TRAORI[(n)], TRANSMIT[(n)], TRACYL(d[, n]), TRAFOOF and the orientation words A3= B3= C3= are described in [cha:kinematic-transformations].