diff --git a/doc/log/commit_log_v1.1.txt b/doc/log/commit_log_v1.1.txt index 9ce813b..fed54e7 100644 --- a/doc/log/commit_log_v1.1.txt +++ b/doc/log/commit_log_v1.1.txt @@ -1,3 +1,19 @@ +---------------- +Date: 2016-10-26 +Author: Sonny Jeon +Subject: Add high-frequency spindle output option. Minor parking motion re-factoring. + +- Some laser controllers were reported to need a very high PWM +frequency. Added a line to enable this in cpu_map.h, if needed. + +- Cleaned up some of the parking code. Mostly just editing the comments. + +- Moved the accessory state resetting after the initial parking +retract. Should ensure the accessory state is properly handled upon an +aborted parking restore. Not certain if this was a problem before +though. Just to be sure. + + ---------------- Date: 2016-10-25 Author: chamnit diff --git a/grbl/config.h b/grbl/config.h index c5ea217..f65dfd8 100644 --- a/grbl/config.h +++ b/grbl/config.h @@ -569,7 +569,12 @@ #define PARKING_PULLOUT_RATE 100.0 // Pull-out/plunge slow feed rate in mm/min. #define PARKING_PULLOUT_INCREMENT 5.0 // Spindle pull-out and plunge distance in mm. Incremental distance. // Must be positive value or equal to zero. - + +// Experimental feature that adjusts laser power (PWM output) based on current running speed of the +// machine. When laser mode is enabled, Grbl will turn off the spindle PWM pin whenever it is not +// moving, which may be confusing to some users to why their laser is not on. This behavior may change +// in future iterations of this feature, where it will turn on to the minimum rpm value when active. +// #define LASER_CONSTANT_POWER_PER_RATE /* --------------------------------------------------------------------------------------- OEM Single File Configuration Option diff --git a/grbl/grbl.h b/grbl/grbl.h index 2753b7f..4f91c6c 100644 --- a/grbl/grbl.h +++ b/grbl/grbl.h @@ -23,7 +23,7 @@ // Grbl versioning system #define GRBL_VERSION "1.1d" -#define GRBL_VERSION_BUILD "20161026" +#define GRBL_VERSION_BUILD "20161027" // Define standard libraries used by Grbl. #include diff --git a/grbl/planner.c b/grbl/planner.c index 7ca1d80..0343cd7 100644 --- a/grbl/planner.c +++ b/grbl/planner.c @@ -258,12 +258,9 @@ uint8_t plan_check_full_buffer() // NOTE: All system motion commands, such as homing/parking, are not subject to overrides. float plan_compute_profile_nominal_speed(plan_block_t *block) { - float nominal_speed; - if (block->condition & PL_COND_FLAG_RAPID_MOTION) { - nominal_speed = block->rapid_rate; - nominal_speed *= (0.01*sys.r_override); - } else { - nominal_speed = block->programmed_rate; + float nominal_speed = block->programmed_rate; + if (block->condition & PL_COND_FLAG_RAPID_MOTION) { nominal_speed *= (0.01*sys.r_override); } + else { if (!(block->condition & PL_COND_FLAG_NO_FEED_OVERRIDE)) { nominal_speed *= (0.01*sys.f_override); } if (nominal_speed > block->rapid_rate) { nominal_speed = block->rapid_rate; } } @@ -385,8 +382,11 @@ uint8_t plan_buffer_line(float *target, plan_line_data_t *pl_data) block->rapid_rate = limit_value_by_axis_maximum(settings.max_rate, unit_vec); // Store programmed rate. - block->programmed_rate = pl_data->feed_rate; - if (block->condition & PL_COND_FLAG_INVERSE_TIME) { block->programmed_rate *= block->millimeters; } + if (block->condition & PL_COND_FLAG_RAPID_MOTION) { block->programmed_rate = block->rapid_rate; } + else { + block->programmed_rate = pl_data->feed_rate; + if (block->condition & PL_COND_FLAG_INVERSE_TIME) { block->programmed_rate *= block->millimeters; } + } // TODO: Need to check this method handling zero junction speeds when starting from rest. if ((block_buffer_head == block_buffer_tail) || (block->condition & PL_COND_FLAG_SYSTEM_MOTION)) { diff --git a/grbl/planner.h b/grbl/planner.h index f272bc8..0bac916 100644 --- a/grbl/planner.h +++ b/grbl/planner.h @@ -45,6 +45,7 @@ #define PL_COND_FLAG_SPINDLE_CCW bit(5) #define PL_COND_FLAG_COOLANT_FLOOD bit(6) #define PL_COND_FLAG_COOLANT_MIST bit(7) +#define PL_COND_MOTION_MASK (PL_COND_FLAG_RAPID_MOTION|PL_COND_FLAG_SYSTEM_MOTION|PL_COND_FLAG_NO_FEED_OVERRIDE) #define PL_COND_ACCESSORY_MASK (PL_COND_FLAG_SPINDLE_CW|PL_COND_FLAG_SPINDLE_CCW|PL_COND_FLAG_COOLANT_FLOOD|PL_COND_FLAG_COOLANT_MIST) diff --git a/grbl/protocol.c b/grbl/protocol.c index 938e79a..3f13c15 100644 --- a/grbl/protocol.c +++ b/grbl/protocol.c @@ -698,32 +698,39 @@ static void protocol_exec_rt_suspend() // Feed hold manager. Controls spindle stop override states. // NOTE: Hold ensured as completed by condition check at the beginning of suspend routine. - if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_INITIATE) { // Handles beginning of spindle stop - - if (gc_state.modal.spindle != SPINDLE_DISABLE) { - spindle_set_state(SPINDLE_DISABLE,0.0); // De-energize - sys.spindle_stop_ovr = SPINDLE_STOP_OVR_ENABLED; // Set stop override state to enabled, if de-energized. - } else { + if (sys.spindle_stop_ovr) { + // Handles beginning of spindle stop + if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_INITIATE) { + if (gc_state.modal.spindle != SPINDLE_DISABLE) { + spindle_set_state(SPINDLE_DISABLE,0.0); // De-energize + sys.spindle_stop_ovr = SPINDLE_STOP_OVR_ENABLED; // Set stop override state to enabled, if de-energized. + } else { + sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state + } + // Handles restoring of spindle state + } else if (sys.spindle_stop_ovr & (SPINDLE_STOP_OVR_RESTORE | SPINDLE_STOP_OVR_RESTORE_CYCLE)) { + if (gc_state.modal.spindle != SPINDLE_DISABLE) { + report_feedback_message(MESSAGE_SPINDLE_RESTORE); + if (bit_istrue(settings.flags,BITFLAG_LASER_MODE)) { + // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. + 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) { + system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program. + } sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state } - - } else if (sys.spindle_stop_ovr & (SPINDLE_STOP_OVR_RESTORE | SPINDLE_STOP_OVR_RESTORE_CYCLE)) { // Handles restoring of spindle state - - if (gc_state.modal.spindle != SPINDLE_DISABLE) { - report_feedback_message(MESSAGE_SPINDLE_RESTORE); - if (bit_istrue(settings.flags,BITFLAG_LASER_MODE)) { - // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. - 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); - } + } else { + // Handles spindle state during hold. NOTE: Spindle speed overrides may be altered during hold state. + // NOTE: STEP_CONTROL_UPDATE_SPINDLE_PWM is automatically reset upon resume in step generator. + if (bit_istrue(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM)) { + spindle_set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed); + bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_PWM); } - if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_RESTORE_CYCLE) { - system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program. - } - sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state - } } diff --git a/grbl/spindle_control.c b/grbl/spindle_control.c index b799830..b24b11b 100644 --- a/grbl/spindle_control.c +++ b/grbl/spindle_control.c @@ -154,7 +154,7 @@ void spindle_stop() // Compute intermediate PWM value with linear spindle speed model. // NOTE: A nonlinear model could be installed here, if required, but keep it light-weight. sys.spindle_speed = rpm; - pwm_value = floor( (rpm-settings.rpm_min)*pwm_gradient + (SPINDLE_PWM_MIN_VALUE+0.5)); + pwm_value = floor( (rpm-settings.rpm_min)*pwm_gradient + (SPINDLE_PWM_MIN_VALUE+0.5) ); } return(pwm_value); } @@ -189,6 +189,10 @@ void spindle_stop() #endif #ifdef VARIABLE_SPINDLE + #ifdef LASER_CONSTANT_POWER_PER_RATE + // NOTE: Assumes all calls to this function is when Grbl is not moving or must remain off. + if (settings.flags & BITFLAG_LASER_MODE) { rpm = 0.0; } // TODO: May need to be rpm_min*(100/MAX_SPINDLE_SPEED_OVERRIDE); + #endif spindle_set_speed(spindle_compute_pwm_value(rpm)); #else // NOTE: Without variable spindle, the enable bit should just turn on or off, regardless diff --git a/grbl/stepper.c b/grbl/stepper.c index c59951c..57cc89d 100644 --- a/grbl/stepper.c +++ b/grbl/stepper.c @@ -151,6 +151,10 @@ typedef struct { float exit_speed; // Exit speed of executing block (mm/min) float accelerate_until; // Acceleration ramp end measured from end of block (mm) 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 + #endif } st_prep_t; static st_prep_t prep; @@ -644,6 +648,11 @@ void st_prep_buffer() } else { prep.current_speed = sqrt(pl_block->entry_speed_sqr); } + + #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; + #endif } /* --------------------------------------------------------------------------------- @@ -742,19 +751,6 @@ void st_prep_buffer() #endif } - #ifdef VARIABLE_SPINDLE - if (sys.step_control & STEP_CONTROL_UPDATE_SPINDLE_PWM) { - // Configure correct spindle PWM state for block. Updates with planner changes and spindle speed overrides. - 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 - // Initialize new segment segment_t *prep_segment = &segment_buffer[segment_buffer_head]; @@ -860,7 +856,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 + #ifdef LASER_CONSTANT_POWER_PER_RATE + if ((settings.flags & BITFLAG_LASER_MODE) || (sys.step_control & STEP_CONTROL_UPDATE_SPINDLE_PWM)) { + #else + if (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 + /* ----------------------------------------------------------------------------------- Compute segment step rate, steps to execute, and apply necessary rate corrections. NOTE: Steps are computed by direct scalar conversion of the millimeter distance @@ -976,8 +1001,8 @@ void st_prep_buffer() // divided by the ACCELERATION TICKS PER SECOND in seconds. float st_get_realtime_rate() { - if (sys.state & (STATE_CYCLE | STATE_HOMING | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)){ - return prep.current_speed; - } + if (sys.state & (STATE_CYCLE | STATE_HOMING | STATE_HOLD | STATE_JOG | STATE_SAFETY_DOOR)){ + return prep.current_speed; + } return 0.0f; }