diff --git a/config.h b/config.h index 93fd1ee..d1587fa 100644 --- a/config.h +++ b/config.h @@ -3,7 +3,7 @@ Part of Grbl Copyright (c) 2009-2011 Simen Svale Skogsrud - Copyright (c) 2011-2012 Sungeun K. Jeon + Copyright (c) 2011-2013 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -107,13 +107,12 @@ // The "Stepper Driver Interrupt" employs the Pramod Ranade inverse time algorithm to manage the // Bresenham line stepping algorithm. The value ISR_TICKS_PER_SECOND is the frequency(Hz) at which -// the Ranade algorithm ticks at. Maximum step frequencies are limited by the Ranade frequency by -// approximately 0.75-0.9 * ISR_TICK_PER_SECOND. Meaning for 20kHz, the max step frequency is roughly -// 15-18kHz. An Arduino can safely complete a single interrupt of the current stepper driver algorithm -// theoretically up to a frequency of 35-40kHz, but CPU overhead increases exponentially as this -// frequency goes up. So there will be little left for other processes like arcs. -// In future versions, more work will be done to increase the step rates but still stay around -// 20kHz by performing two steps per step event, rather than just one. +// the Ranade algorithm ticks at. Recommended step frequencies are limited by the Ranade frequency by +// approximately 0.75-0.9 * ISR_TICK_PER_SECOND. Meaning for 30kHz, the max step frequency is roughly +// 22.5-27kHz, but 30kHz is still possible, just not optimal. An Arduino can safely complete a single +// interrupt of the current stepper driver algorithm theoretically up to a frequency of 35-40kHz, but +// CPU overhead increases exponentially as this frequency goes up. So there will be little left for +// other processes like arcs. #define ISR_TICKS_PER_SECOND 30000L // Integer (Hz) // The temporal resolution of the acceleration management subsystem. Higher number give smoother @@ -208,7 +207,7 @@ // 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 Teensy or Sanguino. Or decrease if the Arduino +// available RAM, like when re-compiling for a Mega or Sanguino. Or decrease if the Arduino // begins to crash due to the lack of available RAM or if the CPU is having trouble keeping // up with planning new incoming motions as they are executed. // #define BLOCK_BUFFER_SIZE 18 // Uncomment to override default in planner.h. diff --git a/defaults.h b/defaults.h index 293e934..df3903c 100644 --- a/defaults.h +++ b/defaults.h @@ -2,7 +2,7 @@ defaults.h - defaults settings configuration file Part of Grbl - Copyright (c) 2012 Sungeun K. Jeon + Copyright (c) 2012-2013 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -42,6 +42,7 @@ #define DEFAULT_REPORT_INCHES 0 // false #define DEFAULT_AUTO_START 1 // true #define DEFAULT_INVERT_ST_ENABLE 0 // false + #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false #define DEFAULT_HARD_LIMIT_ENABLE 0 // false #define DEFAULT_HOMING_ENABLE 0 // false #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir @@ -51,6 +52,9 @@ #define DEFAULT_HOMING_PULLOFF 1.0 // mm #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255) #define DEFAULT_DECIMAL_PLACES 3 + #define DEFAULT_X_MAX_TRAVEL 200 // mm + #define DEFAULT_Y_MAX_TRAVEL 200 // mm + #define DEFAULT_Z_MAX_TRAVEL 200 // mm #endif #ifdef DEFAULTS_SHERLINE_5400 @@ -72,6 +76,7 @@ #define DEFAULT_REPORT_INCHES 1 // false #define DEFAULT_AUTO_START 1 // true #define DEFAULT_INVERT_ST_ENABLE 0 // false + #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false #define DEFAULT_HARD_LIMIT_ENABLE 0 // false #define DEFAULT_HOMING_ENABLE 0 // false #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir @@ -81,6 +86,9 @@ #define DEFAULT_HOMING_PULLOFF 1.0 // mm #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255) #define DEFAULT_DECIMAL_PLACES 3 + #define DEFAULT_X_MAX_TRAVEL 200 // mm + #define DEFAULT_Y_MAX_TRAVEL 200 // mm + #define DEFAULT_Z_MAX_TRAVEL 200 // mm #endif #ifdef DEFAULTS_SHAPEOKO @@ -105,6 +113,7 @@ #define DEFAULT_REPORT_INCHES 0 // false #define DEFAULT_AUTO_START 1 // true #define DEFAULT_INVERT_ST_ENABLE 0 // false + #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false #define DEFAULT_HARD_LIMIT_ENABLE 0 // false #define DEFAULT_HOMING_ENABLE 0 // false #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir @@ -114,6 +123,9 @@ #define DEFAULT_HOMING_PULLOFF 1.0 // mm #define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-255) #define DEFAULT_DECIMAL_PLACES 3 + #define DEFAULT_X_MAX_TRAVEL 200 // mm + #define DEFAULT_Y_MAX_TRAVEL 200 // mm + #define DEFAULT_Z_MAX_TRAVEL 200 // mm #endif #ifdef DEFAULTS_ZEN_TOOLWORKS_7x7 @@ -136,6 +148,7 @@ #define DEFAULT_REPORT_INCHES 0 // false #define DEFAULT_AUTO_START 1 // true #define DEFAULT_INVERT_ST_ENABLE 0 // false + #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false #define DEFAULT_HARD_LIMIT_ENABLE 0 // false #define DEFAULT_HOMING_ENABLE 0 // false #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir @@ -145,6 +158,9 @@ #define DEFAULT_HOMING_PULLOFF 1.0 // mm #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255) #define DEFAULT_DECIMAL_PLACES 3 + #define DEFAULT_X_MAX_TRAVEL 200 // mm + #define DEFAULT_Y_MAX_TRAVEL 200 // mm + #define DEFAULT_Z_MAX_TRAVEL 200 // mm #endif #endif diff --git a/gcode.c b/gcode.c index 4445787..b52de4b 100644 --- a/gcode.c +++ b/gcode.c @@ -3,7 +3,7 @@ Part of Grbl Copyright (c) 2009-2011 Simen Svale Skogsrud - Copyright (c) 2011-2012 Sungeun K. Jeon + Copyright (c) 2011-2013 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -322,7 +322,7 @@ uint8_t gc_execute_line(char *line) target[i] = gc.position[i]; } } - mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], -1.0, false); + mc_line(target, -1.0, false); } // Retreive G28/30 go-home position data (in machine coordinates) from EEPROM float coord_data[N_AXIS]; @@ -331,7 +331,7 @@ uint8_t gc_execute_line(char *line) } else { if (!settings_read_coord_data(SETTING_INDEX_G30,coord_data)) { return(STATUS_SETTING_READ_FAIL); } } - mc_line(coord_data[X_AXIS], coord_data[Y_AXIS], coord_data[Z_AXIS], -1.0, false); + mc_line(coord_data, -1.0, false); memcpy(gc.position, coord_data, sizeof(coord_data)); // gc.position[] = coord_data[]; axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags. break; @@ -404,7 +404,7 @@ uint8_t gc_execute_line(char *line) break; case MOTION_MODE_SEEK: if (!axis_words) { FAIL(STATUS_INVALID_STATEMENT);} - else { mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], -1.0, false); } + else { mc_line(target, -1.0, false); } break; case MOTION_MODE_LINEAR: // TODO: Inverse time requires F-word with each statement. Need to do a check. Also need @@ -412,8 +412,7 @@ uint8_t gc_execute_line(char *line) // and after an inverse time move and then check for non-zero feed rate each time. This // should be efficient and effective. if (!axis_words) { FAIL(STATUS_INVALID_STATEMENT);} - else { mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], - (gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode); } + else { mc_line(target, (gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode); } break; case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC: // Check if at least one of the axes of the selected plane has been specified. If in center diff --git a/limits.c b/limits.c index 1da9c54..a235057 100644 --- a/limits.c +++ b/limits.c @@ -3,7 +3,7 @@ Part of Grbl Copyright (c) 2009-2011 Simen Svale Skogsrud - Copyright (c) 2012 Sungeun K. Jeon + Copyright (c) 2012-2013 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -244,3 +244,29 @@ void limits_go_home() st_go_idle(); // Call main stepper shutdown routine. } + + +// Performs a soft limit check. Called from mc_line() only. Assumes the machine has been homed, +// and the workspace volume is in all negative space. +void limits_soft_check(float *target) +{ + if ( target[X_AXIS] > 0 || target[X_AXIS] < -settings.max_travel[X_AXIS] || + target[Y_AXIS] > 0 || target[Y_AXIS] < -settings.max_travel[Y_AXIS] || + target[Z_AXIS] > 0 || target[Z_AXIS] < -settings.max_travel[Z_AXIS] ) { + + // Force feed hold if cycle is active. All buffered blocks are guaranteed to be within + // workspace volume so just come to a controlled stop so position is not lost. When complete + // enter alarm mode. + if (sys.state == STATE_CYCLE) { + st_feed_hold(); + while (sys.state == STATE_HOLD) { + protocol_execute_runtime(); + if (sys.abort) { return; } + } + } + + mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown. + sys.execute |= EXEC_CRIT_EVENT; // Indicate soft limit critical event + protocol_execute_runtime(); // Execute to enter critical event loop and system abort + } +} diff --git a/limits.h b/limits.h index 847c667..ac94dd6 100644 --- a/limits.h +++ b/limits.h @@ -3,6 +3,7 @@ Part of Grbl Copyright (c) 2009-2011 Simen Svale Skogsrud + Copyright (c) 2013 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,10 +22,13 @@ #ifndef limits_h #define limits_h -// initialize the limits module +// Initialize the limits module void limits_init(); -// perform the homing cycle +// Perform the homing cycle void limits_go_home(); +// Check for soft limit violations +void limits_soft_check(float *target); + #endif \ No newline at end of file diff --git a/main.c b/main.c index b1e7734..84b0313 100644 --- a/main.c +++ b/main.c @@ -3,7 +3,7 @@ Part of Grbl Copyright (c) 2009-2011 Simen Svale Skogsrud - Copyright (c) 2011-2012 Sungeun K. Jeon + Copyright (c) 2011-2013 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -106,7 +106,7 @@ int main(void) // When the serial protocol returns, there are no more characters in the serial read buffer to // be processed and executed. This indicates that individual commands are being issued or // streaming is finished. In either case, auto-cycle start, if enabled, any queued moves. - if (sys.auto_start) { st_cycle_start(); } + mc_auto_cycle_start(); } return 0; /* never reached */ diff --git a/motion_control.c b/motion_control.c index ca23c87..15601e6 100644 --- a/motion_control.c +++ b/motion_control.c @@ -3,7 +3,7 @@ Part of Grbl Copyright (c) 2009-2011 Simen Svale Skogsrud - Copyright (c) 2011-2012 Sungeun K. Jeon + Copyright (c) 2011-2013 Sungeun K. Jeon Copyright (c) 2011 Jens Geisler Grbl is free software: you can redistribute it and/or modify @@ -41,19 +41,15 @@ // (1 minute)/feed_rate time. // NOTE: This is the primary gateway to the grbl planner. All line motions, including arc line // segments, must pass through this routine before being passed to the planner. The seperation of -// mc_line and plan_buffer_line is done primarily to make backlash compensation or canned cycle -// integration simple and direct. -// TODO: Check for a better way to avoid having to push the arguments twice for non-backlash cases. -// However, this keeps the memory requirements lower since it doesn't have to call and hold two -// plan_buffer_lines in memory. Grbl only has to retain the original line input variables during a -// backlash segment(s). -void mc_line(float x, float y, float z, float feed_rate, uint8_t invert_feed_rate) +// mc_line and plan_buffer_line is done primarily to place non-planner-type functions from being +// in the planner and to let backlash compensation or canned cycle integration simple and direct. +void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate) { - // TODO: Perform soft limit check here. Just check if the target x,y,z values are outside the - // work envelope. Should be straightforward and efficient. By placing it here, rather than in - // the g-code parser, it directly picks up motions from everywhere in Grbl. - - // If in check gcode mode, prevent motion by blocking planner. + // If enabled, check for soft limit violations. Placed here all line motions are picked up + // from everywhere in Grbl. + if (bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)) { limits_soft_check(target); } + + // If in check gcode mode, prevent motion by blocking planner. Soft limits still work. if (sys.state == STATE_CHECK_MODE) { return; } // TODO: Backlash compensation may be installed here. Only need direction info to track when @@ -68,22 +64,15 @@ void mc_line(float x, float y, float z, float feed_rate, uint8_t invert_feed_rat do { protocol_execute_runtime(); // Check for any run-time commands if (sys.abort) { return; } // Bail, if system abort. - } while ( plan_check_full_buffer() ); - plan_buffer_line(x, y, z, feed_rate, invert_feed_rate); + if ( plan_check_full_buffer() ) { mc_auto_cycle_start(); } // Auto-cycle start when buffer is full. + else { break; } + } while (1); + + plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], feed_rate, invert_feed_rate); // If idle, indicate to the system there is now a planned block in the buffer ready to cycle // start. Otherwise ignore and continue on. if (!sys.state) { sys.state = STATE_QUEUED; } - - // Auto-cycle start immediately after planner finishes. Enabled/disabled by grbl settings. During - // a feed hold, auto-start is disabled momentarily until the cycle is resumed by the cycle-start - // runtime command. - // NOTE: This is allows the user to decide to exclusively use the cycle start runtime command to - // begin motion or let grbl auto-start it for them. This is useful when: manually cycle-starting - // when the buffer is completely full and primed; auto-starting, if there was only one g-code - // command sent during manual operation; or if a system is prone to buffer starvation, auto-start - // helps make sure it minimizes any dwelling/motion hiccups and keeps the cycle going. - // if (sys.auto_start) { st_cycle_start(); } } @@ -191,14 +180,14 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8 arc_target[axis_0] = center_axis0 + r_axis0; arc_target[axis_1] = center_axis1 + r_axis1; arc_target[axis_linear] += linear_per_segment; - mc_line(arc_target[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], feed_rate, invert_feed_rate); + mc_line(arc_target, feed_rate, invert_feed_rate); // Bail mid-circle on system abort. Runtime command check already performed by mc_line. if (sys.abort) { return; } } } // Ensure last segment arrives at target location. - mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], feed_rate, invert_feed_rate); + mc_line(target, feed_rate, invert_feed_rate); } @@ -230,31 +219,35 @@ void mc_go_home() protocol_execute_runtime(); // Check for reset and set system abort. if (sys.abort) { return; } // Did not complete. Alarm state set by mc_alarm. - // The machine should now be homed and machine zero has been located. Upon completion, - // reset system position and sync internal position vectors. - clear_vector_float(sys.position); // Set machine zero - sys_sync_current_position(); - sys.state = STATE_IDLE; // Set system state to IDLE to complete motion and indicate homed. - - // Pull-off axes (that have been homed) from limit switches before continuing motion. + // The machine should now be homed and machine limits have been located. By default, + // grbl defines machine space as all negative, as do most CNCs. Since limit switches + // can be on either side of an axes, check and set machine zero appropriately. + // At the same time, set up pull-off maneuver from axes limit switches that have been homed. // This provides some initial clearance off the switches and should also help prevent them // from falsely tripping when hard limits are enabled. - int8_t x_dir, y_dir, z_dir; - x_dir = y_dir = z_dir = 0; - if (HOMING_LOCATE_CYCLE & (1< (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) diff --git a/planner.c b/planner.c index baaba6c..c1a4d4f 100644 --- a/planner.c +++ b/planner.c @@ -3,7 +3,7 @@ Part of Grbl Copyright (c) 2009-2011 Simen Svale Skogsrud - Copyright (c) 2011-2012 Sungeun K. Jeon + Copyright (c) 2011-2013 Sungeun K. Jeon Copyright (c) 2011 Jens Geisler Grbl is free software: you can redistribute it and/or modify @@ -360,11 +360,7 @@ inline block_t *plan_get_current_block() // Returns the availability status of the block ring buffer. True, if full. uint8_t plan_check_full_buffer() { - if (block_buffer_tail == next_buffer_head) { - // TODO: Move this back into motion control. Shouldn't be here, but it's efficient. - if (sys.auto_start) { st_cycle_start(); } // Auto-cycle start when buffer is full. - return(true); - } + if (block_buffer_tail == next_buffer_head) { return(true); } return(false); } diff --git a/planner.h b/planner.h index a16c8c9..ce5126d 100644 --- a/planner.h +++ b/planner.h @@ -3,7 +3,7 @@ Part of Grbl Copyright (c) 2009-2011 Simen Svale Skogsrud - Copyright (c) 2011-2012 Sungeun K. Jeon + Copyright (c) 2011-2013 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -52,7 +52,7 @@ typedef struct { uint32_t d_next; // Scaled distance to next step } block_t; -// Initialize the motion plan subsystem +// Initialize the motion plan subsystem void plan_init(); // Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in diff --git a/protocol.c b/protocol.c index c97770a..56aad3c 100644 --- a/protocol.c +++ b/protocol.c @@ -3,7 +3,7 @@ Part of Grbl Copyright (c) 2009-2011 Simen Svale Skogsrud - Copyright (c) 2011-2012 Sungeun K. Jeon + Copyright (c) 2011-2013 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -105,15 +105,17 @@ void protocol_execute_runtime() if (rt_exec & (EXEC_ALARM | EXEC_CRIT_EVENT)) { sys.state = STATE_ALARM; // Set system alarm state - // Critical event. Only hard limit qualifies. Update this as new critical events surface. + // Critical event. Only hard/soft limit errors currently qualify. if (rt_exec & EXEC_CRIT_EVENT) { - report_alarm_message(ALARM_HARD_LIMIT); + report_alarm_message(ALARM_LIMIT_ERROR); report_feedback_message(MESSAGE_CRITICAL_EVENT); bit_false(sys.execute,EXEC_RESET); // Disable any existing reset do { // Nothing. Block EVERYTHING until user issues reset or power cycles. Hard limits // typically occur while unattended or not paying attention. Gives the user time - // to do what is needed before resetting, like killing the incoming stream. + // to do what is needed before resetting, like killing the incoming stream. The + // same could be said about soft limits. While the position is not lost, the incoming + // stream could be still engaged and cause a serious crash if it continues afterwards. } while (bit_isfalse(sys.execute,EXEC_RESET)); // Standard alarm event. Only abort during motion qualifies. diff --git a/report.c b/report.c index 6b810ad..c115dc7 100644 --- a/report.c +++ b/report.c @@ -2,7 +2,7 @@ report.c - reporting and messaging methods Part of Grbl - Copyright (c) 2012 Sungeun K. Jeon + Copyright (c) 2012-2013 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -74,6 +74,8 @@ void report_status_message(uint8_t status_code) printPgmString(PSTR("Busy or queued")); break; case STATUS_ALARM_LOCK: printPgmString(PSTR("Alarm lock")); break; + case STATUS_SOFT_LIMIT_ERROR: + printPgmString(PSTR("Homing not enabled")); break; } printPgmString(PSTR("\r\n")); } @@ -84,8 +86,8 @@ void report_alarm_message(int8_t alarm_code) { printPgmString(PSTR("ALARM: ")); switch (alarm_code) { - case ALARM_HARD_LIMIT: - printPgmString(PSTR("Hard limit")); break; + case ALARM_LIMIT_ERROR: + printPgmString(PSTR("Hard/soft limit")); break; case ALARM_ABORT_CYCLE: printPgmString(PSTR("Abort during cycle")); break; } @@ -112,7 +114,7 @@ void report_feedback_message(uint8_t message_code) case MESSAGE_ENABLED: printPgmString(PSTR("Enabled")); break; case MESSAGE_DISABLED: - printPgmString(PSTR("Disabled")); break; + printPgmString(PSTR("Disabled")); break; } printPgmString(PSTR("]\r\n")); } @@ -153,25 +155,29 @@ void report_grbl_settings() { printPgmString(PSTR(" (z v_max, mm/min)\r\n$6=")); printFloat(settings.acceleration[X_AXIS]/(60*60)); // Convert from mm/min^2 for human readability printPgmString(PSTR(" (x accel, mm/sec^2)\r\n$7=")); printFloat(settings.acceleration[Y_AXIS]/(60*60)); // Convert from mm/min^2 for human readability printPgmString(PSTR(" (y accel, mm/sec^2)\r\n$8=")); printFloat(settings.acceleration[Z_AXIS]/(60*60)); // Convert from mm/min^2 for human readability - printPgmString(PSTR(" (z accel, mm/sec^2)\r\n$9=")); printInteger(settings.pulse_microseconds); - printPgmString(PSTR(" (step pulse, usec)\r\n$10=")); printFloat(settings.default_feed_rate); - printPgmString(PSTR(" (default feed, mm/min)\r\n$11=")); printInteger(settings.invert_mask); + printPgmString(PSTR(" (z accel, mm/sec^2)\r\n$9=")); printFloat(settings.max_travel[X_AXIS]); + printPgmString(PSTR(" (x max travel, mm)\r\n$10=")); printFloat(settings.max_travel[Y_AXIS]); + printPgmString(PSTR(" (y max travel, mm)\r\n$11=")); printFloat(settings.max_travel[Z_AXIS]); + printPgmString(PSTR(" (z max travel, mm)\r\n$12=")); printInteger(settings.pulse_microseconds); + printPgmString(PSTR(" (step pulse, usec)\r\n$13=")); printFloat(settings.default_feed_rate); + printPgmString(PSTR(" (default feed, mm/min)\r\n$14=")); printInteger(settings.invert_mask); printPgmString(PSTR(" (step port invert mask, int:")); print_uint8_base2(settings.invert_mask); - printPgmString(PSTR(")\r\n$12=")); printInteger(settings.stepper_idle_lock_time); - printPgmString(PSTR(" (step idle delay, msec)\r\n$13=")); printFloat(settings.junction_deviation); - printPgmString(PSTR(" (junction deviation, mm)\r\n$14=")); printFloat(settings.arc_tolerance); - printPgmString(PSTR(" (arc tolerance, mm)\r\n$15=")); printInteger(settings.decimal_places); - printPgmString(PSTR(" (n-decimals, int)\r\n$16=")); printInteger(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)); - printPgmString(PSTR(" (report inches, bool)\r\n$17=")); printInteger(bit_istrue(settings.flags,BITFLAG_AUTO_START)); - printPgmString(PSTR(" (auto start, bool)\r\n$18=")); printInteger(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)); - printPgmString(PSTR(" (invert step enable, bool)\r\n$19=")); printInteger(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)); - printPgmString(PSTR(" (hard limits, bool)\r\n$20=")); printInteger(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)); - printPgmString(PSTR(" (homing cycle, bool)\r\n$21=")); printInteger(settings.homing_dir_mask); + printPgmString(PSTR(")\r\n$15=")); printInteger(settings.stepper_idle_lock_time); + printPgmString(PSTR(" (step idle delay, msec)\r\n$16=")); printFloat(settings.junction_deviation); + printPgmString(PSTR(" (junction deviation, mm)\r\n$17=")); printFloat(settings.arc_tolerance); + printPgmString(PSTR(" (arc tolerance, mm)\r\n$18=")); printInteger(settings.decimal_places); + printPgmString(PSTR(" (n-decimals, int)\r\n$19=")); printInteger(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)); + printPgmString(PSTR(" (report inches, bool)\r\n$20=")); printInteger(bit_istrue(settings.flags,BITFLAG_AUTO_START)); + printPgmString(PSTR(" (auto start, bool)\r\n$21=")); printInteger(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)); + printPgmString(PSTR(" (invert step enable, bool)\r\n$22=")); printInteger(bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)); + printPgmString(PSTR(" (soft limits, bool)\r\n$23=")); printInteger(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)); + printPgmString(PSTR(" (hard limits, bool)\r\n$24=")); printInteger(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)); + printPgmString(PSTR(" (homing cycle, bool)\r\n$25=")); printInteger(settings.homing_dir_mask); printPgmString(PSTR(" (homing dir invert mask, int:")); print_uint8_base2(settings.homing_dir_mask); - printPgmString(PSTR(")\r\n$22=")); printFloat(settings.homing_feed_rate); - printPgmString(PSTR(" (homing feed, mm/min)\r\n$23=")); printFloat(settings.homing_seek_rate); - printPgmString(PSTR(" (homing seek, mm/min)\r\n$24=")); printInteger(settings.homing_debounce_delay); - printPgmString(PSTR(" (homing debounce, msec)\r\n$25=")); printFloat(settings.homing_pulloff); + printPgmString(PSTR(")\r\n$26=")); printFloat(settings.homing_feed_rate); + printPgmString(PSTR(" (homing feed, mm/min)\r\n$27=")); printFloat(settings.homing_seek_rate); + printPgmString(PSTR(" (homing seek, mm/min)\r\n$28=")); printInteger(settings.homing_debounce_delay); + printPgmString(PSTR(" (homing debounce, msec)\r\n$29=")); printFloat(settings.homing_pulloff); printPgmString(PSTR(" (homing pull-off, mm)\r\n")); } diff --git a/report.h b/report.h index 8f1555c..cd7f42d 100644 --- a/report.h +++ b/report.h @@ -2,7 +2,7 @@ report.h - reporting and messaging methods Part of Grbl - Copyright (c) 2012 Sungeun K. Jeon + Copyright (c) 2012-2013 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -35,9 +35,10 @@ #define STATUS_SETTING_READ_FAIL 10 #define STATUS_IDLE_ERROR 11 #define STATUS_ALARM_LOCK 12 +#define STATUS_SOFT_LIMIT_ERROR 13 // Define Grbl alarm codes. Less than zero to distinguish alarm error from status error. -#define ALARM_HARD_LIMIT -1 +#define ALARM_LIMIT_ERROR -1 #define ALARM_ABORT_CYCLE -2 // Define Grbl feedback message codes. diff --git a/settings.c b/settings.c index 2f75e6e..9225a91 100644 --- a/settings.c +++ b/settings.c @@ -3,7 +3,7 @@ Part of Grbl Copyright (c) 2009-2011 Simen Svale Skogsrud - Copyright (c) 2011-2012 Sungeun K. Jeon + Copyright (c) 2011-2013 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -88,6 +88,7 @@ void settings_reset(bool reset_all) { if (DEFAULT_REPORT_INCHES) { settings.flags |= BITFLAG_REPORT_INCHES; } if (DEFAULT_AUTO_START) { settings.flags |= BITFLAG_AUTO_START; } if (DEFAULT_INVERT_ST_ENABLE) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; } + if (DEFAULT_SOFT_LIMIT_ENABLE) { settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE; } if (DEFAULT_HARD_LIMIT_ENABLE) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; } if (DEFAULT_HOMING_ENABLE) { settings.flags |= BITFLAG_HOMING_ENABLE; } settings.homing_dir_mask = DEFAULT_HOMING_DIR_MASK; @@ -97,6 +98,9 @@ void settings_reset(bool reset_all) { settings.homing_pulloff = DEFAULT_HOMING_PULLOFF; settings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME; settings.decimal_places = DEFAULT_DECIMAL_PLACES; + settings.max_travel[X_AXIS] = DEFAULT_X_MAX_TRAVEL; + settings.max_travel[Y_AXIS] = DEFAULT_Y_MAX_TRAVEL; + settings.max_travel[Z_AXIS] = DEFAULT_Z_MAX_TRAVEL; write_global_settings(); } @@ -165,41 +169,50 @@ uint8_t settings_store_global_setting(int parameter, float value) { case 6: settings.acceleration[X_AXIS] = value*60*60; break; // Convert to mm/min^2 for grbl internal use. case 7: settings.acceleration[Y_AXIS] = value*60*60; break; // Convert to mm/min^2 for grbl internal use. case 8: settings.acceleration[Z_AXIS] = value*60*60; break; // Convert to mm/min^2 for grbl internal use. - case 9: + case 9: settings.max_travel[X_AXIS] = value; break; + case 10: settings.max_travel[Y_AXIS] = value; break; + case 11: settings.max_travel[Z_AXIS] = value; break; + case 12: if (value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); } settings.pulse_microseconds = round(value); break; - case 10: settings.default_feed_rate = value; break; - case 11: settings.invert_mask = trunc(value); break; - case 12: settings.stepper_idle_lock_time = round(value); break; - case 13: settings.junction_deviation = fabs(value); break; - case 14: settings.arc_tolerance = value; break; - case 15: settings.decimal_places = round(value); break; - case 16: + case 13: settings.default_feed_rate = value; break; + case 14: settings.invert_mask = trunc(value); break; + case 15: settings.stepper_idle_lock_time = round(value); break; + case 16: settings.junction_deviation = fabs(value); break; + case 17: settings.arc_tolerance = value; break; + case 18: settings.decimal_places = round(value); break; + case 19: if (value) { settings.flags |= BITFLAG_REPORT_INCHES; } else { settings.flags &= ~BITFLAG_REPORT_INCHES; } break; - case 17: // Reset to ensure change. Immediate re-init may cause problems. + case 20: // Reset to ensure change. Immediate re-init may cause problems. if (value) { settings.flags |= BITFLAG_AUTO_START; } else { settings.flags &= ~BITFLAG_AUTO_START; } break; - case 18: // Reset to ensure change. Immediate re-init may cause problems. + case 21: // Reset to ensure change. Immediate re-init may cause problems. if (value) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; } else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; } break; - case 19: + case 22: + if (value) { + if (bit_isfalse(settings.flags, BITFLAG_HOMING_ENABLE)) { return(STATUS_SOFT_LIMIT_ERROR); } + settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE; + } else { settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; } + break; + case 23: if (value) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; } else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; } limits_init(); // Re-init to immediately change. NOTE: Nice to have but could be problematic later. break; - case 20: + case 24: if (value) { settings.flags |= BITFLAG_HOMING_ENABLE; } else { settings.flags &= ~BITFLAG_HOMING_ENABLE; } break; - case 21: settings.homing_dir_mask = trunc(value); break; - case 22: settings.homing_feed_rate = value; break; - case 23: settings.homing_seek_rate = value; break; - case 24: settings.homing_debounce_delay = round(value); break; - case 25: settings.homing_pulloff = value; break; + case 25: settings.homing_dir_mask = trunc(value); break; + case 26: settings.homing_feed_rate = value; break; + case 27: settings.homing_seek_rate = value; break; + case 28: settings.homing_debounce_delay = round(value); break; + case 29: settings.homing_pulloff = value; break; default: return(STATUS_INVALID_STATEMENT); } diff --git a/settings.h b/settings.h index 221c4fb..3369845 100644 --- a/settings.h +++ b/settings.h @@ -3,7 +3,7 @@ Part of Grbl Copyright (c) 2009-2011 Simen Svale Skogsrud - Copyright (c) 2011-2012 Sungeun K. Jeon + Copyright (c) 2011-2013 Sungeun K. Jeon Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,7 +29,7 @@ // Version of the EEPROM data. Will be used to migrate existing data from older versions of Grbl // when firmware is upgraded. Always stored in byte 0 of eeprom -#define SETTINGS_VERSION 52 +#define SETTINGS_VERSION 53 // Define bit flag masks for the boolean settings in settings.flag. #define BITFLAG_REPORT_INCHES bit(0) @@ -37,6 +37,7 @@ #define BITFLAG_INVERT_ST_ENABLE bit(2) #define BITFLAG_HARD_LIMIT_ENABLE bit(3) #define BITFLAG_HOMING_ENABLE bit(4) +#define BITFLAG_SOFT_LIMIT_ENABLE bit(5) // Define EEPROM memory address location values for Grbl settings and parameters // NOTE: The Atmega328p has 1KB EEPROM. The upper half is reserved for parameters and @@ -74,7 +75,7 @@ typedef struct { uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable. uint8_t decimal_places; float max_velocity[N_AXIS]; -// float mm_soft_limit[N_AXIS]; + float max_travel[N_AXIS]; // uint8_t status_report_mask; // Mask to indicate desired report data. } settings_t; extern settings_t settings;