New configuration options.

- New configuration option at compile-time:
 - Force alarm upon power-up or hard reset. When homing is enabled,
this is already the default behavior. This simply forces this all of
the time.
 - GUI reporting mode. Removes most human-readable strings that GUIs
don’t need. This saves nearly 2KB in flash space that can be used for
other features.
 - Hard limit force state check: In the hard limit pin change ISR, Grbl
by default sets the hard limit alarm upon any pin change to guarantee
the alarm is set. If this option is set, it’ll check the state within
the ISR, but can’t guarantee the pin will be read correctly if the
switch is bouncing. This option makes hard limit behavior a little less
annoying if you have a good buffered switch circuit that removes
bouncing and electronic noise.

- Software debounce bug fix. It was reading the pin incorrectly for the
setting.

- Re-factored some of the ‘$’ settings code.
This commit is contained in:
Sonny Jeon 2015-02-23 18:45:26 -07:00
parent d034dc2181
commit c7db1c4546
6 changed files with 240 additions and 159 deletions

View File

@ -106,8 +106,8 @@
// this feature. Since the two switches are sharing a single pin, there is no way for Grbl to tell
// which one is enabled. This option only effects homing, where if a limit is engaged, Grbl will
// alarm out and force the user to manually disengage the limit switch. Otherwise, if you have one
// limit switch for each axis, don't enable this option. By keeping it disabled, you can homing while
// on the limit switch and not have to move the machine off of it.
// limit switch for each axis, don't enable this option. By keeping it disabled, you can perform a
// homing cycle while on the limit switch and not have to move the machine off of it.
// #define LIMITS_TWO_SWITCHES_ON_AXES
// Allows GRBL to track and report gcode line numbers. Enabling this means that the planning buffer
@ -161,9 +161,22 @@
// with little to no benefit during normal operation.
// #define REPORT_INPUT_PIN_STATES // Default disabled. Uncomment to enable.
// When Grbl powers-cycles or is hard reset with the Arduino reset button, Grbl boots up with no ALARM
// by default. This is to make it as simple as possible for new users to start using Grbl. When homing
// is enabled and a user has installed limit switches, Grbl will boot up in an ALARM state to indicate
// Grbl doesn't know its position and to force the user to home before proceeding. This option forces
// Grbl to always initialize into an ALARM state regardless of homing or not. This option is more for
// OEMs and LinuxCNC users that would like this power-cycle behavior.
// #define FORCE_INITIALIZATION_ALARM // Default disabled. Uncomment to enable.
// ---------------------------------------------------------------------------------------
// ADVANCED CONFIGURATION OPTIONS:
// Enables minimal reporting feedback mode for GUIs, where human-readable strings are not as important.
// This saves nearly 2KB of flash space and may allow enough space to install other/future features.
// NOTE: This feature is new and experimental. Make sure the GUI you are using supports this mode.
#define REPORT_GUI_MODE // Default disabled. Uncomment to enable.
// The temporal resolution of the acceleration management subsystem. A higher number gives smoother
// acceleration, particularly noticeable on machines that run at very high feedrates, but may negatively
// impact performance. The correct value for this parameter is machine dependent, so it's advised to
@ -180,8 +193,10 @@
// step smoothing. See stepper.c for more details on the AMASS system works.
#define ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING // Default enabled. Comment to disable.
// Sets the maximum step rate allowed to be written as a Grbl setting. This value is strictly limited
// by the CPU speed and will change if something other than an AVR running at 16MHz is used.
// Sets the maximum step rate allowed to be written as a Grbl setting. This option enables an error
// check in the settings module to prevent settings values that will exceed this limitation. The maximum
// step rate is strictly limited by the CPU speed and will change if something other than an AVR running
// at 16MHz is used.
// NOTE: For now disabled, will enable if flash space permits.
// #define MAX_STEP_RATE_HZ 30000 // Hz
@ -318,6 +333,17 @@
// work well and are cheap to find) and wire in a low-pass circuit into each limit pin.
// #define ENABLE_SOFTWARE_DEBOUNCE // Default disabled. Uncomment to enable.
// Force Grbl to check the state of the hard limit switches when the processor detects a pin
// change inside the hard limit ISR routine. By default, Grbl will trigger the hard limits
// alarm upon any pin change, since bouncing switches can cause a state check like this to
// misread the pin. When hard limits are triggers, this should be 100% reliable, which is the
// reason that this option is disabled by default. Only if your system/electronics can guarantee
// the pins don't bounce, we recommend enabling this option. If so, this will help prevent
// triggering a hard limit when the machine disengages from the switch.
// NOTE: This option has no effect if SOFTWARE_DEBOUNCE is enabled.
// #define HARD_LIMIT_FORCE_STATE_CHECK // Default disabled. Uncomment to enable.
// ---------------------------------------------------------------------------------------
// TODO: Install compile-time option to send numeric status codes rather than strings.

View File

@ -22,8 +22,8 @@
#define grbl_h
// Grbl versioning system
#define GRBL_VERSION "0.9h"
#define GRBL_VERSION_BUILD "20150215"
#define GRBL_VERSION "0.9i"
#define GRBL_VERSION_BUILD "20150223"
// Define standard libraries used by Grbl.
#include <avr/io.h>

View File

@ -79,9 +79,19 @@ void limits_disable()
// limit setting if their limits are constantly triggering after a reset and move their axes.
if (sys.state != STATE_ALARM) {
if (!(sys.rt_exec_alarm)) {
#ifdef HARD_LIMIT_FORCE_STATE_CHECK
uint8_t bits = (LIMIT_PIN & LIMIT_MASK);
// Check limit pin state.
if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { bits ^= LIMIT_MASK; }
if (bits) {
mc_reset(); // Initiate system kill.
bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event
}
#else
mc_reset(); // Initiate system kill.
bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event
#endif
}
}
}
#else // OPTIONAL: Software debounce limit pin routine.
@ -92,10 +102,10 @@ void limits_disable()
WDTCSR &= ~(1<<WDIE); // Disable watchdog timer.
if (sys.state != STATE_ALARM) { // Ignore if already in alarm state.
if (!(sys.rt_exec_alarm)) {
uint8_t bits = LIMIT_PIN;
uint8_t bits = (LIMIT_PIN & LIMIT_MASK);
// Check limit pin state.
if (bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { bits ^= LIMIT_MASK; }
if (bits & LIMIT_MASK) {
if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { bits ^= LIMIT_MASK; }
if (bits) {
mc_reset(); // Initiate system kill.
bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event
}

View File

@ -49,6 +49,11 @@ int main(void)
if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { sys.state = STATE_ALARM; }
#endif
// Force Grbl into an ALARM state upon a power-cycle or hard reset.
#ifdef FORCE_INITIALIZATION_ALARM
sys.state = STATE_ALARM;
#endif
// Grbl initialization loop upon power-up or a system abort. For the latter, all processes
// will return to this loop to be cleanly re-initialized.
for(;;) {

View File

@ -43,6 +43,9 @@ void report_status_message(uint8_t status_code)
printPgmString(PSTR("ok\r\n"));
} else {
printPgmString(PSTR("error: "));
#ifdef REPORT_GUI_MODE
print_uint8_base10(status_code);
#else
switch(status_code) {
case STATUS_EXPECTED_COMMAND_LETTER:
printPgmString(PSTR("Expected command letter")); break;
@ -81,6 +84,7 @@ void report_status_message(uint8_t status_code)
printPgmString(PSTR("Invalid gcode ID:"));
print_uint8_base10(status_code); // Print error code for user reference
}
#endif
printPgmString(PSTR("\r\n"));
}
}
@ -89,6 +93,9 @@ void report_status_message(uint8_t status_code)
void report_alarm_message(int8_t alarm_code)
{
printPgmString(PSTR("ALARM: "));
#ifdef REPORT_GUI_MODE
print_uint8_base10(alarm_code);
#else
switch (alarm_code) {
case ALARM_HARD_LIMIT_ERROR:
printPgmString(PSTR("Hard limit")); break;
@ -101,6 +108,7 @@ void report_alarm_message(int8_t alarm_code)
case ALARM_HOMING_FAIL:
printPgmString(PSTR("Homing fail")); break;
}
#endif
printPgmString(PSTR("\r\n"));
delay_ms(500); // Force delay to ensure message clears serial write buffer.
}
@ -140,6 +148,7 @@ void report_init_message()
// Grbl help message
void report_grbl_help() {
#ifndef REPORT_GUI_MODE
printPgmString(PSTR("$$ (view Grbl settings)\r\n"
"$# (view # parameters)\r\n"
"$G (view parser state)\r\n"
@ -154,6 +163,7 @@ void report_grbl_help() {
"! (feed hold)\r\n"
"? (current status)\r\n"
"ctrl-x (reset Grbl)\r\n"));
#endif
}
@ -161,6 +171,28 @@ void report_grbl_help() {
// NOTE: The numbering scheme here must correlate to storing in settings.c
void report_grbl_settings() {
// Print Grbl settings.
#ifdef REPORT_GUI_MODE
printPgmString(PSTR("$0=")); print_uint8_base10(settings.pulse_microseconds);
printPgmString(PSTR("\r\n$1=")); print_uint8_base10(settings.stepper_idle_lock_time);
printPgmString(PSTR("\r\n$2=")); print_uint8_base10(settings.step_invert_mask);
printPgmString(PSTR("\r\n$3=")); print_uint8_base10(settings.dir_invert_mask);
printPgmString(PSTR("\r\n$4=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE));
printPgmString(PSTR("\r\n$5=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_LIMIT_PINS));
printPgmString(PSTR("\r\n$6=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_INVERT_PROBE_PIN));
printPgmString(PSTR("\r\n$10=")); print_uint8_base10(settings.status_report_mask);
printPgmString(PSTR("\r\n$11=")); printFloat_SettingValue(settings.junction_deviation);
printPgmString(PSTR("\r\n$12=")); printFloat_SettingValue(settings.arc_tolerance);
printPgmString(PSTR("\r\n$13=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES));
printPgmString(PSTR("\r\n$20=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE));
printPgmString(PSTR("\r\n$21=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));
printPgmString(PSTR("\r\n$22=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));
printPgmString(PSTR("\r\n$23=")); print_uint8_base10(settings.homing_dir_mask);
printPgmString(PSTR("\r\n$24=")); printFloat_SettingValue(settings.homing_feed_rate);
printPgmString(PSTR("\r\n$25=")); printFloat_SettingValue(settings.homing_seek_rate);
printPgmString(PSTR("\r\n$26=")); print_uint8_base10(settings.homing_debounce_delay);
printPgmString(PSTR("\r\n$27=")); printFloat_SettingValue(settings.homing_pulloff);
printPgmString(PSTR("\r\n"));
#else
printPgmString(PSTR("$0=")); print_uint8_base10(settings.pulse_microseconds);
printPgmString(PSTR(" (step pulse, usec)\r\n$1=")); print_uint8_base10(settings.stepper_idle_lock_time);
printPgmString(PSTR(" (step idle delay, msec)\r\n$2=")); print_uint8_base10(settings.step_invert_mask);
@ -185,6 +217,7 @@ void report_grbl_settings() {
printPgmString(PSTR(" (homing seek, mm/min)\r\n$26=")); print_uint8_base10(settings.homing_debounce_delay);
printPgmString(PSTR(" (homing debounce, msec)\r\n$27=")); printFloat_SettingValue(settings.homing_pulloff);
printPgmString(PSTR(" (homing pull-off, mm)\r\n"));
#endif
// Print axis settings
uint8_t idx, set_idx;
@ -200,6 +233,9 @@ void report_grbl_settings() {
case 2: printFloat_SettingValue(settings.acceleration[idx]/(60*60)); break;
case 3: printFloat_SettingValue(-settings.max_travel[idx]); break;
}
#ifdef REPORT_GUI_MODE
printPgmString(PSTR("\r\n"));
#else
printPgmString(PSTR(" ("));
switch (idx) {
case X_AXIS: printPgmString(PSTR("x")); break;
@ -213,6 +249,7 @@ void report_grbl_settings() {
case 3: printPgmString(PSTR(" max travel, mm")); break;
}
printPgmString(PSTR(")\r\n"));
#endif
}
val += AXIS_SETTINGS_INCREMENT;
}

View File

@ -109,18 +109,18 @@ uint8_t system_execute_line(char *line)
float parameter, value;
switch( line[char_counter] ) {
case 0 : report_grbl_help(); break;
case '$': case 'G': case 'C': case 'X':
if ( line[(char_counter+1)] != 0 ) { return(STATUS_INVALID_STATEMENT); }
switch( line[char_counter] ) {
case '$' : // Prints Grbl settings
if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); }
if ( sys.state & (STATE_CYCLE | STATE_HOLD) ) { return(STATUS_IDLE_ERROR); } // Block during cycle. Takes too long to print.
else { report_grbl_settings(); }
break;
case 'G' : // Prints gcode parser state
// TODO: Move this to realtime commands for GUIs to request this data during suspend-state.
if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); }
else { report_gcode_modes(); }
report_gcode_modes();
break;
case 'C' : // Set check g-code mode [IDLE/CHECK]
if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); }
// Perform reset when toggling off. Check g-code mode should only work if Grbl
// is idle and ready, regardless of alarm locks. This is mainly to keep things
// simple and consistent.
@ -134,7 +134,6 @@ uint8_t system_execute_line(char *line)
}
break;
case 'X' : // Disable alarm lock [ALARM]
if ( line[++char_counter] != 0 ) { return(STATUS_INVALID_STATEMENT); }
if (sys.state == STATE_ALARM) {
report_feedback_message(MESSAGE_ALARM_UNLOCK);
sys.state = STATE_IDLE;
@ -145,7 +144,7 @@ uint8_t system_execute_line(char *line)
}
} // Otherwise, no effect.
break;
// case 'J' : break; // Jogging methods
// case 'J' : break; // Jogging methods
// TODO: Here jogging can be placed for execution as a seperate subprogram. It does not need to be
// susceptible to other realtime commands except for e-stop. The jogging function is intended to
// be a basic toggle on/off with controlled acceleration and deceleration to prevent skipped
@ -157,6 +156,10 @@ uint8_t system_execute_line(char *line)
// handled by the planner. It would be possible for the jog subprogram to insert blocks into the
// 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.
// }
// break;
}
break;
default :
// Block any system command that requires the state as IDLE/ALARM. (i.e. EEPROM, homing)
if ( !(sys.state == STATE_IDLE || sys.state == STATE_ALARM) ) { return(STATUS_IDLE_ERROR); }