Homing and limit updates. Minor bug fixes.

- Updated new homing cycle to error out when a pull-off motion detects
the limit is still active.

- Created a limits_get_state() function to centralize it. It reports
state as a bit-wise booleans according to axis numbering.

- Updated the print uint8 functions. Generalized it to allow both base2
and base10 printouts, while allowing base2 prints with N_AXIS digits
for limit state status reports. Doing this saved about 100bytes of
flash as well.

- Applied CoreXY status reporting bug fix by @phd0. Thanks!
This commit is contained in:
Sonny Jeon 2015-05-23 11:57:30 -06:00
parent e704862f11
commit f85c481ded
10 changed files with 172 additions and 70 deletions

View File

@ -1,3 +1,84 @@
----------------
Date: 2015-05-22
Author: Sonny Jeon
Subject: Merge pull request #702 from ashelly/default-split
Moving defaults to individual files in subdirectory
----------------
Date: 2015-05-22
Author: ashelly
Subject: Moving defaults to individual files in subdirectory
----------------
Date: 2015-05-22
Author: Sonny Jeon
Subject: Merge pull request #700 from ashelly/header-split
Header split
----------------
Date: 2015-05-22
Author: ashelly
Subject: Fixing up comment blocks in headers
----------------
Date: 2015-05-22
Author: ashelly
Subject: Splitting Cpu map into separate files.
Makes comparison, addition of new ones easier
----------------
Date: 2015-05-17
Author: Sonny Jeon
Subject: Critical M0/2/30 fix. Homing updates.
- Critical fix for M0 program pause. Due to its recent change, it would
cause Grbl to suspend but wouldnt notify the user of why Grbl was not
doing anything. The state would show IDLE and a cycle start would
resume it. Grbl now enters a HOLD state to better indicate the state
change.
- Critical fix for M2 and M30 program end. As with M0, the state
previously would show IDLE while suspended. Grbl now does not suspend
upon program end and leaves job control to the GUI. Grbl simply reports
a `[Pgm End]` as a feedback message and resets certain g-code modes.
- M2/30 g-code reseting fix. Previously Grbl would soft-reset after an
M2/30, but this was not complaint to the (linuxcnc) g-code standard. It
simply resets [G1,G17,G90,G94,G40,G54,M5,M9,M48] and keeps all other
modes the same.
- M0/M2/M30 check-mode fix. It now does not suspend the machine during
check-mode.
- Minor bug fix related to commands similar to G90.1, but not G90.1,
not reporting an unsupported command.
- Homing cycle refactoring. To help reduce the chance of users
misunderstanding their limit switch wiring, Grbl only moves a short
distance for the locate cycles only. In addition, the homing cycle
pulls-off the limit switch by the pull-off distance to re-engage and
locate home. This should improve its accuracy.
- HOMING_FORCE_ORIGIN now sets the origin to the pull-off location,
rather than where the limit switch was triggered.
- Updated default junction deviation to 0.01mm. Recent tests showed
that this improves Grbls cornering behavior a bit.
- Added the ShapeOko3 defaults.
- Added new feedback message `[Pgm End]` for M2/30 notification.
- Limit pin reporting is now a $10 status report option. Requested by
OEMs to help simplify support troubleshooting.
---------------- ----------------
Date: 2015-03-29 Date: 2015-03-29
Author: Sonny Jeon Author: Sonny Jeon

View File

@ -26,7 +26,9 @@
Ensure one and only one of these DEFAULTS_XXX values is defined in config.h */ Ensure one and only one of these DEFAULTS_XXX values is defined in config.h */
#ifndef defaults_h #ifndef defaults_h
// Don't #define defaults_h here, let the selected file do it. Prevents incuding more than one.
// Only define the DEFAULT_XXX with where to find the corresponding default_XXX.h file.
// Don't #define defaults_h here, let the selected file do it. Prevents including more than one.
#ifdef DEFAULTS_GENERIC #ifdef DEFAULTS_GENERIC
// Grbl generic default settings. Should work across different machines. // Grbl generic default settings. Should work across different machines.

View File

@ -23,7 +23,7 @@
// Grbl versioning system // Grbl versioning system
#define GRBL_VERSION "0.9i" #define GRBL_VERSION "0.9i"
#define GRBL_VERSION_BUILD "20150516" #define GRBL_VERSION_BUILD "20150523"
// Define standard libraries used by Grbl. // Define standard libraries used by Grbl.
#include <avr/io.h> #include <avr/io.h>

View File

@ -55,6 +55,7 @@ void limits_init()
} }
// Disables hard limits.
void limits_disable() void limits_disable()
{ {
LIMIT_PCMSK &= ~LIMIT_MASK; // Disable specific pins of the Pin Change Interrupt LIMIT_PCMSK &= ~LIMIT_MASK; // Disable specific pins of the Pin Change Interrupt
@ -62,6 +63,24 @@ void limits_disable()
} }
// Returns limit state as a bit-wise uint8 variable. Each bit indicates an axis limit, where
// triggered is 1 and not triggered is 0. Invert mask is applied. Axes are defined by their
// number in bit position, i.e. Z_AXIS is (1<<2) or bit 2, and Y_AXIS is (1<<1) or bit 1.
uint8_t limits_get_state()
{
uint8_t limit_state = 0;
uint8_t pin = (LIMIT_PIN & LIMIT_MASK);
if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { pin ^= LIMIT_MASK; }
if (pin) {
uint8_t idx;
for (idx=0; idx<N_AXIS; idx++) {
if (pin & get_limit_pin_mask(idx)) { limit_state |= (1 << idx); }
}
}
return(limit_state);
}
// This is the Limit Pin Change Interrupt, which handles the hard limit feature. A bouncing // This is the Limit Pin Change Interrupt, which handles the hard limit feature. A bouncing
// limit switch can cause a lot of problems, like false readings and multiple interrupt calls. // limit switch can cause a lot of problems, like false readings and multiple interrupt calls.
// If a switch is triggered at all, something bad has happened and treat it as such, regardless // If a switch is triggered at all, something bad has happened and treat it as such, regardless
@ -84,10 +103,8 @@ void limits_disable()
if (sys.state != STATE_ALARM) { if (sys.state != STATE_ALARM) {
if (!(sys.rt_exec_alarm)) { if (!(sys.rt_exec_alarm)) {
#ifdef HARD_LIMIT_FORCE_STATE_CHECK #ifdef HARD_LIMIT_FORCE_STATE_CHECK
uint8_t bits = (LIMIT_PIN & LIMIT_MASK);
// Check limit pin state. // Check limit pin state.
if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { bits ^= LIMIT_MASK; } if (limits_get_state()) {
if (bits) {
mc_reset(); // Initiate system kill. mc_reset(); // Initiate system kill.
bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event
} }
@ -106,10 +123,8 @@ void limits_disable()
WDTCSR &= ~(1<<WDIE); // Disable watchdog timer. WDTCSR &= ~(1<<WDIE); // Disable watchdog timer.
if (sys.state != STATE_ALARM) { // Ignore if already in alarm state. if (sys.state != STATE_ALARM) { // Ignore if already in alarm state.
if (!(sys.rt_exec_alarm)) { if (!(sys.rt_exec_alarm)) {
uint8_t bits = (LIMIT_PIN & LIMIT_MASK);
// Check limit pin state. // Check limit pin state.
if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { bits ^= LIMIT_MASK; } if (limits_get_state()) {
if (bits) {
mc_reset(); // Initiate system kill. mc_reset(); // Initiate system kill.
bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); // Indicate hard limit critical event
} }
@ -132,13 +147,12 @@ void limits_go_home(uint8_t cycle_mask)
// Initialize // Initialize
uint8_t n_cycle = (2*N_HOMING_LOCATE_CYCLE+1); uint8_t n_cycle = (2*N_HOMING_LOCATE_CYCLE+1);
uint8_t limit_pin[N_AXIS], step_pin[N_AXIS]; uint8_t step_pin[N_AXIS];
float target[N_AXIS]; float target[N_AXIS];
float max_travel = 0.0; float max_travel = 0.0;
uint8_t idx; uint8_t idx;
for (idx=0; idx<N_AXIS; idx++) { for (idx=0; idx<N_AXIS; idx++) {
// Initialize limit and step pin masks // Initialize step pin masks
limit_pin[idx] = get_limit_pin_mask(idx);
step_pin[idx] = get_step_pin_mask(idx); step_pin[idx] = get_step_pin_mask(idx);
#ifdef COREXY #ifdef COREXY
if ((idx==A_MOTOR)||(idx==B_MOTOR)) { step_pin[idx] = (get_step_pin_mask(X_AXIS)|get_step_pin_mask(Y_AXIS)); } if ((idx==A_MOTOR)||(idx==B_MOTOR)) { step_pin[idx] = (get_step_pin_mask(X_AXIS)|get_step_pin_mask(Y_AXIS)); }
@ -199,11 +213,10 @@ void limits_go_home(uint8_t cycle_mask)
do { do {
if (approach) { if (approach) {
// Check limit state. Lock out cycle axes when they change. // Check limit state. Lock out cycle axes when they change.
limit_state = LIMIT_PIN; limit_state = limits_get_state();
if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { limit_state ^= LIMIT_MASK; }
for (idx=0; idx<N_AXIS; idx++) { for (idx=0; idx<N_AXIS; idx++) {
if (axislock & step_pin[idx]) { if (axislock & step_pin[idx]) {
if (limit_state & limit_pin[idx]) { axislock &= ~(step_pin[idx]); } if (limit_state & (1 << idx)) { axislock &= ~(step_pin[idx]); }
} }
} }
sys.homing_axis_lock = axislock; sys.homing_axis_lock = axislock;
@ -211,15 +224,17 @@ void limits_go_home(uint8_t cycle_mask)
st_prep_buffer(); // Check and prep segment buffer. NOTE: Should take no longer than 200us. st_prep_buffer(); // Check and prep segment buffer. NOTE: Should take no longer than 200us.
// Exit routines: User abort homing and alarm upon safety door or no limit switch found. // Exit routines: No time to run protocol_execute_realtime() in this loop.
// No time to run protocol_execute_realtime() in this loop.
if (sys.rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET | EXEC_CYCLE_STOP)) { if (sys.rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET | EXEC_CYCLE_STOP)) {
if ((sys.rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET)) || // Homing failure: Limit switches are still engaged after pull-off motion
((approach) && (sys.rt_exec_state & EXEC_CYCLE_STOP))) { if ( (sys.rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET)) || // Safety door or reset issued
mc_reset(); (!approach && (limits_get_state() & cycle_mask)) || // Limit switch still engaged after pull-off motion
( approach && (sys.rt_exec_state & EXEC_CYCLE_STOP)) ) { // Limit switch not found during approach.
mc_reset(); // Stop motors, if they are running.
protocol_execute_realtime(); protocol_execute_realtime();
return; return;
} else { } else {
// Pull-off motion complete. Disable CYCLE_STOP from executing.
bit_false_atomic(sys.rt_exec_state,EXEC_CYCLE_STOP); bit_false_atomic(sys.rt_exec_state,EXEC_CYCLE_STOP);
break; break;
} }
@ -290,8 +305,7 @@ void limits_go_home(uint8_t cycle_mask)
} }
plan_sync_position(); // Sync planner position to homed machine position. plan_sync_position(); // Sync planner position to homed machine position.
// Set system state to homing before returning. // sys.state = STATE_HOMING; // Ensure system state set as homing before returning.
sys.state = STATE_HOMING;
} }

View File

@ -26,8 +26,12 @@
// Initialize the limits module // Initialize the limits module
void limits_init(); void limits_init();
// Disables hard limits.
void limits_disable(); void limits_disable();
// Returns limit state as a bit-wise uint8 variable.
uint8_t limits_get_state();
// Perform one portion of the homing cycle based on the input settings. // Perform one portion of the homing cycle based on the input settings.
void limits_go_home(uint8_t cycle_mask); void limits_go_home(uint8_t cycle_mask);

View File

@ -225,9 +225,7 @@ void mc_homing_cycle()
// with machines with limits wired on both ends of travel to one limit pin. // with machines with limits wired on both ends of travel to one limit pin.
// TODO: Move the pin-specific LIMIT_PIN call to limits.c as a function. // TODO: Move the pin-specific LIMIT_PIN call to limits.c as a function.
#ifdef LIMITS_TWO_SWITCHES_ON_AXES #ifdef LIMITS_TWO_SWITCHES_ON_AXES
uint8_t limit_state = (LIMIT_PIN & LIMIT_MASK); if (limits_get_state()) {
if (bit_isfalse(settings.flags,BITFLAG_INVERT_LIMIT_PINS)) { limit_state ^= LIMIT_MASK; }
if (limit_state) {
mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown. mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown.
bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT)); bit_true_atomic(sys.rt_exec_alarm, (EXEC_ALARM_HARD_LIMIT|EXEC_CRITICAL_EVENT));
return; return;

View File

@ -60,14 +60,15 @@ void printPgmString(const char *s)
// } // }
void print_uint8_base2(uint8_t n) // Prints an uint8 variable with base and number of desired digits.
void print_unsigned_int8(uint8_t n, uint8_t base, uint8_t digits)
{ {
unsigned char buf[8]; unsigned char buf[digits];
uint8_t i = 0; uint8_t i = 0;
for (; i < 8; i++) { for (; i < digits; i++) {
buf[i] = n & 1; buf[i] = n % base ;
n >>= 1; n /= base;
} }
for (; i > 0; i--) for (; i > 0; i--)
@ -75,23 +76,20 @@ void print_uint8_base2(uint8_t n)
} }
// Prints an uint8 variable in base 2.
void print_uint8_base2(uint8_t n) {
print_unsigned_int8(n,2,8);
}
// Prints an uint8 variable in base 10.
void print_uint8_base10(uint8_t n) void print_uint8_base10(uint8_t n)
{ {
if (n == 0) { uint8_t digits;
serial_write('0'); if (n < 10) { digits = 1; }
return; else if (n < 100) { digits = 2; }
} else { digits = 3; }
print_unsigned_int8(n,10,digits);
unsigned char buf[3];
uint8_t i = 0;
while (n > 0) {
buf[i++] = n % 10 + '0';
n /= 10;
}
for (; i > 0; i--)
serial_write(buf[i - 1]);
} }
@ -119,7 +117,7 @@ void printInteger(long n)
{ {
if (n < 0) { if (n < 0) {
serial_write('-'); serial_write('-');
print_uint32_base10((-n)); print_uint32_base10(-n);
} else { } else {
print_uint32_base10(n); print_uint32_base10(n);
} }
@ -194,12 +192,13 @@ void printFloat_RateValue(float n) {
void printFloat_SettingValue(float n) { printFloat(n,N_DECIMAL_SETTINGVALUE); } void printFloat_SettingValue(float n) { printFloat(n,N_DECIMAL_SETTINGVALUE); }
// Debug tool to print free memory in bytes at the called point. Not used otherwise. // Debug tool to print free memory in bytes at the called point.
void printFreeMemory() // NOTE: Keep commented unless using. Part of this function always gets compiled in.
{ // void printFreeMemory()
extern int __heap_start, *__brkval; // {
uint16_t free; // Up to 64k values. // extern int __heap_start, *__brkval;
free = (int) &free - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); // uint16_t free; // Up to 64k values.
printInteger((int32_t)free); // free = (int) &free - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
printString(" "); // printInteger((int32_t)free);
} // printString(" ");
// }

View File

@ -31,8 +31,13 @@ void printInteger(long n);
void print_uint32_base10(uint32_t n); void print_uint32_base10(uint32_t n);
// Prints uint8 variable with base and number of desired digits.
void print_unsigned_int8(uint8_t n, uint8_t base, uint8_t digits);
// Prints an uint8 variable in base 2.
void print_uint8_base2(uint8_t n); void print_uint8_base2(uint8_t n);
// Prints an uint8 variable in base 10.
void print_uint8_base10(uint8_t n); void print_uint8_base10(uint8_t n);
void printFloat(float n, uint8_t decimal_places); void printFloat(float n, uint8_t decimal_places);

View File

@ -496,10 +496,7 @@ void report_realtime_status()
if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_LIMIT_PINS)) { if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_LIMIT_PINS)) {
printPgmString(PSTR(",Lim:")); printPgmString(PSTR(",Lim:"));
for (idx=0; idx<N_AXIS; idx++) { print_unsigned_int8(limits_get_state(),2,N_AXIS);
if (LIMIT_PIN & get_limit_pin_mask(idx)) { printPgmString(PSTR("1")); }
else { printPgmString(PSTR("0")); }
}
} }
#ifdef REPORT_CONTROL_PIN_STATE #ifdef REPORT_CONTROL_PIN_STATE

View File

@ -252,8 +252,10 @@ float system_convert_axis_steps_to_mpos(int32_t *steps, uint8_t idx)
#ifdef COREXY #ifdef COREXY
if (idx==A_MOTOR) { if (idx==A_MOTOR) {
pos = 0.5*((steps[A_MOTOR] + steps[B_MOTOR])/settings.steps_per_mm[idx]); pos = 0.5*((steps[A_MOTOR] + steps[B_MOTOR])/settings.steps_per_mm[idx]);
} else { // (idx==B_MOTOR) } else if (idx==B_MOTOR) {
pos = 0.5*((steps[A_MOTOR] - steps[B_MOTOR])/settings.steps_per_mm[idx]); pos = 0.5*((steps[A_MOTOR] - steps[B_MOTOR])/settings.steps_per_mm[idx]);
} else {
pos = steps[idx]/settings.steps_per_mm[idx];
} }
#else #else
pos = steps[idx]/settings.steps_per_mm[idx]; pos = steps[idx]/settings.steps_per_mm[idx];