diff --git a/gcode.c b/gcode.c index 235371c..8e09c53 100755 --- a/gcode.c +++ b/gcode.c @@ -72,12 +72,6 @@ void gc_set_current_position(int32_t x, int32_t y, int32_t z) gc.position[Z_AXIS] = z/settings.steps_per_mm[Z_AXIS]; } -// Clears and zeros g-code parser position. Called by homing routine. -void gc_clear_position() -{ - clear_vector(gc.position); -} - static float to_millimeters(float value) { return(gc.inches_mode ? (value * MM_PER_INCH) : value); diff --git a/gcode.h b/gcode.h index c780c41..6369dfe 100755 --- a/gcode.h +++ b/gcode.h @@ -106,7 +106,4 @@ uint8_t gc_execute_line(char *line); // Set g-code parser position. Input in steps. void gc_set_current_position(int32_t x, int32_t y, int32_t z); -// Clear g-code parser position -void gc_clear_position(); - #endif diff --git a/main.c b/main.c index 32bda81..43abb64 100755 --- a/main.c +++ b/main.c @@ -76,12 +76,14 @@ int main(void) limits_init(); st_reset(); // Clear stepper subsystem variables. - // Set cleared gcode and planner positions to current system position, which is only - // cleared upon startup, not a reset/abort. If Grbl does not know or ensure its position, - // a feedback message will be sent back to the user to let them know. - gc_set_current_position(sys.position[X_AXIS],sys.position[Y_AXIS],sys.position[Z_AXIS]); - plan_set_current_position(sys.position[X_AXIS],sys.position[Y_AXIS],sys.position[Z_AXIS]); - + // Sync cleared gcode and planner positions to current system position, which is only + // cleared upon startup, not a reset/abort. If Grbl does not know or can ensure its + // position, a feedback message will be sent back to the user to let them know. Also, + // if position is lost and homing is enabled, the axes motions will be locked, and + // user must either perform the homing cycle '$H' or purge the system locks '$P' to + // resume. + sys_sync_current_position(); + // Reset system variables sys.abort = false; sys.execute = 0; @@ -91,7 +93,7 @@ int main(void) sys.state = STATE_IDLE; } if (bit_istrue(settings.flags,BITFLAG_AUTO_START)) { sys.auto_start = true; } - + // Execute user startup script protocol_execute_startup(); } diff --git a/motion_control.c b/motion_control.c index 7f006ab..a7d4295 100755 --- a/motion_control.c +++ b/motion_control.c @@ -220,10 +220,10 @@ void mc_go_home() } // The machine should now be homed and machine zero has been located. Upon completion, - // reset planner and system internal position vectors, but not gcode parser position yet. - plan_clear_position(); - clear_vector_float(sys.position); - + // reset system position and sync internal position vectors. + clear_vector_float(sys.position); // Set machine zero + sys_sync_current_position(); + // Pull-off all axes from limit switches before continuing motion. This provides some initial // clearance off the switches and should also help prevent them from falsely tripping when // hard limits are enabled. @@ -237,8 +237,8 @@ void mc_go_home() st_cycle_start(); // Move it. Nothing should be in the buffer except this motion. plan_synchronize(); // Make sure the motion completes. - // Explicitly update the gcode parser position since it was circumvented by the pull-off maneuver. - gc_set_current_position(sys.position[X_AXIS],sys.position[Y_AXIS],sys.position[Z_AXIS]); + // The gcode parser position was circumvented by the pull-off maneuver, so sync position vectors. + sys_sync_current_position(); // If hard limits feature enabled, re-enable hard limits interrupt after homing cycle. if (bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)) { PCICR |= (1 << LIMIT_INT); } diff --git a/nuts_bolts.c b/nuts_bolts.c index dbd1788..921ac9a 100755 --- a/nuts_bolts.c +++ b/nuts_bolts.c @@ -19,8 +19,10 @@ along with Grbl. If not, see . */ -#include "nuts_bolts.h" #include +#include "nuts_bolts.h" +#include "gcode.h" +#include "planner.h" #define MAX_INT_DIGITS 8 // Maximum number of digits in int32 (and float) extern float __floatunsisf (unsigned long); @@ -137,3 +139,10 @@ void delay_us(uint32_t us) } } } + + +void sys_sync_current_position() +{ + plan_set_current_position(sys.position[X_AXIS],sys.position[Y_AXIS],sys.position[Z_AXIS]); + gc_set_current_position(sys.position[X_AXIS],sys.position[Y_AXIS],sys.position[Z_AXIS]); +} diff --git a/nuts_bolts.h b/nuts_bolts.h index b894441..7438660 100755 --- a/nuts_bolts.h +++ b/nuts_bolts.h @@ -103,4 +103,7 @@ void delay_ms(uint16_t ms); // Delays variable-defined microseconds. Compiler compatibility fix for _delay_us(). void delay_us(uint32_t us); +// Syncs Grbl's gcode and planner position variables with the system position. +void sys_sync_current_position(); + #endif diff --git a/planner.c b/planner.c index fac89bf..92f2ac1 100755 --- a/planner.c +++ b/planner.c @@ -482,12 +482,6 @@ void plan_set_current_position(int32_t x, int32_t y, int32_t z) pl.position[Z_AXIS] = z; } -// Clear planner position vector. Called by homing routine. -void plan_clear_position() -{ - clear_vector(pl.position); -} - // Re-initialize buffer plan with a partially completed block, assumed to exist at the buffer tail. // Called after a steppers have come to a complete stop for a feed hold and the cycle is stopped. void plan_cycle_reinitialize(int32_t step_events_remaining) diff --git a/planner.h b/planner.h index a326084..37bd188 100755 --- a/planner.h +++ b/planner.h @@ -70,9 +70,6 @@ block_t *plan_get_current_block(); // Reset the planner position vector (in steps) void plan_set_current_position(int32_t x, int32_t y, int32_t z); -// Clear the planner position vector -void plan_clear_position(); - // Reinitialize plan with a partially completed block void plan_cycle_reinitialize(int32_t step_events_remaining); diff --git a/protocol.c b/protocol.c index 5c21d73..ee0926c 100755 --- a/protocol.c +++ b/protocol.c @@ -183,25 +183,33 @@ uint8_t protocol_execute_line(char *line) // block buffer without having the planner plan them. It would need to manage de/ac-celerations // on its own carefully. This approach could be effective and possibly size/memory efficient. case 'S' : // Switch modes + if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } // Set helper_var as switch bitmask or clearing flag switch (line[++char_counter]) { - case 0 : helper_var = 0; break; - case '0' : helper_var = BITFLAG_CHECK_GCODE; break; + case '0' : + helper_var = BITFLAG_CHECK_GCODE; + // Sync position vectors if check mode is being disabled. May be different after checking. + if (bit_istrue(gc.switches,helper_var)) { sys_sync_current_position(); } + break; case '1' : helper_var = BITFLAG_DRY_RUN; break; case '2' : helper_var = BITFLAG_BLOCK_DELETE; break; case '3' : helper_var = BITFLAG_SINGLE_BLOCK; break; case '4' : helper_var = BITFLAG_OPT_STOP; break; default : return(STATUS_INVALID_STATEMENT); } - if (helper_var) { - if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } - gc.switches ^= helper_var; - if (bit_istrue(gc.switches,helper_var)) { report_feedback_message(MESSAGE_SWITCH_ON); } - else { report_feedback_message(MESSAGE_SWITCH_OFF); } - } else { - gc.switches = helper_var; // Clear all switches - report_feedback_message(MESSAGE_SWITCHES_CLEARED); + gc.switches ^= helper_var; + if (bit_istrue(gc.switches,helper_var)) { report_feedback_message(MESSAGE_SWITCH_ON); } + else { report_feedback_message(MESSAGE_SWITCH_OFF); } + break; + case 'P' : // Purge system + if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } + if (sys.state == STATE_CYCLE) { return(STATUS_PURGE_CYCLE); } // Also prevents position error + plan_reset_buffer(); + if (sys.state == STATE_LOST) { + report_feedback_message(MESSAGE_PURGE_AXES_LOCK); + sys_sync_current_position(); // Any motion commands during a lock can unsync position vectors. } + sys.state = STATE_IDLE; break; case 'N' : // Startup lines. if ( line[++char_counter] == 0 ) { // Print startup lines diff --git a/readme.textile b/readme.textile index 2acf3e8..e647f92 100755 --- a/readme.textile +++ b/readme.textile @@ -21,13 +21,13 @@ Grbl includes full acceleration management with look ahead. That means the contr - Re-factored g-code parser with robust error-checking. - 6 work coordinate systems (G54-G59), offsets(G92), and machine coordinate system support. Work coordinate systems are stored in EEPROM and persistent. - G10 L2 and L20 work coordinate settings support. L2 sets one or more axes values. L20 sets the current machine position to the specified work origin. - - Program stop(M0,M1,M2,M30) initial support. + - G28.1 and G30.1 set home position support. These set the internal EEPROM parameter values to the current machine position. (G28 and G30 no longer perform homing cycle, '$H' does. They move to these stored positions.) + - Program stop(M0,M1,M2,M30) support. - Coolant control(M7*,M8,M9) support. (M7 is a compile-time option). - System reset re-initializes grbl without resetting the Arduino and retains machine/home position and work coordinates. - Settings overhauled and dozens of new settings and internal commands are now available, when most were compile-time only. - New startup line setting. Allows users to store a custom g-code block into Grbl's startup routine. Executes immediately upon startup or reset. May be used to set g-code defaults like G20. - Misc bug fixes and removed deprecated acceleration enabled code. - - Planned features: Axis acceleration and max speed individual settings, full-featured status reporting. - Advanced compile-time options: XON/XOFF flow control (limited support), direction and step pulse time delay, and up to 5 startup lines. diff --git a/report.c b/report.c index a036820..42456bf 100644 --- a/report.c +++ b/report.c @@ -73,9 +73,11 @@ void report_status_message(uint8_t status_code) case STATUS_SETTING_READ_FAIL: printPgmString(PSTR("Failed to read EEPROM settings. Using defaults")); break; case STATUS_HOMING_ERROR: - printPgmString(PSTR("Grbl must be idle to home")); break; + printPgmString(PSTR("Must be idle to home")); break; case STATUS_ABORT_CYCLE: - printPgmString(PSTR("Abort during cycle")); break; + printPgmString(PSTR("Abort during cycle. Position may be lost")); break; + case STATUS_PURGE_CYCLE: + printPgmString(PSTR("Can't purge buffer during cycle")); break; } printPgmString(PSTR("\r\n")); } @@ -95,15 +97,15 @@ void report_feedback_message(int8_t message_code) case MESSAGE_SYSTEM_ALARM: printPgmString(PSTR("ALARM: Check and reset Grbl")); break; case MESSAGE_POSITION_LOST: - printPgmString(PSTR("Position unknown. '$H' to home")); break; + printPgmString(PSTR("'$H' to home and enable axes")); break; case MESSAGE_HOMING_ENABLE: printPgmString(PSTR("WARNING: All limit switches must be installed before homing")); break; case MESSAGE_SWITCH_ON: printPgmString(PSTR("Switch enabled")); break; case MESSAGE_SWITCH_OFF: printPgmString(PSTR("Switch disabled")); break; - case MESSAGE_SWITCHES_CLEARED: - printPgmString(PSTR("Switches cleared")); break; + case MESSAGE_PURGE_AXES_LOCK: + printPgmString(PSTR("WARNING: Motion lock disabled. Position unknown.")); break; } printPgmString(PSTR("]\r\n")); } @@ -124,13 +126,13 @@ void report_grbl_help() { "$N (print startup blocks)\r\n" "$x=value (store Grbl setting)\r\n" "$Nx=line (store startup block)\r\n" - "$H (perform homing cycle)\r\n" - "$S (clear all switches)\r\n" "$S0 (toggle check gcode)\r\n" "$S1 (toggle dry run)\r\n" "$S2 (toggle block delete)\r\n" "$S3 (toggle single block)\r\n" "$S4 (toggle optional stop)\r\n" + "$P (purge buffer and locks)\r\n" + "$H (perform homing cycle)\r\n" "~ (cycle start)\r\n" "! (feed hold)\r\n" "? (current position)\r\n" diff --git a/report.h b/report.h index f0b5604..810d199 100644 --- a/report.h +++ b/report.h @@ -36,6 +36,7 @@ #define STATUS_SETTING_READ_FAIL 11 #define STATUS_HOMING_ERROR 12 #define STATUS_ABORT_CYCLE 13 +#define STATUS_PURGE_CYCLE 14 // Define Grbl feedback message codes. Less than zero to distinguish message from error. #define MESSAGE_SYSTEM_ALARM -1 @@ -43,7 +44,7 @@ #define MESSAGE_HOMING_ENABLE -3 #define MESSAGE_SWITCH_ON -4 #define MESSAGE_SWITCH_OFF -5 -#define MESSAGE_SWITCHES_CLEARED -6 +#define MESSAGE_PURGE_AXES_LOCK -6 // Prints system status messages. void report_status_message(uint8_t status_code);