|
@@ -117,7 +117,7 @@
|
117
|
117
|
* G30 - Single Z probe, probes bed at current XY location.
|
118
|
118
|
* G31 - Dock sled (Z_PROBE_SLED only)
|
119
|
119
|
* G32 - Undock sled (Z_PROBE_SLED only)
|
120
|
|
- * G38 - Probe target - similar to G28 except it uses the Z_Probe for all three axis
|
|
120
|
+ * G38 - Probe target - similar to G28 except it uses the Z_MIN endstop for all three axes
|
121
|
121
|
* G90 - Use Absolute Coordinates
|
122
|
122
|
* G91 - Use Relative Coordinates
|
123
|
123
|
* G92 - Set current position to coordinates given
|
|
@@ -277,9 +277,9 @@
|
277
|
277
|
TWIBus i2c;
|
278
|
278
|
#endif
|
279
|
279
|
|
280
|
|
-#ifdef G38_2_3
|
281
|
|
-bool G38_flag = false; // init G38 flags
|
282
|
|
-bool G38_flag_pass = false;
|
|
280
|
+#if ENABLED(G38_2_3)
|
|
281
|
+ bool G38_move = false,
|
|
282
|
+ G38_endstop_hit = false;
|
283
|
283
|
#endif
|
284
|
284
|
|
285
|
285
|
bool Running = true;
|
|
@@ -1343,7 +1343,7 @@ static void set_home_offset(AxisEnum axis, float v) {
|
1343
|
1343
|
* SCARA should wait until all XY homing is done before setting the XY
|
1344
|
1344
|
* current_position to home, because neither X nor Y is at home until
|
1345
|
1345
|
* both are at home. Z can however be homed individually.
|
1346
|
|
- *
|
|
1346
|
+ *
|
1347
|
1347
|
*/
|
1348
|
1348
|
static void set_axis_is_at_home(AxisEnum axis) {
|
1349
|
1349
|
#if ENABLED(DEBUG_LEVELING_FEATURE)
|
|
@@ -2331,146 +2331,6 @@ static void clean_up_after_endstop_or_probe_move() {
|
2331
|
2331
|
|
2332
|
2332
|
#endif // AUTO_BED_LEVELING_BILINEAR
|
2333
|
2333
|
|
2334
|
|
-
|
2335
|
|
-#ifdef G38_2_3
|
2336
|
|
-
|
2337
|
|
-#define G38_minimum_move 0.0275 // minimum distance in mm that will produce a move (determined using the print statement in check_move)
|
2338
|
|
-
|
2339
|
|
-bool check_move() //checks that at least one of the axis in the command line has an actual move
|
2340
|
|
- // motion planner only does moves of 0.001mm and larger
|
2341
|
|
-{
|
2342
|
|
-
|
2343
|
|
- bool move_flag = false;
|
2344
|
|
- for(int8_t i=0; i < 3; i++) {
|
2345
|
|
-/* debug used to determine prints
|
2346
|
|
- SERIAL_PROTOCOLPGM("axis: ");
|
2347
|
|
- SERIAL_PROTOCOL(axis_codes[i]);
|
2348
|
|
- SERIAL_PROTOCOLPGM(" code_seen : ");
|
2349
|
|
- SERIAL_PROTOCOL(code_seen(axis_codes[i]));
|
2350
|
|
- SERIAL_PROTOCOLPGM(" destination : ");
|
2351
|
|
- SERIAL_PROTOCOL(destination[i]);
|
2352
|
|
- SERIAL_PROTOCOLPGM(" current : ");
|
2353
|
|
- SERIAL_PROTOCOL(current_position[i]);
|
2354
|
|
- SERIAL_PROTOCOLPGM(" dif x 1000 : ");
|
2355
|
|
- SERIAL_PROTOCOLLN((destination[i] - current_position[i]) * 1000);
|
2356
|
|
- */
|
2357
|
|
- if (code_seen(axis_codes[i]) && (fabs(destination[i] - current_position[i]) >= G38_minimum_move)) move_flag = true ;
|
2358
|
|
-/*
|
2359
|
|
- ?? 0.0275mm produced a move on my machine along with an updated current position.
|
2360
|
|
- 0.0265mm did NOT produce a move and did NOT change the current position
|
2361
|
|
- this is very different than the 0.001 in the planner.
|
2362
|
|
- 0.001" is .0254mm so maybe the 0.0275 observed comes from digital storage limitations/conversion/rounding
|
2363
|
|
- */
|
2364
|
|
- }
|
2365
|
|
- return move_flag;
|
2366
|
|
-}
|
2367
|
|
-
|
2368
|
|
-
|
2369
|
|
-static void G38_run_probe(bool *G38_pass_fail) {
|
2370
|
|
-
|
2371
|
|
- G38_flag = true; //tell the interrupt handler that we're doing a G38 probe
|
2372
|
|
- *G38_pass_fail = false;
|
2373
|
|
-
|
2374
|
|
-#ifdef X_HOME_BUMP_MM
|
2375
|
|
-#ifdef Y_HOME_BUMP_MM
|
2376
|
|
-#ifdef Z_HOME_BUMP_MM
|
2377
|
|
- float G38_X_retract_mm = home_bump_mm(X_AXIS);
|
2378
|
|
- float G38_Y_retract_mm = home_bump_mm(Y_AXIS);
|
2379
|
|
- float G38_Z_retract_mm = home_bump_mm(Z_AXIS);
|
2380
|
|
-
|
2381
|
|
-#else
|
2382
|
|
-
|
2383
|
|
- float G38_X_retract_mm = 5;
|
2384
|
|
- float G38_Y_retract_mm = 5;
|
2385
|
|
- float G38_Z_retract_mm = 2;
|
2386
|
|
-
|
2387
|
|
-#endif
|
2388
|
|
-#endif
|
2389
|
|
-#endif
|
2390
|
|
-
|
2391
|
|
- // only retract the axis if the axis is in the command
|
2392
|
|
- if( (!code_seen('X') || (code_value_axis_units(X_AXIS) == 0))) G38_X_retract_mm = 0;
|
2393
|
|
- if( (!code_seen('Y') || (code_value_axis_units(Y_AXIS) == 0))) G38_Y_retract_mm = 0;
|
2394
|
|
- if( (!code_seen('Z') || (code_value_axis_units(Z_AXIS) == 0))) G38_Z_retract_mm = 0;
|
2395
|
|
-
|
2396
|
|
- // change the direction of the retract if needed
|
2397
|
|
- if ((destination[X_AXIS] - current_position[X_AXIS])>0) G38_X_retract_mm = -G38_X_retract_mm;
|
2398
|
|
- if ((destination[Y_AXIS] - current_position[Y_AXIS])>0) G38_Y_retract_mm = -G38_Y_retract_mm;
|
2399
|
|
- if ((destination[Z_AXIS] - current_position[Z_AXIS])>0) G38_Z_retract_mm = -G38_Z_retract_mm;
|
2400
|
|
-
|
2401
|
|
-
|
2402
|
|
- stepper.synchronize(); // wait until the machine is idle
|
2403
|
|
-
|
2404
|
|
- bool save_endstops = endstops.enabled; //remember state of endstops so we can retore them at the end
|
2405
|
|
- endstops.enable(true);
|
2406
|
|
-
|
2407
|
|
- // move until you reach the destination or hit an endstop or hit the target
|
2408
|
|
- // it's an error unless have hit the target
|
2409
|
|
- G38_flag_pass = false;
|
2410
|
|
- *G38_pass_fail = false;
|
2411
|
|
-
|
2412
|
|
- planner.buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate_mm_s, active_extruder);
|
2413
|
|
- stepper.synchronize();
|
2414
|
|
-
|
2415
|
|
- // we have to let the planner know where we are right now as it is not where we said to go.
|
2416
|
|
- // and we need to update current_position[axis]
|
2417
|
|
- current_position[X_AXIS] = stepper.get_axis_position_mm(X_AXIS);
|
2418
|
|
- current_position[Y_AXIS] = stepper.get_axis_position_mm(Y_AXIS);
|
2419
|
|
- current_position[Z_AXIS] = stepper.get_axis_position_mm(Z_AXIS);
|
2420
|
|
- planner.set_position_mm(current_position[X_AXIS], current_position[Y_AXIS] , current_position[Z_AXIS] , current_position[E_AXIS]);
|
2421
|
|
-
|
2422
|
|
- *G38_pass_fail = G38_flag_pass ; // only care if hit target on the first move
|
2423
|
|
-
|
2424
|
|
- if (*G38_pass_fail) { // no sense in doing the remaining moves if we didn't hit the endstop
|
2425
|
|
- // move away the retract distance
|
2426
|
|
- float xPosition = current_position[X_AXIS] + G38_X_retract_mm;
|
2427
|
|
- float yPosition = current_position[Y_AXIS] + G38_Y_retract_mm;
|
2428
|
|
- float zPosition = current_position[Z_AXIS] + G38_Z_retract_mm;
|
2429
|
|
-
|
2430
|
|
-
|
2431
|
|
-
|
2432
|
|
- // disable endstops on retract otherwise sometimes can't get away
|
2433
|
|
- endstops.enable(false);
|
2434
|
|
- G38_flag = false;
|
2435
|
|
-
|
2436
|
|
- planner.buffer_line(xPosition, yPosition , zPosition , current_position[E_AXIS], feedrate_mm_s/4, active_extruder);
|
2437
|
|
- stepper.synchronize();
|
2438
|
|
-
|
2439
|
|
-
|
2440
|
|
- // move back slowly
|
2441
|
|
- xPosition -= G38_X_retract_mm * 2;
|
2442
|
|
- yPosition -= G38_Y_retract_mm * 2;
|
2443
|
|
- zPosition -= G38_Z_retract_mm * 2;
|
2444
|
|
-
|
2445
|
|
-
|
2446
|
|
- // enable endstops on move back
|
2447
|
|
- endstops.enable(true);
|
2448
|
|
- G38_flag = true;
|
2449
|
|
-
|
2450
|
|
- planner.buffer_line(xPosition, yPosition , zPosition , current_position[E_AXIS], feedrate_mm_s/4, active_extruder);
|
2451
|
|
- stepper.synchronize();
|
2452
|
|
-
|
2453
|
|
- // we have to let the planner know where we are right now as it is not where we said to go.
|
2454
|
|
- // and we need to update current_position[axis]
|
2455
|
|
- current_position[X_AXIS] = stepper.get_axis_position_mm(X_AXIS);
|
2456
|
|
- current_position[Y_AXIS] = stepper.get_axis_position_mm(Y_AXIS);
|
2457
|
|
- current_position[Z_AXIS] = stepper.get_axis_position_mm(Z_AXIS);
|
2458
|
|
- planner.set_position_mm(current_position[X_AXIS], current_position[Y_AXIS] , current_position[Z_AXIS] , current_position[E_AXIS]);
|
2459
|
|
-
|
2460
|
|
- }
|
2461
|
|
-
|
2462
|
|
-// clean_up_after_endstop_move();
|
2463
|
|
-
|
2464
|
|
- endstops.enable(save_endstops); //restore endstops to same state as when we started
|
2465
|
|
-
|
2466
|
|
- endstops.hit_on_purpose();
|
2467
|
|
- G38_flag = false; //tell the interrupt handler that we're done
|
2468
|
|
-
|
2469
|
|
-}
|
2470
|
|
-
|
2471
|
|
-#endif //G38_2_3
|
2472
|
|
-
|
2473
|
|
-
|
2474
|
2334
|
/**
|
2475
|
2335
|
* Home an individual linear axis
|
2476
|
2336
|
*/
|
|
@@ -4306,25 +4166,93 @@ inline void gcode_G28() {
|
4306
|
4166
|
|
4307
|
4167
|
#endif // HAS_BED_PROBE
|
4308
|
4168
|
|
4309
|
|
-#ifdef G38_2_3
|
4310
|
|
- inline void gcode_G38(float code_num) {
|
4311
|
|
- #if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) || ENABLED(Z_MIN_PROBE_ENDSTOP) //must have valid Z_MIN_PROBE definition for this command to work
|
4312
|
|
- if ((code_num == 38.2 || code_num == 38.3 ) && (code_seen('X') || code_seen('Y') || code_seen('Z'))) {
|
4313
|
|
- gcode_get_destination(); // For X Y Z E F
|
4314
|
|
- if (check_move()) { // see if the commanded movement will result in a physical movement
|
4315
|
|
- bool G38_pass_fail = false;
|
4316
|
|
- G38_run_probe(&G38_pass_fail);
|
4317
|
|
- if (!G38_pass_fail && (code_num == 38.2) ) SERIAL_PROTOCOLLNPGM(" ERROR - failed to reach target ");
|
4318
|
|
- }
|
|
4169
|
+#if ENABLED(G38_2_3)
|
|
4170
|
+
|
|
4171
|
+ static bool G38_run_probe() {
|
|
4172
|
+
|
|
4173
|
+ bool G38_pass_fail = false;
|
|
4174
|
+
|
|
4175
|
+ // Get direction of move and retract
|
|
4176
|
+ float retract_mm[XYZ];
|
|
4177
|
+ LOOP_XYZ(i) {
|
|
4178
|
+ float dist = destination[i] - current_position[i];
|
|
4179
|
+ retract_mm[i] = fabs(dist) < G38_MINIMUM_MOVE ? 0 : home_bump_mm(i) * (dist > 0 ? -1 : 1);
|
4319
|
4180
|
}
|
|
4181
|
+
|
|
4182
|
+ stepper.synchronize(); // wait until the machine is idle
|
|
4183
|
+
|
|
4184
|
+ // Move until destination reached or target hit
|
|
4185
|
+ endstops.enable(true);
|
|
4186
|
+ G38_move = true;
|
|
4187
|
+ G38_endstop_hit = false;
|
|
4188
|
+ prepare_move_to_destination();
|
|
4189
|
+ stepper.synchronize();
|
|
4190
|
+ G38_move = false;
|
|
4191
|
+
|
|
4192
|
+ endstops.hit_on_purpose();
|
|
4193
|
+ set_current_from_steppers_for_axis(ALL_AXES);
|
|
4194
|
+ SYNC_PLAN_POSITION_KINEMATIC();
|
|
4195
|
+
|
|
4196
|
+ // Only do remaining moves if target was hit
|
|
4197
|
+ if (G38_endstop_hit) {
|
|
4198
|
+
|
|
4199
|
+ G38_pass_fail = true;
|
|
4200
|
+
|
|
4201
|
+ // Move away by the retract distance
|
|
4202
|
+ set_destination_to_current();
|
|
4203
|
+ LOOP_XYZ(i) destination[i] += retract_mm[i];
|
|
4204
|
+ endstops.enable(false);
|
|
4205
|
+ prepare_move_to_destination();
|
|
4206
|
+ stepper.synchronize();
|
|
4207
|
+
|
|
4208
|
+ feedrate_mm_s /= 4;
|
|
4209
|
+
|
|
4210
|
+ // Bump the target more slowly
|
|
4211
|
+ LOOP_XYZ(i) destination[i] -= retract_mm[i] * 2;
|
|
4212
|
+
|
|
4213
|
+ endstops.enable(true);
|
|
4214
|
+ G38_move = true;
|
|
4215
|
+ prepare_move_to_destination();
|
|
4216
|
+ stepper.synchronize();
|
|
4217
|
+ G38_move = false;
|
|
4218
|
+
|
|
4219
|
+ set_current_from_steppers_for_axis(ALL_AXES);
|
|
4220
|
+ SYNC_PLAN_POSITION_KINEMATIC();
|
|
4221
|
+ }
|
|
4222
|
+
|
|
4223
|
+ endstops.hit_on_purpose();
|
|
4224
|
+ endstops.not_homing();
|
|
4225
|
+ return G38_pass_fail;
|
4320
|
4226
|
}
|
4321
|
|
-#else
|
4322
|
|
-
|
4323
|
|
- SERIAL_PROTOCOLLNPGM(" ERROR - Z_MIN_PROBE must be enabled ");
|
|
4227
|
+
|
|
4228
|
+ /**
|
|
4229
|
+ * G38.2 - probe toward workpiece, stop on contact, signal error if failure
|
|
4230
|
+ * G38.3 - probe toward workpiece, stop on contact
|
|
4231
|
+ *
|
|
4232
|
+ * Like G28 except uses Z min endstop for all axes
|
|
4233
|
+ */
|
|
4234
|
+ inline void gcode_G38(bool is_38_2) {
|
|
4235
|
+ // Get X Y Z E F
|
|
4236
|
+ gcode_get_destination();
|
|
4237
|
+
|
|
4238
|
+ setup_for_endstop_or_probe_move();
|
|
4239
|
+
|
|
4240
|
+ // If any axis has enough movement, do the move
|
|
4241
|
+ LOOP_XYZ(i)
|
|
4242
|
+ if (fabs(destination[i] - current_position[i]) >= G38_MINIMUM_MOVE) {
|
|
4243
|
+ if (!code_seen('F')) feedrate_mm_s = homing_feedrate_mm_s[i];
|
|
4244
|
+ // If G38.2 fails throw an error
|
|
4245
|
+ if (!G38_run_probe() && is_38_2) {
|
|
4246
|
+ SERIAL_ERROR_START;
|
|
4247
|
+ SERIAL_ERRORLNPGM("Failed to reach target");
|
|
4248
|
+ }
|
|
4249
|
+ break;
|
|
4250
|
+ }
|
|
4251
|
+
|
|
4252
|
+ clean_up_after_endstop_or_probe_move();
|
4324
|
4253
|
}
|
4325
|
|
-#endif
|
4326
|
|
-#endif //G38_2_3
|
4327
|
4254
|
|
|
4255
|
+#endif // G38_2_3
|
4328
|
4256
|
|
4329
|
4257
|
/**
|
4330
|
4258
|
* G92: Set current position to given X Y Z E
|
|
@@ -7447,23 +7375,32 @@ void process_next_command() {
|
7447
|
7375
|
// Skip spaces to get the numeric part
|
7448
|
7376
|
while (*cmd_ptr == ' ') cmd_ptr++;
|
7449
|
7377
|
|
|
7378
|
+ // Allow for decimal point in command
|
|
7379
|
+ #if ENABLED(G38_2_3)
|
|
7380
|
+ uint8_t subcode = 0;
|
|
7381
|
+ #endif
|
|
7382
|
+
|
7450
|
7383
|
uint16_t codenum = 0; // define ahead of goto
|
7451
|
7384
|
|
7452
|
7385
|
// Bail early if there's no code
|
7453
|
7386
|
bool code_is_good = NUMERIC(*cmd_ptr);
|
7454
|
7387
|
if (!code_is_good) goto ExitUnknownCommand;
|
7455
|
7388
|
|
7456
|
|
-#ifdef G38_2_3
|
7457
|
|
- double codenum_float;
|
7458
|
|
- codenum_float = atof(cmd_ptr); //allow for decimal point in command
|
7459
|
|
-#endif
|
7460
|
|
-
|
7461
|
7389
|
// Get and skip the code number
|
7462
|
7390
|
do {
|
7463
|
7391
|
codenum = (codenum * 10) + (*cmd_ptr - '0');
|
7464
|
7392
|
cmd_ptr++;
|
7465
|
7393
|
} while (NUMERIC(*cmd_ptr));
|
7466
|
7394
|
|
|
7395
|
+ // Allow for decimal point in command
|
|
7396
|
+ #if ENABLED(G38_2_3)
|
|
7397
|
+ if (*cmd_ptr == '.') {
|
|
7398
|
+ cmd_ptr++;
|
|
7399
|
+ while (NUMERIC(*cmd_ptr))
|
|
7400
|
+ subcode = (subcode * 10) + (*cmd_ptr++ - '0');
|
|
7401
|
+ }
|
|
7402
|
+ #endif
|
|
7403
|
+
|
7467
|
7404
|
// Skip all spaces to get to the first argument, or nul
|
7468
|
7405
|
while (*cmd_ptr == ' ') cmd_ptr++;
|
7469
|
7406
|
|
|
@@ -7564,12 +7501,13 @@ void process_next_command() {
|
7564
|
7501
|
#endif // Z_PROBE_SLED
|
7565
|
7502
|
#endif // HAS_BED_PROBE
|
7566
|
7503
|
|
7567
|
|
- #ifdef G38_2_3
|
7568
|
|
- case 38: //G38.2 & G38.3
|
7569
|
|
- gcode_G38(codenum_float);
|
|
7504
|
+ #if ENABLED(G38_2_3)
|
|
7505
|
+ case 38: // G38.2 & G38.3
|
|
7506
|
+ if (subcode == 2 || subcode == 3)
|
|
7507
|
+ gcode_G38(subcode == 2);
|
7570
|
7508
|
break;
|
7571
|
|
- #endif
|
7572
|
|
-
|
|
7509
|
+ #endif
|
|
7510
|
+
|
7573
|
7511
|
case 90: // G90
|
7574
|
7512
|
relative_mode = false;
|
7575
|
7513
|
break;
|
|
@@ -9078,7 +9016,7 @@ void prepare_move_to_destination() {
|
9078
|
9016
|
* Morgan SCARA Inverse Kinematics. Results in delta[].
|
9079
|
9017
|
*
|
9080
|
9018
|
* See http://forums.reprap.org/read.php?185,283327
|
9081
|
|
- *
|
|
9019
|
+ *
|
9082
|
9020
|
* Maths and first version by QHARLEY.
|
9083
|
9021
|
* Integrated into Marlin and slightly restructured by Joachim Cerny.
|
9084
|
9022
|
*/
|