Hard limits, homing direction, pull-off limits after homing, status reports in mm or inches, system alarm, and more.

- Thank you statement added for Alden Hart of Synthetos.

- Hard limits option added, which also works with homing by pulling off
the switches to help prevent unintended triggering. Hard limits use a
interrupt to sense a falling edge pin change and immediately go into
alarm mode, which stops everything and forces the user to issue a reset
(Ctrl-x) or reboot.

- Auto cycle start now a configuration option.

- Alarm mode: A new method to kill all Grbl processes in the event of
something catastrophic or potentially catastropic. Just works with hard
limits for now, but will be expanded to include g-code errors (most
likely) and other events.

- Updated status reports to be configurable in inches or mm mode. Much
more to do here, but this is the first step.

- New settings: auto cycle start, hard limit enable, homing direction
mask (which works the same as the stepper mask), homing pulloff
distance (or distance traveled from homed machine zero to prevent
accidental limit trip).

- Minor memory liberation and calculation speed ups.
This commit is contained in:
Sonny Jeon 2012-10-16 21:29:45 -06:00
parent 34f6d2eb4b
commit df5bb70b25
11 changed files with 193 additions and 83 deletions

View File

@ -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

View File

@ -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);

View File

@ -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<<ISC01) | (0<<ISC00); //1 0 triggers at a falling edge.
LIMIT_PCMSK |= LIMIT_MASK; // Enable specific pins of the Pin Change Interrupt
PCICR |= (1 << LIMIT_INT); // Enable Pin Change Interrupt
}
}
// This is the Limit Pin Change Interrupt, which handles the hard limit feature. This is
// called when Grbl detects a falling edge on a limit pin.
// NOTE: Do not attach an e-stop to the limit pins, because this interrupt is disabled during
// homing cycles and will not respond correctly. Upon user request or need, there may be a
// special pinout for an e-stop, but it is generally recommended to just directly connect
// your e-stop switch to the Arduino reset pin, since it is the most correct way to do this.
ISR(LIMIT_INT_vect)
{
// Kill all processes upon hard limit event.
st_go_idle(); // Immediately stop stepper motion
spindle_stop(); // Stop spindle
sys.auto_start = false; // Disable auto cycle start.
sys.execute |= EXEC_ALARM;
// TODO: When Grbl system status is installed, update here to indicate loss of position.
}
// Moves all specified axes in same specified direction (positive=true, negative=false)
// and at the homing rate. Homing is a special motion case, where there is only an
// acceleration followed by abrupt asynchronous stops by each axes reaching their limit
@ -85,6 +108,7 @@ static void homing_cycle(bool x_axis, bool y_axis, bool z_axis, int8_t pos_dir,
// Set default out_bits.
uint8_t out_bits0 = settings.invert_mask;
out_bits0 ^= (settings.homing_dir_mask & DIRECTION_MASK); // Apply homing direction settings
if (!pos_dir) { out_bits0 ^= DIRECTION_MASK; } // Invert bits, if negative dir.
// Initialize stepping variables
@ -160,11 +184,8 @@ static void homing_cycle(bool x_axis, bool y_axis, bool z_axis, int8_t pos_dir,
void limits_go_home()
{
plan_synchronize(); // Empty all motions in buffer.
// Enable steppers by resetting the stepper disable port
STEPPERS_DISABLE_PORT &= ~(1<<STEPPERS_DISABLE_BIT);
{
STEPPERS_DISABLE_PORT &= ~(1<<STEPPERS_DISABLE_BIT); // Enable steppers, but not the cycle.
// Jog all axes toward home to engage their limit switches at faster homing seek rate.
homing_cycle(false, false, true, true, false, settings.homing_seek_rate); // First jog the z axis
@ -186,9 +207,5 @@ void limits_go_home()
}
}
delay_ms(settings.stepper_idle_lock_time);
// Disable steppers by setting stepper disable
if (settings.stepper_idle_lock_time != 0xff) {
STEPPERS_DISABLE_PORT |= (1<<STEPPERS_DISABLE_BIT);
}
st_go_idle(); // Call main stepper shutdown routine.
}

12
main.c
View File

@ -19,6 +19,10 @@
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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 <avr/interrupt.h>
#include <avr/pgmspace.h>
#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.
}

View File

@ -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.
}
}

View File

@ -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;

View File

@ -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);
}
}
}
}
}

View File

@ -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();

View File

@ -69,14 +69,16 @@ typedef struct {
#define DEFAULT_STEPPING_INVERT_MASK ((1<<X_STEP_BIT)|(1<<Y_STEP_BIT)|(1<<Z_STEP_BIT))
// Developmental default settings
#define DEFAULT_REPORT_INCHES 0 // false
#define DEFAULT_AUTO_START 1 // true
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_HOMING_ENABLE 0 // false
#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir
#define DEFAULT_HOMING_RAPID_FEEDRATE 250.0 // mm/min
#define DEFAULT_HOMING_FEEDRATE 50 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 100 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 1 // mm
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255)
// #define DEFAULT_AUTO_START 1 // true
// #define DEFAULT_INCHES_MODE 1 // true
// #define DEFAULT_BLOCK_DELETE 0 // false
#define DEFAULT_DECIMAL_PLACES 3
void settings_reset(bool reset_all) {
@ -95,12 +97,14 @@ void settings_reset(bool reset_all) {
}
// New settings since last version
settings.flags = 0;
// if (DEFAULT_AUTO_START) { settings.flags |= FLAG_BIT_AUTO_START; }
// if (DEFAULT_INCHES_MODE) { settings.flags |= FLAG_BIT_INCHES_MODE; }
if (DEFAULT_HOMING_ENABLE) { settings.flags |= FLAG_BIT_HOMING_ENABLE; }
if (DEFAULT_AUTO_START) { settings.flags |= BITFLAG_AUTO_START; }
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;
settings.homing_feed_rate = DEFAULT_HOMING_FEEDRATE;
settings.homing_seek_rate = DEFAULT_HOMING_RAPID_FEEDRATE;
settings.homing_debounce_delay = DEFAULT_HOMING_DEBOUNCE_DELAY;
settings.homing_pulloff = DEFAULT_HOMING_PULLOFF;
settings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME;
settings.decimal_places = DEFAULT_DECIMAL_PLACES;
}
@ -111,23 +115,29 @@ void settings_reset(bool reset_all) {
void settings_dump() {
printPgmString(PSTR("$0 = ")); printFloat(settings.steps_per_mm[X_AXIS]);
printPgmString(PSTR(" (steps/mm x)\r\n$1 = ")); printFloat(settings.steps_per_mm[Y_AXIS]);
printPgmString(PSTR(" (steps/mm y)\r\n$2 = ")); printFloat(settings.steps_per_mm[Z_AXIS]);
printPgmString(PSTR(" (steps/mm z)\r\n$3 = ")); printInteger(settings.pulse_microseconds);
printPgmString(PSTR(" (microseconds step pulse)\r\n$4 = ")); printFloat(settings.default_feed_rate);
printPgmString(PSTR(" (mm/min default feed rate)\r\n$5 = ")); printFloat(settings.default_seek_rate);
printPgmString(PSTR(" (mm/min default seek rate)\r\n$6 = ")); printFloat(settings.mm_per_arc_segment);
printPgmString(PSTR(" (mm/arc segment)\r\n$7 = ")); printInteger(settings.invert_mask);
printPgmString(PSTR(" (step port invert mask. binary = ")); print_uint8_base2(settings.invert_mask);
printPgmString(PSTR(" (x axis, steps/mm)\r\n$1 = ")); printFloat(settings.steps_per_mm[Y_AXIS]);
printPgmString(PSTR(" (y axis, steps/mm)\r\n$2 = ")); printFloat(settings.steps_per_mm[Z_AXIS]);
printPgmString(PSTR(" (z axis, steps/mm)\r\n$3 = ")); printInteger(settings.pulse_microseconds);
printPgmString(PSTR(" (step pulse, usec)\r\n$4 = ")); printFloat(settings.default_feed_rate);
printPgmString(PSTR(" (default feed rate, mm/min)\r\n$5 = ")); printFloat(settings.default_seek_rate);
printPgmString(PSTR(" (default seek rate, mm/min)\r\n$6 = ")); printFloat(settings.mm_per_arc_segment);
printPgmString(PSTR(" (arc resolution, mm/segment)\r\n$7 = ")); printInteger(settings.invert_mask);
printPgmString(PSTR(" (step port invert mask, int:binary = ")); print_uint8_base2(settings.invert_mask);
printPgmString(PSTR(")\r\n$8 = ")); printFloat(settings.acceleration/(60*60)); // Convert from mm/min^2 for human readability
printPgmString(PSTR(" (acceleration in mm/sec^2)\r\n$9 = ")); printFloat(settings.junction_deviation);
printPgmString(PSTR(" (cornering junction deviation in mm)\r\n$10 = ")); printInteger(bit_istrue(settings.flags,FLAG_BIT_HOMING_ENABLE));
printPgmString(PSTR(" (boolean homing enable)\r\n$11 = ")); printFloat(settings.homing_feed_rate);
printPgmString(PSTR(" (mm/min homing feed rate)\r\n$12 = ")); printFloat(settings.homing_seek_rate);
printPgmString(PSTR(" (mm/min homing seek rate)\r\n$13 = ")); printInteger(settings.homing_debounce_delay);
printPgmString(PSTR(" (milliseconds homing debounce delay)\r\n$14 = ")); printInteger(settings.stepper_idle_lock_time);
printPgmString(PSTR(" (milliseconds stepper idle lock time)\r\n$15 = ")); printInteger(settings.decimal_places);
printPgmString(PSTR(" (float decimal places)"));
printPgmString(PSTR(" (acceleration, mm/sec^2)\r\n$9 = ")); printFloat(settings.junction_deviation);
printPgmString(PSTR(" (cornering junction deviation, mm)\r\n$10 = ")); printInteger(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES));
printPgmString(PSTR(" (status report inches, bool)\r\n$11 = ")); printInteger(bit_istrue(settings.flags,BITFLAG_AUTO_START));
printPgmString(PSTR(" (auto start enable, bool)\r\n$12 = ")); printInteger(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));
printPgmString(PSTR(" (hard limit enable, bool)\r\n$13 = ")); printInteger(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));
printPgmString(PSTR(" (homing enable, bool)\r\n$14 = ")); printInteger(settings.homing_dir_mask);
printPgmString(PSTR(" (homing direction mask, int:binary = ")); print_uint8_base2(settings.homing_dir_mask);
printPgmString(PSTR(")\r\n$15 = ")); printFloat(settings.homing_feed_rate);
printPgmString(PSTR(" (homing feed rate, mm/min)\r\n$16 = ")); printFloat(settings.homing_seek_rate);
printPgmString(PSTR(" (homing seek rate, mm/min)\r\n$17 = ")); printInteger(settings.homing_debounce_delay);
printPgmString(PSTR(" (homing debounce delay, msec)\r\n$18 = ")); printFloat(settings.homing_pulloff);
printPgmString(PSTR(" (homing pull-off travel, mm)\r\n$19 = ")); printInteger(settings.stepper_idle_lock_time);
printPgmString(PSTR(" (stepper idle lock time, msec)\r\n$20 = ")); printInteger(settings.decimal_places);
printPgmString(PSTR(" (decimal places, int)"));
// char buf[4];
// settings_startup_string((char *)buf);
@ -262,15 +272,35 @@ void settings_store_setting(int parameter, float value) {
case 9: settings.junction_deviation = fabs(value); break;
case 10:
if (value) {
settings.flags |= FLAG_BIT_HOMING_ENABLE;
printPgmString(PSTR("Install all axes limit switches before use\r\n"));
} else { settings.flags &= ~FLAG_BIT_HOMING_ENABLE; }
settings.flags |= BITFLAG_REPORT_INCHES;
} else { settings.flags &= ~BITFLAG_REPORT_INCHES; }
break;
case 11: settings.homing_feed_rate = value; break;
case 12: settings.homing_seek_rate = value; break;
case 13: settings.homing_debounce_delay = round(value); break;
case 14: settings.stepper_idle_lock_time = round(value); break;
case 15: settings.decimal_places = round(value); break;
case 11:
if (value) {
settings.flags |= BITFLAG_AUTO_START;
} else { settings.flags &= ~BITFLAG_AUTO_START; }
break;
case 12:
if (value) {
settings.flags |= BITFLAG_HARD_LIMIT_ENABLE;
} else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; }
break;
case 13:
if (value) {
settings.flags |= BITFLAG_HOMING_ENABLE;
printPgmString(PSTR("Install all axes limit switches before use\r\n"));
} else { settings.flags &= ~BITFLAG_HOMING_ENABLE; }
break;
case 14: settings.homing_dir_mask = trunc(value); break;
case 15: settings.homing_feed_rate = value; break;
case 16: settings.homing_seek_rate = value; break;
case 17: settings.homing_debounce_delay = round(value); break;
case 18: settings.homing_pulloff = value; break;
case 19:
settings.stepper_idle_lock_time = round(value);
// TODO: Immediately check and toggle steppers from always enable or disable?
break;
case 20: settings.decimal_places = round(value); break;
default:
printPgmString(PSTR("Unknown parameter\r\n"));
return;

View File

@ -29,12 +29,13 @@
// 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 53
#define SETTINGS_VERSION 55
// Define bit flag masks in settings.flag.
#define FLAG_BIT_HOMING_ENABLE bit(0)
//#define FLAG_BIT_AUTO_START bit(1)
//#define FLAG_BIT_INCHES_MODE bit(2)
#define BITFLAG_REPORT_INCHES bit(0)
#define BITFLAG_AUTO_START bit(1)
#define BITFLAG_HARD_LIMIT_ENABLE bit(2)
#define BITFLAG_HOMING_ENABLE bit(3)
// Current global settings (persisted in EEPROM from byte 1 onwards)
typedef struct {
@ -48,9 +49,11 @@ typedef struct {
float acceleration;
float junction_deviation;
uint8_t flags; // Contains default toggles
uint8_t homing_dir_mask;
float homing_feed_rate;
float homing_seek_rate;
uint16_t homing_debounce_delay;
float homing_pulloff;
uint8_t stepper_idle_lock_time;
uint8_t decimal_places;
} settings_t;

View File

@ -113,8 +113,8 @@ void st_go_idle()
// Force stepper dwell to lock axes for a defined amount of time to ensure the axes come to a complete
// stop and not drift from residual inertial forces at the end of the last movement.
delay_ms(settings.stepper_idle_lock_time);
// Disable steppers by setting stepper disable
if (settings.stepper_idle_lock_time != 0xff) {
// Disable steppers only upon system alarm activated or by user setting to keep enabled.
if ((settings.stepper_idle_lock_time != 0xff) || bit_istrue(sys.execute,EXEC_ALARM)) {
STEPPERS_DISABLE_PORT |= (1<<STEPPERS_DISABLE_BIT);
}
}