Synchronized actions are statements in the part program that the real-time motion controller evaluates every servo cycle, in parallel to the running program - the Siemens "Synchronaktionen" (the syntax follows the SINUMERIK function manual FBSY). They react to inputs, positions and times without the delay of the interpreter’s read-ahead: set an output when the tool passes a position, stop the feed when a distance gets too small, move an axis along with another one, measure at an input edge. LinuxCNC has nothing comparable; the classic way is HAL logic or M66.

Syntax

[ID=n | IDS=n] [WHENEVER | FROM | WHEN | EVERY <condition>] DO <action> [<action> ...]
ID=n

Modal: valid from the following block until program end, reset or CANCEL(n) (n = 1..999).

IDS=n

Static: valid in every mode until CANCEL(n) - also after program end and in MDI/JOG; put static actions into [CHANNEL_n]STARTUP_PROGRAM so that they exist from the start.

(no ID)

Block-wise: valid while the following block runs.

WHENEVER <cond>

every cycle the condition holds.

FROM <cond>

every cycle after the condition held once.

WHEN <cond>

once, the first time the condition holds (the action is done afterwards).

EVERY <cond>

once per rising edge of the condition.

(no keyword)

every cycle (ID=3 DO $AC_OVR = 50 + 10 * $A_INA[1]).

Conditions and values are expressions with + - * / DIV MOD, comparisons == <> < > ⇐ >=, AND OR XOR NOT, bit operators B_AND B_OR B_XOR B_NOT, functions SIN COS TAN ASIN ACOS ATAN2 SQRT ABS POT TRUNC ROUND ROUNDUP LN EXP MINVAL MAXVAL BOUND and the main-run variables below. Comparisons bind weaker than AND/OR (Siemens): write ($AA_IM[X1] > 10) AND ($A_IN[2]==1).

Program statements that belong to the actions: CANCEL(n), LOCK(n), UNLOCK(n), RESET(n), $R[n] = <expr> (a main-run variable written in program order), FCTDEF(…​), MEAWA[…​]=(…​).

Main-run variables

Axes are named with their machine axis names ($AA_IM[X2]), inputs and outputs by their motion I/O index.

Variable Meaning write

$AA_IM[ax], $AA_IEN[ax]

commanded / actual position of the axis (machine)

-

$AA_IW[ax]

commanded position in the work coordinates of the channel (G5x, G92, tool offset)

-

$AA_VACTM[ax], $AA_DTEB[ax]

axis velocity, axis distance to go in the block

-

$AA_HOMED[ax]

1 when the joint is homed (LinuxCNC extension)

-

$AA_OVR[ax]

override (%) of a command axis

yes

$AA_CMDBUSY[ax]

1 while a command axis motion runs (extension)

-

$AA_OFF[ax]

overlaid offset of the axis (read: in force, write: target)

yes

$AA_MM[ax]

position measured by MEAWA

yes

$AC_VACTB, $AC_DTEB, $AC_PATHN, $AC_TIME

path velocity, path distance to go, 0..1 position in the block, seconds since the block started

-

$AC_STAT

0 idle, 1 running, 2 paused

-

$AC_OVR

path override in % for this cycle (default 100)

yes

$AC_DELT

distance deleted by the last DELDTG

-

$AC_MEA[1]

the probe switched in the MEAWA block

yes

$AC_MARKER[n], $AC_PARAM[n], $AC_TIMER[n], $R[n]

16 integer markers, 16 parameters, 4 timers (seconds, start with =0, stop with =-1), 32 R parameters of the channel

yes

$AC_SYNA_MEM

free entries of the action table

-

$A_IN[n], $A_INA[n], $A_PROBE

digital / analog input, the probe input

-

$A_OUT[n], $A_OUTA[n]

digital / analog output (motion.digital-out-NN, motion.analog-out-NN)

yes

$AA_S[sp], $AC_SDIR[sp]

spindle speed (signed) and direction

-

Actions

Action Effect

<variable> = <expr>

assignment to a writable variable ($A_OUT[2]=1, $AC_OVR=0, $R[5]=$AA_IM[X1])

M3, M4, M5, S<n>, S=<expr>

master spindle of the channel (block-wise only with WHEN/EVERY)

H<nr>=<expr>

H function: stat.sa_h_number/value/count, HAL motion[.N].synact-h-number/-value/-count (block-wise only with WHEN/EVERY)

SETM(n, …​), CLEARM(n, …​)

set / clear wait marks of the channel ([cha:multichannel-gcode])

SETAL(65000..69999[, "text"])

alarm on the error channel of the channel, once per episode

LOCK(n), UNLOCK(n), RESET(n)

other actions by ID

POS[ax]=<expr>, POS[ax]=IC(<expr>), POSA

command axis: move the axis to the position (absolute machine, IC incremental) with a trapezoidal profile within the joint limits; the axis must be free (RELEASE it in the program first). GET/GETD take it back once the motion ends.

MOV[ax]=<dir>

endless move of a command axis, +1 / -1 direction, 0 stops

FA[ax]=<feed>

feed of the command axis (units/min; default the joint limit)

DELDTG

delete the distance to go of the path: the block stops within its deceleration, the program goes on with the next block from the stop position (block-wise only). $AC_DELT holds the deleted distance.

DELDTG(ax, …​)

stop command axes

RDISABLE

read-in disable: the channel holds at the block end while the condition is met (ID/IDS only; blocks end with an exact stop while such an action exists)

$AA_OFF[ax]=<expr>, FTOC(<expr>, ax)

overlaid offset of the axis, added between joint and motor (the program and the status positions do not change), ramped with the joint limits, within the soft limits

FCTDEF(n, llimit, ulimit, a0, a1, a2, a3)

polynomial n (0..7): y = a0 + a1 x + a2 x2 + a3 x3 limited to [llimit, ulimit]; also a program statement

SYNFCT(n, <output variable>, <input>)

write the polynomial of the input into any writable variable every cycle (SYNFCT(1, $AA_OFF[Z1], $A_INA[1]))

MEAWA[ax]=(1, edge)

(program statement) measure in the next block without stopping: at the rising (+1) or falling (-1) edge of motion.probe-input the axis position goes to $AA_MM[ax], $AC_MEA[1] becomes 1; while such an action is armed the probe input does not abort the moves ("probe tripped during non-probe move")

Several actions may follow one DO, separated by blanks. Up to 32 actions per channel are active at a time, 16 may wait for their block.

Lifetimes

Block-wise and modal (ID) actions end with M2/M30, with the abort of a running program or MDI command and with the operator’s reset; a mode change of an idle channel keeps them. Static (IDS) actions stay until CANCEL. Command axis motions of block-wise and modal actions stop at program end, those of static actions go on. A definition arrives in the controller together with the following block and becomes active when that block starts; a definition without a following block (MDI) is installed after 0.1 s.

Examples (G200 axis names)

(static: the turrets must not come closer than 30 mm on X)
IDS=1 WHENEVER ($AA_IM[X1] + $AA_IM[X2]) < 30 DO $AC_OVR=0 SETAL(65001, "Revolver zu nah")

(static, power-on program: Z guard between turret 2 and the milling head)
IDS=1 WHENEVER $AA_HOMED[Z2] AND $AA_HOMED[Z3] AND (ABS($AA_IM[Z3] - $AA_IM[Z2]) < 10) DO $AC_OVR=0 SETAL(65010, "Kollision Revolver 2 und Fräskopf in Z")

(the counter spindle slide follows Z1 while input 3 is set)
RELEASE(W)
ID=2 WHENEVER $A_IN[3]==1 DO POS[W]=$AA_IM[Z1]+500 FA[W]=5000
...
CANCEL(2)
GET(W)

(output 2 once the tool is below Z=-30 in the work system)
WHEN $AA_IW[Z1] <= -30 DO $A_OUT[2]=1
G1 Z1=-60 F200

(probing: delete the distance to go at input 1, then read the position)
WHEN $A_IN[1]==1 DO DELDTG
G1 X1=10 F100
M66 E0 L0
#100 = #<_x>
#101 = #<_ac_delt>

(measuring without stopping)
MEAWA[X1]=(1, 1)
G1 X1=50 F200
M66 E0 L0
#102 = #<_aa_mm[X1]>

(piece counter and a delay with a timer)
IDS=5 EVERY $A_IN[0]==1 DO $AC_MARKER[0]=$AC_MARKER[0]+1 $AC_TIMER[1]=0
IDS=6 WHEN $AC_TIMER[1]>=0.5 DO $A_OUTA[3]=$AA_IM[X1] $AC_TIMER[1]=-1

(feed from an analog input, 0..10 V -> 50..150 %)
ID=3 DO $AC_OVR = 50 + 10 * $A_INA[1]

(distance control: offset of Z1 from a sensor on analog input 1)
FCTDEF(1, -1, 1, 0, 0.1, 0, 0)
ID=7 DO SYNFCT(1, $AA_OFF[Z1], $A_INA[1])

Status and operator interface

linuxcnc.stat(channel=N).synact lists the actions of the channel (id, scope, frequency, state, line, hits), ac_marker, ac_param, ac_timer, sa_r, ac_delt, sa_h_*, aa_mm, ac_mea the variables; command.synact(op, id) cancels, locks, unlocks or resets an action. mchmi shows the table under Maschine → Synchronaktionen (double click: LOCK / UNLOCK / RESET / CANCEL) and the variables under Hauptlaufvariablen; its editor has a form for an action.