diff --git a/config.h b/config.h index fc5605e..73c4533 100755 --- a/config.h +++ b/config.h @@ -46,9 +46,9 @@ #define X_LIMIT_BIT 1 // Uno Digital Pin 9 #define Y_LIMIT_BIT 2 // Uno Digital Pin 10 #define Z_LIMIT_BIT 3 // Uno Digital Pin 11 -// #define LIMIT_INT PCIE0 // Pin change interrupt settings -// #define LIMIT_INT_vect PCINT0_vect -// #define LIMIT_PCMSK PCMSK0 +#define LIMIT_INT PCIE0 // Pin change interrupt settings +#define LIMIT_INT_vect PCINT0_vect +#define LIMIT_PCMSK PCMSK0 #define SPINDLE_ENABLE_DDR DDRB #define SPINDLE_ENABLE_PORT PORTB @@ -159,9 +159,7 @@ // TODO: The following options are set as compile-time options for now, until the next EEPROM // settings version has solidified. This is to prevent having to support dozens of different // incremental settings versions. -#define CYCLE_AUTO_START 1 // Cycle auto-start boolean flag for the planner. #define BLOCK_DELETE_ENABLE 0 // Block delete enable/disable flag during g-code parsing -#define REPORT_INCH_MODE 0 // Status reporting unit mode (1 = inch, 0 = mm) // This parameter sets the delay time before disabling the steppers after the final block of movement. // A short delay ensures the steppers come to a complete stop and the residual inertial force in the diff --git a/gcode.c b/gcode.c index c59bac7..8437405 100755 --- a/gcode.c +++ b/gcode.c @@ -108,7 +108,8 @@ void gc_init() // protocol_status_message(settings_execute_startup()); } -// Sets g-code parser position in mm. Input in steps. Called by the system abort routine. +// Sets g-code parser position in mm. Input in steps. Called by the system abort and hard +// limit pull-off routines. void gc_set_current_position(int32_t x, int32_t y, int32_t z) { gc.position[X_AXIS] = x/settings.steps_per_mm[X_AXIS]; @@ -183,7 +184,7 @@ uint8_t gc_execute_line(char *line) case 21: gc.inches_mode = false; break; case 28: case 30: // NOTE: G28.1, G30.1 sets home position parameters. Not currently supported. - if (bit_istrue(settings.flags,FLAG_BIT_HOMING_ENABLE)) { + if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { non_modal_action = NON_MODAL_GO_HOME; } else { FAIL(STATUS_SETTING_DISABLED); diff --git a/limits.c b/limits.c index da36409..0785fa5 100755 --- a/limits.c +++ b/limits.c @@ -38,8 +38,31 @@ void limits_init() { LIMIT_DDR &= ~(LIMIT_MASK); // Set as input pins LIMIT_PORT |= (LIMIT_MASK); // Enable internal pull-up resistors. Normal high operation. + + if bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE) { + MCUCR = (1<. */ +/* A big thanks to Alden Hart of Synthetos, supplier of grblshield and TinyG, who has + been integral throughout the development of the higher level details of Grbl, as well + as being a consistent sounding board for the future of accessible and free CNC. */ + #include #include #include "config.h" @@ -46,7 +50,9 @@ int main(void) memset(&sys, 0, sizeof(sys)); // Clear all system variables sys.abort = true; // Set abort to complete initialization - + + // TODO: When Grbl system status is installed, need to set position lost state upon startup. + for(;;) { // Execute system reset upon a system abort, where the main program will return to this loop. @@ -87,9 +93,9 @@ int main(void) // Set system runtime defaults // TODO: Eventual move to EEPROM from config.h when all of the new settings are worked out. // Mainly to avoid having to maintain several different versions. - #ifdef CYCLE_AUTO_START + if (bit_istrue(settings.flags,BITFLAG_AUTO_START)) { sys.auto_start = true; - #endif + } // TODO: Install G20/G21 unit default into settings and load appropriate settings. } diff --git a/motion_control.c b/motion_control.c index 26f16bc..76d8092 100755 --- a/motion_control.c +++ b/motion_control.c @@ -196,9 +196,30 @@ void mc_dwell(float seconds) // Execute homing cycle to locate and set machine zero. void mc_go_home() { - limits_go_home(); + plan_synchronize(); // Empty all motions in buffer before homing. + PCICR &= ~(1 << LIMIT_INT); // Disable hard limits pin change interrupt + + limits_go_home(); // Perform homing routine. + // Upon completion, reset all internal position vectors (g-code parser, planner, system) gc_clear_position(); plan_clear_position(); clear_vector_float(sys.position); + + // If hard limits enabled, move all axes off limit switches before enabling the hard limit + // pin change interrupt. This should help prevent the switches from falsely tripping. + // NOTE: G-code parser was circumvented so its position needs to be updated explicitly. + if (bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)) { + int8_t x_dir, y_dir, z_dir; + x_dir = y_dir = z_dir = 1; + if (bit_istrue(settings.homing_dir_mask,bit(X_DIRECTION_BIT))) { x_dir = -1; } + if (bit_istrue(settings.homing_dir_mask,bit(Y_DIRECTION_BIT))) { y_dir = -1; } + if (bit_istrue(settings.homing_dir_mask,bit(Z_DIRECTION_BIT))) { z_dir = -1; } + mc_line(x_dir*settings.homing_pulloff, y_dir*settings.homing_pulloff, + z_dir*settings.homing_pulloff, settings.homing_feed_rate, false); + st_cycle_start(); // Nothing should be in the buffer except this motion. + plan_synchronize(); // Make sure the motion completes. + gc_set_current_position(sys.position[X_AXIS],sys.position[Y_AXIS],sys.position[Z_AXIS]); + PCICR |= (1 << LIMIT_INT); // Re-enable hard limits. + } } diff --git a/nuts_bolts.h b/nuts_bolts.h index 8e9b58b..d4ecb2d 100755 --- a/nuts_bolts.h +++ b/nuts_bolts.h @@ -35,6 +35,7 @@ #define Z_AXIS 2 #define MM_PER_INCH (25.4) +#define INCH_PER_MM (0.03937) // Useful macros #define clear_vector(a) memset(a, 0, sizeof(a)) @@ -60,16 +61,29 @@ #define EXEC_CYCLE_STOP bit(2) // bitmask 00000100 #define EXEC_FEED_HOLD bit(3) // bitmask 00001000 #define EXEC_RESET bit(4) // bitmask 00010000 -// #define bit(5) // bitmask 00100000 +#define EXEC_ALARM bit(5) // bitmask 00100000 // #define bit(6) // bitmask 01000000 // #define bit(7) // bitmask 10000000 +// Define bit flag masks for sys.switches. (8 flag limit) +#define BITFLAG_BLOCK_DELETE bit(0) +#define BITFLAG_SINGLE_BLOCK bit(1) +#define BITFLAG_OPT_STOP bit(2) +// #define bit(3) +// #define bit(4) +// #define bit(5) +// #define bit(6) +// #define bit(7) + // Define global system variables typedef struct { uint8_t abort; // System abort flag. Forces exit back to main loop for reset. uint8_t feed_hold; // Feed hold flag. Held true during feed hold. Released when ready to resume. uint8_t auto_start; // Planner auto-start flag. Toggled off during feed hold. Defaulted by settings. - + uint8_t alarm; // Alarm mode. Causes all functions to immediately cease until a system abort + // is issued by the user. +// uint8_t switches; // Switches state bitflag variable. For settings not governed by g-code. + int32_t position[3]; // Real-time machine (aka home) position vector in steps. // NOTE: This may need to be a volatile variable, if problems arise. @@ -82,6 +96,7 @@ typedef struct { volatile uint8_t cycle_start; // Cycle start flag. Set by stepper subsystem or main program. volatile uint8_t execute; // Global system runtime executor bitflag variable. See EXEC bitmasks. + } system_t; extern system_t sys; diff --git a/protocol.c b/protocol.c index 78e42bf..234ad45 100755 --- a/protocol.c +++ b/protocol.c @@ -73,7 +73,7 @@ void protocol_status_report() // may be distance to go on block, processed block id, and feed rate. A secondary, non-critical // status report may include g-code state, i.e. inch mode, plane mode, absolute mode, etc. // The report generated must be as short as possible, yet still provide the user easily readable - // information, i.e. 'x0.23,y120.4,z2.4'. This is necessary as it minimizes the computational + // information, i.e. '[0.23,120.4,2.4]'. This is necessary as it minimizes the computational // overhead and allows grbl to keep running smoothly, especially with g-code programs with fast, // short line segments and interface setups that require real-time status reports (5-20Hz). @@ -85,24 +85,33 @@ void protocol_status_report() // home position by the user (likely through '$' setting interface). // Successfully tested at a query rate of 10-20Hz while running a gauntlet of programs at various // speeds. - int32_t print_position[3]; - memcpy(print_position,sys.position,sizeof(sys.position)); - #if REPORT_INCH_MODE - printString("MPos:["); printFloat(print_position[X_AXIS]/(settings.steps_per_mm[X_AXIS]*MM_PER_INCH)); - printString(","); printFloat(print_position[Y_AXIS]/(settings.steps_per_mm[Y_AXIS]*MM_PER_INCH)); - printString(","); printFloat(print_position[Z_AXIS]/(settings.steps_per_mm[Z_AXIS]*MM_PER_INCH)); - printString("],WPos:["); printFloat((print_position[X_AXIS]/settings.steps_per_mm[X_AXIS]-sys.coord_system[sys.coord_select][X_AXIS]-sys.coord_offset[X_AXIS])/MM_PER_INCH); - printString(","); printFloat((print_position[Y_AXIS]/settings.steps_per_mm[Y_AXIS]-sys.coord_system[sys.coord_select][Y_AXIS]-sys.coord_offset[Y_AXIS])/MM_PER_INCH); - printString(","); printFloat((print_position[Z_AXIS]/settings.steps_per_mm[Z_AXIS]-sys.coord_system[sys.coord_select][Z_AXIS]-sys.coord_offset[Z_AXIS])/MM_PER_INCH); - #else - printString("MPos:["); printFloat(print_position[X_AXIS]/(settings.steps_per_mm[X_AXIS])); - printString(","); printFloat(print_position[Y_AXIS]/(settings.steps_per_mm[Y_AXIS])); - printString(","); printFloat(print_position[Z_AXIS]/(settings.steps_per_mm[Z_AXIS])); - printString("],WPos:["); printFloat(print_position[X_AXIS]/settings.steps_per_mm[X_AXIS]-sys.coord_system[sys.coord_select][X_AXIS]-sys.coord_offset[X_AXIS]); - printString(","); printFloat(print_position[Y_AXIS]/settings.steps_per_mm[Y_AXIS]-sys.coord_system[sys.coord_select][Y_AXIS]-sys.coord_offset[Y_AXIS]); - printString(","); printFloat(print_position[Z_AXIS]/settings.steps_per_mm[Z_AXIS]-sys.coord_system[sys.coord_select][Z_AXIS]-sys.coord_offset[Z_AXIS]); - #endif - printString("]\r\n"); + uint8_t i; + int32_t current_position[3]; // Copy current state of the system position variable + memcpy(current_position,sys.position,sizeof(sys.position)); + float print_position[3]; + + // Report machine position + printPgmString(PSTR("MPos:[")); + for (i=0; i<= 2; i++) { + print_position[i] = current_position[i]/settings.steps_per_mm[i]; + if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { print_position[i] *= INCH_PER_MM; } + printFloat(print_position[i]); + if (i < 2) { printPgmString(PSTR(",")); } + } + + // Report work position + printPgmString(PSTR("],WPos:[")); + for (i=0; i<= 2; i++) { + if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { + print_position[i] -= (sys.coord_system[sys.coord_select][i]+sys.coord_offset[i])*INCH_PER_MM; + } else { + print_position[i] -= sys.coord_system[sys.coord_select][i]+sys.coord_offset[i]; + } + printFloat(print_position[i]); + if (i < 2) { printPgmString(PSTR(",")); } + } + + printPgmString(PSTR("]\r\n")); } @@ -129,6 +138,12 @@ void protocol_execute_runtime() { if (sys.execute) { // Enter only if any bit flag is true uint8_t rt_exec = sys.execute; // Avoid calling volatile multiple times + + // System alarm. Something has gone wrong. Disable everything until system reset. + if (rt_exec & EXEC_ALARM) { + while (bit_isfalse(sys.execute,EXEC_RESET)) { sleep_mode(); } + bit_false(sys.execute,EXEC_ALARM); + } // System abort. Steppers have already been force stopped. if (rt_exec & EXEC_RESET) { @@ -157,12 +172,12 @@ void protocol_execute_runtime() if (rt_exec & EXEC_CYCLE_START) { st_cycle_start(); // Issue cycle start command to stepper subsystem - #ifdef CYCLE_AUTO_START + if (bit_istrue(settings.flags,BITFLAG_AUTO_START)) { sys.auto_start = true; // Re-enable auto start after feed hold. - #endif + } bit_false(sys.execute,EXEC_CYCLE_START); - } - } + } + } } diff --git a/serial.c b/serial.c index aa35237..a346cd3 100755 --- a/serial.c +++ b/serial.c @@ -165,7 +165,11 @@ ISR(USART_RX_vect) case CMD_STATUS_REPORT: sys.execute |= EXEC_STATUS_REPORT; break; // Set as true case CMD_CYCLE_START: sys.execute |= EXEC_CYCLE_START; break; // Set as true case CMD_FEED_HOLD: sys.execute |= EXEC_FEED_HOLD; break; // Set as true - case CMD_RESET: + case CMD_RESET: + sys.alarm |= EXEC_ALARM; // Set alarm to allow subsystem disable for certain settings. + + // TODO: When Grbl system status is installed, set position lost state if the cycle is active. + // Immediately force stepper and spindle subsystem idle at an interrupt level. if (!(sys.execute & EXEC_RESET)) { // Force stop only first time. st_go_idle(); diff --git a/settings.c b/settings.c index e012c5c..d4e723c 100755 --- a/settings.c +++ b/settings.c @@ -69,14 +69,16 @@ typedef struct { #define DEFAULT_STEPPING_INVERT_MASK ((1<