code changes to implement G38 commands
1) modified 3 code files Marlin.h Marlin_main.cpp endstops.cpp 2) modified config files so I could test on my machine Testing was done on an AzteegX3pro based machine. The probe was hooked to the Z_MIN endstop. My controller doesn't have a dedicated Z_PROBE input so I couldn't test that functionality. Verified that a large file (without any G38 commands) executed the same before and after the changes. Verified that the head moves as expected when G38.2 and G38.3 commands are issued. Single & multiple axis moves were tested along with + and - directions. Code was added to the main ISR. In normal operation only one extra IF statement is evaluated. I didn't notice any performance degradation because of the added code. The G38 commands are expected to be issued manually by the operator during machine setup. The G38 commands wait until the machine is idle before proceeding. That way the other commands are minimally impacted by the extra ISR overhead when a G38 command is in the queue. The G38 commands are very similar to the G28 commands except 1) only the Z_PROBE is used and movement can be in the + or - direction. See issue 4677 for a discussion on adding G38 commands to Marlin. Feature request: add ability to use G38.2 command (CNC) MarlinFirmware/Marlin#4677
This commit is contained in:
committed by
Scott Lahteine
parent
74d048e77e
commit
2911aa7ffa
@ -117,6 +117,7 @@
|
||||
* G30 - Single Z probe, probes bed at current XY location.
|
||||
* G31 - Dock sled (Z_PROBE_SLED only)
|
||||
* G32 - Undock sled (Z_PROBE_SLED only)
|
||||
* G38 - Probe target - similar to G28 except it uses the Z_Probe for all three axis
|
||||
* G90 - Use Absolute Coordinates
|
||||
* G91 - Use Relative Coordinates
|
||||
* G92 - Set current position to coordinates given
|
||||
@ -276,6 +277,11 @@
|
||||
TWIBus i2c;
|
||||
#endif
|
||||
|
||||
#ifdef G38_2_3
|
||||
bool G38_flag = false; // init G38 flags
|
||||
bool G38_flag_pass = false;
|
||||
#endif
|
||||
|
||||
bool Running = true;
|
||||
|
||||
uint8_t marlin_debug_flags = DEBUG_NONE;
|
||||
@ -2325,6 +2331,146 @@ static void clean_up_after_endstop_or_probe_move() {
|
||||
|
||||
#endif // AUTO_BED_LEVELING_BILINEAR
|
||||
|
||||
|
||||
#ifdef G38_2_3
|
||||
|
||||
#define G38_minimum_move 0.0275 // minimum distance in mm that will produce a move (determined using the print statement in check_move)
|
||||
|
||||
bool check_move() //checks that at least one of the axis in the command line has an actual move
|
||||
// motion planner only does moves of 0.001mm and larger
|
||||
{
|
||||
|
||||
bool move_flag = false;
|
||||
for(int8_t i=0; i < 3; i++) {
|
||||
/* debug used to determine prints
|
||||
SERIAL_PROTOCOLPGM("axis: ");
|
||||
SERIAL_PROTOCOL(axis_codes[i]);
|
||||
SERIAL_PROTOCOLPGM(" code_seen : ");
|
||||
SERIAL_PROTOCOL(code_seen(axis_codes[i]));
|
||||
SERIAL_PROTOCOLPGM(" destination : ");
|
||||
SERIAL_PROTOCOL(destination[i]);
|
||||
SERIAL_PROTOCOLPGM(" current : ");
|
||||
SERIAL_PROTOCOL(current_position[i]);
|
||||
SERIAL_PROTOCOLPGM(" dif x 1000 : ");
|
||||
SERIAL_PROTOCOLLN((destination[i] - current_position[i]) * 1000);
|
||||
*/
|
||||
if (code_seen(axis_codes[i]) && (fabs(destination[i] - current_position[i]) >= G38_minimum_move)) move_flag = true ;
|
||||
/*
|
||||
?? 0.0275mm produced a move on my machine along with an updated current position.
|
||||
0.0265mm did NOT produce a move and did NOT change the current position
|
||||
this is very different than the 0.001 in the planner.
|
||||
0.001" is .0254mm so maybe the 0.0275 observed comes from digital storage limitations/conversion/rounding
|
||||
*/
|
||||
}
|
||||
return move_flag;
|
||||
}
|
||||
|
||||
|
||||
static void G38_run_probe(bool *G38_pass_fail) {
|
||||
|
||||
G38_flag = true; //tell the interrupt handler that we're doing a G38 probe
|
||||
*G38_pass_fail = false;
|
||||
|
||||
#ifdef X_HOME_BUMP_MM
|
||||
#ifdef Y_HOME_BUMP_MM
|
||||
#ifdef Z_HOME_BUMP_MM
|
||||
float G38_X_retract_mm = home_bump_mm(X_AXIS);
|
||||
float G38_Y_retract_mm = home_bump_mm(Y_AXIS);
|
||||
float G38_Z_retract_mm = home_bump_mm(Z_AXIS);
|
||||
|
||||
#else
|
||||
|
||||
float G38_X_retract_mm = 5;
|
||||
float G38_Y_retract_mm = 5;
|
||||
float G38_Z_retract_mm = 2;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// only retract the axis if the axis is in the command
|
||||
if( (!code_seen('X') || (code_value_axis_units(X_AXIS) == 0))) G38_X_retract_mm = 0;
|
||||
if( (!code_seen('Y') || (code_value_axis_units(Y_AXIS) == 0))) G38_Y_retract_mm = 0;
|
||||
if( (!code_seen('Z') || (code_value_axis_units(Z_AXIS) == 0))) G38_Z_retract_mm = 0;
|
||||
|
||||
// change the direction of the retract if needed
|
||||
if ((destination[X_AXIS] - current_position[X_AXIS])>0) G38_X_retract_mm = -G38_X_retract_mm;
|
||||
if ((destination[Y_AXIS] - current_position[Y_AXIS])>0) G38_Y_retract_mm = -G38_Y_retract_mm;
|
||||
if ((destination[Z_AXIS] - current_position[Z_AXIS])>0) G38_Z_retract_mm = -G38_Z_retract_mm;
|
||||
|
||||
|
||||
stepper.synchronize(); // wait until the machine is idle
|
||||
|
||||
bool save_endstops = endstops.enabled; //remember state of endstops so we can retore them at the end
|
||||
endstops.enable(true);
|
||||
|
||||
// move until you reach the destination or hit an endstop or hit the target
|
||||
// it's an error unless have hit the target
|
||||
G38_flag_pass = false;
|
||||
*G38_pass_fail = false;
|
||||
|
||||
planner.buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate_mm_s, active_extruder);
|
||||
stepper.synchronize();
|
||||
|
||||
// we have to let the planner know where we are right now as it is not where we said to go.
|
||||
// and we need to update current_position[axis]
|
||||
current_position[X_AXIS] = stepper.get_axis_position_mm(X_AXIS);
|
||||
current_position[Y_AXIS] = stepper.get_axis_position_mm(Y_AXIS);
|
||||
current_position[Z_AXIS] = stepper.get_axis_position_mm(Z_AXIS);
|
||||
planner.set_position_mm(current_position[X_AXIS], current_position[Y_AXIS] , current_position[Z_AXIS] , current_position[E_AXIS]);
|
||||
|
||||
*G38_pass_fail = G38_flag_pass ; // only care if hit target on the first move
|
||||
|
||||
if (*G38_pass_fail) { // no sense in doing the remaining moves if we didn't hit the endstop
|
||||
// move away the retract distance
|
||||
float xPosition = current_position[X_AXIS] + G38_X_retract_mm;
|
||||
float yPosition = current_position[Y_AXIS] + G38_Y_retract_mm;
|
||||
float zPosition = current_position[Z_AXIS] + G38_Z_retract_mm;
|
||||
|
||||
|
||||
|
||||
// disable endstops on retract otherwise sometimes can't get away
|
||||
endstops.enable(false);
|
||||
G38_flag = false;
|
||||
|
||||
planner.buffer_line(xPosition, yPosition , zPosition , current_position[E_AXIS], feedrate_mm_s/4, active_extruder);
|
||||
stepper.synchronize();
|
||||
|
||||
|
||||
// move back slowly
|
||||
xPosition -= G38_X_retract_mm * 2;
|
||||
yPosition -= G38_Y_retract_mm * 2;
|
||||
zPosition -= G38_Z_retract_mm * 2;
|
||||
|
||||
|
||||
// enable endstops on move back
|
||||
endstops.enable(true);
|
||||
G38_flag = true;
|
||||
|
||||
planner.buffer_line(xPosition, yPosition , zPosition , current_position[E_AXIS], feedrate_mm_s/4, active_extruder);
|
||||
stepper.synchronize();
|
||||
|
||||
// we have to let the planner know where we are right now as it is not where we said to go.
|
||||
// and we need to update current_position[axis]
|
||||
current_position[X_AXIS] = stepper.get_axis_position_mm(X_AXIS);
|
||||
current_position[Y_AXIS] = stepper.get_axis_position_mm(Y_AXIS);
|
||||
current_position[Z_AXIS] = stepper.get_axis_position_mm(Z_AXIS);
|
||||
planner.set_position_mm(current_position[X_AXIS], current_position[Y_AXIS] , current_position[Z_AXIS] , current_position[E_AXIS]);
|
||||
|
||||
}
|
||||
|
||||
// clean_up_after_endstop_move();
|
||||
|
||||
endstops.enable(save_endstops); //restore endstops to same state as when we started
|
||||
|
||||
endstops.hit_on_purpose();
|
||||
G38_flag = false; //tell the interrupt handler that we're done
|
||||
|
||||
}
|
||||
|
||||
#endif //G38_2_3
|
||||
|
||||
|
||||
/**
|
||||
* Home an individual linear axis
|
||||
*/
|
||||
@ -4160,6 +4306,26 @@ inline void gcode_G28() {
|
||||
|
||||
#endif // HAS_BED_PROBE
|
||||
|
||||
#ifdef G38_2_3
|
||||
inline void gcode_G38(float code_num) {
|
||||
#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
|
||||
if ((code_num == 38.2 || code_num == 38.3 ) && (code_seen('X') || code_seen('Y') || code_seen('Z'))) {
|
||||
gcode_get_destination(); // For X Y Z E F
|
||||
if (check_move()) { // see if the commanded movement will result in a physical movement
|
||||
bool G38_pass_fail = false;
|
||||
G38_run_probe(&G38_pass_fail);
|
||||
if (!G38_pass_fail && (code_num == 38.2) ) SERIAL_PROTOCOLLNPGM(" ERROR - failed to reach target ");
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
SERIAL_PROTOCOLLNPGM(" ERROR - Z_MIN_PROBE must be enabled ");
|
||||
}
|
||||
#endif
|
||||
#endif //G38_2_3
|
||||
|
||||
|
||||
/**
|
||||
* G92: Set current position to given X Y Z E
|
||||
*/
|
||||
@ -7287,6 +7453,11 @@ void process_next_command() {
|
||||
bool code_is_good = NUMERIC(*cmd_ptr);
|
||||
if (!code_is_good) goto ExitUnknownCommand;
|
||||
|
||||
#ifdef G38_2_3
|
||||
double codenum_float;
|
||||
codenum_float = atof(cmd_ptr); //allow for decimal point in command
|
||||
#endif
|
||||
|
||||
// Get and skip the code number
|
||||
do {
|
||||
codenum = (codenum * 10) + (*cmd_ptr - '0');
|
||||
@ -7393,6 +7564,12 @@ void process_next_command() {
|
||||
#endif // Z_PROBE_SLED
|
||||
#endif // HAS_BED_PROBE
|
||||
|
||||
#ifdef G38_2_3
|
||||
case 38: //G38.2 & G38.3
|
||||
gcode_G38(codenum_float);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 90: // G90
|
||||
relative_mode = false;
|
||||
break;
|
||||
|
Reference in New Issue
Block a user