Improved constant laser power per rate mode. Re-factored for flash size. Minor bug fixes.
- NOTE: This commit has largely been untested. - Constant laser power per rate mode has been improved. Altered its implementation to be more responsive and accurate. - Based on LaserWeb dev feedback, only G1, G2, and G3 moves operate with constant laser power mode. Meaning that G0, G38.x, and $J jogging motions operate without it and will keep a constant power output. This was specifically requested as a way to focus the laser by keeping the laser on when not moving. Operationally, this shouldn’t alter how the laser mode operates. - Re-factored parts of the g-code parser and g-code state reports to save a few hundred bytes of flash. What was done makes the code a bit more unreadable (bad), but the flash space was in dire need. So, I’m willing to live with it for now. - Fixed a problem with $G g-code state reports. Showed `M0` program pause during a run state. Now fixed to show nothing during a run state. Also, `M30` program end was shown as `M2`. This was also corrected. - Improved spindle stop override responsiveness by removing the enforced spindle restoring delay. It’s not needed for a feature that is user controlled. - Fixed a bug with G2/3 arcs in inverse time mode. - Updated the interface.md document to make it more clear how WPos: or MPos: can be calculated from WCO:. Some GUI devs have failed to catch this in the documentation.
This commit is contained in:
80
grbl/gcode.c
80
grbl/gcode.c
@ -149,35 +149,12 @@ uint8_t gc_execute_line(char *line)
|
||||
// No break. Continues to next line.
|
||||
case 4: case 53:
|
||||
word_bit = MODAL_GROUP_G0;
|
||||
switch(int_value) {
|
||||
case 4: gc_block.non_modal_command = NON_MODAL_DWELL; break; // G4
|
||||
case 10: gc_block.non_modal_command = NON_MODAL_SET_COORDINATE_DATA; break; // G10
|
||||
case 28:
|
||||
switch(mantissa) {
|
||||
case 0: gc_block.non_modal_command = NON_MODAL_GO_HOME_0; break; // G28
|
||||
case 10: gc_block.non_modal_command = NON_MODAL_SET_HOME_0; break; // G28.1
|
||||
default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G28.x command]
|
||||
}
|
||||
mantissa = 0; // Set to zero to indicate valid non-integer G command.
|
||||
break;
|
||||
case 30:
|
||||
switch(mantissa) {
|
||||
case 0: gc_block.non_modal_command = NON_MODAL_GO_HOME_1; break; // G30
|
||||
case 10: gc_block.non_modal_command = NON_MODAL_SET_HOME_1; break; // G30.1
|
||||
default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G30.x command]
|
||||
}
|
||||
mantissa = 0; // Set to zero to indicate valid non-integer G command.
|
||||
break;
|
||||
case 53: gc_block.non_modal_command = NON_MODAL_ABSOLUTE_OVERRIDE; break; // G53
|
||||
case 92:
|
||||
switch(mantissa) {
|
||||
case 0: gc_block.non_modal_command = NON_MODAL_SET_COORDINATE_OFFSET; break; // G92
|
||||
case 10: gc_block.non_modal_command = NON_MODAL_RESET_COORDINATE_OFFSET; break; // G92.1
|
||||
default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G92.x command]
|
||||
}
|
||||
mantissa = 0; // Set to zero to indicate valid non-integer G command.
|
||||
break;
|
||||
}
|
||||
gc_block.non_modal_command = int_value;
|
||||
if ((int_value == 28) || (int_value == 30) || (int_value == 92)) {
|
||||
if ((mantissa != 0) || (mantissa != 10)) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); }
|
||||
gc_block.non_modal_command += mantissa;
|
||||
mantissa = 0; // Set to zero to indicate valid non-integer G command.
|
||||
}
|
||||
break;
|
||||
case 0: case 1: case 2: case 3: case 38:
|
||||
// Check for G0/1/2/3/38 being called with G10/28/30/92 on same block.
|
||||
@ -187,37 +164,22 @@ uint8_t gc_execute_line(char *line)
|
||||
// No break. Continues to next line.
|
||||
case 80:
|
||||
word_bit = MODAL_GROUP_G1;
|
||||
switch(int_value) {
|
||||
case 0: gc_block.modal.motion = MOTION_MODE_SEEK; break; // G0
|
||||
case 1: gc_block.modal.motion = MOTION_MODE_LINEAR; break; // G1
|
||||
case 2: gc_block.modal.motion = MOTION_MODE_CW_ARC; break; // G2
|
||||
case 3: gc_block.modal.motion = MOTION_MODE_CCW_ARC; break; // G3
|
||||
case 38:
|
||||
switch(mantissa) {
|
||||
case 20: gc_block.modal.motion = MOTION_MODE_PROBE_TOWARD; break; // G38.2
|
||||
case 30: gc_block.modal.motion = MOTION_MODE_PROBE_TOWARD_NO_ERROR; break; // G38.3
|
||||
case 40: gc_block.modal.motion = MOTION_MODE_PROBE_AWAY; break; // G38.4
|
||||
case 50: gc_block.modal.motion = MOTION_MODE_PROBE_AWAY_NO_ERROR; break; // G38.5
|
||||
default: FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G38.x command]
|
||||
}
|
||||
mantissa = 0; // Set to zero to indicate valid non-integer G command.
|
||||
break;
|
||||
case 80: gc_block.modal.motion = MOTION_MODE_NONE; break; // G80
|
||||
}
|
||||
gc_block.modal.motion = int_value;
|
||||
if (int_value == 38){
|
||||
if ((mantissa != 20) || (mantissa != 30) || (mantissa != 40) || (mantissa != 50)) {
|
||||
FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); // [Unsupported G38.x command]
|
||||
}
|
||||
gc_block.modal.motion += (mantissa/10)+100;
|
||||
}
|
||||
break;
|
||||
case 17: case 18: case 19:
|
||||
word_bit = MODAL_GROUP_G2;
|
||||
switch(int_value) {
|
||||
case 17: gc_block.modal.plane_select = PLANE_SELECT_XY; break;
|
||||
case 18: gc_block.modal.plane_select = PLANE_SELECT_ZX; break;
|
||||
case 19: gc_block.modal.plane_select = PLANE_SELECT_YZ; break;
|
||||
}
|
||||
gc_block.modal.plane_select = int_value - 17;
|
||||
break;
|
||||
case 90: case 91:
|
||||
if (mantissa == 0) {
|
||||
word_bit = MODAL_GROUP_G3;
|
||||
if (int_value == 90) { gc_block.modal.distance = DISTANCE_MODE_ABSOLUTE; } // G90
|
||||
else { gc_block.modal.distance = DISTANCE_MODE_INCREMENTAL; } // G91
|
||||
gc_block.modal.distance = int_value - 90;
|
||||
} else {
|
||||
word_bit = MODAL_GROUP_G4;
|
||||
if ((mantissa != 10) || (int_value == 90)) { FAIL(STATUS_GCODE_UNSUPPORTED_COMMAND); } // [G90.1 not supported]
|
||||
@ -227,13 +189,11 @@ uint8_t gc_execute_line(char *line)
|
||||
break;
|
||||
case 93: case 94:
|
||||
word_bit = MODAL_GROUP_G5;
|
||||
if (int_value == 93) { gc_block.modal.feed_rate = FEED_RATE_MODE_INVERSE_TIME; } // G93
|
||||
else { gc_block.modal.feed_rate = FEED_RATE_MODE_UNITS_PER_MIN; } // G94
|
||||
gc_block.modal.feed_rate = 94 - int_value;
|
||||
break;
|
||||
case 20: case 21:
|
||||
word_bit = MODAL_GROUP_G6;
|
||||
if (int_value == 20) { gc_block.modal.units = UNITS_MODE_INCHES; } // G20
|
||||
else { gc_block.modal.units = UNITS_MODE_MM; } // G21
|
||||
gc_block.modal.units = 21 - int_value;
|
||||
break;
|
||||
case 40:
|
||||
word_bit = MODAL_GROUP_G7;
|
||||
@ -258,7 +218,7 @@ uint8_t gc_execute_line(char *line)
|
||||
case 54: case 55: case 56: case 57: case 58: case 59:
|
||||
// NOTE: G59.x are not supported. (But their int_values would be 60, 61, and 62.)
|
||||
word_bit = MODAL_GROUP_G12;
|
||||
gc_block.modal.coord_select = int_value-54; // Shift to array indexing.
|
||||
gc_block.modal.coord_select = int_value - 54; // Shift to array indexing.
|
||||
break;
|
||||
case 61:
|
||||
word_bit = MODAL_GROUP_G13;
|
||||
@ -284,7 +244,7 @@ uint8_t gc_execute_line(char *line)
|
||||
switch(int_value) {
|
||||
case 0: gc_block.modal.program_flow = PROGRAM_FLOW_PAUSED; break; // Program pause
|
||||
case 1: break; // Optional stop not supported. Ignore.
|
||||
case 2: case 30: gc_block.modal.program_flow = PROGRAM_FLOW_COMPLETED; break; // Program end and reset
|
||||
default: gc_block.modal.program_flow = int_value; // Program end and reset
|
||||
}
|
||||
break;
|
||||
#ifndef USE_SPINDLE_DIR_AS_ENABLE_PIN
|
||||
@ -891,7 +851,7 @@ uint8_t gc_execute_line(char *line)
|
||||
|
||||
// [2. Set feed rate mode ]:
|
||||
gc_state.modal.feed_rate = gc_block.modal.feed_rate;
|
||||
pl_data->condition |= gc_state.modal.feed_rate; // Set condition flag for planner use.
|
||||
if (gc_state.modal.feed_rate) { pl_data->condition |= PL_COND_FLAG_INVERSE_TIME; } // Set condition flag for planner use.
|
||||
|
||||
// [3. Set feed rate ]:
|
||||
gc_state.feed_rate = gc_block.values.f; // Always copy this value. See feed rate error-checking.
|
||||
|
54
grbl/gcode.h
54
grbl/gcode.h
@ -51,54 +51,60 @@
|
||||
|
||||
// Define command actions for within execution-type modal groups (motion, stopping, non-modal). Used
|
||||
// internally by the parser to know which command to execute.
|
||||
// NOTE: Some macro values are assigned specific values to make g-code state reporting and parsing
|
||||
// compile a litte smaller. Necessary due to being completely out of flash on the 328p. Although not
|
||||
// ideal, just be careful with values that state 'do not alter' and check both report.c and gcode.c
|
||||
// to see how they are used, if you need to alter them.
|
||||
|
||||
// Modal Group G0: Non-modal actions
|
||||
#define NON_MODAL_NO_ACTION 0 // (Default: Must be zero)
|
||||
#define NON_MODAL_DWELL 1 // G4
|
||||
#define NON_MODAL_SET_COORDINATE_DATA 2 // G10
|
||||
#define NON_MODAL_GO_HOME_0 3 // G28
|
||||
#define NON_MODAL_SET_HOME_0 4 // G28.1
|
||||
#define NON_MODAL_GO_HOME_1 5 // G30
|
||||
#define NON_MODAL_SET_HOME_1 6 // G30.1
|
||||
#define NON_MODAL_ABSOLUTE_OVERRIDE 7 // G53
|
||||
#define NON_MODAL_SET_COORDINATE_OFFSET 8 // G92
|
||||
#define NON_MODAL_RESET_COORDINATE_OFFSET 9 //G92.1
|
||||
#define NON_MODAL_DWELL 4 // G4 (Do not alter value)
|
||||
#define NON_MODAL_SET_COORDINATE_DATA 10 // G10 (Do not alter value)
|
||||
#define NON_MODAL_GO_HOME_0 28 // G28 (Do not alter value)
|
||||
#define NON_MODAL_SET_HOME_0 38 // G28.1 (Do not alter value)
|
||||
#define NON_MODAL_GO_HOME_1 30 // G30 (Do not alter value)
|
||||
#define NON_MODAL_SET_HOME_1 40 // G30.1 (Do not alter value)
|
||||
#define NON_MODAL_ABSOLUTE_OVERRIDE 53 // G53 (Do not alter value)
|
||||
#define NON_MODAL_SET_COORDINATE_OFFSET 92 // G92 (Do not alter value)
|
||||
#define NON_MODAL_RESET_COORDINATE_OFFSET 102 //G92.1 (Do not alter value)
|
||||
|
||||
// Modal Group G1: Motion modes
|
||||
#define MOTION_MODE_SEEK 0 // G0 (Default: Must be zero)
|
||||
#define MOTION_MODE_LINEAR 1 // G1
|
||||
#define MOTION_MODE_CW_ARC 2 // G2
|
||||
#define MOTION_MODE_CCW_ARC 3 // G3
|
||||
#define MOTION_MODE_PROBE_TOWARD 4 // G38.2 NOTE: G38.2, G38.3, G38.4, G38.5 must be sequential. See report_gcode_modes().
|
||||
#define MOTION_MODE_PROBE_TOWARD_NO_ERROR 5 // G38.3
|
||||
#define MOTION_MODE_PROBE_AWAY 6 // G38.4
|
||||
#define MOTION_MODE_PROBE_AWAY_NO_ERROR 7 // G38.5
|
||||
#define MOTION_MODE_NONE 8 // G80
|
||||
#define MOTION_MODE_LINEAR 1 // G1 (Do not alter value)
|
||||
#define MOTION_MODE_CW_ARC 2 // G2 (Do not alter value)
|
||||
#define MOTION_MODE_CCW_ARC 3 // G3 (Do not alter value)
|
||||
#define MOTION_MODE_PROBE_TOWARD 140 // G38.2 (Do not alter value)
|
||||
#define MOTION_MODE_PROBE_TOWARD_NO_ERROR 141 // G38.3 (Do not alter value)
|
||||
#define MOTION_MODE_PROBE_AWAY 142 // G38.4 (Do not alter value)
|
||||
#define MOTION_MODE_PROBE_AWAY_NO_ERROR 143 // G38.5 (Do not alter value)
|
||||
#define MOTION_MODE_NONE 80 // G80 (Do not alter value)
|
||||
|
||||
// Modal Group G2: Plane select
|
||||
#define PLANE_SELECT_XY 0 // G17 (Default: Must be zero)
|
||||
#define PLANE_SELECT_ZX 1 // G18
|
||||
#define PLANE_SELECT_YZ 2 // G19
|
||||
#define PLANE_SELECT_ZX 1 // G18 (Do not alter value)
|
||||
#define PLANE_SELECT_YZ 2 // G19 (Do not alter value)
|
||||
|
||||
// Modal Group G3: Distance mode
|
||||
#define DISTANCE_MODE_ABSOLUTE 0 // G90 (Default: Must be zero)
|
||||
#define DISTANCE_MODE_INCREMENTAL 1 // G91
|
||||
#define DISTANCE_MODE_INCREMENTAL 1 // G91 (Do not alter value)
|
||||
|
||||
// Modal Group G4: Arc IJK distance mode
|
||||
#define DISTANCE_ARC_MODE_INCREMENTAL 0 // G91.1 (Default: Must be zero)
|
||||
|
||||
// Modal Group M4: Program flow
|
||||
#define PROGRAM_FLOW_RUNNING 0 // (Default: Must be zero)
|
||||
#define PROGRAM_FLOW_PAUSED 1 // M0, M1
|
||||
#define PROGRAM_FLOW_COMPLETED 2 // M2, M30
|
||||
#define PROGRAM_FLOW_PAUSED 3 // M0
|
||||
#define PROGRAM_FLOW_OPTIONAL_STOP 1 // M1 NOTE: Not supported, but valid and ignored.
|
||||
#define PROGRAM_FLOW_COMPLETED_M2 2 // M2 (Do not alter value)
|
||||
#define PROGRAM_FLOW_COMPLETED_M30 30 // M30 (Do not alter value)
|
||||
|
||||
// Modal Group G5: Feed rate mode
|
||||
#define FEED_RATE_MODE_UNITS_PER_MIN 0 // G94 (Default: Must be zero)
|
||||
#define FEED_RATE_MODE_INVERSE_TIME PL_COND_FLAG_INVERSE_TIME // G93 (NOTE: Uses planner condition bit flag)
|
||||
#define FEED_RATE_MODE_INVERSE_TIME 1 // G93 (Do not alter value)
|
||||
|
||||
// Modal Group G6: Units mode
|
||||
#define UNITS_MODE_MM 0 // G21 (Default: Must be zero)
|
||||
#define UNITS_MODE_INCHES 1 // G20
|
||||
#define UNITS_MODE_INCHES 1 // G20 (Do not alter value)
|
||||
|
||||
// Modal Group G7: Cutter radius compensation mode
|
||||
#define CUTTER_COMP_DISABLE 0 // G40 (Default: Must be zero)
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
// Grbl versioning system
|
||||
#define GRBL_VERSION "1.1d"
|
||||
#define GRBL_VERSION_BUILD "20161027"
|
||||
#define GRBL_VERSION_BUILD "20161104"
|
||||
|
||||
// Define standard libraries used by Grbl.
|
||||
#include <avr/io.h>
|
||||
|
@ -106,8 +106,11 @@ void mc_arc(float *target, plan_line_data_t *pl_data, float *position, float *of
|
||||
// Multiply inverse feed_rate to compensate for the fact that this movement is approximated
|
||||
// by a number of discrete segments. The inverse feed_rate should be correct for the sum of
|
||||
// all segments.
|
||||
if (pl_data->condition & PL_COND_FLAG_INVERSE_TIME) { pl_data->feed_rate *= segments; }
|
||||
|
||||
if (pl_data->condition & PL_COND_FLAG_INVERSE_TIME) {
|
||||
pl_data->feed_rate *= segments;
|
||||
bit_false(pl_data->condition,PL_COND_FLAG_INVERSE_TIME); // Force as feed absolute mode over arc segments.
|
||||
}
|
||||
|
||||
float theta_per_segment = angular_travel/segments;
|
||||
float linear_per_segment = (target[axis_linear] - position[axis_linear])/segments;
|
||||
|
||||
|
@ -40,7 +40,7 @@
|
||||
#define PL_COND_FLAG_RAPID_MOTION bit(0)
|
||||
#define PL_COND_FLAG_SYSTEM_MOTION bit(1) // Single motion. Circumvents planner state. Used by home/park.
|
||||
#define PL_COND_FLAG_NO_FEED_OVERRIDE bit(2) // Motion does not honor feed override.
|
||||
#define PL_COND_FLAG_INVERSE_TIME bit(3)
|
||||
#define PL_COND_FLAG_INVERSE_TIME bit(3) // Interprets feed rate value as inverse time when set.
|
||||
#define PL_COND_FLAG_SPINDLE_CW bit(4)
|
||||
#define PL_COND_FLAG_SPINDLE_CCW bit(5)
|
||||
#define PL_COND_FLAG_COOLANT_FLOOD bit(6)
|
||||
|
@ -716,7 +716,6 @@ static void protocol_exec_rt_suspend()
|
||||
bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM);
|
||||
} else {
|
||||
spindle_set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed);
|
||||
delay_sec(SAFETY_DOOR_SPINDLE_DELAY, DELAY_MODE_SYS_SUSPEND);
|
||||
}
|
||||
}
|
||||
if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_RESTORE_CYCLE) {
|
||||
|
@ -33,6 +33,8 @@
|
||||
void report_util_setting_prefix(uint8_t n) { serial_write('$'); print_uint8_base10(n); serial_write('='); }
|
||||
static void report_util_line_feed() { printPgmString(PSTR("\r\n")); }
|
||||
static void report_util_feedback_line_feed() { serial_write(']'); report_util_line_feed(); }
|
||||
static void report_util_gcode_modes_G() { printPgmString(PSTR(" G")); }
|
||||
static void report_util_gcode_modes_M() { printPgmString(PSTR(" M")); }
|
||||
// static void report_util_comment_line_feed() { serial_write(')'); report_util_line_feed(); }
|
||||
static void report_util_axis_values(float *axis_value) {
|
||||
uint8_t idx;
|
||||
@ -439,54 +441,48 @@ void report_gcode_modes()
|
||||
#else
|
||||
printPgmString(PSTR("[GC:G"));
|
||||
#endif
|
||||
switch (gc_state.modal.motion) {
|
||||
case MOTION_MODE_SEEK : serial_write('0'); break;
|
||||
case MOTION_MODE_LINEAR : serial_write('1'); break;
|
||||
case MOTION_MODE_CW_ARC : serial_write('2'); break;
|
||||
case MOTION_MODE_CCW_ARC : serial_write('3'); break;
|
||||
case MOTION_MODE_NONE : printPgmString(PSTR("80")); break;
|
||||
default:
|
||||
printPgmString(PSTR("38."));
|
||||
print_uint8_base10(gc_state.modal.motion - (MOTION_MODE_PROBE_TOWARD-2));
|
||||
if (gc_state.modal.motion >= MOTION_MODE_PROBE_TOWARD) {
|
||||
printPgmString(PSTR("38."));
|
||||
print_uint8_base10(gc_state.modal.motion - (MOTION_MODE_PROBE_TOWARD-2));
|
||||
} else {
|
||||
print_uint8_base10(gc_state.modal.motion);
|
||||
}
|
||||
|
||||
printPgmString(PSTR(" G"));
|
||||
report_util_gcode_modes_G();
|
||||
print_uint8_base10(gc_state.modal.coord_select+54);
|
||||
|
||||
printPgmString(PSTR(" G1"));
|
||||
switch (gc_state.modal.plane_select) {
|
||||
case PLANE_SELECT_XY : serial_write('7'); break;
|
||||
case PLANE_SELECT_ZX : serial_write('8'); break;
|
||||
case PLANE_SELECT_YZ : serial_write('9'); break;
|
||||
report_util_gcode_modes_G();
|
||||
print_uint8_base10(gc_state.modal.plane_select+17);
|
||||
|
||||
report_util_gcode_modes_G();
|
||||
print_uint8_base10(21-gc_state.modal.units);
|
||||
|
||||
report_util_gcode_modes_G();
|
||||
print_uint8_base10(gc_state.modal.distance+90);
|
||||
|
||||
report_util_gcode_modes_G();
|
||||
print_uint8_base10(94-gc_state.modal.feed_rate);
|
||||
|
||||
if (gc_state.modal.program_flow) {
|
||||
report_util_gcode_modes_M();
|
||||
switch (gc_state.modal.program_flow) {
|
||||
case PROGRAM_FLOW_PAUSED : serial_write('0'); break;
|
||||
// case PROGRAM_FLOW_OPTIONAL_STOP : serial_write('1'); break; // M1 is ignored and not supported.
|
||||
case PROGRAM_FLOW_COMPLETED_M2 :
|
||||
case PROGRAM_FLOW_COMPLETED_M30 :
|
||||
print_uint8_base10(gc_state.modal.program_flow);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printPgmString(PSTR(" G2"));
|
||||
if (gc_state.modal.units == UNITS_MODE_MM) { serial_write('1'); }
|
||||
else { serial_write('0'); }
|
||||
|
||||
printPgmString(PSTR(" G9"));
|
||||
if (gc_state.modal.distance == DISTANCE_MODE_ABSOLUTE) { serial_write('0'); }
|
||||
else { serial_write('1'); }
|
||||
|
||||
printPgmString(PSTR(" G9"));
|
||||
if (gc_state.modal.feed_rate == FEED_RATE_MODE_INVERSE_TIME) { serial_write('3'); }
|
||||
else { serial_write('4'); }
|
||||
|
||||
printPgmString(PSTR(" M"));
|
||||
switch (gc_state.modal.program_flow) {
|
||||
case PROGRAM_FLOW_RUNNING : serial_write('0'); break;
|
||||
case PROGRAM_FLOW_PAUSED : serial_write('1'); break;
|
||||
case PROGRAM_FLOW_COMPLETED : serial_write('2'); break;
|
||||
}
|
||||
|
||||
printPgmString(PSTR(" M"));
|
||||
report_util_gcode_modes_M();
|
||||
switch (gc_state.modal.spindle) {
|
||||
case SPINDLE_ENABLE_CW : serial_write('3'); break;
|
||||
case SPINDLE_ENABLE_CCW : serial_write('4'); break;
|
||||
case SPINDLE_DISABLE : serial_write('5'); break;
|
||||
}
|
||||
|
||||
printPgmString(PSTR(" M"));
|
||||
report_util_gcode_modes_M();
|
||||
#ifdef ENABLE_M7
|
||||
if (gc_state.modal.coolant) { // Note: Multiple coolant states may be active at the same time.
|
||||
if (gc_state.modal.coolant & PL_COND_FLAG_COOLANT_MIST) { serial_write('7'); }
|
||||
|
@ -152,7 +152,7 @@ void spindle_stop()
|
||||
}
|
||||
} else {
|
||||
// Compute intermediate PWM value with linear spindle speed model.
|
||||
// NOTE: A nonlinear model could be installed here, if required, but keep it light-weight.
|
||||
// NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight.
|
||||
sys.spindle_speed = rpm;
|
||||
pwm_value = floor( (rpm-settings.rpm_min)*pwm_gradient + (SPINDLE_PWM_MIN_VALUE+0.5) );
|
||||
}
|
||||
|
@ -58,12 +58,16 @@
|
||||
// discarded when entirely consumed and completed by the segment buffer. Also, AMASS alters this
|
||||
// data for its own use.
|
||||
typedef struct {
|
||||
uint8_t direction_bits;
|
||||
#ifdef VARIABLE_SPINDLE
|
||||
uint8_t spindle_pwm;
|
||||
#endif
|
||||
uint32_t steps[N_AXIS];
|
||||
uint32_t step_event_count;
|
||||
uint8_t direction_bits;
|
||||
#ifdef VARIABLE_SPINDLE
|
||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
||||
uint8_t is_pwm_rate_adjusted; // Tracks motions that require constant laser power/rate
|
||||
#else
|
||||
uint8_t spindle_pwm;
|
||||
#endif
|
||||
#endif
|
||||
} st_block_t;
|
||||
static st_block_t st_block_buffer[SEGMENT_BUFFER_SIZE-1];
|
||||
|
||||
@ -72,14 +76,17 @@ static st_block_t st_block_buffer[SEGMENT_BUFFER_SIZE-1];
|
||||
// planner buffer. Once "checked-out", the steps in the segments buffer cannot be modified by
|
||||
// the planner, where the remaining planner block steps still can.
|
||||
typedef struct {
|
||||
uint16_t n_step; // Number of step events to be executed for this segment
|
||||
uint8_t st_block_index; // Stepper block data index. Uses this information to execute this segment.
|
||||
uint16_t cycles_per_tick; // Step distance traveled per ISR tick, aka step rate.
|
||||
uint16_t n_step; // Number of step events to be executed for this segment
|
||||
uint16_t cycles_per_tick; // Step distance traveled per ISR tick, aka step rate.
|
||||
uint8_t st_block_index; // Stepper block data index. Uses this information to execute this segment.
|
||||
#ifdef ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
|
||||
uint8_t amass_level; // Indicates AMASS level for the ISR to execute this segment
|
||||
#else
|
||||
uint8_t prescaler; // Without AMASS, a prescaler is required to adjust for slow timing.
|
||||
#endif
|
||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
||||
uint8_t rate_adjusted_pwm;
|
||||
#endif
|
||||
} segment_t;
|
||||
static segment_t segment_buffer[SEGMENT_BUFFER_SIZE];
|
||||
|
||||
@ -153,7 +160,7 @@ typedef struct {
|
||||
float decelerate_after; // Deceleration ramp start measured from end of block (mm)
|
||||
|
||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
||||
float inv_rate; // Used by PWM laser mode
|
||||
float inv_rate; // Used by PWM laser mode to speed up segment calculations.
|
||||
#endif
|
||||
} st_prep_t;
|
||||
static st_prep_t prep;
|
||||
@ -353,12 +360,20 @@ ISR(TIMER1_COMPA_vect)
|
||||
|
||||
#ifdef VARIABLE_SPINDLE
|
||||
// Set real-time spindle output as segment is loaded, just prior to the first step.
|
||||
spindle_set_speed(st.exec_block->spindle_pwm);
|
||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
||||
spindle_set_speed(st.exec_segment->rate_adjusted_pwm);
|
||||
#else
|
||||
spindle_set_speed(st.exec_block->spindle_pwm);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
} else {
|
||||
// Segment buffer empty. Shutdown.
|
||||
st_go_idle();
|
||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
||||
// Ensure pwm is set properly upon completion of rate-controlled motion.
|
||||
if (st.exec_block->is_pwm_rate_adjusted) { spindle_set_speed(SPINDLE_PWM_OFF_VALUE); }
|
||||
#endif
|
||||
system_set_exec_state_flag(EXEC_CYCLE_STOP); // Flag main program for cycle end
|
||||
return; // Nothing to do but exit.
|
||||
}
|
||||
@ -650,8 +665,14 @@ void st_prep_buffer()
|
||||
}
|
||||
|
||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
||||
// Pre-compute inverse programmed rate to speed up PWM updating per step segment.
|
||||
prep.inv_rate = 1.0/pl_block->programmed_rate;
|
||||
// Setup laser mode variables. PWM rate adjusted motions will always complete a motion with the
|
||||
// spindle off.
|
||||
st_prep_block->is_pwm_rate_adjusted = false;
|
||||
if (settings.flags & BITFLAG_LASER_MODE) {
|
||||
// Pre-compute inverse programmed rate to speed up PWM updating per step segment.
|
||||
prep.inv_rate = 1.0/pl_block->programmed_rate;
|
||||
if (!(pl_block->condition & PL_COND_MOTION_MASK)) { st_prep_block->is_pwm_rate_adjusted = true; }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -746,7 +767,7 @@ void st_prep_buffer()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VARIABLE_SPINDLE
|
||||
#ifdef VARIABLE_SPINDLE
|
||||
bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); // Force update whenever updating block.
|
||||
#endif
|
||||
}
|
||||
@ -856,34 +877,36 @@ void st_prep_buffer()
|
||||
}
|
||||
} while (mm_remaining > prep.mm_complete); // **Complete** Exit loop. Profile complete.
|
||||
|
||||
/* -----------------------------------------------------------------------------------
|
||||
Compute spindle speed PWM output for step segment
|
||||
*/
|
||||
#ifdef VARIABLE_SPINDLE
|
||||
|
||||
/* -----------------------------------------------------------------------------------
|
||||
Compute spindle speed PWM output for step segment
|
||||
*/
|
||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
||||
if ((settings.flags & BITFLAG_LASER_MODE) || (sys.step_control & STEP_CONTROL_UPDATE_SPINDLE_PWM)) {
|
||||
if (st_prep_block->is_pwm_rate_adjusted || (sys.step_control & STEP_CONTROL_UPDATE_SPINDLE_PWM)) {
|
||||
if (pl_block->condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)) {
|
||||
float rpm = pl_block->spindle_speed;
|
||||
// NOTE: Feed and rapid overrides are independent of PWM value and do not alter laser power/rate.
|
||||
if (st_prep_block->is_pwm_rate_adjusted) { rpm *= (prep.current_speed * prep.inv_rate); }
|
||||
// If current_speed is zero, then may need to be rpm_min*(100/MAX_SPINDLE_SPEED_OVERRIDE)
|
||||
// but this would be instantaneous only and during a motion. May not matter at all.
|
||||
prep_segment->rate_adjusted_pwm = spindle_compute_pwm_value(rpm);
|
||||
} else {
|
||||
sys.spindle_speed = 0.0;
|
||||
prep_segment->rate_adjusted_pwm = SPINDLE_PWM_OFF_VALUE;
|
||||
}
|
||||
bit_false(sys.step_control,STEP_CONTROL_UPDATE_SPINDLE_PWM);
|
||||
}
|
||||
#else
|
||||
if (sys.step_control & STEP_CONTROL_UPDATE_SPINDLE_PWM) {
|
||||
if (pl_block->condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)) {
|
||||
st_prep_block->spindle_pwm = spindle_compute_pwm_value(pl_block->spindle_speed);
|
||||
} else {
|
||||
sys.spindle_speed = 0.0;
|
||||
st_prep_block->spindle_pwm = SPINDLE_PWM_OFF_VALUE;
|
||||
}
|
||||
bit_false(sys.step_control,STEP_CONTROL_UPDATE_SPINDLE_PWM);
|
||||
}
|
||||
#endif
|
||||
if (pl_block->condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)) {
|
||||
float rpm = pl_block->spindle_speed;
|
||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
||||
// NOTE: Feed and rapid overrides are independent of PWM value and do not alter laser power/rate.
|
||||
if (settings.flags & BITFLAG_LASER_MODE) {
|
||||
// If current_speed is zero, then may need to be rpm_min*(100/MAX_SPINDLE_SPEED_OVERRIDE)
|
||||
// but this would be instantaneous only and during a motion. May not matter at all.
|
||||
rpm *= (prep.current_speed * prep.inv_rate);
|
||||
}
|
||||
#endif
|
||||
st_prep_block->spindle_pwm = spindle_compute_pwm_value(rpm);
|
||||
} else {
|
||||
sys.spindle_speed = 0.0;
|
||||
st_prep_block->spindle_pwm = SPINDLE_PWM_OFF_VALUE;
|
||||
}
|
||||
bit_false(sys.step_control,STEP_CONTROL_UPDATE_SPINDLE_PWM);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* -----------------------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user