Skip to content

Commit cd3497b

Browse files
committed
rs274ngc: add G28.2 to home the machine from G-code
G28.2 lets a program or MDI line reference the machine instead of requiring the GUI Home All button. The bare form homes every joint in HOME_SEQUENCE order; an optional Pn homes joint n only (0-based [JOINT_n] numbering), reusing the existing EMC_JOINT_HOME 'joint' field so no NML change is needed and it works on any kinematics. Axis-letter forms are deliberately not supported - resolving a letter to a joint needs the kinematics map, and homing is a joint concept. There is no G-code unhome (dropped in review of PR LinuxCNC#4172). New canon calls HOME_CYCLE() / HOME_CYCLE_JOINT(n). The milltask backend flushes the segment buffer before queuing the home, or a move buffered for arc-blend lookahead would reorder after it. When the cycle finishes the interpreter resyncs its current position from the machine, the same way it does after probing or a tool change (home_flag -> INTERP_EXECUTE_FINISH -> refresh_actual_position() in read_inputs). An immediate home rewrites the joint coordinate to HOME_OFFSET even with no physical motion, so without the resync a following G91 move or an I/J/K arc centre is computed from the stale pre-home point - on a wrapped rotary head re-homed mid-program with G28.2 Pn, the axis would then sweep the whole error. (Raised in PR LinuxCNC#4172 review.)
1 parent 0117296 commit cd3497b

12 files changed

Lines changed: 133 additions & 3 deletions

src/emc/nml_intf/canon.hh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,13 @@ extern void SET_G92_OFFSET(double x, double y, double z,
243243

244244
extern void SET_XY_ROTATION(double t);
245245

246+
/* G28.2: trigger the machine homing cycle from G-code (bare form = all
247+
* joints, in HOME_SEQUENCE order). Maps to EMC_JOINT_HOME(-1). */
248+
extern void HOME_CYCLE(void);
249+
/* G28.2 Pn: home a single joint by its 0-based joint number (matching
250+
* [JOINT_n] INI section numbering). Maps to EMC_JOINT_HOME(joint). */
251+
extern void HOME_CYCLE_JOINT(int joint);
252+
246253
/* Offset the origin to the point with absolute coordinates x, y, z,
247254
a, b, c, u, v, and w. Values of x, y, z, a, b, c, u, v, and w are real
248255
numbers. The units are whatever length units are being used at the time

src/emc/rs274ngc/gcodemodule.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,9 @@ void SELECT_PLANE(CANON_PLANE pl) {
705705
Py_XDECREF(result);
706706
}
707707

708+
void HOME_CYCLE(void) {}
709+
void HOME_CYCLE_JOINT(int) {}
710+
708711
void SET_TRAVERSE_RATE(double rate) {
709712
maybe_new_line();
710713
if(interp_error) return;

src/emc/rs274ngc/interp_array.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ const int Interp::gees[] = {
8484
/* 220 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
8585
/* 240 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
8686
/* 260 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
87-
/* 280 */ 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
87+
/* 280 */ 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, // 282=G28.2
8888
/* 300 */ 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
8989
/* 320 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1,-1,-1,-1,-1,-1,-1,-1,-1,
9090
/* 340 */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,

src/emc/rs274ngc/interp_check.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ int Interp::check_g_codes(block_pointer block, //!< pointer to a block to be c
100100
} else if (mode1 == G_5_2){
101101
} else if (mode1 == G_6_2){
102102
} else if (mode0 == G_28_1 || mode0 == G_30_1) {
103+
} else if (mode0 == G_28_2) { // G-code homing
103104
} else if (mode0 == G_52) {
104105
} else if (mode0 == G_53) {
105106
CHKS(((block->motion_to_be != G_0) && (block->motion_to_be != G_1)),
@@ -326,12 +327,14 @@ int Interp::check_other_codes(block_pointer block) //!< pointer to a block
326327
(motion != G_6) && (motion != G_6_2) &&
327328
(motion != G_2) && (motion != G_3) &&
328329
(motion != G_74) && (motion != G_84) &&
330+
(block->g_modes[GM_MODAL_0] != G_28_2) &&
329331
(block->m_modes[9] != 50) && (block->m_modes[9] != 51) && (block->m_modes[9] != 52) &&
330332
(block->m_modes[9] != 53) && (block->m_modes[5] != 62) && (block->m_modes[5] != 63) &&
331333
(block->m_modes[5] != 64) && (block->m_modes[5] != 65) && (block->m_modes[5] != 66) &&
332334
(block->m_modes[7] != 19) && (block->user_m != 1) &&
333335
(block->o_type != M_98)),
334336
_("P word with no G2 G3 G4 G10 G64 G5 G5.2 G6, G6.2, G76 G82 G86 G88 G89"
337+
" G28.2"
335338
" or M50 M51 M52 M53 M62 M63 M64 M65 M66 M98 "
336339
"or user M code to use it"));
337340
int p_value = round_to_int(block->p_number);

src/emc/rs274ngc/interp_convert.cc

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3166,6 +3166,70 @@ Called by: convert_modal_0.
31663166
31673167
*/
31683168

3169+
/*! convert_home_cycle
3170+
3171+
Handles G28.2 (run the homing cycle) from a G-code line, so machines can
3172+
reference themselves from MDI or a program instead of only from the GUI's
3173+
*Home All* button. The bare form homes all joints, in HOME_SEQUENCE order.
3174+
3175+
An optional Pn word homes a single joint by its 0-based joint number
3176+
(matching [JOINT_n] INI section numbering, e.g. P1 -> JOINT_1). This is the
3177+
primitive raised in the PR #4172 discussion for re-homing a joint that is
3178+
switched between rotary-axis and spindle use mid-program
3179+
(https://github.com/LinuxCNC/linuxcnc/pull/4172) -- it reuses the existing
3180+
EMC_JOINT_HOME 'joint' field, so it needs no NML change and works
3181+
identically on any kinematics. Axis-letter forms (G28.2 X) are deliberately
3182+
NOT supported: resolving an axis letter to a joint needs the kinematics
3183+
coordinate map and isn't trivial even on trivkins (duplicate letters on
3184+
gantries), and homing is a joint concept, not an axis one.
3185+
3186+
There is deliberately no G-code unhome. A G28.3 was part of the original
3187+
proposal and was dropped during review of PR #4172: no use was found for it
3188+
that a numbered parameter would not serve better under NO_FORCE_HOMING=1,
3189+
and it was the one operation able to leave a running program on an
3190+
unreferenced machine. The GUI, halui and linuxcncrsh keep their existing
3191+
unhome.
3192+
3193+
On a synchronized (negative HOME_SEQUENCE) joint pair, Pn on either joint
3194+
homes both (motion's existing gantry-homing behavior); on a positive shared
3195+
sequence Pn homes only the named joint -- use the bare form to home both.
3196+
3197+
Motion still enforces its own safety (idle / not on limits). The joint
3198+
number is range-checked against the machine's configured joint count in
3199+
task (emcJointHome(), taskintf.cc), which is where that count is known --
3200+
the interpreter has no joint count in its state.
3201+
*/
3202+
int Interp::convert_home_cycle(block_pointer block,
3203+
setup_pointer settings)
3204+
{
3205+
CHKS((settings->cutter_comp_side != CUTTER_COMP::OFF),
3206+
"Cannot home (G28.2) with cutter radius compensation on");
3207+
3208+
int joint = -1;
3209+
if (block->p_flag) {
3210+
CHKS(((block->p_number < 0.0) ||
3211+
(block->p_number != round_to_int(block->p_number))),
3212+
"P value for G28.2 must be a non-negative whole joint number"
3213+
" (omit P to home every joint)");
3214+
joint = round_to_int(block->p_number);
3215+
}
3216+
3217+
if (joint < 0) {
3218+
HOME_CYCLE();
3219+
} else {
3220+
HOME_CYCLE_JOINT(joint);
3221+
}
3222+
3223+
// Homing re-establishes machine zero and, for an immediate home,
3224+
// rewrites the joint coordinate with no physical motion. Stop reading
3225+
// ahead here (INTERP_EXECUTE_FINISH, via execute_block) and, once the
3226+
// cycle has run, resync current_* from the machine in read_inputs() so
3227+
// a following G91 move or I/J/K arc centre is right. Same pattern as
3228+
// probing and tool change.
3229+
settings->home_flag = true;
3230+
return INTERP_OK;
3231+
}
3232+
31693233
int Interp::convert_home(int move, //!< G-code, must be G_28 or G_30
31703234
block_pointer block, //!< pointer to a block of RS274 instructions
31713235
setup_pointer settings) //!< pointer to machine settings
@@ -4349,6 +4413,8 @@ int Interp::convert_modal_0(int code, //!< G-code, must be from group 0
43494413
CHP(convert_home(code, block, settings));
43504414
} else if ((code == G_28_1) || (code == G_30_1)) {
43514415
CHP(convert_savehome(code, block, settings));
4416+
} else if (code == G_28_2) {
4417+
CHP(convert_home_cycle(block, settings));
43524418
} else if ((code == G_52) || (code == G_92)) {
43534419
CHP(convert_axis_offsets(code, block, settings));
43544420
} else if ((code == G_5_3)||(code == G_6_3)) { // jjf

src/emc/rs274ngc/interp_execute.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,8 @@ Returned Value: int
199199
convert_speed
200200
convert_stop
201201
convert_tool_select
202-
Otherwise, if the probe_flag in the settings is true,
203-
or the input_flag is set to true this returns
202+
Otherwise, if the probe_flag, input_flag, toolchange_flag or home_flag
203+
in the settings is true, this returns
204204
INTERP_EXECUTE_FINISH.
205205
Otherwise, it returns INTERP_OK.
206206
@@ -324,6 +324,9 @@ int Interp::execute_block(block_pointer block, //!< pointer to a block of RS27
324324
if (settings->toolchange_flag)
325325
return (INTERP_EXECUTE_FINISH);
326326

327+
if (settings->home_flag)
328+
return (INTERP_EXECUTE_FINISH);
329+
327330
// All changes to settings are complete
328331
write_canon_state_tag(block, settings);
329332
return INTERP_OK;

src/emc/rs274ngc/interp_internal.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ enum GCodes
220220
G_21 = 210,
221221
G_28 = 280,
222222
G_28_1 = 281,
223+
G_28_2 = 282, /* G-code homing cycle (home one/all joints) */
223224
G_30 = 300,
224225
G_30_1 = 301,
225226
G_33 = 330,
@@ -747,6 +748,7 @@ struct setup
747748
bool probe_flag; // flag indicating probing done
748749
bool input_flag; // flag indicating waiting for input done
749750
bool toolchange_flag; // flag indicating we just had a tool change
751+
bool home_flag; // flag indicating a G28.2 homing cycle just ran
750752
int input_index; // channel queried
751753
bool input_digital; // input queried was digital (false=analog)
752754
bool cutter_comp_firstmove; // this is the first comp move

src/emc/rs274ngc/interp_setup.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ setup::setup() :
117117
probe_flag(0),
118118
input_flag(0),
119119
toolchange_flag(0),
120+
home_flag(0),
120121
input_index(0),
121122
input_digital(0),
122123
cutter_comp_firstmove(0),

src/emc/rs274ngc/rs274ngc_interp.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,8 @@ public:
324324
setup_pointer settings);
325325
int convert_savehome(int move, block_pointer block,
326326
setup_pointer settings);
327+
int convert_home_cycle(block_pointer block, // G28.2
328+
setup_pointer settings);
327329
int convert_length_units(int g_code, setup_pointer settings);
328330
int convert_m(block_pointer block, setup_pointer settings);
329331
int convert_modal_0(int code, block_pointer block,

src/emc/rs274ngc/rs274ngc_pre.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,7 @@ int Interp::init()
11931193
//_setup.plane set in Interp::synch
11941194
_setup.probe_flag = false;
11951195
_setup.toolchange_flag = false;
1196+
_setup.home_flag = false;
11961197
_setup.input_flag = false;
11971198
_setup.input_index = -1;
11981199
_setup.input_digital = false;
@@ -1458,6 +1459,19 @@ int Interp::read_inputs(setup_pointer settings)
14581459
load_tool_table();
14591460
settings->toolchange_flag = false;
14601461
}
1462+
if (settings->home_flag) {
1463+
// A G28.2 homing cycle re-establishes machine zero and, for an
1464+
// immediate (index/switchless) home, rewrites the joint coordinate
1465+
// even when nothing physically moved. Pull the interpreter's model
1466+
// of the current position back in line with the machine so a
1467+
// following G91 move or an I/J/K arc centre is computed from where
1468+
// the tool actually is, not from the pre-home point. Same mechanism
1469+
// as the tool-change resync above, without the tool-table reload.
1470+
CHKS((GET_EXTERNAL_QUEUE_EMPTY() == 0),
1471+
_("Queue is not empty after homing"));
1472+
refresh_actual_position(&_setup);
1473+
settings->home_flag = false;
1474+
}
14611475
// always track toolchanger-fault and toolchanger-reason codes
14621476
settings->parameters[5600] = GET_EXTERNAL_TC_FAULT();
14631477
settings->parameters[5601] = GET_EXTERNAL_TC_REASON();
@@ -2674,6 +2688,7 @@ int Interp::on_abort(int reason, const char *message)
26742688
// if set, may cause a "Queue is not empty after tool change" error
26752689
_setup.toolchange_flag = false;
26762690
_setup.probe_flag = false;
2691+
_setup.home_flag = false;
26772692
_setup.input_flag = false;
26782693

26792694
if (_setup.on_abort_command == NULL) {

0 commit comments

Comments
 (0)