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:
Sonny Jeon
2016-11-04 09:15:34 -06:00
parent e8b717604b
commit 6e3fb6bd13
12 changed files with 185 additions and 161 deletions

View File

@ -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
/* -----------------------------------------------------------------------------------