Skip to content

Commit

Permalink
Improved Threading synchronization, and minor changes
Browse files Browse the repository at this point in the history
Improved Threading synchronization
Added a step enable delay to support servo drivers in step/dir mode (like Lichuan A4 series)
Some minor changes

Update setting_codes_en_US.csv

Update config.h
  • Loading branch information
HuubBuis committed Oct 2, 2021
1 parent d10a1dd commit 5fa1321
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 37 deletions.
2 changes: 1 addition & 1 deletion doc/csv/setting_codes_en_US.csv
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"$-Code"," Setting"," Units"," Setting Description"
"0","Step pulse time","microseconds","Sets time length per step. Minimum 3usec."
"1","Step idle delay","milliseconds","Sets a short hold delay when stopping to let dynamics settle before disabling steppers. Value 255 keeps motors enabled with no delay."
"1","Step enable & idle delay","milliseconds","Sets a short hold delay when starting & stopping to let dynamics settle after enabling but before stepping or disabling steppers. Value 255 keeps motors enabled with no delay."
"2","Step pulse invert","mask","Inverts the step signal. Set axis bit to invert (00000ZYX)."
"3","Step direction invert","mask","Inverts the direction signal. Set axis bit to invert (00000ZYX)."
"4","Invert step enable pin","boolean","Inverts the stepper driver enable pin signal."
Expand Down
7 changes: 7 additions & 0 deletions grbl/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,13 @@
// values for certain setups have ranged from 5 to 20us.
// #define STEP_PULSE_DELAY 10 // Step pulse delay in microseconds. Default disabled.

// Creates a delay between the first step pulse after enabling and after the last step pulse before disabling.
// Lichuan servo's running in step-dir mode need a 100 ms delay between the motor enable signal and the first step pulse
// They also needs some time after the last step pulse before they can be disabled without losing steps
// The delay is executed in the st_wake_up() and st_go_idle() routine
// The delay time is the same as the stepper_idle_lock_time ($1)
#define STEP_ENABLE_DELAY // Step enable and disable delay in milliseconds. Used for running servo's in step-dir mode (Lichuan) // default enabled

// The number of linear motions in the planner buffer to be planned at any give time. The vast
// majority of RAM that Grbl uses is based on this buffer size. Only increase if there is extra
// available RAM, like when re-compiling for a Mega or Sanguino. Or decrease if the Arduino
Expand Down
4 changes: 2 additions & 2 deletions grbl/grbl.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
#define grbl_h

// Grbl versioning system
#define GRBL_VERSION "1.1g2"
#define GRBL_VERSION_BUILD "20200510.Mega"
#define GRBL_VERSION "1.1g3"
#define GRBL_VERSION_BUILD "20211002.Mega"

// Define standard libraries used by Grbl.
#include <util/atomic.h>
Expand Down
4 changes: 2 additions & 2 deletions grbl/planner.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,9 +265,9 @@ float plan_compute_profile_nominal_speed(plan_block_t *block)
system_clear_threading_exec_flag(EXEC_PLANNER_SYNC_PULSE); // clear the bit to avoid processing again.
threading_millimeters_target-=threading_mm_per_synchronization_pulse; // calculate the new target
synchronization_millimeters_error=threading_millimeters_target-block->millimeters; // calculate the position error. Note that block->millimeters counts down This has to be compensated at the next spindle pulse
block->programmed_rate=(threading_mm_per_synchronization_pulse-synchronization_millimeters_error) / ((float) threading_index_timer_tics_passed / threading_feed_rate_calculation_factor); //calculate the new feed rate to reduce the error. threading_feed_rate_calculation_factor= ((float) 15000000 * (float) settings.sync_pulses_per_revolution));
block->programmed_rate=(threading_mm_per_index_pulse-synchronization_millimeters_error) / (((float) threading_sync_timer_tics_passed ) / threading_feed_rate_calculation_factor); //calculate the new feed rate to reduce the error.
if (block->programmed_rate>block->rapid_rate) // limit speed to max-rate set for this block
block->programmed_rate=block->rapid_rate; //block->rapid_rate
block->programmed_rate=block->rapid_rate; // don't run faster than block->rapid_rate
}
} else {
if (!(block->condition & PL_COND_FLAG_NO_FEED_OVERRIDE)) { nominal_speed *= (0.01*sys.f_override); }
Expand Down
4 changes: 2 additions & 2 deletions grbl/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,10 @@ void protocol_exec_rt_system()
process_spindle_index_pulse(); // Process the pulse so the RPM will be updated in the real time status report
if (spindle_synchronization_active()) { // if spindle synchronization is active
if bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_SYNC_STATE){ // if setting report mask is set for reporting the synchronization status in the real time status report
system_set_threading_exec_flag((EXEC_SYNCHRONIZATION_STATE_REPORT | EXEC_SYNCHRONIZATION_STATE_REPORT_FINAL)); // set the reporting flags to report the synchronization status now and once when finished
system_set_threading_exec_flag(EXEC_SYNCHRONIZATION_STATE_REPORT); // set the reporting flags to report the synchronization status now and once when finished
}
if bit_istrue(settings.status_report_mask,BITFLAG_FEED_BACK_SYNC_STATUS){ // if setting report mask is set for synchronization error feedback
system_set_threading_exec_flag((EXEC_SYNCHRONIZATION_STATE_FEEDBACK_ERROR)); // set the reporting flags to feedback the synchronization error
system_set_threading_exec_flag((EXEC_SYNCHRONIZATION_STATE_FEEDBACK_ERROR)); // set the reporting flags to feedback the synchronization error
}
}
}
Expand Down
45 changes: 21 additions & 24 deletions grbl/report.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static void report_util_setting_string(uint8_t n) {
serial_write('(');
switch(n) {
case 0: printPgmString(PSTR("stp pulse")); break;
case 1: printPgmString(PSTR("idl delay")); break;
case 1: printPgmString(PSTR("idl delay")); break;
case 2: printPgmString(PSTR("stp inv")); break;
case 3: printPgmString(PSTR("dir inv")); break;
case 4: printPgmString(PSTR("stp en inv")); break;
Expand Down Expand Up @@ -101,8 +101,8 @@ static void report_util_uint16_setting(uint16_t n, int val) {
print_uint32_base10((uint32_t)val);
report_util_line_feed(); // report_util_setting_string(n);
}
static void report_util_float_setting(uint8_t n, float val, uint8_t n_decimal) {
report_util_setting_prefix(n);
static void report_util_float_setting(uint8_t n, float val, uint8_t n_decimal) {
report_util_setting_prefix(n);
printFloat(val,n_decimal);
report_util_line_feed(); // report_util_setting_string(n);
}
Expand Down Expand Up @@ -196,7 +196,7 @@ void report_init_message()

// Grbl help message
void report_grbl_help() {
printPgmString(PSTR("[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H ~ ! ? ctrl-x]\r\n"));
printPgmString(PSTR("[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H ~ ! ? ctrl-x]\r\n"));
}

// Grbl global settings print out.
Expand Down Expand Up @@ -321,8 +321,8 @@ void report_gcode_modes()
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 :
case PROGRAM_FLOW_COMPLETED_M2 :
case PROGRAM_FLOW_COMPLETED_M30 :
print_uint8_base10(gc_state.modal.program_flow);
break;
}
Expand All @@ -342,12 +342,12 @@ void report_gcode_modes()
} else { serial_write('9'); }

#ifdef ENABLE_PARKING_OVERRIDE_CONTROL
if (sys.override_ctrl == OVERRIDE_PARKING_MOTION) {
if (sys.override_ctrl == OVERRIDE_PARKING_MOTION) {
report_util_gcode_modes_M();
print_uint8_base10(56);
}
#endif

printPgmString(PSTR(" T"));
print_uint8_base10(gc_state.tool);

Expand Down Expand Up @@ -389,7 +389,7 @@ void report_build_info(char *line)
serial_write('N'); // Line number reporting standard.
serial_write('M'); // M7 mist coolant standard.
serial_write('+'); // Safety door support standard.
serial_write('X'); // Extended lathe command set
serial_write('X'); // Extended lathe command set
serial_write('1'); // Extended lathe command set Version 1: G33 spindle synchronization support for threading.
#ifdef COREXY
serial_write('C');
Expand Down Expand Up @@ -618,24 +618,21 @@ void report_realtime_status()
}
if (cl_state & COOLANT_STATE_FLOOD) { serial_write('F'); }
if (cl_state & COOLANT_STATE_MIST) { serial_write('M'); }
}
}
}
#endif

// report the synchronization state (G33)
//if (spindle_synchronization_active()) {
if (bit_istrue(threading_exec_flags,(EXEC_SYNCHRONIZATION_STATE_REPORT))) { // report if a report is flagged
printPgmString(PSTR("|Se:"));
printFloat_CoordValue(synchronization_millimeters_error); // print the synchronization error in the unit set
bit_false(threading_exec_flags,EXEC_SYNCHRONIZATION_STATE_REPORT); // clear the flag to avoid reporting the same value again
}
//} else if (bit_istrue(threading_exec_flags,EXEC_SYNCHRONIZATION_STATE_REPORT_FINAL)) { // if a final report is flagged and spindle synchronization is inactive
else {
printPgmString(PSTR("|Se:")); // Report report a 0 value after G33 , looks better in a GUI
printFloat(0,2);
bit_false(threading_exec_flags,EXEC_SYNCHRONIZATION_STATE_REPORT_FINAL); // clear the flag to avoid reporting the same value again

// report the synchronization state (G33)
if (bit_istrue(threading_exec_flags,(EXEC_SYNCHRONIZATION_STATE_REPORT))) { // report if a report is flagged
printPgmString(PSTR("|Se:"));
printFloat_CoordValue(synchronization_millimeters_error); // print the synchronization error in the unit set
bit_false(threading_exec_flags,EXEC_SYNCHRONIZATION_STATE_REPORT); // clear the flag to avoid reporting the same value again
}
else {
printPgmString(PSTR("|Se:")); // report a 0 value after G33 , looks better in a GUI
printFloat(0,2);
}

serial_write('>');
report_util_line_feed();
}
Expand Down
4 changes: 4 additions & 0 deletions grbl/stepper.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,10 @@ void st_wake_up()
st.step_outbits = step_port_invert_mask;
#endif // Ramps Board

#ifdef STEP_ENABLE_DELAY
delay_ms(settings.stepper_idle_lock_time); //Wait a bit to give the driver time to wake up. Is used for servo drivers in step-dir mode like Lichuan
#endif

// Initialize step pulse timing from settings. Here to ensure updating after re-writing.
#ifdef STEP_PULSE_DELAY
// Set total step pulse time after direction pin set. Ad hoc computation from oscilloscope.
Expand Down
10 changes: 6 additions & 4 deletions grbl/threading.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ volatile uint32_t threading_index_Last_timer_tics; // Time at the last index
volatile uint32_t threading_index_timer_tics_passed=0; // Time passed at the last index pulse
volatile uint32_t threading_index_spindle_speed; // The measured spindle speed used for G33 initial speed and reporting the real spindle speed
float threading_mm_per_synchronization_pulse; // The factor to calculate the feed rate from the spindle speed
float threading_mm_per_index_pulse; // The factor to calculate the feed rate from the spindle speed
volatile float threading_millimeters_target; // The threading feed target as reported by the planner
volatile float synchronization_millimeters_error; // The synchronization feed error calculated at every synchronization pulse. It can be reported to check the threading accuracy
float threading_feed_rate_calculation_factor; // factor is used in plan_compute_profile_nominal_speed(), depends on the number of synchronization pulses and is calculated on startup for performance reasons.
Expand All @@ -38,9 +39,10 @@ float threading_feed_rate_calculation_factor; // factor is used in plan_comp
void threading_init(float K_value)
{
threading_mm_per_synchronization_pulse= K_value / (float) settings.sync_pulses_per_revolution; // Calculate the global mm feed per synchronization pulse value.
threading_feed_rate_calculation_factor = ((float) 15000000 * (float) settings.sync_pulses_per_revolution); //calculate the factor to speedup the planner during threading
timekeeper_reset(); //reset the timekeeper to avoid calculation errors when timer overflow occurs (to be sure)
threading_reset(); //Sets the target position to zero and calculates the next target position
threading_mm_per_index_pulse= K_value; // Calculate the global mm feed per synchronization pulse value.
threading_feed_rate_calculation_factor = ((float) 15000000 / (float) settings.sync_pulses_per_revolution); // Calculate the factor to speedup the planner during threading
timekeeper_reset(); // Reset the timekeeper to avoid calculation errors when timer overflow occurs (to be sure)
threading_reset(); // Sets the target position to zero and calculates the next target position
}
// Reset variables to start the threading
void threading_reset()
Expand Down Expand Up @@ -75,7 +77,7 @@ void process_spindle_index_pulse()
void process_spindle_synchronization_pulse()
{
threading_sync_timer_tics_passed=get_timer_ticks()-threading_sync_Last_timer_tics; // Calculate the time between synchronization pulses
threading_sync_timer_tics_passed+=threading_sync_timer_tics_passed; // adjust for calculating the next time
threading_sync_Last_timer_tics+=threading_sync_timer_tics_passed; // adjust for calculating the next time
threading_sync_pulse_count++; // Increase the synchronization pulse count
}

Expand Down
5 changes: 3 additions & 2 deletions grbl/threading.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ extern volatile uint32_t threading_index_spindle_speed; // The spindle speed
extern volatile float threading_millimeters_target; // The threading target feed to go as reported by the planner
extern volatile float synchronization_millimeters_error; // The threading feed error calculated at every synchronization pulse
extern float threading_mm_per_synchronization_pulse; // Z-axis motion at each sync pulse. Is not declared as volatile because it is not updated by an ISR routine.
extern float threading_feed_rate_calculation_factor; // factor used in plan_compute_profile_nominal_speed() and is calculated on startup for performance reasons.
extern float threading_mm_per_index_pulse; // Z-axis motion at each index pulse. Is not declared as volatile because it is not updated by an ISR routine.
extern float threading_feed_rate_calculation_factor; // Factor is used in plan_compute_profile_nominal_speed() and is calculated at threading start for performance reasons.

void threading_init(float K_value); //initializes the G33 threading pass using the K value set in the gcode
void threading_init(float K_value); // Initializes the G33 threading pass using the K value set in the gcode
uint32_t timer_tics_passed_since_last_index_pulse();
void process_spindle_index_pulse();
void process_spindle_synchronization_pulse();
Expand Down

0 comments on commit 5fa1321

Please sign in to comment.