MOTION(9)
okay bestie, welcome to MOTION(9) from the HAL Component section ๐ this is the manual page for motion, and it's literally the realtime motion module that accepts NML motion commands and interacts with HAL in realtime. no cap, it's giving main character energy for your CNC. ๐
๐ NAME ๐
motion โ accepts NML motion commands, interacts with HAL in realtime. periodt.
โจ SYNOPSIS โจ
so you load it like this, and yes the line breaks are exactly like this:
loadrt motmod [base_period_nsec=period] [base_thread_fp=0 or 1]
[servo_period_nsec=period] [traj_period_nsec=period] [num_joints=[1-16]]
[num_dio=[1-64]] [num_aio=[1-64]] [num_misc_error=[0-64] |
names_misc_errors] [num_spindles=[1-8]] [unlock_joints_mask=jointmask]
[num_extrajoints=[0-16]]
here's the full vibe check on those loadrt args, one by one:
[base_period_nsec=period][base_thread_fp=0 or 1][servo_period_nsec=period][traj_period_nsec=period][num_joints=[1-16]][num_dio=[1-64]][num_aio=[1-64]][num_misc_error=[0-64] | names_misc_errors][num_spindles=[1-8]][unlock_joints_mask=jointmask][num_extrajoints=[0-16]]
the limits for the following items are compile-time settings, so don't try to fight them:
num_joints: maximum number of joints is set byEMCMOT_MAX_JOINTS.num_dio: maximum number of digital inputs is set byEMCMOT_MAX_DIO.num_aio: maximum number of analog inputs is set byEMCMOT_MAX_AIO.num_misc_error: maximum number of extra error inputs is set byEMCMOT_MAX_MISC_ERRORS.names_misc_errors: a comma-separated list of names for extra error inputs.- this parameter is mutually exclusive with
num_misc_error. if you're usingnum_misc_errorthe additional error input pins will have names likemotion.misc-error-00whereasnames_misc_errors=overtemp,undertempwill create hal pinsmotion.err-overtempandmotion.err-undertemp.
- this parameter is mutually exclusive with
num_spindles: maximum number of spindles is set byEMCMOT_MAX_SPINDLES.
optionally the number of Digital I/O is set with num_dio. the number of Analog I/O is set with num_aio. the default is 4 each. ๐
pin names starting with "joint" or "axis" are read and updated by the motion-controller function.
๐ธ DESCRIPTION ๐ธ
by default, the base thread does not support floating point. software stepping, software encoder counting, and software pwm do not use floating point. base_thread_fp can be used to enable floating point in the base thread (for example for brushless DC motor control). fr fr.
these pins and parameters are created by the realtime motmod module. this module provides a HAL interface for LinuxCNC's motion planner. basically motmod takes in a list of waypoints and generates a nice blended and constraint-limited stream of joint positions to be fed to the motor drives. it's iconic, honestly.
the optional num_extrajoints parameter specifies a quantity of joints that participate in homing but are not used by kinematics transformations. after homing, control of an 'extra' joint is transferred to a posthome command HAL pin (joint.N.posthome-cmd) and the motor feedback value is ignored. 'extra' joints must be managed by independent motion planners/controllers (typically using limit3 HAL components). extra joints maybe unhomed only when motion is disabled. periodt.
the maximum num_extrajoints value is equal to the num_joints value. (note that using the maximum value would allow no operation in world coordinates). the num_joints value must be equal to the sum of the number of joints used for kinematics calculations plus the number of 'extra' joints.
the num_joints parameter is conventionally set using the INI file setting [KINS]JOINTS=value. the num_extrajoints is set by the additional motmod parameter [EMCMOT]motmod num_extrajoints=value. Hal pin numbering for all joints is zero based [0 ... num_joints-1]. when specified, 'extra' joints are assigned the last num_extrajoints in the numbering sequence. for example, specifying [KINS]JOINTS=5 and [EMCMOT]motmod num_extrajoints=2 for a 3 joint trivkins configuration [KINS] KINEMATICS=trivkins coordinates=xyz uses joints 0,1,2 for the kinematic joints and joints 3,4 for the 'extra' joints. ๐
๐ MOTION PINS ๐
okay bestie, here come the pins the motion module itself is serving. every single one, no skipping, we're thorough in this house. ๐
motion-command-handler.timeOUT S32 โ time (in CPU clocks) for the motion modulemotion-command-handler. yes it's a pin name with a dash instead of a dot, that's just how it is, don't @ me.motion-controller.timeOUT S32 โ time (in CPU clocks) for the motion modulemotion-controller.motion.adaptive-feedIN FLOAT โ when adaptive feed is turned on withM52 P1, the commanded velocity gets multiplied by this value. this stacks multiplicatively with the NML-level feed override value andmotion.feed-hold. and listen โ negative values are valid and they will run the G-code path in reverse. iconic behaviour honestly. ๐motion.analog-in-NNIN FLOAT โ these pins are used by theM66 Ennwait-for-input mode.motion.analog-out-NNOUT FLOAT โ these pins are used byM67-68.motion.coord-errorOUT BIT โ TRUE when motion has hit an error, like exceeding a soft limit. ๐จmotion.coord-modeOUT BIT โ TRUE when motion is in "coordinated mode", as opposed to "teleop mode".motion.current-velOUT FLOAT โ current cartesian velocity.motion.digital-in-NNIN BIT โ these pins are used byM66 Pnnwait-for-input mode.motion.digital-out-NNOUT BIT โ these pins are controlled by theM62throughM65words.motion.distance-to-goOUT FLOAT โ distance remaining in the current move.motion.enableIN BIT โ if this bit gets driven FALSE, motion stops, the machine goes into the "machine off" state, and a message pops up for the operator. for normal motion, drive this bit TRUE. ๐motion.eoffset-activeOUT BIT โ says external offsets are active (non-zero).motion.eoffset-limitedOUT BIT โ says motion with external offsets was limited by a soft limit constraint ([AXIS_L]MIN_LIMIT,MAX_LIMIT).motion.feed-holdIN BIT โ when Feed Stop Control is enabled withM53 P1, and this bit is TRUE, the feed rate is set to0.
note: feed-hold applies to G-code commands โ not jogs.
motion.feed-inhibitIN BIT โ when this pin is TRUE, machine motion is inhibited for G-code commands.
if the machine is doing a spindle synchronized move when this pin goes TRUE, the spindle synchronized motion will finish, and any following moves will be inhibited (this is to prevent damage to the machine, the tool, or the work piece ๐ซฃ).
if the machine is in the middle of a (non-spindle synchronized) move when this pin goes TRUE, the machine will decelerate to a stop at the maximum allowed acceleration rate.
motion resumes when this pin goes FALSE.
note: feed-inhibit applies to G-code commands โ not jogs.
motion.feed-upmOUT FLOAT โ current feed rate in G-code program units per minute formotion.motion-typefeed(2) and arc(3). the value is the G-code program F value multiplied by the current feed override value and themotion.adaptive-feedsetting (ifM52is active). the value is zero ifmotion.feed-holdormotion.feed-inhibitare asserted. and if units (G20orG21) aren't specified in the G-code file then units will be the last units used.motion.feed-inches-per-minuteOUT FLOAT โ current feed rate in inches per minute formotion.motion-typefeed(2) and arc(3). value is the inch equivalent of the G-code program F value multiplied by the current feed override value and themotion.adaptive-feedsetting (ifM52active). value is zero ifmotion.feed-holdormotion.feed-inhibitare asserted.motion.feed-inches-per-secondOUT FLOAT โ current feed rate in inches per second formotion.motion-typefeed(2) and arc(3). value is the inch equivalent of the G-code program F value multiplied by the current feed override value and themotion.adaptive-feedsetting (ifM52active). value is zero ifmotion.feed-holdormotion.feed-inhibitare asserted.motion.feed-mm-per-minuteOUT FLOAT โ current feed rate in mm per minute formotion.motion-typefeed(2) and arc(3). value is the mm equivalent of the G-code program F value multiplied by the current feed override value and themotion.adaptive-feedsetting (ifM52active). value is zero ifmotion.feed-holdormotion.feed-inhibitare asserted.motion.feed-mm-per-secondOUT FLOAT โ current feed rate in mm per second formotion.motion-typefeed(2) and arc(3). value is the mm equivalent of the G-code program F value multiplied by the current feed override value and themotion.adaptive-feedsetting (ifM52active). value is zero ifmotion.feed-holdormotion.feed-inhibitare asserted.motion.homing-inhibitIN BIT โ if this bit is TRUE, starting any joint homing move (including "Home All") is disallowed and an error is reported. by default, homing is allowed in joint mode whenever motion is enabled.motion.is-all-homedOUT BIT โ TRUE if all active joints is homed.motion.jog-inhibitIN BIT โ if this bit is TRUE, jogging of any joint or axis is disallowed and an error is reported. ๐motion.jog-stopIN BIT โ if any jog is active when the pin state changes to TRUE, then that jog will be stopped following the associated acceleration values.motion.jog-stop-immediateIN BIT โ if any jog is active when the pin state changes to TRUE, then that jog will be stopped immediately. no decel, just vibes ending. ๐motion.jog-is-activeOUT BIT โ TRUE if any joint or axis is jogging.motion.in-positionOUT BIT โ TRUE if the machine is in position (ie, not currently moving towards the commanded position).motion.misc-error-NNIN BIT โ extra error inputs for faults like over-temperature sensors, low coolant warnings, custom HAL component errors. if driven TRUE this will disable a machine. similar tospindle.amp-fault-in.motion.motion-enabledOUT BIT โ (no description given, she just exists, mysterious queen ๐)motion.motion-typeOUT S32 โ these values are fromsrc/emc/nml_intf/motion_types.h.0โ Idle (no motion)1โ Traverse2โ Linear feed3โ Arc feed4โ Tool change5โ Probing6โ Rotary unlock for traverse
motion.on-soft-limitOUT BIT โ (also no description, keep it moving ๐)motion.probe-inputIN BIT โG38.nuses the value on this pin to determine when the probe has made contact. TRUE for probe contact closed (touching), FALSE for probe contact open.motion.program-lineOUT S32 โ the current program line while executing. zero if not running or between lines while single stepping.motion.requested-velOUT FLOAT โ the current requested velocity in user units per second. this value is the F-word setting from the G-code file, possibly reduced to accommodate machine velocity and acceleration limits. the value on this pin does not reflect the feed override or any other adjustments.motion.servo.last-periodOUT U32 โ the number of CPU clocks between invocations of the servo thread. typically, this number divided by the CPU speed gives the time in seconds, and can be used to determine whether the realtime motion controller is meeting its timing constraints.motion.switchkins-typeIN float โ kinematics modules that define the functionskinematicsSwitchable()andkinematicsSwitch()receive the integer value of this pin to select the machine kinematics functions. extra G-code commands may be required to synchronize task and motion before and after changes to the pin value.motion.teleop-modeOUT BIT โ motion mode is teleop (axis coordinate jogging available).motion.tooloffset.LOUT FLOAT โ current tool offset for each axis where (Lis the axis letter, one of:x y z a b c u v w).motion.tp-reverseOUT BIT โ trajectory planning is reversed (reverse run).
๐ฆ AXIS PINS ๐ฆ
quick heads up before we dive in: (L is the axis letter, one of: x y z a b c u v w). every one of these gets the L swapped out for whichever axis you're talking about. slay. โจ
axis.L.eoffsetOUT FLOAT โ current external offset.axis.L.eoffset-clearIN BIT โ clear external offset request.axis.L.eoffset-countsIN S32 โ counts input for external offset. the eoffset-counts are transferred to an internal register. the applied external offset is the product of the register counts and theeoffset-scalevalue. the register is reset to zero at each machine startup. if the machine is turned off with an external offset active, theeoffset-countspin should be set to zero before restarting. ๐ซถaxis.L.eoffset-enableIN BIT โ enable for external offset (also requires INI file setting for[AXIS_L]OFFSET_AV_RATIO).axis.L.eoffset-requestOUT FLOAT โ debug pin for requested external offset.axis.L.eoffset-scaleIN FLOAT โ scale for external offset.axis.L.jog-accel-fractionIN FLOAT โ sets acceleration for wheel jogging to a fraction of the INImax_accelerationfor the axis. values greater than1or less than zero are ignored.axis.L.jog-countsIN S32 โ connect to the "counts" pin of an external encoder to use a physical jog wheel. ๐กaxis.L.jog-enableIN BIT โ when TRUE (and in manual mode), any change to "jog-counts" will result in motion. when false, "jog-counts" is ignored.axis.L.jog-scaleIN FLOAT โ sets the distance moved for each count on "jog-counts", in machine units.axis.L.jog-vel-modeIN BIT โ when FALSE (the default), the jogwheel operates in position mode. the axis will move exactlyjog-scaleunits for each count, regardless of how long that might take. when TRUE, the wheel operates in velocity mode โ motion stops when the wheel stops, even if that means the commanded motion is not completed.axis.L.kb-jog-activeOUT BIT โ (free planner axis jogging active (keyboard or halui))axis.L.pos-cmdOUT FLOAT โ the axis commanded position. there may be several offsets between the axis and motor coordinates: backlash compensation, screw error compensation, and home offsets. external offsets are reported separately (axis.L.eoffset).axis.L.teleop-pos-cmdOUT FLOAT โ (no description, she's just there ๐)axis.L.teleop-tp-enableOUT BIT โ TRUE when the "teleop planner" is enabled for this axis.axis.L.teleop-vel-cmdOUT FLOAT โ the axis's commanded velocity.axis.L.teleop-vel-limOUT FLOAT โ the velocity limit for the teleop planner.axis.L.wheel-jog-activeOUT BIT โ (no description, but she's out here living her best life ๐ธ)
๐ฆ JOINT PINS ๐ฆ
okay so N is the joint number and it goes (0 ... num_joints-1)) ๐
๐จ bestie listen โ pins marked (DEBUG) are literally just debugging aids and they're subject to change or removal at any time. they could get deleted tomorrow and we'd all have to cope. ๐
joint.N.acc-cmdOUT FLOAT (DEBUG)โ the joint's commanded acceleration โจjoint.N.activeOUT BIT (DEBUG)โ TRUE when this joint is active, like it's awake and doing the thing ๐ซถjoint.N.amp-enable-outOUT BITโ TRUE if the amplifier for this joint should be enabled ๐ฅjoint.N.amp-fault-inIN BITโ you should drive this TRUE if an external fault is detected with the amplifier for this joint ๐joint.N.backlash-corrOUT FLOAT (DEBUG)โ backlash or screw compensation raw valuejoint.N.backlash-filtOUT FLOAT (DEBUG)โ backlash or screw compensation filtered value, and yes it respects motion limits ๐joint.N.backlash-velOUT FLOAT (DEBUG)โ backlash or screw compensation velocityjoint.N.coarse-pos-cmdOUT FLOAT (DEBUG)joint.N.errorOUT BIT (DEBUG)โ TRUE when this joint has encountered an error, like a limit switch closing ๐ญjoint.N.f-errorOUT FLOAT (DEBUG)โ the actual following errorjoint.N.f-error-limOUT FLOAT (DEBUG)โ the following error limitjoint.N.f-erroredOUT BIT (DEBUG)โ TRUE when this joint has exceeded the following error limit ๐จjoint.N.faultedOUT BIT (DEBUG)joint.N.free-pos-cmdOUT FLOAT (DEBUG)โ the "free planner" commanded position for this jointjoint.N.free-tp-enableOUT BIT (DEBUG)โ TRUE when the "free planner" is enabled for this jointjoint.N.free-vel-limOUT FLOAT (DEBUG)โ the velocity limit for the free plannerjoint.N.home-stateOUT S32 (DEBUG)โ homing state machine state, the whole journey frjoint.N.home-sw-inIN BITโ should be driven TRUE if the home switch for this joint is closed ๐joint.N.homedOUT BIT (DEBUG)โ TRUE if the joint has been homed ๐joint.N.homingOUT BITโ TRUE if the joint is currently homing, like it's mid-glow-up โจjoint.N.in-positionOUT BIT (DEBUG)โ TRUE if the joint is using the "free planner" and has come to a stop โjoint.N.index-enableIO BITโ should be attached to theindex-enablepin of the joint's encoder so you can enable homing to index pulse ๐joint.N.is-unlockedIN BITโ indicates the joint is unlocked (peep the JOINT UNLOCK PINS section below) ๐joint.N.jog-accel-fractionIN FLOATโ sets acceleration for wheel jogging to a fraction of the INImax_accelerationfor the joint. values greater than 1 or less than zero are just ignored, respectfully ๐joint.N.jog-countsIN S32โ connect this to the "counts" pin of an external encoder if you want to use a physical jog wheel ๐กjoint.N.jog-enableIN BITโ when TRUE (and you're in manual mode), any change to "jog-counts" will result in motion. when false, "jog-counts" gets ignored entirely ๐joint.N.jog-scaleIN FLOATโ sets the distance moved for each count on "jog-counts", in machine units ๐joint.N.jog-vel-modeIN BITโ when FALSE (that's the default btw), the jogwheel operates in position mode. the joint will move exactlyjog-scaleunits for each count, no matter how long that might take. when TRUE, the wheel operates in velocity mode โ motion stops when the wheel stops, even if that means the commanded motion is not completed ๐joint.N.kb-jog-activeOUT BIT (DEBUG)โ (free planner joint jogging active (keyboard or halui))joint.N.motor-offsetOUT FLOAT (DEBUG)โ joint motor offset established when the joint is homedjoint.N.motor-pos-cmdOUT FLOATโ the commanded position for this jointjoint.N.motor-pos-fbIN FLOATโ the actual position for this jointjoint.N.neg-hard-limitOUT BIT (DEBUG)โ the negative hard limit for the jointjoint.N.neg-lim-sw-inIN BITโ should be driven TRUE if the negative limit switch for this joint is trippedjoint.N.pos-cmdOUT FLOATโ the joint (as opposed to motor) commanded position. heads up, there may be several offsets between the joint and motor coordinates: backlash compensation, screw error compensation, and home offsets ๐งjoint.N.pos-fbOUT FLOATโ the joint feedback position. this value is computed from the actual motor position minus joint offsets. super useful for machine visualization โจjoint.N.pos-hard-limitOUT BIT (DEBUG)โ the positive hard limit for the jointjoint.N.pos-lim-sw-inIN BITโ should be driven TRUE if the positive limit switch for this joint is trippedjoint.N.unlockOUT BITโ TRUE if the axis is a locked joint (typically a rotary) and a move is commanded (see JOINT UNLOCK PINS) ๐joint.N.vel-cmdOUT FLOAT (DEBUG)โ the joint's commanded velocityjoint.N.wheel-jog-activeOUT BIT (DEBUG)
๐ธ JOINT posthome pins ๐ธ
every joint that's designated as an 'extra' joint gets its very own HAL pin, joint.N.posthome-cmd ๐ซถ before homing happens, the pin value is literally ignored. but after homing, the pin value gets augmented by the motor offset value and then routed to joint.N.motor-pos-cmd. that's the whole pipeline bestie ๐ซ
๐ JOINT unlock pins ๐
the joint pins used for unlocking a joint (joint.N.unlock, joint.N.is-unlocked) are created according to the unlock_joints_mask=jointmask parameter for motmod. these pins may be required for locking indexers (typically a rotary joint) ๐
the jointmask bits are: (lsb)0:joint0, 1:joint1, 2:joint2, ...
example:
loadrt motmod ... unlock_joints_mask=0x38
that one creates unlock pins for joints 3,4,5 ๐ slay.
๐ SPINDLE PINS ๐
(M is the spindle number (0 ... num_spindles-1))
spindle.M.amp-fault-inIN BITโ should be driven TRUE if an external fault is detected with the amplifier for this spindle ๐spindle.M.at-speedIN BITโ motion will pause until this pin is TRUE, under these conditions: before the first feed move after each spindle start or speed change; before the start of every chain of spindle-synchronized moves; and if in CSS mode, at every rapid->feed transition โspindle.M.brakeOUT BITโ TRUE when the spindle brake should be applied ๐spindle.M.forwardOUT BITโ TRUE when the spindle should rotate forward โก๏ธspindle.M.index-enableI/O BITโ for correct operation of spindle synchronized moves, this signal must be hooked to theindex-enablepin of the spindle encoder ๐spindle.M.inhibitIN BITโ when TRUE, the spindle speed is set and held to 0 ๐spindle.M.is-orientedIN BITโ acknowledge pin forspindle-orient. completes the orient cycle. ifspindle-orientwas true whenspindle-is-orientedwas asserted, thespindle-orientpin is cleared and thespindle-lockedpin is asserted. also, thespindle-brakepin is asserted ๐spindle.M.lockedOUT BITโ spindle orient complete pin. cleared by any ofM3,M4,M5๐spindle.M.onOUT BITโ TRUE when spindle should rotate ๐ฅspindle.M.orientOUT BITโ indicates start of spindle orient cycle. set byM19. cleared by any ofM3,M4,M5.
if spindle-orient-fault is not zero during spindle-orient true, the M19 command fails with an error message ๐จ
spindle.M.orient-angleOUT FLOATโ desired spindle orientation forM19. value of theM19Rword parameter plus the value of the[RS274NGC]ORIENT_OFFSETINI parameter ๐ฏspindle.M.orient-faultIN S32โ fault code input for orient cycle. any value other than zero will cause the orient cycle to abort ๐spindle.M.orient-modeOUT BITโ desired spindle rotation mode. reflects theM19Pparameter word ๐spindle.M.reverseOUT BITโ TRUE when the spindle should rotate backward โฌ ๏ธspindle.M.revsIN FLOATโ for correct operation of spindle synchronized moves, this signal must be hooked to the position pin of the spindle encoder ๐spindle.M.speed-cmd-rpsFLOAT OUTโ commanded spindle speed in units of revolutions per secondspindle.M.speed-inIN FLOATโ actual spindle speed feedback in revolutions per second; used forG96(constant surface speed) andG95(feed per revolution) modes ๐spindle.M.speed-outOUT FLOATโ desired spindle speed in rotations per minutespindle.M.speed-out-absOUT FLOATโ desired spindle speed in rotations per minute, always positive regardless of spindle direction โจspindle.M.speed-out-rpsOUT FLOATโ desired spindle speed in rotations per secondspindle.M.speed-out-rps-absOUT FLOATโ desired spindle speed in rotations per second, always positive regardless of spindle direction โจ
๐ง MOTION PARAMETERS ๐ง
ngl, a lot of these parameters are debugging aids, and they are subject to change or removal at any time. don't get too attached ๐
motion-command-handler.tmaxRW S32โ show information about the execution time of these HAL functions in CPU clocks โฑ๏ธmotion-command-handler.tmax-increasedRO S32motion-controller.tmaxRW S32โ show information about the execution time of these HAL functions in CPU clocks โฑ๏ธmotion-controller.tmax-increasedRO BITmotion.debug-*โ these values are used for debugging purposes ๐
โก FUNCTIONS โก
generally, these functions are both added to the servo-thread in the order shown ๐
motion-command-handlerโ receive and process incoming motion commands. the pin namedmotion-command-handler.timeand parametersmotion-command-handler.tmax,tmax-increasedareare created for this function ๐ฅmotion-controllerโ runs the LinuxCNC motion controller. the pin namedmotion-controller.timeand parametersmotion-controller.tmax,tmax-increasedare created for this function ๐ฎ
๐ BUGS ๐
- this manual page is incomplete. yeah. we know. ๐ญ
- identification of pins categorized with (DEBUG) is dubious ๐
๐ซถ SEE ALSO ๐ซถ
iocontrol(1), milltask(1), spindle(9)
okay that's a wrap bestie ๐ this one's straight outta the LinuxCNC Documentation, filed under MOTION(9) โ go forth and wire up your pins, you absolute icon ๐โจ
๐ฆ where this page comes from
- debian trixie: linuxcnc-uspace 1:2.9.4-2+deb13u1 ยท GFDL-1.1-or-later
- ubuntu questing: linuxcnc-uspace 1:2.9.4-2ubuntu2
- ubuntu resolute: linuxcnc-uspace 1:2.9.4-2ubuntu4 ยท GFDL-1.1-or-later
- ubuntu stonking: linuxcnc-uspace 1:2.9.4-2ubuntu4 ยท GFDL-1.1-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms